Schemesh - fusione tra una shell Unix e un REPL Lisp

5 views
Skip to first unread message

Massimiliano Ghilardi

unread,
Mar 3, 2025, 3:27:37 AMMar 3
to gu...@googlegroups.com
Ciao a tutti,

approfitto del silenzio per fare un po' di pubblicità ad un mio nuovo
software,
ovviamente per Linux e Open Source.

Si tratta di schemesh https://github.com/cosmos72/schemesh
ed è una shell Unix interattiva, intesa anche come shell di login.


Ha tutte le funzionalità classiche delle shell tradizionali:

* line editing, compreso l'editing multi-linea e l'highlight delle
parentesi e delle virgolette
* redirezione di input, output e file descriptors arbitrari di un
comando con la sintassi classica <   <>   >  >> <&   >&
* esecuzione di comandi aggregati con la sintassi classica &&  ||   {   }
* pipelines tra più comandi, con la sintassi classica |   |&
* esecuzione di più comandi in foreground con ; o in background con &
* esecuzione di sub-shell, la sintassi è [   ] anziché (   )
* cattura dell'output di un comando, la sintassi è la classica ` ` 
oppure  $[   ] anziché $(   )
* controllo dei job con CTRL+C CTRL+Z   'fg N'   'bg N'


Con la differenza che è scriptabile in Lisp,
e anzi è un ambiente interattivo basato su Chez Scheme (un compilatore
Lisp nativo che genera codice ottimizzato)
ed è *completo*, cioè offre tutte le funzionalità dei REPL Lisp,
inclusa la possibilità di eseguire codice, usare variabili, funzioni,
macro, librerie e definirne di nuove.
Si possono anche usare librerie di terze parti direttamente dal prompt,
ad esempio quelle distribuite da https://akkuscm.org/


La funzionalità più interessante è che si può passare da sintassi shell
a quella Lisp e viceversa praticamente dappertutto:

* All'interno di un comando shell si possono inserire espressioni Lisp,
racchiudendole in ()
   Esempio:
     > ls -l (lisp-expression-returning-some-string arg1 arg2) --sort=size
   Le espressioni Lisp devono restituire una stringa, o una lista di
stringhe,
   o una funzione che a sua volta restituisce una stringa o una lista
di stringhe.

* All'interno di un'espressione Lisp si possono inserire comandi shell,
racchiudendoli in { }
   Il comando shell è un oggetto Lisp "first-class": può essere salvato
in una variabile, passato a funzioni, restituito, ecc.
   E chiaramente può essere eseguito.
   Esempio:
     > (set! job {sleep 5 && ls -l > ls.out || echo "ls failed"})
     > (sh-start job)
     ; job  1            (running 1)         {ls "--color=auto" -l
1>ls.out || echo "ls failed"}
     (running 1)

     > fg 1

I passaggi da una sintassi all'altra si possono nidificare, ad esempio:

     > (set! job2 {find (sh-run/string {echo $HOME}) -type f | grep ^lib})
     > (sh-run/i job2)

Chiaramente si può usare anche come REPL Lisp:

     > (* 1/3 7/3 9)
     7

     > (string-split "a b c" #\space)
     ("a" "b" "c")

     > (set! l (directory-list "/"))
     > (values l)
     ("dev" "srv" "boot" "run" "etc" "root" ...)

     > (define (fibonacci n)
         (if (> n 2)
           (+ (fibonacci (- n 1)) (fibonacci (- n 2)))
           1))
     > (fibonacci 20)
     6765

Da quasi un mese la sto usando come shell di login, ed è comodissima :)

Ciao,

Max

--

----------------------------------------------------
Massimiliano Ghilardi
email: mghi...@mbigroup.it

M.B.I. Group
Via Francesco Squartini 7
56121 Pisa
website: www.mbigroup.it
----------------------------------------------------


Reply all
Reply to author
Forward
0 new messages