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>