The clesh Reference Manual

Table of Contents

Next: , Previous: , Up: (dir)   [Contents][Index]

The clesh Reference Manual

This is the clesh Reference Manual, generated automatically by Declt version 2.4 patchlevel 1 "Will Decker" on Mon Jul 29 15:20:06 2019 GMT+0.


Next: , Previous: , Up: Top   [Contents][Index]

1 Introduction

CLESH — A Unix shell interface for Common Lisp

Christian von Essen

This manual documents CLESH (Common Lisp Embedded Shell) , a very short and simple program, written in Common Lisp, that extends Common Lisp to embed shell code in a manner similar to perl's backtick. It has been forked from from SHELISP by Alexandru Dan Corlana

Quick guide to clesh

Load any Common Lisp implemenation, and on the REPL load clesh by invoking

(load "clesh.lisp")
(use-package 'named-readtables)
(in-readtable clesh:syntax)

The bang (!) escape to shell

For convenience, and for use from the REPL, you can emit single line calls to the shell using the bang.

You can say (the '*' is already put there by your CL):

* !ls

And it will execute the shell ls command (by running a bash instance and passing the command to it. Of course, you are actually in Lisp. You can try this:

* (defun factorial (x) (if (zerop x) 1 (* x (factorial (1- x)))))
FACTORIAL
* (factorial 33) 8683317618811886495518194401280000000

So, if you enter '!' the rest of the line (until the first end of line that is not escaped with a “\”) is interpreted as a bash command and the result is printed on the standard output. Now try:

* !echo ?(+ 2 3) zuzu 5 zuzu

The '?' is the 'lisp escape'. It is followed by an s-expression which is read, executed and printed (with princ) and the printed result replaces the '?' and the expression in the shell command. It can be any Lisp expression.

* !echo ?(+ 2/3 2/11) " <- this is a fraction" 28/33 <- this is a
fraction
* !echo ?(factorial 100) " <- this is a beegnum"
933262154439441526816992388562667004907159682643816\
21468592963895217599993229915608941463\
97615651828625369792082722375825118521091686400\
0000000000000000000000 <- this is a beegnum

Provided that you already entered the factorial definition above. You may escape the '?' with a '\' to have it transfered to the shell command. for example:

* !echo \?\(+ 2 3\) ?(+ 2 3) 4

Embedded shell scripts

Anything written between square brackets is interpreted as a shell script. What the script prints on the standard output, however, is not displayed, but collected in a string and returned as a result of the bracketed expression. For example:

* [echo hi there!] "hi there! " "" 0

One thing that you can't ordinarily do in bash:

* (dotimes (i 7) (princ [echo ?i])) 0 1 2 3 4 5 6

You can now say:

* (defun count-to (x) (dotimes (i x) (princ [echo ?i ]))) COUNT-TO
* (COUNT-TO 3) 0 1 2

Or, for example:

* (defun c-c-count-to (x) (dotimes (i x) (princ
    [echo ?i | sed 's/\(.\)/\1-\1-\1/' ]) )) C-C-COUNT-TO
* (c-c-count-to 3) 0-0-0 1-1-1 2-2-2

Switching to shell mode (double-bang, '!!')

If you enter a double bang ('!!') then the prompter is changed to '$' and you can issue unescaped shell command until you start a line with '!!' again - then you revert to 'lisp mode'. Constructs with '?' are honored and are read and evaluated immediately by Lisp. Results of commands are printed immediately after being issued. For example:

* !! $ ls Makefile clesh.lisp clesh_mn.aux clesh_mn.log
clesh_mn.pdf clesh_mn.tex clesh_sc.aux clesh_sc.log clesh_sc.pdf
clesh_sc.tex clesh.tex spec.txt $ # ?(setq bb 33.34) $ echo ?bb "
is " ?(sqrt bb) " squared." 33.34 is 5.77408 squared. $ echo ?bb "
is " ?(sqrt bb) " squared." >somefile.txt $ cat somefile.txt 33.34
is 5.77408 squared. $ echo "I am almost sure that " 'cat
somefile.txt' I am almost sure that 33.34 is 5.77408 squared. $ !!
$ NIL *

Notice how purely Lisp commands, such as variable assignement (bindings), can be escaped with '#' char-acters as bash comments.

Run scripts as Lisp calls

The function script takes as argument a string and executes it as a bash script, returning the standard output of the script as a string as first value, the error output of the script as second value and the return value as last value.

* (script "ls") " Makefile clesh.lisp clesh_mn.aux clesh_mn.log
clesh_mn.pdf clesh_mn.tex clesh_sc.aux clesh_sc.log clesh_sc.pdf
clesh_sc.tex clesh.tex spec.txt " "" 0

Templates

A template is a string introduced with '#[' and ended with ']#'. It is treated like an usual string, however '?'-preceded lisp expressions are evaluated and their result printed inside the string. For example:

(defvar *title* "Title of an empty page")
    
...

(prin1
#[Content-type: text/html <html> <head><title> ?*title* </title></head> <body></body> </html> ]#)

Will print to '*standard-output*':

Content-type: text/html <html> <head><title>Title of an empty
page</title></head> <body></body> </html>

Storable templates

One problem with templates is that we might desire to run them at a later time, in a different context. For example, we might want to define a variable with a generic web-page template and then generate actual web pages at later times, with various contents. We use '#{' and '}#' for this purpose. In the example below notice that each time the value of variable A is evaluated, the BB in the evaluation context is used.

*(setf bb 9) 9
* (setf a #{ plus: ?bb :sulp }#) (MIXED-TEMPLATE " plus: " BB "
:sulp ")
* (setf bb 10) 10
* (eval a) " plus: 10 :sulp "
* (setf bb 22) 22
* (eval a) " plus: 22 :sulp "
* (defun calc-a (bb) (eval a)) CALC-A
* (calc-a 88) " plus: 88 :sulp "
* (eval a) " plus: 22 :sulp "

Other fun things to do

The program that is called for the embedded script is controlled by the variable *shell* in package clesh. If you want to use another shell (or indeed anything else), then set this variable to the path of the program to use.

For example, you can set it to cat -n, and you will get everything you enclose in brackets back with line numbers in front:

  [ foo
    bar
    baz ]

will return as first string

 1 foo
 2 bar
 3 baz

Furthermore, this easily allows to talk to remote PCs via an ssh connection or via netcat.

Escape policy

We use the backslash chatacter '\' to escape special parts of an input string. Special characters are: '?' and whatever is used as end-markers (i.e., ']' or '}'). If they are seen with a backslash before, then the backslash will vanish and the usual, special meaning of the character will be ignored. In all other cases, the backslash will just be left alone.

When you have multiple backslashes in front of a special char, then a double back-slash will be replaced with a single-backslash. If a single backslash remains after this replacement, then it escapes the special character. Otherwise, the special character keeps its usual meaning.

Assume x is bound to 1.

#[?x]#    ==> "1"
#[\?x]#   ==> "?x"
#[\\?x]#  ==> '\?x'
#[\\\?x]# ==> '\1'

Technical issues

Expressions preceded with '?' in the embedded shell scripts (with the '[]' syntax) are evaluated in the context where they appear, at 'eval' time; expressions in the 'bang' context (with the '!' or the '!!' syntax) are evaluated at read time, in the context of the last top level form before the form containing the bangs. This is because the bangs are intended for shell-only commands, normally given at the top level (command line) with immediate results. The embedded scripts are supposed to become part of functions or more complex forms, are parsed at read time and prepared to be executed at runtime.

In the 'bang' forms only simple shell commands can be issued as the reader does not detect the circumstances when a construct (such as ca 'case') occupies more than one line. In the embedded form or with the script command, any script can be exe


Next: , Previous: , Up: Top   [Contents][Index]

2 Systems

The main system appears first, followed by any subsystem dependency.


Previous: , Up: Systems   [Contents][Index]

2.1 clesh

Author

Christian von Essen <christian@mvonessen.de>

License

FreeBSD (see LICENSE)

Description

Clesh is a very short program that provides
mechanisms for running and composing Unix shell commands and constructs from Common Lisp.

Essentially, it provides a ’!’ syntax that you can use to run commands and a ’[]’ embedded mode where you can enter bash scripts and obtain the standard output as a lisp string, and some other features.

Lisp expressions can be included in any command or script using a ’?’ syntax.

Clesh works on every implementation of Common Lisp that is supported by trivial-shell.

Dependencies
Source

clesh.asd (file)

Component

clesh.lisp (file)


Next: , Previous: , Up: Top   [Contents][Index]

3 Files

Files are sorted by type and then listed depth-first from the systems components trees.


Previous: , Up: Files   [Contents][Index]

3.1 Lisp


Next: , Previous: , Up: Lisp files   [Contents][Index]

3.1.1 clesh.asd

Location

clesh.asd

Systems

clesh (system)


Previous: , Up: Lisp files   [Contents][Index]

3.1.2 clesh/clesh.lisp

Parent

clesh (system)

Location

clesh.lisp

Packages

clesh

Exported Definitions
Internal Definitions

Next: , Previous: , Up: Top   [Contents][Index]

4 Packages

Packages are listed by definition order.


Previous: , Up: Packages   [Contents][Index]

4.1 clesh

Source

clesh.lisp (file)

Nickname

clsh

Use List
Exported Definitions
Internal Definitions

Next: , Previous: , Up: Top   [Contents][Index]

5 Definitions

Definitions are sorted by export status, category, package, and then by lexicographic order.


Next: , Previous: , Up: Definitions   [Contents][Index]

5.1 Exported definitions


Next: , Previous: , Up: Exported definitions   [Contents][Index]

5.1.1 Special variables

Special Variable: *shell*

Program to use to execute shell commands.

Package

clesh

Source

clesh.lisp (file)


Previous: , Up: Exported definitions   [Contents][Index]

5.1.2 Functions

Function: lines-to-list TEXT

Transform the string TEXT into a list of strings, each representing
on line of TEXT. This is suitable to postprocessing the standard output of many Unix commands (such as find or df) that return one result per line.

Package

clesh

Source

clesh.lisp (file)

Function: script STR &key PROGRAM

Execute the STR string as a standard input of the program.

Returns three values.
1. Standard output of the program
2. Standard error of the program
3. Exit code of the program

Package

clesh

Source

clesh.lisp (file)


Previous: , Up: Definitions   [Contents][Index]

5.2 Internal definitions


Previous: , Up: Internal definitions   [Contents][Index]

5.2.1 Functions

Function: embedded-shell-escape-reader STREAM CHAR
Package

clesh

Source

clesh.lisp (file)

Function: enter-shell-mode STREAM

Read and execute successive shell commands, with any
lisp expressions embedded. Expressions are evaluated at
read time, as soon as a line is delivered. Implements the !! reader macro.

Package

clesh

Source

clesh.lisp (file)

Function: mixed-script &rest STRLIST

Concatenate arguments like MIXED-TEMPLATE, execute result like SCRIPT.

Returns three values.
1. Standard output of the program
2. Standard error of the program
3. Exit code of the program

Package

clesh

Source

clesh.lisp (file)

Function: mixed-template &rest STRLIST

Concatenate list of arguments into a string.

Turns any argument that is not a string already into string using format’s ~A.

Package

clesh

Source

clesh.lisp (file)

Function: read-escapes STR END-CHAR1 BUFFER

Read escapes, push the appropriate number of escapes onto the buffer. If the last character is special and not escaped, then this character is returned. Otherwise we return nil.

Package

clesh

Source

clesh.lisp (file)

Function: read-interpolated-string STR END-CHAR1 &optional END-CHAR2 EVAL-AT-READ

Read from a stream until a delimiter is found and interpolate.

The delimiter is
- the character END-CHAR1 if END-CHAR2 is nil
- the sequence END-CHAR2 END-CHAR1 if END-CHAR2 is not nil.

Interpolation starts with ?, and the next form (i.e., lisp form)
is interpolated. If EVAL-AT-READ is not NIL, then the form will
be evaluated and converted into a string immediately.
Otherwise the form will be returned as is.

Returns a list. In this list, normal strings and interpolations alternate. For example the string "asd foo ?(+ 2 2) bar ?(+ 3 3)"
will be read as ("asd foo " (+ 2 2) " bar " (+ 3 3)).

Package

clesh

Source

clesh.lisp (file)

Function: simple-shell-escape-reader STREAM CHAR
Package

clesh

Source

clesh.lisp (file)

Function: storable-template-escape-reader STREAM CHAR1 CHAR2
Package

clesh

Source

clesh.lisp (file)

Function: template-escape-reader STREAM CHAR1 CHAR2
Package

clesh

Source

clesh.lisp (file)


Previous: , Up: Top   [Contents][Index]

Appendix A Indexes


Next: , Previous: , Up: Indexes   [Contents][Index]

A.1 Concepts

Jump to:   C   F   L  
Index Entry  Section

C
clesh.asd: The clesh<dot>asd file
clesh/clesh.lisp: The clesh/clesh<dot>lisp file

F
File, Lisp, clesh.asd: The clesh<dot>asd file
File, Lisp, clesh/clesh.lisp: The clesh/clesh<dot>lisp file

L
Lisp File, clesh.asd: The clesh<dot>asd file
Lisp File, clesh/clesh.lisp: The clesh/clesh<dot>lisp file

Jump to:   C   F   L  

Next: , Previous: , Up: Indexes   [Contents][Index]

A.2 Functions

Jump to:   E   F   L   M   R   S   T  
Index Entry  Section

E
embedded-shell-escape-reader: Internal functions
enter-shell-mode: Internal functions

F
Function, embedded-shell-escape-reader: Internal functions
Function, enter-shell-mode: Internal functions
Function, lines-to-list: Exported functions
Function, mixed-script: Internal functions
Function, mixed-template: Internal functions
Function, read-escapes: Internal functions
Function, read-interpolated-string: Internal functions
Function, script: Exported functions
Function, simple-shell-escape-reader: Internal functions
Function, storable-template-escape-reader: Internal functions
Function, template-escape-reader: Internal functions

L
lines-to-list: Exported functions

M
mixed-script: Internal functions
mixed-template: Internal functions

R
read-escapes: Internal functions
read-interpolated-string: Internal functions

S
script: Exported functions
simple-shell-escape-reader: Internal functions
storable-template-escape-reader: Internal functions

T
template-escape-reader: Internal functions

Jump to:   E   F   L   M   R   S   T  

Next: , Previous: , Up: Indexes   [Contents][Index]

A.3 Variables

Jump to:   *  
S  
Index Entry  Section

*
*shell*: Exported special variables

S
Special Variable, *shell*: Exported special variables

Jump to:   *  
S  

Previous: , Up: Indexes   [Contents][Index]

A.4 Data types

Jump to:   C   P   S  
Index Entry  Section

C
clesh: The clesh system
clesh: The clesh package

P
Package, clesh: The clesh package

S
System, clesh: The clesh system

Jump to:   C   P   S