123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333 |
- #import std
- #import nat
- #import flo
- #import stt
- #comment -[
- some routines to interface with command line interpreters
- Copyright (C) 2007-2010 Dennis Furey]-
- #library+
- -------------------------------------------------------- constants ---------------------------------------------------------
- eof = 4%cOi& # end of file character
- ---------------------------------------------------- data structures --------------------------------------------------------
- #optimize+
- shell :: # interface specification of a command line interpreter
- opener %s # command to invoke the shell
- login %sLWL # password negotiation protocol, if required
- prompt %scLU # shell prompt to expect
- settings %sL # commands to be executed when the shell opens
- declarer %fOZ ~declarer||0!! # takes an assignment (n: m) to a client that binds the value of m to the symbol n
- releaser %fOZ ~releaser||0!! # takes an assignment (n: m) to a client that releases the storage for the symbol n
- closers %sL # commands to close the shell
- answerer %fOZ ~answerer||~&! # postprocessor for answers returned by the ask function, taking %ssLA
- nop %s # shell command that does nothing, used by ask, usually just the empty string
- wrapper %fOZ ~wrapper||~&! # postprocessor to the client generated by sh for anything not covered above
- ------------------------------------------- functions pertaining to protocols ------------------------------------------------
- (# A protocol is represented as a list of pairs of lists of strings <(<command..>,<prompt..>)..>, such that the client sends
- the commands and waits for the prompts. If the last list of prompts is <<eof>>, the client will wait until the server closes
- the connection. If the last list of prompts is <''>, the client will close the connection upon sending the last command.
- Otherwise, the client will close the connection when the last prompt is received. This semantics is a consequence of the
- virtual machine's interact combinator calling conventions. #)
- handshake = ^|DrlXS(:/''+ ~&iNC,* --<''>+ ~&iNC) # takes a prompt string and a list of command strings to a protocol
- completing = ~&i&& ^lrNCT/~&y ~&\<<eof>>+ ~&zl # takes a protocol to one that waits for the server to close the connection
- closing = ~&i&& ^lrNCT/~&y ~&\<''>+ ~&zl # takes a protocol to one that ends with the client closing the connection
- -------------------------------------------------- functions of clients -----------------------------------------------------
- watch = ~&iNHiF+ interact # takes a client to a verbose trace of type %scLULL
- exec = ~&Z&&+ !+ ~&NiX\<<eof>>+ ~&iNC # takes a string to a client that executes only one command
- expect = # takes a protocol to a client usable as an argument to the interact combinator
- %scLULWLMk; ~&i&& (~&?^\!+~&hr ~&l?\0!+ ~&l;+ =:+ ~&t)+ -+
- %aaZscLULWXXLMk+ ~&a^& :^\~&fatPR ^/~&ahl ^\~&ahr ~&atihlPB,
- %ascLULWXLMk+ ^p\~& %aLMk+ ~&aahPNfatPRXfatPRNXQaaXqS+ ~&xrSPS+ zipp0*+ ~&ziD+ iol+-
- (# seq takes a prompt p to a function that takes a list of clients to their sequential composition in a shell with prompt
- p. If any client closes the connection, interaction with the next one starts immediately. If any client waits for the server
- to close the connection (with <<eof>>), the prompt <'',p> is expected instead (i.e., p preceded by a line break), any
- accompanying command from the client has a line break appended, and the interaction of the next client commences when <'',p>
- is received. If the initial output of the next client is a single string, a line break is appended to the command, and if its
- initial prompt is a single string, a line break is inserted in the prompt. #)
- seq =
- "p". :-0 ~&l?\~&r ~&r?\~&l ~&lNH?\~&r ~&rNH?\~&l ("f","g"). -!~&Z,~&ll==&l!-?(
- "f"+~&ilrPrXB; ~&?(
- <<eof>>?=rr(~&/&+ ~&\<'',"p">+ ~&rl,^|\~& ~&/&l),
- ! ^|(~&/&r,^|(~&t?/~& --<''>,-!~&ZtY,==<<eof>>!-?/~& ~&NiC)) "g" 0),
- &?=l(! ^|(~&/&r,^|(~&t?/~& --<''>,-!~&ZtY,==<<eof>>!-?/~& ~&NiC)) "g" 0,(~&i&& ^|\~& ~&/&r)+ "g"+ ~&lrPrX))
- (# When used as a wrapper in a shell, prompt_counter substitutes \n in prompt strings with a count that's incremented each
- time starting from 1. #)
- prompt_counter =
- "f". -+
- ~&r&& (~&i&& ~&r; any substring/'\n')?rr\~&lrlPXrrPX -+
- %ngXsLWXMk+ ^/~&lrlPX ^/~&rrl ^H\~&rrr '\n'%=*+ ~&h+ %nP+ ~&l,
- %ngsLWXXMk+ ^\~&r ~&rrlihtYB?/successor+~&l ~&l+-,
- %ngsLWXXMk+ ~&?(^/~&ll "f"+ ~&lrPrX,! ~&NiX "f" 0)+-
- ------------------------------------------------------- specific shells ----------------------------------------------------
- #optimize-
- bash = # system command line interpreter
- shell[
- opener: 'bash --noediting',
- prompt: '$ ',
- settings: <'export PS1="$ " PS2="$ "','set +H'>,
- declarer: %sI?m(
- ("n","m"). exec 'export '--"n"--'="'--"m"--'"',
- ("n","m"). seq'$ ' <
- exec 'touch '--"n",
- (sh shell[opener: 'ed '--"n",settings: <'%d','a'>,closers: <'.','wq'>])/<> ~='.'*~ "m">),
- releaser: %sI?m/0! exec+ 'rm '--+ ~&n,
- closers: <'exit'>]
- psh = shell opener:='psh'! bash
- R = # statistical package
- shell[
- opener: 'R -q',
- prompt: '> ',
- declarer: expect+ completing+ handshake/'> '+ -?
- %eLI+~&m: :^(
- ^T/~&n '=rep(0,'--+ --')'+ ~&h+ %nP+ length+ ~&m,
- ^D(~&n,num+~&m); * ^T/~&l ~&r; ^T('['--+ --']='+ ~&h+ %nP+ successor+ ~&l,printf/'%0.20e'+ ~&r)),
- %eLLI+~&m: :^(
- ^T/~&n '=matrix(0,'--+ --')'+ ^T(~&l,:/`,+ ~&r)+ ~&bh+ %nP~~+ length~~+ ~&m; ^/~& ~&z+ leql-<,
- ^D(~&n,num+~&m); *= -+
- * ^T/~&l ~&r; ^T('['--+ --']'+ ^T/~&l :/`,+ ~&h+ %nP+ successor+ ~&rl,:/`=+ printf/'%0.20e'+ ~&rr),
- ^D/~&l ~&r; ^D\num+~&r ~&h+ %nP+ successor+~&l+-),
- %eI+~&m: ^TNC/~&n :/`=+ printf/'%0.20e'+ ~&m,
- -&~&,%sLI&-+~&m: :^(~&lrhPX; ^|T/~& ' <- '--,~&rt)+ ^lrNCT(~&y,--';'+ ~&z)+ ~&m,
- <'unknown R type'>!%?-,
- closers: <'q()'>]
- octave = # numerical package
- shell[
- opener: 'octave --q --no-line-editing',
- prompt: '> ',
- settings: <'PS1=''> ''','PS2='' > ''','split_long_rows=0','format hex','PAGER="cat"'>,
- declarer: expect+ completing+ handshake/'> '+ -?
- %eLLI+~&m: :^/(^T/~&n '=eye('--+ --');'+ ^|T(~&,:/`,)+ ~&bh+ %nP~~+ length~~+ ~&mmhPX) ^D(~&n,num+~&m); *= -+
- * ^T(
- ^T/~&l ~&r; '('--+ --')'+ ^T/~&l :/`,+ ~&h+ %nP+ successor+ ~&rl,
- ~&r; :/`=+ --';'+ printf/'%0.20e'+ ~&rr),
- ^D/~&l ~&r; ^D\num+~&r ~&h+ %nP+ successor+~&l+-,
- %eLI+~&m: :^/(^T/~&n '=(1:'--+ --')'';'+ ~&h+ %nP+ length+ ~&m) ^D(~&n,num+~&m); * ^T(
- ^|T/~& '('--+ --')'+ ~&h+ %nP+ successor+ ~&l,
- :/`=+ --';'+ printf/'%0.20e'+ ~&rr),
- %eI+~&m: ^TNC/~&n :/`=+ --';'+ printf/'%0.20e'+ ~&m,
- -&~&,%sLI&-+~&m: :^(~&nmhPX; ^|T/~& ' = '--,~&mt),
- <'unknown octave type'>!%?-,
- closers: <'quit'>,
- answerer: ||~& (substring/' ='+ ~&ihB)&& ~&itZBhiQ+ ~&F+ * sep` ; -+
- ~&itZBhiQ+ octhex*,
- *~ eql/'0000000000000000'&& subset\digits--'abcdef'+-]
- gap = # group theory package
- shell[
- opener: 'gap -b -n',
- prompt: 'gap> ',
- settings: <'ColorPrompt(false);'>,
- declarer: expect+ completing+ handshake/'> '+ -+
- ^lrNCT(~&y,--';'+ ~&z)+ '<'%=*'['+ '>'%=*']',
- :^(~&lrhPX; ^|T/~& ':='--,~&rt)^/~&n ~&m; -|
- -|%nI&& %nP,%nLI&& %nLP,%nLLI&& %nLLP|-,
- -&%sLI,any substring/'function',~&i&-,
- ''''%=*'"'+ '"'%=*'\"'+ -|%sI&& %sP,%sLI&& %sLP,%sLLI&& %sLLP|-,
- ~&l?('/1'%=*''+ ~&r,~&r)+ -?
- %qI: ^\%qP ~&rr=='1',
- %qLI: ^\%qLP all ~&rr=='1',
- %qLLI: ^\%qLLP all all ~&rr=='1',
- <'unknown gap type'>!%?-|-+-,
- wrapper: //+ ||~& -&
- -&~&,~&r,~&rr==<'','gap> '>&-&& ~&rl; -&~&,~&t,~&ttZ,~&thZ&-&& ~&h; -&~&,~&z~=`;&-,
- &rlh:= --';'+ ~&rlh&-,
- closers: <'quit;'>]
- gp = # number theoretic computer algebra system
- shell[
- opener: 'gp -q',
- prompt: '? ',
- settings: 'default'--* <'(colors,no)','(output,0)','(readline,0)','(prompt_cont,"? ")','(format,"e0.28")'>,
- declarer: expect+ completing+ handshake/''+ ^lrNCT(--'\'*+ ~&y,--';'+ ~&z)^C(^|T/~& ' = '--+ ~&h,~&rt)^/~&n ~&m; -|
- -?%nI: %nP,%qI: %qP,%eI: ~&iNC+ printf/'%0.20e',%EI: ~&iNC+ mpfr..mp2str,%sI: ~&iNC,0!?-,
- -?%nLI: ~&hS+ %nP*,%qLI: ~&hS+ %qP*,%eLI: printf/*'%0.20e',%ELI: * mpfr..mp2str,-&%sLI,all ~&wZ/`=&-: ~&,0!?-; ~&i&& -+
- ^C\~&t '['--+ ~&h,
- ^lrNCT(--','*+ ~&y,--']'+ ~&z)+-,
- -?%nLLI: ~&hSS+ %nP**,%qLLI: ~&hSS+ %qP**,%eLLI: printf/**'%0.20e',%ELLI: mpfr..mp2str**,%sLLI: ~&,0!?-; ~&i&& -+
- ^C('['--+ ~&h,~&t)+ ~&L+ ^lrNCT(~&y; * ^lrNCT/~&y --';'+ ~&z,~&z; ^lrNCT/~&y --']'+ ~&z),
- * ^lrNCT(--','*+ ~&y,~&z)+-,
- %sLI?/~& <'unknown gp type'>!%|-,
- closers: <'\q'>]
- maxima = # computer algebra
- shell[
- opener: 'maxima --quiet --disable-readline',
- prompt: '(%i\n) ',
- settings: <'display2d: false;'>,
- declarer: expect+ completing+ handshake/''+ -+
- ^lrNCT(~&y,--'$'+ ~&z)^C\~&rt ^|T/~& ': '--+ ~&h,
- ^/~&n ~&m; %sI?/~&iNC %sLI?/~& <'unknown maxima type'>!%+-,
- closers: <'quit();'>,
- nop: '0$',
- wrapper: prompt_counter; //+ ||~& -&
- -&~&,~&r,~&rr; -&~&,~&hZ,~&t,~&ttZ,~&t=]'(%i'&-&-&& ~&rl; -&~&,~&t,~&ttZ,~&thZ&-&& ~&h; -&~&,~&z~<';$'&-,
- &rlh:= --';'+ ~&rlh&-,
- answerer: ~&ihZBtiQ; =]'(%o'?ihB\~& :^\~&t ~&ritB+ ~=` -~+ ~&h]
- axiom = # computer algebra
- shell[
- opener: 'axiom -noht -nogr -nogr -nox',
- prompt: '(\n) -> ',
- settings: <')set quit unprotected'>,
- declarer: expect+ completing+ handshake/''+ ^lrNCT(--'_'*+ ~&y,--';'+ ~&z)^C(^|T/~& ' := '--+ ~&h,~&rt)^/~&n ~&m; -|
- -?%nI: %nP,%qI: %qP,%eI: ~&iNC+ printf/'%0.20e',%EI: ~&iNC+ mpfr..mp2str,%sI: ~&iNC,0!?-,
- -?%nLI: ~&hS+ %nP*,%qLI: ~&hS+ %qP*,%eLI: printf/*'%0.20e',%ELI: * mpfr..mp2str,-&%sLI,all ~&wZ/`=&-: ~&,0!?-; ~&i&& -+
- ^C\~&t '['--+ ~&h,
- ^lrNCT(--','*+ ~&y,--']'+ ~&z)+-,
- -?%nLLI: ~&hSS+ %nP**,%qLLI: ~&hSS+ %qP**,%eLLI: printf/**'%0.20e',%ELLI: mpfr..mp2str**,%sLLI: ~&,0!?-; ~&i&& -+
- ^C('matrix['--+ ~&h,~&t)+ ~&L+ ^lrNCT(~&y; * ^lrNCT/~&y --','+ ~&z,~&z; ^lrNCT/~&y --']'+ ~&z),
- * ^C('['--+ ~&h,~&t)^lrNCT(--','*+ ~&y,--']'+ ~&z)+-,
- %sLI?/~& <'unknown axiom type'>!%|-,
- closers: <')quit'>,
- wrapper: "f". -+
- ~&r&& (~&i&& ~&r; any substring/'\n')?rr\~&lrlPXrrPX -+
- %ngXscLULWXMk+ ^/~&lrlPX ^/~&rrl ^H\~&rrr '\n'%=*+ ~&h+ %nP+ ~&l,
- %ngscLULWXXMk+ -!~&lZ,~&rrlihtihBPYB&& ~&rrlh; not -!=]')',=]'--',=]'++'!-!-?(
- ^/successor+~&l ~&r,
- ^/~&l ~&r; ^/~&l ~&r; ^/~&l ~&r; ~&i&& :^/~&h ~&t; ~&i&& ^llTrC\~&t :/13%cOi&+ ~&h)+-,
- %ngscLULWXXMk+ ~&?(^/~&ll "f"+ ~&lrPrX,! ~&NiX "f" 0)+-,
- answerer: -+
- ~&a^& =]' Loading'?ah\~&a `.?=ahz/~&fatPR ~&fatitB2R,
- ~=13%cOi&*~*+ ~&rihZtiQB+ -~ ~&+-]
- scilab = # numerical package
- shell[
- opener: 'scilab -nb -nw -nwni -nogui',
- prompt: '-->',
- declarer: expect+ completing+ handshake/'-->'+ ^C(^|T/~& ' = '--+ ~&h,~&rt)^/~&n ~&m; -|
- -?
- %nI: %nP,
- %qI: %qP,
- %eI: ~&iNC+ printf/'%0.20e',
- %EI: ~&iNC+ mpfr..mp2str,
- %bI: ~&?/<'%t'>! <'%f'>!,
- %sI: ~&iNC+ :/`'+ --'''',
- 0!?-,
- (~&i&& :/'['+ --<']'>)+ -?
- %nLI: ~&hS+ %nP*,
- %qLI: ~&hS+ %qP*,
- %eLI: printf/*'%0.20e',
- %ELI: * mpfr..mp2str,
- %bLI: * ~&?/'%t'! '%f'!,
- -&%sLI,all ~&wZ/`=&-: * :/`'+ --'''',
- 0!?-,
- (~&i&& ~&K7; :/'[['+ --<']]'>+ mat'][')+ -?
- %nLLI: ~&hSS+ %nP**,
- %qLLI: ~&hSS+ %qP**,
- %eLLI: printf/**'%0.20e',
- %ELLI: mpfr..mp2str**,
- %bLLI: * * ~&?/'%t'! '%f'!,
- %sLLI: * * :/`'+ --'''',
- 0!?-,
- %sLI?/~& <'unknown scilab type'>!%|-,
- answerer: ~=' '*~; `=?=ihBz\~& ~&t,
- closers: <'quit'>]
- ---------------------------------------------- functions operating on shells ------------------------------------------------
- #optimize+
- ssh = sh++ hop
- sask = ask++ hop
- sopen = open++ hop
- multihop = -++-+ hop*
- su = ("u","p"). shell$i[opener: ! 'su'-- (~&i&& :/` ) "u",login: ! <(<''>,<'word: '>),(<"p",''>,<' '>)>] bash
- hop = # takes a hostname ho and password p to a nestable function that makes a shell remote
- ("ho","p"). shell$i[
- opener: ! 'ssh'-- (~&i&& :/` ) "ho",
- login: -+
- //~&T <(<''>,<'word: '>),(<"p",''>,<=]'root@'?(':~# '!,':~$ '!) "ho">)>,
- "s". :/(<~opener "s",''>,<''>) ~login "s"+-]
- sh = # takes a shell specification to a function that takes an environment and a list of command strings to a client
- "s". ("e","c"). (~&?(~&,~&!) ~wrapper "s") (seq ~prompt "s") <
- expect :\~login"s" ^biNC(~opener,~login.&Z&& ~prompt) "s",
- expect completing handshake ~(prompt,settings) "s",
- (seq ~prompt "s") ~declarer"s"* "e",
- expect completing handshake (~prompt "s","c"),
- (seq ~prompt "s") ~releaser"s"* "e",
- expect closing handshake ~(prompt,closers) "s">
- open = # takes a shell specification to a function taking an environment and a list of clients to a client
- "s". ("e","c"). (~&?(~&,~&!) ~wrapper "s") (seq ~prompt "s") <
- expect :\~login"s" ^biNC(~opener,~login.&Z&& ~prompt) "s",
- expect completing handshake ~(prompt,settings) "s",
- (seq ~prompt "s") ~&L <~declarer"s"* "e","c",~releaser"s"* "e">,
- expect closing handshake ~(prompt,closers) "s">
- ask = # takes a shell to a function that takes an environment and a list of command strings to a result of type %sLm
- "s". -+
- ^p(~&nS,~answerer"s"*+ ~&mS)+ ~&mF+ rlc~&rititZBPBZ; %sLLLMk; * %sLLCk ~&hihBPtihiyBPBPX; ^A/~&l ~&lrihBPEritBPrQ,
- %sLLMk+ ~&ritBitB+ ~=<~nop "s",''>-~+ ~&liyB+ ~=<~nop "s",''>~-+ watch+ sh"s"^|/~& :/~nop"s"+ --<~nop "s">+-
- ------------------------------------------------- functions using shells ----------------------------------------------------
- (# now ignores its argument, octhex takes a hexadecimal string to a floating point number, choleski takes a positive
- definite matrix to a matrix, and eigen takes a symmetric matrix to a list of vectors and values. #)
- now = ~&hmh+ (ask bash)/<>+ <'date -R'>!
- octhex = block2; ~&x+ * -$characters ~&iiK0lrNCCS '0123456789abcdef'
- eigen = ~&itBthm2hmPpBx+ (ask octave)\<'[v,d]=eig(a);','diag(d)','v'>+ ~&ANC/'a'
- choleski = -|~&ihimitBiK7BPBPB,~&ihmPB&& ~&hm%|-+ (ask octave)\<'chol(a)'>+ ~&ANC/'a'
- stdmvnorm = # takes (<lower..>,<upper..>,<<sigma..>..>) to a standard multivariate normal probability using R
- -&~&,~&r,eql+~&lrlPX,eql+~&lrrPX,~&rr,eql+~&lrrh2X,~&rr; all_same length&-?\<'abnormal'>!% -+
- math..strtod+ (~&i&& ~&z; substring/'Normal Completion')?/~&httt <'abnormal completion'>!%,
- =]'[1]'*~+ ~&zm+ (ask R)^/<.'lower':+ ~&l,'upper':+ ~&rl,'sigma':+ ~&rr> -+
- :/'library(mvtnorm)'+ ~&iNC+ 'print(digits=16,pmvnorm(mean=rep(0,'--+ --'),lower,upper,sigma))',
- ~&h+ %nP+ length+ ~&l+-+-
- mvnorm = # takes (<lower..>,<upper..>,<mean..>,<<sigma..>..>) to a multivariate normal probability using R
- -&~&,~&r,eql+~&lrlPX,eql+~&lrrl2X,~&rrr,eql+~&lrrrh3X,~&rrr; all_same length&-?\<'abnormal'>!% -+
- math..strtod+ (~&i&& ~&z; substring/'Normal Completion')?/~&httt <'abnormal completion'>!%,
- =]'[1]'*~+ ~&zm+ -+
- (ask R)\<'library(mvtnorm)','print(digits=16,pmvnorm(mean=means,lower,upper,sigma))'>,
- <.'lower':+ ~&l,'upper':+ ~&rl,'means':+ ~&rrl,'sigma':+ ~&rrr>+-+-
- axparse = # parses a list of strings returned by an axiom command of the form expression::InputForm to a tree of strings
- -&~&r==<'Type:','InputForm'>,~&l&-+ -+
- ~&a^?\<'bad S-exp'>!% ')'?=ah/~&NaX '('?=ah\~&ahNVtX ~&NfatPJX; ~&rah~=')'->lxhdPtV2rat2X ~&lrffaRJPX; ~&ral2lCrfarPJPX,
- ~&itB+ ~&itB+ ~&itB+ ~&L; sep` ; *= rlc neither -='()'+-
|