Scripting

There are two possibilities to get the PicoLisp interpreter into doing useful work: via command line arguments, or as a stand-alone script.

Command line arguments for the PicoLisp interpreter

The command line can specify either files for execution, or arbitrary Lisp expressions for direct evaluation (see Invocation: If an argument starts with a hyphen, it is evaluated, otherwise loaded as a file. A typical invocation might look like:
   $ ./dbg app/file1.l -main app/file2.l
It loads the debugging environment, an application source file, calls the main function, and then loads another application source. In a typical development and debugging session, this line is often modified using the shell's history mechanisms, e.g. by inserting debugging statements:
   $ ./dbg app/file1.l -"trace 'foo" -main -"debug 'bar" app/file2.l
Another convenience during debugging and testing is to put things into the command line (shell history) which would otherwise have to be done each time in the application's user interface:
   $ ./dbg app/file1.l -main app/file2.l -go -'login "name" "password"'
The final production release of an application usually includes a shell script, which initializes the environment, does some bookkeeping and cleanup, and calls the application with a proper command line. It is no problem if the command line is long and complicated.

For small utility programs, however, this is overkill. Enter full PicoLisp scripts.

PicoLisp scripts

It is better to write a single executable file using the mechanisms of "interpreter files". If the first two characters in an executable file are "#!", the operating system kernel will pass this file to an interpreter program whose pathname is given in the first line (optionally followed by a single argument). This is fast and efficient, because the overhead of a subshell is avoided.

Let's assume you installed PicoLisp in the directory "/home/foo/picolisp/", and put links to the executable and the installation directory as:
   $ ln -s /home/foo/picolisp /usr/lib/picolisp
   $ ln -s /usr/lib/picolisp/bin/picolisp /usr/bin/picolisp
Then a simple hello-world script might look like:
   #!/usr/bin/picolisp /usr/lib/picolisp/lib.l
   (prinl "Hello world!")
   (bye)
If you write this into a text file, and use 'chmod' to set it to "executable", it can be executed like any other command. Note that - because '#' is the comment character in PicoLisp - the first line will not be interpreted, and you can still use that file as a normal command line argument to PicoLisp (useful during debugging).

Grab command line arguments from PicoLisp scripts

The fact that a hyphen causes evaluation of command line arguments can be used to simulate something like command line options. The following script defines two functions 'a' and 'f', and then calls (load) to process the rest of the command line (which otherwise would be ignored because of the bye statement):
   #!/usr/bin/picolisp /usr/lib/picolisp/lib.l

   (de a ()
      (println '-a '-> (opt)) )

   (de f ()
      (println '-f '-> (opt)) )

   (load T)
   (bye)


(opt retrieves the next command line option)

Calling this script (let's say we named it "testOpts") gives:
   $ ./testOpts -f abc
   -f -> "abc"
   $ ./testOpts -a xxx  -f yyy
   -a -> "xxx"
   -f -> "yyy"
We have to be aware of the fact, however, that the aggregation of arguments like
   $ ./testOpts -axxx  -fyyy
or
   $ ./testOpts -af yyy
cannot be achieved with this simple and general mechanism of command line processing.

Run scripts from arbitrary places on the host file system

Utilities are typically used outside the context of the PicoLisp environment. All examples above assumed that the current working directory is the PicoLisp installation directory, which is usually all right for applications developed in that environment. Command line file arguments like "dbg.l" or "app/file1.l" will be properly found.

To allow utilities to run in arbitrary places on the host file system, the concept of home directory substitution was introduced. The interpreter remembers internally at start-up the pathname of its first argument (usually "lib.l"), and substitutes any leading '@' character in subsequent file names with that pathname. Thus, to run the above example in some other place, simply write:
   $ /home/foo/picolisp/dbg @app/file1.l -main @app/file2.l
that is, supply a full path name to the initial command (here 'p'), or put it into your 'PATH' variable, and prefix each file which has to be loaded from the PicoLisp home directory with a '@' character. "Normal" files (not prefixed by '@') will be opened or created relative to the current working directory as usual.

Stand-alone scripts will often want to load additional modules from the PicoLisp environment, beyond the "lib.l" we provided in the first line of the hello-world script. Typically, at least a call to
   (load "@lib/misc.l")
(note the home directory substitution) will be included near the beginning of the script.

As a more complete example, here is a script which extracts the date, name and size of the latest official PicoLisp release version from the download web site, and prints it to standard output:
   #!/usr/bin/picolisp /usr/lib/picolisp/lib.l

   (load "@lib/misc.l" "@lib/http.l")

   (use (@Date @Name @Size)
      (when
         (match
            '(@Date " " "-" " " @Name " " "(" @Size ")")
            (client "software-lab.de" 80 "down.html"
               (from "Release Archive")
               (from ".tgz\">")
               (till "") ) )
         (prinl @Name)
         (prinl @Date " -- " @Size) ) )

   (bye)


Editing scripts

We recommend that you have a terminal window open, and try the examples by yourself. You may either type them in, directly to the PicoLisp interpreter, or edit a separate source file (e.g. "test.l") in a second terminal window and load it into PicoLisp with
   : (load "test.l")
each time you have modified and saved it.

Editing scripts with vi

Once a function is loaded from a source file, you can call 'vim' directly on that function with
   : (vi 'foo)
The function 'vi' opens the appropriate source file, and jumps to the right line where 'foo' is defined. When you modify it, you can simply call 'ld' to (re)load that source file
   : (ld)

http://picolisp.com/wiki/?tutscript

09jan17    abu