CMDLINE.CMD
[Autolink] Menu
/* BEGINNING OF CmdLine CODE BY ALBERT CROSBY */
/* */
/* */
/* CmdLine.CMD Version 1.0 */
/* (c) 1994 by Albert Crosby <acrosby@comp.uark.edu> */
/* */
/* This code may be distributed freely and used in other programs.*/
/* Please give credit where credit is due. */
/* */
/* CmdLine.CMD is REXX code that creates a full featured version */
/* of the OS/2 command line parser that may be called from your */
/* programs. */
/* */
/* see also the Documentation */
/* */
/* bug corrections by Bernd Schemmer */
/* */
/* 03.10.1994 /bs */
/* - changed variable "key" to "key1" */
/* - added variable "userDefinedKey" */
/* 24.06.1995 /bs */
/* - added code to save the and load the history list */
/* - added code to show an online help */
/* 08.01.1996 /bs */
/* - added code to handle dropping of REXXUTIL functions */
/* */
/* */
/* This is a CmdLine function for REXX. It supports */
/* * OS/2 style command history. (1) */
/* * Keeps insert state. (1) */
/* * Command line _can_ include control chars. */
/* * Allows for "hidden" input, for passwords. */
/* * A call can be restricted from accessing the history. */
/* * A call can be restricted from updating the history. */
/* * A predefined value can be given to extended keys. (1) (2) */
/* */
/* NOTE */
/* (1) These functions work ONLY if CmdLine is included in the source */
/* file for your program. */
/* (2) Format: !history.nn="string" where nn is the DECIMAL */
/* value for the second character returned when the extended */
/* key is pressed. */
/* */
/* The following two lines are used in case CmdLine is called as an */
/* external function */
parse source . . name
if translate(filespec("name",name))="CMDLINE.CMD" then signal extproc
CmdLine: procedure expose !history. !rexxUtilLoaded (exposeList)
extproc: /* CmdLine called as an external proc or command line */
/* Parameters can be any combination of */
/* Hidden Characters are displayed as "*", no history, */
/* not kept. */
/* Forget Do not add the result of this call to the */
/* history list. */
/* No History Do not allow access to the history list. */
/* Clear Clear the history list with this call (no input */
/* action made.) */
/* Also clears any predefined keys! */
/* Insert Set insert mode ON. */
/* Overwrite Set overwrite mode OFF. */
/* SameLine Keep cursor on sameline after input. */
/* (Default off) */
/* Required null values are not accepted. (Default off) */
/* Valid Next parameter specifies the valid charachters */
/* (no translation) unless specified elsewhere. (1)*/
/* Upper Translate input to upper case. (1) */
/* Lower Translate input to lower case. (1) */
/* Width Next parameter specifies the maximum width. (1) */
/* Autoskip Do not wait for enter after last char on a */
/* field with a width. */
/* X Next parameter specifies the initial X (column) */
/* position. */
/* Y Next parameter specifies the initial Y (row) */
/* position. */
/* Prompt Displays the next parameter as a prompt in front*/
/* of the entry field. */
/* */
/* Only the first letter matters. Enter each desired parameter */
/* seperated by commas. */
/* */
/* NOTES */
/* (1) Upper, Lower, Width, and VALID preclude access to the */
/* history list. */
/* */
/* */
hidden=0
history=1
keep=1
sameline=0
required=0
reset=0
valid=xrange()
upper=0
lower=0
width=0
autoskip=0
/* ------------------------ RXT&T v2.00 start ----------------------- */
/* install a local error handler */
signal on syntax Name cmdLineError
/* ------------------------ RXT&T v2.00 end ------------------------- */
/* ------------------------ RXT&T v1.70 start ----------------------- */
if symbol( "!history.file" ) <> "VAR" | ,
value( "!history.file" ) = "" then
!history.file = "EREXXTRY.HST"
/* ------------------------ RXT&T v1.70 end ------------------------- */
parse value SysCurPos() with x y
do i=1 to arg()
cmd=translate(left(arg(i),1))
parm=""
if pos("=",arg(i))\=0 then
parse value arg(i) with ."="parm
select
when cmd="X" then
do
parse value SysCurPos() with x y
if parm="" then
do;i=i+1;parm=arg(i);end
if datatype(parm,"W") then
Call SysCurPos parm,y
end
when cmd="Y" then
do
parse value SysCurPos() with x y
if parm="" then
do;i=i+1;parm=arg(i);end
if datatype(parm,"W") then
Call SysCurPos x,parm
end
when cmd="T" then
do
if parm="" then
do;i=i+1;parm=arg(i);end
call charout, parm
end
when cmd="H" then
do
hidden=1
keep=0
history=0
end
when cmd="C" then
reset=1
when cmd="O" then
!history.insert=0
when cmd="I" then
!history.insert=1
when cmd="F" then
keep=0
when cmd="S" then
sameline=1
when cmd="R" then
required=1
when cmd="V" then
do
if parm="" then
do;i=i+1;parm=arg(i);end
valid=parm
history=0
keep=0
end
when cmd="U" then
do; upper=1; lower=0; history=0; keep=0; end
when cmd="L" then
do; upper=0; lower=1; history=0; keep=0; end
when cmd="A" then
autoskip=1
when cmd="W" then
do
if parm="" then
do;i=i+1;parm=arg(i);end
width=parm
if \datatype(width,"Whole") then width=0
if width<0 then width=0
history=0
keep=0
end
otherwise nop
end
end
if width=0 then autoskip=0
if reset then
do
drop !history.
return ""
end
if symbol("!history.0")="LIT" then
!history.0=0
if symbol("!history.insert")="LIT" then
!history.insert=1
historical=-1
key1=SysGetKey("NoEcho")
word=""
pos=0
do forever /* while key1\=d2c(13)*/
userDefinedkey=0
if key1=d2c(13) then /* Enter key */
if required & word="" then nop;
else leave
else if (key1=d2c(8)) then /* Backspace */
do
if length(word)>0 then
do
word=delstr(word,pos,1)
call rubout 1
pos=pos-1
if pos<length(word) then
do
if \hidden then call charout, substr(word,pos+1)||" "
else call charout, copies("*",length(substr(word,pos+1)))||" "
call charout, copies(d2c(8),length(word)-pos+1)
end
end
end
else if key1=d2c(27) then /* Escape */
do
if pos<length(word) then
if \hidden then call charout, substr(word,pos+1)
else call charout, copies("*",length(substr(word,pos+1)))
call rubout length(word)
word=""
pos=0
end
else if key1=d2c(10) | key1=d2c(9) then /* Ctrl-Enter and TAB */
nop; /* Ignored */
else if key1=d2c(224) | key1=d2c(0) then /* Extended key handler */
do
key2=SysGetKey("NoEcho")
select
/* ----------------------- RXT&T v1.70 start ------------------------ */
when key2=d2c( 94 ) then /* CTRL-F1 */
do
call ShowKeys
word = ''
pos = 0
userDefinedKey = 1
end /* when */
when key2=d2c( 60 ) then /* F2 */
do
/* save the history list */
call SLHist 'SAVE'
word = ''
pos = 0
userDefinedKey = 1
end /* when */
when key2=d2c( 85) then /* SHIFT-F2 */
do
/* load the history list */
call SLHist 'LOAD'
word = ''
pos = 0
userDefinedKey = 1
end /* when */
when key2=d2c( 105 ) then /* ALT-F2 */
do
/* append the history list */
call SLHist 'APPEND'
word = ''
pos = 0
userDefinedKey = 1
end /* when */
when key2=d2c( 95 ) then /* CTRL-F2 */
do
/* change the current history file */
call SLHist 'FILE'
word = ''
pos = 0
userDefinedKey = 1
end /* when */
when key2=d2c( 107 ) then /* ALT-F4 */
do
/* save the history list and exit */
/* (without a warning if the list is empty */
call SLHist 'SAVE', 'QUIET'
word = 'EXIT'
userdefinedkey = 1
end /* when */
/* ------------------------ RXT&T v1.70 end ------------------------- */
when key2=d2c(59) then /* F1 */
if (history) & (!history.0<>0) then
do
if symbol("search")="LIT" then
search=word
if symbol("LastFind")="LIT" then
search=word
else if LastFind\=word
then search=word
if historical=-1 then
start=!history.0
else start=historical-1
if start=0 then start=!history.0
found=0
do i=start to 1 by -1
if abbrev(!history.i,search) then
do
found=1
historical=i
LastFind=!history.i
leave
end
end
if found then
do
if pos<length(word) then
if \hidden then call charout, substr(word,pos+1)
else call charout, copies("*",length(substr(word,pos+1)))
call rubout length(word)
word=!history.historical
pos=length(word)
if \hidden then call charout, word
else call charout, copies("*",length(word))
end
end
when key2=d2c(72) then /* Up arrow */
if (history) & (!history.0<>0) then
do
if historical=-1 then
historical=!history.0
else historical=historical-1
if historical=0 then
historical=!history.0
if pos<length(word) then
if \hidden then call charout, substr(word,pos+1)
else call charout, copies("*",length(substr(word,pos+1)))
call rubout length(word)
word=!history.historical
pos=length(word)
if \hidden then call charout, word
else call charout, copies("*",length(word))
end
when key2=d2c(80) then /* Down arrow */
if (history) & (!history.0<>0) then
do
if historical=-1 then
historical=1
else historical=historical+1
if historical>!history.0 then
historical=1
if pos<length(word) then
if \hidden then call charout, substr(word,pos+1)
else call charout, copies("*",length(substr(word,pos+1)))
call rubout length(word)
word=!history.historical
pos=length(word)
if \hidden then call charout, word
else call charout, copies("*",length(word))
end
when key2=d2c(75) then /* Left arrow */
if pos>0 then
do
call Charout, d2c(8)
pos=pos-1
end
when key2=d2c(77) then /* Right arrow */
if pos<length(word) then
do
if \hidden then call Charout, substr(word,pos+1,1)
else call charout, "*"
pos=pos+1
end
when key2=d2c(115) then /* Ctrl-Left arrow */
if pos>0 then
do
call charout, d2c(8)
pos=pos-1
do forever
if pos=0 then leave
if substr(word,pos+1,1)\==" " & substr(word,pos,1)==" " then
leave
else
do
call charout, d2c(8)
pos=pos-1
end
end
end
when key2=d2c(116) then /* Ctrl-Right arrow */
if pos<length(word) then
do
if \hidden then call Charout, substr(word,pos+1,1)
else call charout, "*"
pos=pos+1
do forever
if pos=length(word) then
leave
if substr(word,pos,1)==" " & substr(word,pos+1,1)\==" " then
leave
else
do
if \hidden then call Charout, substr(word,pos+1,1)
else call charout, "*"
pos=pos+1
end
end
end
when key2=d2c(83) then /* Delete key */
if pos<length(word) then
do
word=delstr(word,pos+1,1)
if \hidden then call Charout, substr(word,pos+1)||" "
else call Charout, copies("*",length(substr(word,pos+1)))||" "
call charout, copies(d2c(8),length(word)-pos+1)
end
when key2=d2c(82) then /* Insert key */
!history.insert=\!history.insert
when key2=d2c(79) then /* End key */
if pos<length(word) then
do
if \hidden then call Charout, substr(word,pos+1)
else call Charout, copies("*",length(substr(word,pos+1)))
pos=length(word)
end
when key2=d2c(71) then /* Home key */
if pos\=0 then
do
call Charout, copies(d2c(8),pos)
pos=0
end
when key2=d2c(117) then /* Control-End key */
if pos<length(word) then
do
call Charout, copies(" ",length(word)-pos)
call Charout, copies(d2c(8),length(word)-pos)
word=left(word,pos)
end
when key2=d2c(119) then /* Control-Home key */
if pos>0 then
do
if pos<length(word) then
if \hidden then call charout, substr(word,pos+1)
else call charout, copies("*",length(substr(word,pos+1)))
call rubout length(word)
word=substr(word,pos+1)
if \hidden then call Charout, word
else call Charout, copies("*",length(word))
call Charout, copies(d2c(8),length(word))
pos=0
end
otherwise
if history & symbol("!history.key."||c2d(key2))\="LIT" then /* Is there a defined string? */
do
if pos<length(word) then
if \hidden then call charout, substr(word,pos+1)
else call charout, copies("*",length(substr(word,pos+1)))
call rubout length(word)
i=c2d(key2)
word=!history.key.i
pos=length(word)
if \hidden then call charout, word
else call charout, copies("*",length(word))
userDefinedkey=1
end
end
end
else if width=0 | length(word)<width then /* The key is a normal key & within width */
do
if upper then key1=translate(key1);
if lower then key1=translate(key1,"abcdefghijklmnopqrstuvwxyz","ABCDEFGHIJKLMNOPQRSTUVWXYZ")
if pos(key1,valid)\=0 then
do;
if \hidden then call Charout, key1;
else call charout, "*"
if !history.insert then
word=insert(key1,word,pos);
else word=overlay(key1,word,pos+1)
pos=pos+1;
if pos<length(word) then
do
if \hidden then
call Charout, substr(word,pos+1)
else call Charout, copies("*", length(substr(word,pos+1)))
call Charout, copies(d2c(8),length(word)-pos)
end
end
else beep(400,4)
end
if (autoskip & length(word)=width) | userDefinedKey then leave
key1=SysGetKey("NoEcho")
end
if \sameline then say
if (keep) & (word\=="") then
do
historical=!history.0
if word\=!history.historical then
do
!history.0=!history.0+1
historical=!history.0
!history.historical=word
end
end
return word
rubout: procedure
arg n
do i=1 to n
call Charout, d2c(8)||" "||d2c(8)
end
return
/* END OF CmdLine CODE BY ALBERT CROSBY */
/* ----------------------- RXT&T v1.70 start ------------------------ */
/* ------------------------------------------------------------------ */
/* Function: Save or Load the history list or change the name of the */
/* history file */
/* */
/* Usage: SLHist [SAVE|APPEND|LOAD|FILE], {QUIET} */
/* */
/* */
/* where: SAVE - save the history list to the history file */
/* (overwrite an existing file) */
/* APPEND - append the history list to the history file */
/* LOAD - load the histry list from the history file */
/* FILE - change the current history file */
/* */
/* QUIET - suppress all mesages */
/* This parameter is ignored, if the first */
/* parameter is FILE */
/* */
SLHist: PROCEDURE expose !history.
parse upper arg action, quietMode
SIGNAL OFF NOTREADY
crLF = "0D0A"x
select
when action = "FILE" then
do
call lineOut, crLF || "The current history file is " || !history.file || "." ,
crLF || "Enter the new name for the history file ("""" to abort):"
userInput = strip( lineIN() )
if userInput <> "" then
do
!History.file = userInput
call lineOut , "The history file is now " || !history.file || "."
end /* if userInput = "" then */
else
call lineOut, "History file not changed."
end /* when */
when !History.file = "" then
do
if quietMode <> "QUIET" then
call lineOut ,crLF || "No history file defined!"
end
when action = "SAVE" | action = "APPEND" then
do
if !history.0 = 0 then
do
if quietMode <> "QUIET" then
call LineOut , crLF || "Historylist is empty. No data saved."
end /* if !history.0 = 0 then */
else
do
if action = "SAVE" then
do
/* delete an existing history file */
if stream( !history.file, "c", "QUERY EXISTS" ) <> "" then
"@del " !history.file "2>NUL 1>NUL"
actionMsg = "Saving"
end /* if action = "SAVE" then */
else
actionmsg = "Appending"
if quietMode <> "QUIET" then
call CharOut , crLF || actionmsg || " the history list to the file" ,
crLF !history.file || " ..."
do i = 1 to !history.0
if quietMode <> "QUIET" then
call CharOut , "."
call lineOut !history.file, !history.i
end /* do i = 1 to history.0 */
/* close the file */
call stream !history.file, "c", "CLOSE"
if quietMode <> "QUIET" then
call lineOut, " done (" || i-1 || " commands written)."
end /* else */
end /* when */
when action = "LOAD" then
do
if stream( !history.file, "c", "QUERY EXISTS" ) = "" then
do
if quietMode <> "QUIET" then
call LineOut , crLF || "Historyfile " || ,
!history.file || " not found!"
end /* if stream( ... */
else
do
if quietMode <> "QUIET" then
call CharOut , crLF || "Loading the history list from the file" ,
crLF !history.file || " ..."
!history.0 = 0
do i=1 while lines( !history.file ) <> 0
if quietMode <> "QUIET" then
call CharOut , "."
!history.i = lineIn( !history.file )
end /* do i=1 while lines( !history.file ) <> 0 */
!history.0 = i-1
/* close the file */
call stream !history.file, "c", "CLOSE"
if quietMode <> "QUIET" then
call lineOut, "done (" || i-1 || " commands read)."
end /* else */
end /* when */
otherwise
do
if quietMode <> "QUIET" then
call lineOut,crLF || "Invalid call to SLHist!"
end /* otherwise */
end /* select */
RETURN 0
/* ------------------------------------------------------------------ */
/* Function: Show a usage help for the new keys */
/* */
/* Usage: ShowKeys */
/* */
/* where: - */
/* */
/* returns: - */
/* */
ShowKeys:
crLF = "0D0A"x
call LineOut ,,
crLF || ,
"Keys for editing the command line: " || crLF || ,
" [Up] Cycle to the previous entry in the history list" || crLF || ,
" [Down] Cycle to the next entry in the history list" || crLF || ,
" [Left] Move the cursor to the left" || crLF || ,
" [Right] Move the cursor to the right" || crLF || ,
" [ESC] Clear the input line" || crLF || ,
" [Home] Moves the cursor to the beginning of the input line" || crLF || ,
" [End] Moves the cursor to the end of the input line" || crLF || ,
" [^Home] Erases from the cursor to the beginning of the input line" || crLF || ,
" [^End] Erases from the cursor to the end of the input line" || crLF || ,
" [Ins] Toggles Insert/Typeover mode" || crLF || ,
" [Del] Deletes character under the cursor" || crLF || ,
" [Bkspc] Deletes the charcter in front of the cursor" || crLF || ,
" [^Left] Moves to the beginning of the previous word" || crLF || ,
" [^Right] Moves to the beginning of the next word" || crLF || ,
" " || crLF || ,
" [F2] Save the history list (overwrite an existing file)" || crLF || ,
" [ALT-F2] Save the history list (append to an existing file)" || crLF || ,
" [SHIFT-F2] Load the history list" || crLF || ,
" [CTRL-F2] Change the history list file" || crLF || ,
" [ALT-F4] Save history list and exit program"
RETURN
/* ------------------------ RXT&T v1.70 end ------------------------- */
/* ------------------------ RXT&T v2.00 start ----------------------- */
cmdLineError:
/* error handler for syntax error */
/* some program dropped the REXXUTIL function --- */
/* use old input routine again */
call LineOut , ""
call LineOut , "07"x || "Warning: Some program dropped the REXXUTIL functions!"
call LineOut , "07"x || " Now using the old input routine again."
call LineOut , ""
call LineOut , "Execute 'SIGNAL Restart' to load the functions again."
call LineOut , ""
!rexxUtilLoaded = 0
RETURN ""
/* ------------------------ RXT&T v2.00 end ------------------------- */
[Back: Extend the program REXXTRY.CMD]
[Next: Documentation for CMDLINE.CMD]