hunt@spar.SPAR.SLB.COM (Neil Hunt) (12/12/87)
In article <> ggs@ulysses.homer.nj.att.com (Griff Smith) writes: >In article <12726@think.UUCP>, barmar@think.UUCP writes: >>>In article <> ok@quintus.UUCP (Richard A. O'Keefe) writes: >>>>Have you ever used TOPS-10? [Globbing not in the shell results in every command being different] > >As a veteran of the TOPS-10 SCAN/WILD wars, I agree with the first >complaint. When command parsing is done in the application program >there is too much opportunity for "creativity". > >DEC did have a library that "simplified" directory scanning ("WILD") >and command arg parsing ("SCAN"). It required the user to build tables >of expected arguments, default values, etc. Some people took the >trouble to learn how to use it, many gave up and did their own quick >and dirty versions. VMS comments - don't do it like this ! ====================================== If I remember correctly, VMS (VM$ !) has (had ?) a horrible system. A command could be installed `foreign', in which case you could call some $y$tem$call with a long$ name$ to obtain the complete command line with spaces zapped; it was up to you to parse this as you would. Otherwise you built a file describing the command options allowed (options had to begin with '/', of course) in some incredibly non obviou$ $yntax, and executed some command which incorporated this into your command interface. To get a command with real options included into the interface for everyone required the services of a wheel (superuser). Only with the latter option could standardised globbing be done. Even then, the shell didn't make use of any of this extra data in an interesting way - it simply syntax checked your command. THere was no completion, or prompting ! There was a library of $y$tem$call$with$long$name$ which allowed one to access directories, so it was possible to perform some kind of expansion in a program using the foreign interface, but the speed was absolutely appaling ! An idea - take the idea behind the VMS approach, but do it right. ================================================================= Now I run a UNIX shell called cshedit -- a local hack -- where typing ESC in the middle of a line does filename completion, and '?' prompts with a list of possible completions of the current line as typed so far. Some limited intelligence is provided; if a word is the first word in the line, or after a ';' or '&', the completion is by files in the current path; otherwise it is over files in the current directory. This shell is incredibly useful. Users who have become familiar with it will not touch any other, not even the newer csh which has completion on ESC, but automatically gives you a list of possible completions whenever there is ambiguity. The '?' mechanism is much more useful. E.g. you want to see what will go when you type 'rm ab*' -- you type 'rm ab?' and the shell gives you a list of all the matches. If you haven't specified enough, add some more letters, then *, then CR and away it goes (and so do your files -- as previewed !). (By the way it also has complete EMACS line editing commands built in... ^B, ^F, ^P move forward and back in the line and command history, type ^RccESC to search the history for the last cc command; add ^Rcc -cESC for the last cc -c command, and repeat ^R^R^R to search back again for previous commands in the history ...) Arguably, the ESC '?' feature could be extended in a simple way to allow the command itself (after the command name (verb) has been typed, anyway) to provide the shell with some guidance on how to expand or interpret names, along the lines of a usage message. If there were a standard way to obtain a usage message [e.g. command -Help], and some better conventions about how to interpret one, then one could imagine the shell, when first given an ESC or '?', could invoke the program to obtain its usage message (which could then be cached); for example: Usage: command [-a %d] [-b %f] [-fast] [-verbose|-silent] file.end file Now we could have % commESC # ESC asks for completion. ------- % command -? # ? asks for options with '-'. -- # (shell obtains usage message) [-a %d] [-b %f] [-fast] [-verbose|-silent] # list of pos options. % command -faESC # completion. ----- % command -fast f? # options begining 'f'. -- f123.end f456.end f789.end # list of files matching f # and also having .end % command -fast f1ESC ---- % command -fast f123.end f1*3? # ? asks for completions ----- f123.end f123.results f123.results.old f113.results % command -fast f123.end f1*3.rESC # complete on .r _____ % command -fast f123.end f1*3.resultsBEEP # still ambiguous - BEEP warns. % command -fast f123.end f1*3.results.ESC ---- % command -fast f123.end f1*3.results.old # final command; confirm with CR ======== {{ underlining indicates what the user types, eveything else is provided ----------- by the shell, except the commentary # commentary which is to explain this protocol. }} ======== One could see a faster way where the usage message was called by some standard name inside the program, and the shell could extract the message from the object without the cost of execing the program just to get hold of the message: --------- char *usage_messages[] = { "[-a %d] [-b %f] [-fast] [-verbose|-silent] file.end file", "# explanation (human readable) after command marks", "[more [options [here | or here]]]", NULL, }; main() { if(...) usage(usage_mesages); /* Library func prints "usage: argv[0] ..." */ ... } --------- Now the shell can open the command object file, read the symbol table, and extract the strings directly. Advantages ========== Such a scheme is backward compatible - if a command has no usage_messages strings, then the shell will make some assumptions - no worse than now. New commands with appropriate stuff will work. Users not liking the stuff can use a standard shell, rather than the modified version. By the way - this still doesn't stop you typing rm * ! Comments anyone ? Neil/.