Readline interface: Difference between revisions
Content added Content deleted
(category terminal control) |
(→{{header|REXX}}: added the REXX language. -- ~~~~) |
||
Line 135: | Line 135: | ||
> save |
> save |
||
> quit |
> quit |
||
=={{header|REXX}}== |
|||
This REXX programs supports a REDO (re-do) with very limited editing to keep the program simple. |
|||
<br>It has a history (which can be interrogated) and a few simple (DOS) commands. |
|||
<br>The HELP (?), REDO, error checking, and abbreviations took up most of the program. |
|||
<lang rexx>/*REXX program to implement a simple "readline" shell. */ |
|||
trace off /*suppress echoing of non-zero RC*/ |
|||
signal on syntax; signal on novalue /*handle REXX program errors. */ |
|||
cmds1='? DIR CALendar HISTory Kedit LLL PROMPT Quit Rexx REDO Type' |
|||
cmds2='?|Help DIR CALendar HISTory Kedit LLL PROMPT Quit Rexx REDO Type' |
|||
cls='CLS' /*define the pgm to clear screen.*/ |
|||
@hist.='*** command not defined. ***' /*initialize the history database*/ |
|||
hist#=0 /*number of commands in history. */ |
|||
prompt='Enter one of:' cmds1 /*the default PROMPT message. */ |
|||
sw=linesize() /*some REXX don't have this BIF. */ |
|||
call .CLS /*start with a clean slate. */ |
|||
redoing=0 |
|||
do forever |
|||
call prompter; if xxx=='' then iterate |
|||
select /*now then, let's rock & roll. */ |
|||
when xxxF=='CAL' then call .cal |
|||
when xxxF=='CLS' then call .cls |
|||
when xxxF=='DIR' then call .dir |
|||
when xxxF=='HISTORY' then call .history |
|||
when xxxF=='HELP' then call .help |
|||
when xxxF=='KEDIT' then call .kedit |
|||
when xxxF=='LLL' then call .lll |
|||
when xxxF=='PROMPT' then call .prompt |
|||
when xxxF=='QUIT' then leave |
|||
when xxxF=='REDO' then call .redo |
|||
when xxxF=='REXX' then call .rexx |
|||
when xxxF=='TYPE' then call .type |
|||
otherwise say 'unknown command:' xxx yyy /*oops-say.*/ |
|||
end /*select*/ |
|||
end /*forever*/ |
|||
say 'Quitting...' /*say goodbye, 'cause it's polite*/ |
|||
exit /*stick a fork in it, we're done.*/ |
|||
/*───────────────────────────────error handling subroutines and others.─*/ |
|||
er: say; say arg(1); say; return |
|||
err: say; say; say center(' error! ',max(40,linesize()%2),"*"); say |
|||
do j=1 for arg(); say arg(j); say; end; say; exit 13 |
|||
novalue: syntax: call err 'REXX program' condition('C') "error",, |
|||
condition('D'),'REXX source statement (line' sigl"):",, |
|||
sourceline(sigl) |
|||
/*──────────────────────────────────.CAL subroutine─────────────────────*/ |
|||
.cal: 'CAL' yyy; return |
|||
/*──────────────────────────────────.CLS subroutine─────────────────────*/ |
|||
.cls: cls; return |
|||
/*──────────────────────────────────.DIR subroutine─────────────────────*/ |
|||
.dir: 'DIR' yyy; return |
|||
/*──────────────────────────────────.HELP subroutine────────────────────*/ |
|||
.help: say center(strip(xxx yyy),sw-1,'-'); cmds_=cmds2 |
|||
cmdsH='CLS DIR TYPE' |
|||
help. = ' No help is available for the' yyy "command." |
|||
help.cal = 'shows a calendar for the current month or specified month.' |
|||
help.kedit = 'KEDITs the file specified.' |
|||
help.lll = 'shows a formatted listing of files in the current directory.' |
|||
help.prompt= 'sets the PROMPT message to the specified text.' |
|||
help.q = 'exits this program.' |
|||
help.redo = 're-does the a command # specified (or the last command).' |
|||
help.rexx = 'executes the REXX program specified.' |
|||
yyyF=unabbrev(yyy) |
|||
if yyy=='' then do j=1 while cmds_\=='' |
|||
parse var cmds_ x cmds_ |
|||
say left('',sw%2) changestr('|',x," | ") |
|||
end |
|||
else select |
|||
when wordpos(yyyF,cmdsH)\==0 then yyyF '/?' |
|||
otherwise cmd?=yyyF |
|||
if left(help.yyyF,1)\==' ' then say yyyF ' ' help.yyyF |
|||
else day help.yyyF |
|||
end |
|||
return |
|||
/*──────────────────────────────────.HISTORY subroutine─────────────────*/ |
|||
.history: say center('history',sw-1,'-'); w=length(hist#) |
|||
do j=1 for hist# |
|||
say right(j,w) '===>' @hist.j |
|||
end |
|||
return |
|||
/*──────────────────────────────────.KEDIT subroutine───────────────────*/ |
|||
.kedit: 'KEDIT' yyy; return |
|||
/*──────────────────────────────────.LLL subroutine─────────────────────*/ |
|||
.lll: 'LLL' yyy; return |
|||
/*──────────────────────────────────PROMPTER subroutine─────────────────*/ |
|||
prompter: if redoing then do /*special case for naked REDO */ |
|||
redoing=0; z=hist#-1 |
|||
parse var @hist.z xxx yyy |
|||
end |
|||
else do |
|||
if prompt\=='' then do; say; say prompt; end |
|||
parse pull xxx yyy |
|||
end |
|||
xxxU=xxx; upper xxxU; if xxx=='' then return |
|||
yyyU=yyy; upper yyyU; yyyU=strip(yyyU) |
|||
hist#=hist#+1; /*bump the history counter. */ |
|||
@hist.hist#=strip(xxx yyy) /*assign to history. */ |
|||
xxxF=unAbbrev(xxx) /*expand the abbreviation (maybe)*/ |
|||
return |
|||
/*──────────────────────────────────.PROMPT subroutine──────────────────*/ |
|||
.prompt: if yyyU\=='' then prompt=yyy; return |
|||
/*──────────────────────────────────.redo subroutine────────────────────*/ |
|||
.redo: |
|||
select |
|||
when yyyU=='' then redoing=1 /*assume they want the last cmd. */ |
|||
when words(yyy)\==1 then call er 'too many args specified for' xxx |
|||
when \datatype(yyy,'W') then call er "2nd arg isn't numeric for" xxx |
|||
otherwise nop |
|||
end |
|||
if redoing then return /*handle with kid gloves. */ |
|||
yyy=yyy/1 /*normalize it: +7 7. 1e1 007 7.0*/ |
|||
say 'Re-doing:' @hist.yyy |
|||
@hist.yyy |
|||
return |
|||
/*──────────────────────────────────.REXX subroutine────────────────────*/ |
|||
.rexx: 'REXX' yyy; return |
|||
/*──────────────────────────────────.TYPE subroutine────────────────────*/ |
|||
.type: 'TYPE' yyy; return |
|||
/*──────────────────────────────────UNABBREV subroutine─────────────────*/ |
|||
unabbrev: procedure; arg ccc |
|||
select |
|||
when abbrev('CALENDAR',ccc,3) then return 'CAL' |
|||
when abbrev('CLEARSCREEN',ccc,5) |, |
|||
ccc='CLS' then return 'CLS' |
|||
when abbrev('HISTORY',ccc,4) then return 'HISTORY' |
|||
when abbrev('HELP',ccc,1) |, |
|||
ccc=='?' then return 'HELP' |
|||
when abbrev('KEDIT',ccc,1) then return 'KEDIT' |
|||
when ccc=='PROMPT' then return 'PROMPT' |
|||
when abbrev('QUIT',ccc,1) then return 'QUIT' |
|||
when abbrev('REXX',ccc,1) then return 'REXX' |
|||
when abbrev('TYPE',ccc,1) then return 'TYPE' |
|||
otherwise nop |
|||
end |
|||
return ccc</lang> |