Here is a script: nls - I am using as my combined newLISP and UNIX shell on Mac OS X. It also contains Cormullion's help function from here:
http://unbalanced-parentheses.nfshost.com/simplehelpfornewlisp
#!/usr/bin/newlisp
; - nls- newLISP shell, put this script with executable permissions into
; the executable path on UNIX.
(define (help func-name)
(if (find func-name "|+*-") (push "\" func-name))
(set 'html-text (join (find-all (format {<b>(syntax: (%s.*?)</b>} func-name)
(read-file "/usr/share/doc/newlisp/newlisp_manual.html")) "n"))
(println (replace "<.*?>" html-text "" 0))
"")
; set the prompt to the current path
(prompt-event (fn () (append (real-path) "> ")))
; handle some special commands, newLISP expressions and shell commands
(command-event (fn (s)
(if
; get syntax help
(starts-with s "help")
(help (last (parse s " ")))
; restart newLISP
(starts-with s "reset")
(reset true) ; restart
; avoid X-windows beeing started on OS X
(starts-with s "x")
""
; directory must be changed inside newLISP
(starts-with s "cd")
(string " " (true? (change-dir (last (parse s " ")))))
; else handle as a shell command, start newLISP expressions
; with either a space or a parenthesis
(starts-with s "[a-zA-Z]" 0)
(append "!" s)
true s)))
;; eof
Best to be used with this version of the manual which is cleaned up, so that all syntax descritions are parse'able:
http://www.newlisp.org/downloads/development/newlisp_manual.html
The scriupt in action, with help:
Users/lutz> help file
syntax: (file-info str_name [int-index])
syntax: (file? str-name)
/Users/lutz> (+ 1 2 3 4)
10
/Users/lutz> ls -ltr *.txt
-rw-r--r-- 1 lutz lutz 81786 Jan 28 14:43 wget.txt
-rw-r--r-- 1 lutz lutz 152 Mar 23 09:39 stats-log.txt
/Users/lutz>
That's really cool. I was thinking that it would be nice to avoid the parentheses when asking for help.
I must point out that you wrote that help function, Lutz - I just modified it... :)
Please explain why this or a modification won't work in windows?
--hsm
p.s. I'm not saying it should, just curious...
Now that Lutz has posted some sensible uses for command-event, let's see it used for some wilder stuff:
The first one allows [] (square brackets) to define lambdas:
(command-event
(fn (s) (if (= s "[]")
"(lambda ())"
(replace {[((.+?),s+?)?(.+?)]} s (string "(lambda (" $2 ") " $3 ")") 0))
)
)
This lets us do the following:
> []
(lambda ())
> [n, (+ n n)]
(lambda (n) (+ n n))
> ([n, (+ n n)] 4)
8
> (define (tripled) (map [e, (* 3 e)] (args)))
(lambda () (map (lambda (e) (* 3 e)) (args)))
> (tripled 1 2 3)
(3 6 9)
> ;; nested anonymous functions will need more regexing to work:
> (set 'tripled [(map [e, (* 3 e)] (args))])
ERR: missing parenthesis : "...led (lambda ((map [e) (* 3 e)) (args"
> _
The second one allows contexts returned from expressions to use the : (colon) to access context symbols:
(command-event
(fn (s) (replace {(([^(])):([^W])} s (string "(context " $1 { "} $2 {")}) 0))
)
And could be used like so:
> (set 'C:n 9 'C:f (fn (n) (+ n n)))
(lambda (n) (+ n n))
> (define (f) C)
(lambda () C)
> (f):n
9
> ((f):f 5)
10
> _
Both of these can be combined into one:
(command-event
(fn (s)
(if (= s "[]")
"(lambda ())"
(replace
{(([^(])):([^W])}
(replace
{[((.+?),s+?)?(.+?)]}
s
(string "(lambda (" $2 ") " $3 ")")
0
)
(string "(context " $1 { "} $2 {")})
0
)
)
)
)
While these may not be useful in practice or even a good idea, it shows the potential of command-event to drastically alter the behavior of the newLISP shell.
m i c h a e l
I've slightly modified the Lutz/cormullion help function and Lutz's command-event function to allow for the following:
> help pop
syntax: (pop list [int-index-1 [int-index-2 ... ]])
syntax: (pop list [list-indexes])
syntax: (pop str [int-index [int-length]])
syntax: (pop (list-alist expr-key-1 [expr-key-2 ... ])
> help push
syntax: (push exp list [int-index-1 [int-index-2 ... ]])
syntax: (push exp list [list-indexes])
syntax: (push str-1 str-2 [int-index])
> _
I was unable to call the help function directly (as in Lutz's example), so I formatted the expression into a string, which did work. Also, in the help function, I accounted for a that was hiding in pop's help text, as well as answering cormullion's question of how to handle silent and the missing prompt:
(define-macro (help func-name)
(set 'func-name (string func-name))
(when (find func-name "|+*-") (push "\" func-name))
(set 'html-text
(join
(find-all
(format {<b>(syntax: (%s.*?)</b>} func-name)
(read-file "/usr/share/doc/newlisp/newlisp_manual.html")
)
"n"
)
)
(silent (println (replace { } (replace "<.*?>" html-text "" 0) " ")))
(print "> ")
)
And in command-event's function, I changed (help (last (parse s " "))) to (format "(help %s)" (last (parse s " "))).
If we wanted to go even more minimal, we could also parse for a "?", as in:
> ? select
syntax: (select list list-selection)
syntax: (select list [int-index_i ... ])
syntax: (select string list-selection)
syntax: (select string [int-index_i ... ])
> _
m i c h a e l
good job! thanks
I had trouble using the newLISP debugger effectively when I had some of these customized command-event things defined. If you use the debugger you can quickly revert back to default mode using (command-event nil), which seems to work.
... you could define the 'command-event' function separately, e.g.:
(define (handler s) .....)
and then enable it with:
(command-event handler)
or disable it with 'nil'