An Exec command and other new features of Stringscope
I continued working on Stringscope, the string listing tool I'm developing with Medley Interlisp. I added the function STRINGS
to print the strings to the primary output stream rather than in a new window, as well as an Executive command that does the same.
To reflect this work I updated the Stringscope code and documentation hosted on a GitHub gist, describing also the function EXTRACT.STRINGS
as part of the interface. The code in the gist is intended for publication and can't be loaded as is into Interlisp.
The functions STRINGS
and STRINGSCOPE
In addition to the same arguments as STRINGSCOPE
, i.e. a file name FILENAME
and the minimum length MIN.LEN
strings must have, STRINGS
accepts a third optional boolean argument NEWWIN
. By default NEWWIN
is NIL
and makes STRINGS
print to the primary output, otherwise the function opens a new window and works exactly like STRINGSCOPE
. In fact, STRINGSCOPE
is now just a wrapper that calls STRINGS
with NEWWIN
set to T
.
STRINGSCOPE
and STRINGS
return a window if the functions open it otherwise the primary output stream. In case the input file can not be opened or contains no strings, the functions return NIL
and print a warning to the prompt window.
Interlisp functions that create or manipulate a window usually return the window itself as their value, so I adopted a similar convention.
The macro WITH.INPUT-FILE
An early version of STRINGS
duplicated a lot of the code of STRINGSCOPE
for opening the input stream, checking for errors, evaluating some forms with the stream bound to a variable, and closing the stream. I factored that boilerplate into the macro WITH.INPUT.FILE
:
(DEFMACRO WITH.INPUT.FILE ((STREAM FILE)
&BODY BODY &AUX (RESULT (GENSYM))
(VALUE (GENSYM)))
(* Opens an input stream to FILE and evaluates the forms in BODY with the stream
bound to STREAM. Returns the value of the last form in BODY, or NIL if FILE can
not be opened.)
`(PROG NIL
[SETQ ,RESULT (NLSETQ (OPENSTREAM ,FILE 'INPUT]
(if ,RESULT
then (SETQ ,STREAM (CAR ,RESULT))
(SETQ ,VALUE (PROGN ,@BODY))
(CLOSEF ,STREAM)
(RETURN ,VALUE)
else (RETURN NIL))))
The Executive command STRINGS
The reason I implemented a function like STRINGS
that prints the output to the console is I wanted to try out creating an Executive command.
Also known as a listener in other Lisp environments, an Executive is an Interlisp window that provides a read-eval-print loop. In addition to Lisp expressions, an Executive accepts commands with a non-parenthesized syntax such as DIR
(the equivalent of DIR
on MS-DOS and ls
on Unix) or CONN directory
(cd directory
on MS-DOS and Unix).
So I defined the Stringscope Executive command STRINGS
that works exactly like the function STRINGS
but takes only the file name and the minimum length arguments:
STRINGS FILENAME MIN.LEN
The macro DEFCOMMAND
defines an Executive command and is really easy to use, here's the definition of STRINGS
:
(DEFCOMMAND (STRINGS :EVAL) (FILE &OPTIONAL (MIN.LENGTH SSCOPE.MIN.LEN))
(STRINGS FILE MIN.LENGTH)
(CL:VALUES))
The STRINGS
command is just a wrapper that calls the function STRINGS
with appropriate arguments.
Compiling Stringscope
I initially run Stringscope compiled but it was time to start using the File Manager commands for compiling the code, (MAKEFILE 'STRINGSCOPE 'C)
and (CLEANUP 'STRINGSCOPE)
. However, these commands apparently compile only in memory and don't write a compiled file like (TCOMPL 'STRINGSCOPE)
, which I have to call manually.
The File Manager is an Interlisp subsystem conceptually similar to the Unix tool Make. It's a collection of tools to notice, keep track of, and write to files the code changes to a Lisp system under development.
Another confusing aspect of compilation is when I load Stringscope with (FILESLOAD STRINGSCOPE)
, I get a warning I don't understand concerning a comment in the macro WITH.INPUT.FILE
: Warning: Possible comment not stripped
. I actually see the compiler couldn't strip a comment from the compiled code to save space, but not why.
Further development
Some of these new features were on my initial roadmap, others emerged while coding and using Stringscope.
Since this is an exploration and learning project, going forward I'll go with the flow and implement what I need or find interesting, and consider the initial roadmap more like a source of ideas than an action plan. Which is the kind of exploratory development Lisp supports and makes enjoyable.
Discuss... Email | Reply @amoroso@fosstodon.org