Customizing the newLISP console

Started by Lutz, April 30, 2008, 07:52:52 AM

Previous topic - Next topic

Lutz

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">http://unbalanced-parentheses.nfshost.c ... fornewlisp">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">http://www.newlisp.org/downloads/develo ... anual.html">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>

cormullion

#1
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... :)

hsmyers

#2
Please explain why this or a modification won't work in windows?



--hsm

p.s. I'm not saying it should, just curious...
\"Censeo Toto nos in Kansa esse decisse.\"—D. Gale \"[size=117]ℑ♥λ[/size]\"—Toto

m i c h a e l

#3
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

m i c h a e l

#4
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 &nbsp; 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 {&nbsp;} (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

cormullion

#5
good job! thanks

cormullion

#6
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.

Lutz

#7
... 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'