% Hacked for the apm, FDC, 4.6.85 % File : /usr/lib/prolog/edit % Author : Lawrence Byrd, Peter Ross, and Richard A. O'Keefe. % Updated: Friday May 26th, 1984 % Purpose: Definitions of some useful commands for use % when editing files from within Prolog. /* These commands use the Prolog evaluable predicate shell/1 to call various UNIX commands. Thus you can "more" files or edit them just by calling a Prolog predicate. These UNIX commands run as separate processes, and Prolog waits for them to finish. So the effect is just like a procedure call. When they finish you are returned to Prolog. Since the shell/1 predicate FAILS if the UNIX command you invoke with it returns a non-zero status, so do these commands fail. If for example you get out of "top" with ^C, the edit command will fail. This is used to avoid reconsulting a file when you decide not to change it after all. All of the commands which take a single argument have been defined as prefix operators. This means that Prolog can accept commands in a format resembling UNIX commands. For example, "more changes" is alternative syntax for "more(changes)". But you mustn't forget the full stop which has to end EVERY input to Prolog. Don't forget that the file name is a Prolog atom, so that if it has a solidus (/) or a full stop (.) in it you will have to quote it. For example, saying "edit fred.pl." won't work. You have to quote the file name, saying "edit 'fred.pl'.". The following commands are provided. l Predicate. Same as listing(Predicate) only shorter. l. Same as listing only shorter. r Key. List everything recorded under Key. r. List the entire recorded data base. cd Directory. Make Directory the current directory. cd. cd to your login directory. ls Directory. List Directory using "ls -lf". ls. List the current directory using "ls -lf". sh Command. Execute the Unix command Command. sh. Start up an subordinate shell. more File. Display the File on your terminal using the "more" program. more. Display the last mentioned file using "more". edit File. Edit the File using $EDITOR. edit. Edit the last file mentioned. redo File. Edit the File using $EDITOR, then reconsult the File. redo. Redo the last file mentioned. wc File. Find out how big File is using "wc". con File. Consult the File. con. Consult the last file mentioned. rec File. Reconsult the File. rec. Reconsult the last file mentioned. The commands "more File", "edit File", "redo File", "con File", and "rec File" all "notice" the File name. In other words, they record the file name so that you can give other commands pertaining to the same file without repeating the name. This is the only real point in the "con" and "rec" commands; [File] does the same as con(File), and [-File] does the same as rec(File), *except* that the bracketed forms don't remember the file name. If you say "con 'fred.pl', and that file turns out to have a syntax error, you can immediately say "redo" or "edit" if you prefer, without having to retype what might be a long file name. The shell/1 predicate expects a string as its argument. cd/1 wants an atom. These predicates are built into C Prolog so we can't make them act differently here. But all the other one-argument commands will take either a string or an atom. It would be possible to make them take terms using (/)/2 as well, but I haven't done that. The question arises, what editor should be used? Fortunately, UNIX has a way of letting you specify things like this. In the C shell (csh, newcsh, or tcsh) you say setenv EDITOR "the name of your favourite editor" In the standard (Bourne) shell (sh) you say export EDITOR; EDITOR="the name of your favourite editor" Most UNIX programs that offer an editor escape (such as the mailer) already look at this variable, so you have probably set it already. If you give an edit or redo command without this variable being set the default editor is /usr/local/emacs. Why emacs? Once upon a time this package was based on VILE. (It's been based on other editors in previous incarnations.) But VILE is a memory hog, and isn't really practical on system as heavily over- loaded as ours. If you don't give a damn about other users, you've only to "setenv EDITOR vi" in your .login or .profile. Emacs is a fair bit smaller than VILE, and is also available under VMS. There are similar editors on many different machines, such as the Dec-10 and the Perq. You might like to try another editor called "top", a very much smaller (and faster) editor than emacs or VILE, but which resembles emacs, has commands useful for Prolog (such as a command for checking a clause for syntax errors), and is given away free to C Prolog customers. Emacs is a good all-round choice. The original idea of this collection was Lawrence Byrd's. The code for C Prolog was done by Peter Ross, then rewritten by R.A.O'Keefe. */ :- op(600, fy, [ % Has to be fy so can "edit edit". l, r, % list clauses, records cd, ls, sh, % UNIX commands more, edit, redo, con, rec, wc ]). /* Commands pertaining to the Prolog data base */ l(Predicate) :- % List a predicate. listing(Predicate). l :- % List the entire data base. listing. r(Key) :- % List all terms recorded under a given key. '$functorspec'(Key, Name, Arity), functor(MGT, Name, Arity), recorded(MGT, Term, Ref), writeq(Name/Arity), write(' -> '), write(Ref), write(' = '), numbervars(Term, 0, _), print(Term), write(.), nl, fail ; true. r :- % List the entire recorded data base. current_functor(_, MGT), r(MGT), fail ; true. /* UNIX commands which don't relate to single source files */ % cd(Directory) is built in and demands an ATOM for its argument. cd :- % Change to the user's login directory. cd('~'). ls(Directory) :- % List the contents of a directory. atom(Directory), !, name(Directory, DirectoryString), 'append colon'(DirectoryString, String), shell("f", String). ls(Directory) :- 'append colon'(Directory, String), shell("f", String). ls :- % List the contents of the current directory. shell("f"). sh(Command) :- % Execute a shell command. (sh/0 is built in.) atom(Command), !, name(Command, String), shell(String). sh(Command) :- shell(Command). cli :- shell("shell"). /* UNIX or Prolog commands pertaining to a source file */ % Well written editors like emacs and top can remember for themselves % what file you edited last. Because VILE and ed cannot, and because % redo needs to know what file anyway, these commands rely on $notice % to keep track of the "last mentioned" file. If the first of these % commands you give is 'edit', the editor will be called without any % arguments. more(File) :- % Display a file using "more". '$notice'(File), shell("t", File). more :- % Display the last mentioned file. '$noticed'(more, File), shell("t", File). edit(File) :- % Edit a new file. '$notice'(File), editor(Editor), shell(Editor, File). edit :- % Edit the last mentioned file '$noticed'(File), !, % we have edited before editor(Editor), shell(Editor, File). % re-edit that file. edit :- % no previous edit editor(Editor), shell(Editor). % call editor with no argument. vi(File) :- % obsolete form for VILE write('Obsolete command. Use edit with $EDITOR=vi'), nl, '$notice'(File), shell("vi", File). redo(File) :- % Edit and reconsult a file. '$notice'(File), editor(Editor), shell(Editor, File), reconsult(File). redo :- '$noticed'(redo, File), editor(Editor), shell(Editor, File), reconsult(File). wc(File) :- % Get some idea of how big File is '$notice'(File), shell("wc", File). con(File) :- % Consult a file and remember it. ( atom(File), F = File ; name(F, File) ), !, '$notice'(F), consult(F). con :- % Consult the last mentioned file. '$noticed'(con, File), consult(File). rec(File) :- % Reconsult a file and remember it. ( atom(File), F = File ; name(F, File) ), !, '$notice'(F), reconsult(F). rec :- % Reconsult the last mentioned file. '$noticed'(rec, File), reconsult(File). /* Support routines for the user-oriented predicates above */ '$notice'(File) :- % remember which file was last mentioned abolish('$noticed', 1), assert('$noticed'(File)). '$noticed'(_, File) :- % Command wants to know what File '$noticed'(File), !. % was last mentioned, and will complain '$noticed'(Command, _) :- % if there wasn't one, e.g. write(Command), % redo WhatFile? write(' WhatFile'), write(?), nl, fail. % We get the editor name from the environment variable $EDITOR. % If that isn't defined, we default to /usr/local/emacs. If you % want a different editor, and don't want to set $EDITOR, or are % using an operating system where you can't, reconsult a Prolog % file which says editor("yaloe") or whatever. Note that a string % is needed, not an atom. /* editor(String) :- expand_file_name('$EDITOR', Editor), !, name(Editor, String). */ editor("ie"). % shell(Command, Argument) appends a space and the argument (or % the name of the argument) to the command and calls the result. shell(Command, Argument) :- atom(Command), !, name(Command, CommandString), 'finish command'(CommandString, Argument, String), shell(String). shell(Command, Argument) :- 'finish command'(Command, Argument, String), shell(String). 'finish command'([C|Cs], Argument, [C|Ss]) :- !, 'finish command'(Cs, Argument, Ss). 'finish command'([], [A|As], [0' ,A|As]) :- !. 'finish command'([], Argument, [0' |Name]) :- name(Argument, Name). 'append colon'([C|Cs], [C|Ss]) :- !, 'append colon'(Cs, Ss). 'append colon'([], [0':]) :- !.