;;;; common-shell.lisp
#|
scm, ldbeth and I were talking about lisp and shells on our phlogs and
mastodon. A shell is a program whose main responsibility is to fork and
exec. Making system(3) calls to the parent shell is a kind of shell
scripting, but it would also be cool to be a shell ourselves.
I figure I need a reader macro that calls strings and gets their output.
Using direct control of *read-table* and read-time macros is one iconic
feature of lisp. #:uiop, which is wrapped in with #:asdf provides a portable
posix compatibility layer.
BUT FIRST I feel like I have been a little too tech-blogger lately. Lisp and
falteringly jamming soft synth is part of who I am, but I will try and make
at least a phlog a week that is not just C, lisp and systems. But that is a
topic for later. |#
(require 'asdf)
;; in order to get the portable #'uiop:run-program
(defun my-shell (s c m) "
(my-shell stream character number)
collects READs from stream until the next read-char is #\], which is eaten.
maps #'uiop:run-program to that list, except *standard-output* is collected
as a list of newline delimited strings. "
(declare (ignore c m))
`(let ((list ',(loop for r = (read s nil nil)
for ch = (read-char s nil nil)
collect r
while (not (char= ch #\])) do (unread-char ch s))))
(mapcar (lambda (x)
(let ((response (with-output-to-string (*standard-output*)
(uiop:run-program x :output t))))
(with-input-from-string (*standard-input* response)
(loop for line = (read-line *standard-input* nil nil)
while line
nconcing (unless (string= "" line)
`(,line))))))
list)))
;; And let's Make that the reader macro for #[
(set-dispatch-macro-character #\# #\[ #'my-shell)
#|
I think this is pretty powerful already. To see it in action, we must evoke
the reader (this file is finished being read prior to being evaluated to
begin with, so we have to READ something else to see it in action.) |#
#|
$ rlwrap ecl --load common-shell.lisp
ECL (Embeddable Common-Lisp) 21.2.1 (git:UNKNOWN)
Copyright (C) 1984 Taiichi Yuasa and Masami Hagiya
Copyright (C) 1993 Giuseppe Attardi
Copyright (C) 2013 Juan J. Garcia-Ripoll
Copyright (C) 2018 Daniel Kochmanski
Copyright (C) 2021 Daniel Kochmanski and Marius Gerbershagen
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 in: #<process TOP-LEVEL 0x1cf7126f80>.
> (shell-reader-example-1)
(("Mon Nov 14 09:17:18 UTC 2022") ("fleo" "blah"))
>
Alright that seems to be working.
|#
(NIL NIL ("$ date" "Mon Nov 14 09:22:26 UTC 2022" "$"))
interesting.
|#
#|
Otherwise... I still owe jns copying an org file from some laptops that are
sleeping right now basically, which is incredibly cool and trivial to do.
And if darkness didn't get figured out I should probably try to participate
in that. Once I post that org file, it would be cool if lots of people used
it. The org file ended up very convenient (not pictured here).
And I didn't use ronald's gopher revision control yet, though it will make
my life infinitely better once I get to it.
|#