example of using external libraries or packages in Common Lisp - linux

In Common Lisp, quicklisp is a popular library management tool. I'm going to use that tool and I'm going to try and use CL-WHO. I use the SBCL 1.0.57 implementation. I'm going to answer my own question below.
As a beginner, it's not clear how ASDF and quicklisp actually work together. And so it's not clear how to actually use packages or libraries that you've downloaded through quicklisp in an external source file. The quicklisp FAQ, at least at this moment, does not help. In python, it's incredibly simple: you can just put 'import somemodule' and life is great. Is there an equivalent for CL+quicklisp?
If you search, you find many results. Here are some of the most relevant ones I've found:
Lisp importing/loading file
How to use packages installed by quicklisp?
When I was reading through these originally, at least one question came to mind: do I actually have to care about ASDF if I'm using quicklisp? Quicklisp seems to be a higher level management tool. Other people suggest using quickproject. But is that really necessary?

The analogy to Python's imports is the system definition... well, this is a very loose analogy, but, it's the way to go. You declare dependencies in the system definition and then in source code you expect it to be there, so that if you later refer to the bits of the foreign code, you just do it.
Eg. in the system definition you might have: (usually it would be in my-program.asd file)
(defsystem :my-program
:version "0.0.1"
:serial t
:description "My program"
:components ((:file "some-source-file"))
;; `some-external-package' here is the "import", i.e. here you
;; declared that you will be using code from this package.
;; ASDF will generally "know" how to get the code of that package
;; from here on. But if it doesn't, then there are ways to "help it"
;; similar to how in Python there's a procedure to prepare your local
;; files to be used by easy_install
:depends-on (:some-external-package))
Later on in your code you just assume that the some-external-package is available to your program, e.g.:
(some-external-package:exported-symbol)
should just work. ("Your code" is the some-source-file.lisp, you've specified in the components).
This is the ASDF documentation on how to define systems
After you have this file in the place where ASDF might find it*, assuming you have ASDF installed (available to your Lisp, SBCL comes bundled with it), you'd load this system using (asdf:load-system :my-program) Explained here.
* - A quick way to test it would be to do
(push "/path/to/your/system/definition/" asdf:*central-registry*)

Download cl-who through the instructions on the quicklisp page and run this:
#!/usr/bin/sbcl --script
(load "~/quicklisp/setup.lisp")
(ql:quickload "asdf")
(asdf:load-system 'cl-who)
(with-open-file (*standard-output* "out.html" :direction :output)
(cl-who:with-html-output (*standard-output* nil :indent t)
(:html
(:head
(:title "Test page"))
(:body
(:p "CL-WHO is really easy to use")))))
To the beginner, or someone who's really lazy, there's no reason why you should have to write 3 lines at the top instead of just one (like in python).

Related

How to use helm-semantic-or-imenu for code navigation with type annotated python code

I would like to use the helm-semantic-or-imenu command to navigate components of type annotated Python code, but whatever code analyzer is used to dentify the components doesn't seem to recognize the type annotated python code. Functions with the return type annotation doesn't get recognized at all and functions with annotated arguments show the type instead of the arguments names in the signatures
The main problem I have is that I do not properly understand the components that is involved in making this work (when it does work). Obviously it might help to somehow update the code analyzer, but in which project do I find that? helm? semantic? imenu? or as someone mentioned somewhere else with regards to code analysis python.el? I could really use some help getting started to solve this. If the code analyzer is found in python.el, can I then try to modify and make emacs use a local version preferentially over the installed one?
EDIT:
After making the initial post I finally made a break through in trying to figure out where the components come from. I searched for python*.el in all of the file systemsystem and discovered these:
./usr/share/emacs/26.2/lisp/cedet/semantic/wisent/python.elc
./usr/share/emacs/26.2/lisp/cedet/semantic/wisent/python-wy.elc
I found the source for emacs 26.2 and discovered that indeed it seems python-el is responsible for parsing python files for semantic. It also internally uses the python-wy for recognizing a large portion of the language components. But unfortunately that is where I hit a brick wall. I was hoping to be able to monkey patch the function that recognizes a function definition via an re or something, but semantic actually solves the problem the right way. So python-wy seems to be auto-generated from a formal grammar definition file (in emacs git admin/grammars/python.wy) and figuring out how to modify that it is unfortunately much beyond my abilities.
The semantic python backend doesn't appear to parse type annotations correctly (and there hasn't been much recent development on those libraries as far as I can tell). Since helm-semantic-or-imenu favors semantic when it is active, you can disable semantic altogether for python buffers unless you use its other features (personally I only use it for C/C++).
When the semantic mode-specific libraries are loaded they set imenu-create-default-create-index and imenu-default-goto-function, causing imenu to use semantic instead of python.el's imenu function.
To disable semantic support for your python files you can customize the semantic-new-buffer-setup-functions, only adding entries for modes you want semantic support for, eg. in your semantic hook (or alternatively with the customize UI),
(setq semantic-new-buffer-setup-functions
'((c-mode . semantic-default-c-setup)
(c++-mode . semantic-default-c-setup)
(srecode-template-mode . srecode-template-setup-parser)
(texinfo-mode . semantic-default-texi-setup)
;; etc.
;; (makefile-automake-mode . semantic-default-make-setup)
;; (makefile-mode . semantic-default-make-setup)
;; (makefile-gmake-mode . semantic-default-make-setup)
))

How do I use a CPAN module in a perl script that I want to give to others?

I'm writing a Perl script that takes data and writes it to an Excel file. I'm using Excel::Writer::XLSX to do this.
I'm hoping to write the script and then give it to the rest of my team so we can all use it to compile the data when we need to.
I have a few questions about this:
Do my colleagues need to have the module installed to for the script to work?
If not, how do I wrap up the module with the script to give it to them?
Is there a better way of doing this that using the module I've chosen?
There are a few ways of doing this. One options is to put together a Makefile.PL that specifies the dependencies. This allows you to bundle your script as a distribution. E.g.
use ExtUtils::MakeMaker;
WriteMakefile(
ABSTRACT => 'myscript creates Excel files',
AUTHOR => 'A.U. Thor',
EXE_FILES => [ 'myscript' ],
NAME => 'myscript',
VERSION => '1.2.3',
PREREQ_PM => {
'Excel::Writer::XLSX' => '0.88',
},
);
Then, people can do perl Makefile.PL which will inform them of the dependencies. If you do make dist, and distribute the resulting archive file, they can also use cpanm to install your script along with its dependencies.
Another option is to put together a cpanfile. Then, recipients can install all the dependencies using a tool such as cpanm.
Now, if you are distributing the script to people who do not use Perl normally, and you want them to be able to just click and run etc, you might want to look into pp.
A long time ago, I wrote a program I called scriptdist to turn a single-file program into a CPAN-like distribution, complete with a build file. That way you could pass it around as an archive and people could treat it like any other CPAN distribution. It basically automates what Sinan posted. I wrote about it for Dr. Dobbs.
There's a trick that you can use if you want to pass around the archive. The cpan tool can install from the current directory. That will get the dependencies (which, by the nature of being dependencies, are required):
$ cpan .
That way, you can install your program and its dependencies without putting anything in a CPAN-like repository.
It's far from clear what you need to know
Do my colleagues need to have the module installed to for the script to work?
I think it's obvious that your colleagues need access to your code to be able to make use of it
It's not clear what you have written, but if you have created a module then any program with access to your module files can simply use it to access its capabilities
If not, how do I wrap up the module with the script to give it to them?
Your "if not" isn't clear. What you have written means "If they don't need to have the module installed to for the script to work", and I doubt if that is your intention
"how do I wrap up the module with the script" Are you asking how to create a module, or do you already have one? Typically, modules are accessed by programmers who write a script with the use statement
If you have a module and you want other people to be able to load it with use then it must appear in one of the directories listed in their #INC array. If you are working on separate systems then it is best to create a package that you can alter as necessary and have others update
Is there a better way of doing this (than) using the module I've chosen?
Are you referring to Excel::Writer::XLSX or your own module?
If Excel::Writer::XLSX is doing what you need then you probably shgouldn't change. But if you are having problems with it in some way then you need to ask a new question and describe those issues

Running Haddock on its own

I would like to start using Haddock; the primary reason is not that I do (or anyone else does) need nice HTML documentation for what I'm writing right now, but that it will teach me a standardized way commenting Haskell modules.
For this reason, I'd like to get my hands dirty with it, but I've run into a pretty basic problem.
Source:
module Main where
-- |This is the main function.
main = putStrLn "Hello World!"
Haddock invocation:
> haddock -h test.hs
Haddock coverage:
50% ( 1 / 2) in 'Main'
Warning: Main: could not find link destinations for:
GHC.Types.IO
It looks like Haddock doesn't know where to look for the standard libraries, but that's just a wild guess. The docs say something about a "-B" parameter, but are not really explaining much about it.
I've searched for the problem online, and it was basically answered with "use a Cabal package and it'll do everything for you". However, I would much rather not deal with Cabal right now, but learn Haddock on its own (Cabal can wait). Is there a nice and easy(ish) solution to the problem?
I'm going to echo the wisdom of the comments to your question and say, just use Cabal. It's not an extra thing to learn, it's something to learn instead precisely because it takes care of all these tedious details for you. You'll probably need to know about it anyway since everyone else uses it, so you might as well get the benefit of that knowledge.
For completeness, I ran cabal haddock -v on one of my projects, and this is the invocation of haddock that it used:
/usr/local/bin/haddock --prologue=dist/doc/html/notcpp/haddock-prolog1566.txt --dump-interface=dist/doc/html/notcpp/notcpp.haddock --optghc=-package-name --optghc=notcpp-0.2.0.2 --hide=NotCPP.Utils --verbosity=1 --html --read-interface=/usr/local/share/doc/ghc/html/libraries/array-0.4.0.1,/usr/local/share/doc/ghc/html/libraries/array-0.4.0.1/array.haddock --read-interface=/usr/local/share/doc/ghc/html/libraries/base-4.6.0.0,/usr/local/share/doc/ghc/html/libraries/base-4.6.0.0/base.haddock --read-interface=/usr/local/share/doc/ghc/html/libraries/containers-0.5.0.0,/usr/local/share/doc/ghc/html/libraries/containers-0.5.0.0/containers.haddock --read-interface=/usr/local/share/doc/ghc/html/libraries/deepseq-1.3.0.1,/usr/local/share/doc/ghc/html/libraries/deepseq-1.3.0.1/deepseq.haddock --read-interface=/usr/local/share/doc/ghc/html/libraries/ghc-prim-0.3.0.0,/usr/local/share/doc/ghc/html/libraries/ghc-prim-0.3.0.0/ghc-prim.haddock --read-interface=/usr/local/share/doc/ghc/html/libraries/integer-gmp-0.5.0.0,/usr/local/share/doc/ghc/html/libraries/integer-gmp-0.5.0.0/integer-gmp.haddock --read-interface=/usr/local/share/doc/ghc/html/libraries/pretty-1.1.1.0,/usr/local/share/doc/ghc/html/libraries/pretty-1.1.1.0/pretty.haddock --read-interface=/usr/local/share/doc/ghc/html/libraries/template-haskell-2.8.0.0,/usr/local/share/doc/ghc/html/libraries/template-haskell-2.8.0.0/template-haskell.haddock --odir=dist/doc/html/notcpp/ --title=notcpp-0.2.0.2: Avoiding the C preprocessor via cunning use of Template Haskell --optghc=-fbuilding-cabal-package --optghc=-O --optghc=-odir --optghc=dist/build/tmp-1566 --optghc=-hidir --optghc=dist/build/tmp-1566 --optghc=-stubdir --optghc=dist/build/tmp-1566 --optghc=-i --optghc=-idist/build --optghc=-i. --optghc=-idist/build/autogen --optghc=-Idist/build/autogen --optghc=-Idist/build --optghc=-optP-include --optghc=-optPdist/build/autogen/cabal_macros.h --optghc=-hide-all-packages --optghc=-package-id --optghc=base-4.6.0.0-eac4fa0d0988628e5bd960fef8805b26 --optghc=-package-id --optghc=template-haskell-2.8.0.0-102a52a4fda28374255d0a3a8e99f26c --optghc=-XHaskell98 --optghc=-XTemplateHaskell --optghc=-W -B/usr/local/lib/ghc-7.6.1 dist/build/tmp-1566/NotCPP/ScopeLookup.hs dist/build/tmp-1566/NotCPP/LookupValueName.hs dist/build/tmp-1566/NotCPP/OrphanEvasion.hs dist/build/tmp-1566/NotCPP/Utils.hs
Now, I'm sure much of that is optional, but I'm not about to spend the time working out which bits are and which aren't.

documentation for cabal-install configuration file

The ~/.cabal/config stores configuration which cabal-install uses. I wanted to do some hackery on it. (Specifically, having multiple GHC versions installed, I wish to have separate documentation indexes).
I couldn't, however, find any documentation about its' syntax or variables except for what is included in default file. Is there any documentation available?
Edit: I've stated the goal above, but let me add some details: If the same package (eg. GTK) is installed in two versions of GHC they end up in the same documentation index file. I wan't that local documentation index to be separate for each GHC installation. I believe it is possible in some way using documentation directory setting, but there has to be a variable for currently used GHC version. If there isn't one there might be some workarounds available, but I won't be able to say that unless I see the documentation.
This seems to work, although I've only tested it with one version of GHC:
documentation: True
doc-index-file: $datadir/doc/$compiler/index.html
install-dirs user
docdir: $datadir/doc/$compiler/$pkgid
With the other options left at the default, this generates documentation in .cabal/share/doc/<ghc-version>/<package-name>, and the index in .cabal/share/doc/<ghc-version>/index.html.
There appears to be very little online - not even the haddocks for the cabal-install code. So your best bet may be to puzzle it out from the source. cabal unpack cabal-install, or view the cabal-install repo online. Look at SavedConfig in Distribution/Client/Config.hs. As an example, it imports GlobalFlags from Setup.hs; the individual flags, eg globalCacheDir, are associated with their config-file syntax (which is also the command-line syntax) in the globalCommand function below, remote-repo-cache in this case.
You should also ask dcoutts in the #haskell channel on irc.freenode.net, in case he has new docs available.

can an RPM spec file "include" other files?

Is there a kind of "include" directive in RPM spec? I couldn't find an answer by googling.
Motivation: I have a RPM spec template which the build process modifies with the version, revision and other build-specific data. This is done by sed currently. I think it would be cleaner if the spec would #include a build-specific definitions file, which would be generated by the build process, so I don't need to search and replace in the spec.
If there is no include, is there an idiomatic way to do this (quite common, I believe) task?
Sufficiently recent versions of rpmbuild certainly do support %include:
%include common.inc
Unfortunately, they aren't very smart about it -- there is no known set of directories, in which it will look for the requested files, for example. But it is there and variables are expanded, for example:
%include %{_topdir}/Common/common.inc
RPM does not support includes.
I have solved similar problems with either m4 macro processor or by just concatenating parts of spec (when the "include" was at the beginning).
If you only need to pass a few variables at build time, and not include several lines from another file, you can run
rpmbuild --define 'myvar SOMEVALUE' -bb myspec.spec
and you can use %myvar in the spec.
I faced this same issue recently. I wanted to define multiple sub-packages that were similar, but each varied just slightly (they were language-specific RPMs). I didn't want to repeat the same boiler-plate stuff for each sub-package.
Here's a generic version of what I did:
%define foo_spec() %{expand:%(cat '%{myloc}/main-foo.spec')}
%{foo_spec bar}
%{foo_spec baz}
%{foo_spec qux}
The use of %{expand} ensures that %(cat) is only executed a single time, when the macro is defined. The content of the main-foo.spec file is then three times, and each time %1 in the main-foo.spec file expands to each of bar, baz and qux, in turn, allowing me to treat it as a template. You could easily expand this to more than one parameter, if you have the need (I did not).
For the underlying issue, there maybe two additional solutions that are present in all rpm versions that I am aware of.
Subpackages
macro and rpmrc files.
Subpackages
Another alternative (and perhaps the "RPM way") is to use sub-packages. Maximum RPM also has information and examples of subpackages.
I think the question is trying to structure something like,
two spec files; say rpm_debug.spec and rpm_production.spec
both use %include common.spec
debug and production could also be client and server, etc. For the examples of redefining a variable, each subpackage can have it's own list of variables.
Limitations
The main advantage of subpackages is that only one build takes place; This may also be a disadvantage. The debug and production example may highlight this. That can be worked around using strip to create variants or compiling twice with different output; perhaps using VPATH with Gnu Make). Having to compile large packages and then only have simple variations, like with/without developer info, like headers, static libraries, etc. can make you appreciate this approach.
Macros and Rpmrc
Subpackages don't solve the problem of structural defines that you wish for an entire rootfs hierarchy, or larger collection of RPMs. We have rpmbuild --showrc for this. You can have a large amount of variables and macros defined by altering rpmrc and macros when you run rpm and rpmbuild. From the man page,
rpmrc Configuration
/usr/lib/rpm/rpmrc
/usr/lib/rpm/redhat/rpmrc
/etc/rpmrc
~/.rpmrc
Macro Configuration
/usr/lib/rpm/macros
/usr/lib/rpm/redhat/macros
/etc/rpm/macros
~/.rpmmacros
I think these two features can solve all the problems that %include can. However, %include is a familiar concept and was probably added to make rpm more full-featured and developer friendly.
Which version are you talking about? I currently have %include filename.txt in my spec file and it seems to work just like the C #include directive.
> rpmbuild --version
RPM version 4.8.1
You can include the *.inc files from the SOURCES directory (%_sourcedir):
Source1: common.inc
%include %{SOURCE1}
In this way they will go automatically into SRPMS.
I've used scripts (name your favorite) to take a template and create the spec file from that. Also, the %files tag can import a file that is created by another process, e.g. Python's bdist-rpm.

Resources