Hi,
This must be one of the commonest requests - and it is something of
a mystery to me why Poplog does not provide some nice "poppish"
interfaces. We have sysobey, piputils, and run_unix_program - but
they are either simple-but-inflexible or complex-but-useless.
Here are some ideas for making idiomatic UNIX programming more
straightforward. The first part of the message is about enhancing
or replacing -sysobey- with a new procedure called -system-. The
second part discusses making environment variables simpler.
Ideas for -sysobey/system-
--------------------------
I'd like to see the following enhancement to -sysobey-, or possibly
a replacement called -system-. I have made up an optional argument
syntax which I hope is more or less obvious since this is the kind
of procedure that cries out for optional arguments in my view.
1. -system- should be a synonym for -sysobey- or an enhanced version
of -sysobey-. All C + Perl + UNIX programmers know this command
by this name and I can see no merit in being different. At the very
least, the documentation should support programmers looking for it
by this name.
2. It should be possible to explicitly select the shell
used to execute the command. These days there are rather more
popular shells than just sh and csh!
As an aside, we really should consider introducing
optional argument syntax to do this sort of thing. Here is a
badly thought-out syntax which I'll use to illustrate some
ideas throughout the rest of this letter. e.g.
system[ shell = '/bin/tcsh' ]( 'ls' )
where the new syntax
f[ word = <expr>, ... ]
introduces a specialisation of "f" with the options of that procedure
set appropriately. I would also expect that it would be OK to
write
f[ foo=a, bar=b ][ gort=c ]
i.e. that you can cascade optional arg lists.
I will write a follow-up message about how this can be done efficiently.
Option shell = <string>
3. It should be possible to capture the result of the command in
a file/character-repeater/device. (Similarly stderr.) Note
that the keyword "device" would mean return a device from which
output can be read. The keyword "chars" would mean return a
character repeater. The keyword "string" would mean return the
output as a string. The keyword "lines" would return a line
repeater and "list" a list of lines.
Option output = <string|"string"|"chars"|"lines"|"list"|"device"|device>
errput = <string|"string"|"chars"|"lines"|"list"|"device"|device>
4. It should be possible to supply the command with a standard input
that is drawn from a file/list/repeater/device. Note that
"device" would mean return a device from to which input can be
written. The repeater would be allowed to return strings or
characters. Similarly true for a list.
Option input = <string|procedure|"device"|device>
3. It should be possible to execute sysobey in the background i.e. there
should be an optional wait flag i.e. the general calling interface would
be
sysobey( <command:string>, <shell:char>, <wait:boolean> )
with two optional parameters. -wait- would default to -true-. If
my "demo" optional argument syntax is adopted the interface would be
written as
system[
shell = <string>,
wait = <boolean>,
output = <string|"string"|"chars"|"lines"|"list"|"device"|device>
input = <string|"string"|"chars"|"lines"|"list"|"device"|device>
](
<command:string> | <file:string>, <args:list>
) -> [ <input> ] [ <output> ] [ <errput> ]
5. I would like the default shell of -sysobey- to be explicitly
changed to /bin/bash (whenever available). It is pretty much
exclusively used under Linux.
I would imagine that one of the commonest uses would be
commands such as
system[ output="repeater", input=my_repeater ]( 'grep -v foo' ) -> rep;
where the output and input parameters are bound. This would create
an output repeater that would automatically invoke the input repeater
on demand. Also common would be
system[ output="list" ]( 'find . -type f' ) -> list_of_lines
and
system[ output="string" ]( 'uname -a' ) -> uname_string
Shorthand
---------
I think that the $( ... ) brackets in /bin/bash are a very
useful shorthand - these are used for getting the output of a command
as a string e.g.
system[ output="string" ]( 'uname -a' )
could be written as
$( 'uname -a' )
In this case, I would see "$( ... )" as a syntactic shorthand for
system[ output = "string" ]( ... )
Using Environment Variables
---------------------------
In addition, there are a variety of UNIX idioms that are very
common and I believe UNIX versions of Poplog should support. For
example "$" for accessing environment variables is something that
I have been using for years in my local library to good effect.
One mistake is that my version does not recognise ${foo} as
identical to $foo. Here's a quick hack that remedies that ...
compile_mode :pop11 +strict;
section;
define global syntax $ ;
lvars it = readitem();
if it == "{" then
readitem() -> it;
pop11_need_nextreaditem( "}" ).erase;
endif;
sysPUSHQ( it sys_>< nullstring );
sysCALL -> pop_expr_inst;
"systranslate" -> pop_expr_item;
enddefine;
endsection;
Using this syntax word, you can access and update variables in a
way that is very natural to UNIX programmers. e.g.
$TERM =>
** linux
'vt100' -> $TERM;
---oooOOOooo---
Of course, these are just ideas. I would very much like to be able
to program using these facilities - and I definitely would find a
general and efficient optional argument syntax invaluable. What
do others think?
Steve
|