📜 ⬆️ ⬇️

Installing common lisp as a user

made with lisp
There is a problem : On working servers (we use the policy of thin clients, thick servers) no lisp machines are installed, and I, of course, do not administer them.
Two decisions immediately come to mind:

The first option is suitable for real implementers. I unfortunately do not have sufficient arguments why all terminal servers should acquire a lisp machine.
Therefore, here we will talk about the second option. (Namely, ECL on linux in the custom directory).


Going along this path, I first of all remembered 2 implementations with which I work at home:

I did not manage to force any of them to work from a non-standard directory, if anyone can tell, you are welcome. Then I remembered the ECL, which had already rescued me once, when I needed to build a lisp engine into a sish project.

Work environment


In our office there are many identical terminal servers, as well as several network balloon. Home directories are limited to 100 MiB so I don’t really want to install anything here. But there is a human network file storage, which is under the symbolic link "ns" in my home directory:
$ ls ~ -l . . . lrwxrwxrwx 1 necto users 14 Jul 22 12:22 ns -> /network/file/system/users/necto . . . 

')

Installation


How to pick up the distribution is written on the project page . The easiest way (imho):
 $ cd tmp && git clone git://ecls.git.sourceforge.net/gitroot/ecls/ecl && cd ecl 

From ./ configure --help you can learn that in order to install ecl in a non-standard directory, it is enough to specify a couple of prefixes from which it will be repelled. Without hesitation, I install the necessary prefixes:
 $ ./configure --prefix "~/ns/ecl/" --exec-prefix "~/ns/ecl/" 

But it was not there:
 Switching to directory `build' to continue configuration. configure: error: expected an absolute directory name for --exec_prefix: ~/ns/ecl/ 

Well, it's good that the symlink did not force to deploy.
 ./configure --prefix "/home/necto/ns/ecl/" --exec-prefix "/home/necto/ns/ecl/" 

Now canonically:
 $ mkdir ~/ns/ecl && make && make install 

Everything went smoothly for me, and as a result:
  $ ~/ns/ecl/bin/ecl ECL (Embeddable Common-Lisp) 11.1.1 Copyright (C) 1984 Taiichi Yuasa and Masami Hagiya Copyright (C) 1993 Giuseppe Attardi Copyright (C) 2000 Juan J. Garcia-Ripoll ECL is free software, and you are welcome to redistribute it under certain conditions; see file 'Copyright' for details. Type :h for Help. Top level. > (quit) 

If after conflict-free make all the same:
  /home/necto/ns/ecl/bin/ecl: error while loading shared libraries: libecl.so.11.1: cannot open shared object file: No such file or directory 
You can add / home / necto / ns / ecl / lib to LD_LIBRARY_PATH ($ export LD_LIBRARY_PATH = LD_LIBRARY_PATH: / home / necto / ns / ecl / lib).

"Embedded"


First of all, I installed ecl in order to write scripts (for example, to collect statistics on dumps). This means that such an interpreter launch is not convenient: $~/ns/ecl/bin/ecl -load tst.lisp
Therefore it is necessary to patch ./.bashrc . In the same ~ / ns / ecl directory I add a to-bashrc file:
 #/bin/bash # should be included into your .bashrc # should be in .../ecl folder # defines two commands: # ecl - to run lisp interpreter in interactive mode [usage: ecl --help] # cl $file - to execute lisp source with +cmd-args+ bind to # list of commandline arguments path_to_ecl=$(dirname ${BASH_SOURCE[0]}) # Use the next line, if ecl can't find libecl.so export LD_LIBRARY_PATH="$path_to_ecl"/lib:$LD_LIBRARY_PATH alias ecl="$path_to_ecl"'/bin/ecl' function ecl-run { line="(progn (defconstant +cmd-args+ '(${@})) (defconstant +/cl+ \"$path_to_ecl\/\") (load \"$path_to_ecl/my/common.lisp\" :verbose nil) (load \"$1\") (quit))" ecl -eval "$line" } alias cl='ecl-run' 

Here, besides the trivial alias, a variant of file interpretation has been added, with the necessary functions defined in ~ / ns / ecl / my / common.lisp in which, among other convenient buns, there are such functions:
 ;;; common.lisp - aggregator of different tools ;;; being used in scripts ;; add standart lybrary path eg /home/necto/ns/ecl :: use it on such way (load (lib/ "my/common.lisp")) (defun lib/ (str) (if (find-symbol "+/CL+") (concatenate 'string +/cl+ str) str)) ;; Another function useful in everyday scripting: ;; determine is a symb given as argument (if (find-symbol "+CMD-ARGS+") (defun symbol-mentioned-in-params (symb) (find symb +cmd-args+))) ;; Use "verbose" or "talkative" to see debug info from ;; your script (defun verbose-enabled-p () (and (find-symbol "+CMD-ARGS+") (or (find 'talkative +cmd-args+) (find 'verbose +cmd-args+)))) ;; A output stream which you can enable by taking option "talkative" ;; to a script using it (defconstant extra-out (if (verbose-enabled-p) t (make-string-output-stream))) ;; Also if user doesn't want to view all it's loads, disable it: (setf *load-verbose* (verbose-enabled-p)) ;;... 

Full code
By the way, I highly recommend pregexp - a very easy and regexp library. A very small library with only 1 file in ~ 800 lines. It is used in ecl / my / common.lisp very well.

You can also see that the constant + cmd-args + containing the list of all arguments passed to the script will be defined.
Now for the integration of this whole economy, it suffices to add in .bashrc:
  source ~/ns/ecl/to-bashrc 


Using


Now it is enough to create, for example, all-funs.lisp:
 (defun print-funcs () (process-every-file file (make-pathname :directory '(:relative) :name "*" :type "lisp") :input (for-every-appropriate-line file "defun ([^ ]+) \(([^)]*)\)" (funame args) (print-hello funame) (print args extra-out)))) (defun print-hello (name) (format t "~%Hello, ~a." name)) (print-funcs) 

And run it:
$ cl all-funs.lisp
 Hello, print-funcs. Hello, print-hello. 

And if you specify the talkative flag:
$ cl all-funs.lisp talkative
 Hello, print-funcs. Hello, print-hello. name 


But the most interesting thing is that if now a colleague wants to use your work, it will be enough for him to include / net / file / system / users / necto / ecl / to-bashrc in his .bashrc and that's it!

Conclusion



Actually, I wanted to say that embedding common lisp as a convenient script interpreter, along with python or perl, is quite simple, and does not require administrative privileges.

I haven’t yet managed to eliminate one minus: As you know, the lisp is famous for its repl in runtime, and the ECL has an extremely uncomfortable console, and if you accidentally make a mistake, it falls out as an exception handler (specifically, it’s impossible to erase an erroneous character). I find it hard to understand, so the opinion of the public lisp is of interest: how can I replace it with something more editable?

Required components:

Embeddable Common Lisp
bash
Pregexp (by the way, somewhat slow, and sometimes it lacks a stack (on long lines), who will advise the same portable?)
P. s .: Eh, I didn’t find the ecl logo, but I don’t know how to draw, so I put a generic label.
P. s.2: Interestingly, how else does anyone format sorts on lisp? For the source tag lang = "lisp" only adds a gray background for long sources, no more (or is it a preview limitation?).

Source: https://habr.com/ru/post/124725/


All Articles