.TITLE CLE - Command Line Editor .IDENT /1.03/ .NLIST BEX ; Description: CLE is an interactive command line editor for RSX, developed ; and tested under M+ V2.1. It works with MCR, DCL, and CCL. ; With CLE, the user is able to edit his command line before or ; even after dispatching the CLI and it "remembers" the last ; several commands which can be recalled, edited, and resubmitted ; as well. CLE key definitions are described below. ; ; Command edit functions Command recall functions ; ; LEFTARROW backup 1 character UPARROW backup 1 command ; RIGHTARROW advance 1 character DOWNARROW advance 1 command ; GOLD_LEFT backup to begin of cmd GOLD_UP backup to oldest cmd ; GOLD_RIGHT advance to end of command GOLD_DOWN advance to newest cmd ; DELETE delete 1 character left PF3 recall last command ; ^D delete 1 char at cursor PF4 show all commands ; ^B delete to begin of cmd ; ^E delete to end of command PF1 GOLD ; ^R redisplay command PF2 help ; ^U cancel command ^Z exit CLE ; ; Author: Steven L. Jobes, Mayo Foundation ; January, 1986 ; ; Credits: CLE was inspired by a task submitted to the DECUS library by ; F. Kuster of Zurich, Switzerland, who credits D. Sponza with the ; first idea. ; ; Disclaimer: * * * * * * * * * * * * * * * * * * * * * * ; This software is provided free of charge by Mayo Foundation. It ; is supplied on an "as-is" basis without warranty, express or ; implied, of any nature whatsoever. Neither the author nor Mayo ; Foundation shall bear any responsibility or liability for errors ; in this software or its documentation or for any loss or damage ; resulting from its use. Use of this software shall indicate its ; acceptance by the user according to these terms and the user ; hereby acknowledges that any statement or representation to the ; contrary is null and void. ; * * * * * * * * * * * * * * * * * * * * * * ; ; Notes: 1. If a character is inserted or deleted to the left of a ; horizontal tab ("011) or if a tab is inserted to the left of ; any character, the command line will be displayed improperly. ; can be used to redisplay the command line. ; 2. CLE must wait for completion. So pressing while a ; command is executing will generate a CLI prompt, not a CLE ; prompt. Naturally, the command entered at the CLI prompt can ; not be edited. ; ; Registers: R0 Scratch ; R1 Cursor (CURS) position in CMD ; R2 Left-most unused (LMUU) position in CMD ; R3 Scratch ; R4 Addr of oldest command in FIFO ; R5 Addr of next command in FIFO .PAGE CMDL = 78. ;Command line bufr length FIFOL = 300. ;FIFO bufr length B.BYE = 1 ;Set if logging off B.GOLD = 2 ;Set if GOLD on B.ATT = 4 ;Set if attached F.REV = -4 ;FIFO reverse link offset F.FOR = -2 ;FIFO forward link offset .MCALL DIR$,EXIT$S,GCII$,QIOW$,QIOW$S,SPWN$,STSE$S .MCALL JEQ,JHIS,POP,PUSH .MCALL .PCODE,.PDATA,.IDATA .MACRO QIO A,L ;QIO addr[,len] MOV A,WRTDPB+Q.IOPL .iif nb MOV L,WRTDPB+Q.IOPL+2 DIR$ #WRTDPB .ENDM .PDATA ATTDPB: QIOW$ IO.ATT,5,1 ;Attach DPB DETDPB: QIOW$ IO.DET,5,1 ;Detach DPB GCIDPB: GCII$ CII,4 ;GCII DPB RDDPB: QIOW$ IO.RST!TF.RNE,5,1,,IOSB,, ;Read DPB .IDATA SPNDPB: SPWN$ CLI...,,,,,1,,,CMD ;Spawn DPB WRTDPB: QIOW$ IO.CCO,5,1,,,,<,,0> ;Write DPB .PCODE START: QIOW$S #SF.GMC,#5,#1,,,,<#SCP,#2> ;Get characteristics TSTB SCP+1 ;Is it a CRT ? JEQ EXIT ;No MOV #FIFO+4,R5 ;Init next cmd pointer CLR LCPT ;Init last cmd pointer CLR CCPT ;Init current cmd pointer MOV R5,R4 ;Init TOP pointer CLRB STAT ;Init status PROMPT: QIO #PTXT,#3 ;Prompt user MOV #CMD,R1 ;CURS pointer MOV R1,R2 ;LMUU pointer BITB #B.ATT,STAT ;Attached ? BNE NEXT ;Yes DIR$ #ATTDPB ;Attach TI: BISB #B.ATT,STAT ;Attached NEXT: BICB #B.GOLD,STAT ;Clear GOLD on indicator NEXT1: DIR$ #RDDPB ;Read 1 character MOVB IOSB+1,R0 ; BIC #177600,R0 ;7-bit ASCII CMPB R0,#177 ; ? BEQ DEL1LF ;Yes BIC #177740,R0 ;Calc offset into jump table ASL R0 ; JMP @CTABL(R0) ;Jump accordingly HORTAB: MOVB #11,ICH ;ASCII horz tab ;Fall through INSERT: CMP R2,#CMD+CMDL ;End of bufr ? JHIS BEEP ;Yes CMP R1,#CMD ;New line ? BNE 1$ ;No CMPB ICH,#40 ;Space ? BEQ NEXT ;Yes CMPB ICH,#11 ;Horz tab ? BEQ NEXT ;Yes 1$: MOV R2,R3 ;Calc chars to shift SUB R1,R3 ; BEQ 3$ ;None MOV R2,R0 ;Shift right 2$: MOVB -(R0),1(R0) ; SOB R3,2$ ; 3$: MOVB ICH,(R1) ;Insert character INC R2 ;LMUU pointer JSR PC,UPDT ;Display EOL INC R1 ;CURS pointer DEC R3 ;Places to backspace BEQ NEXT ;None JSR PC,BKSP ;Position cursor BR NEXT ;Next character RETYPE: QIO #CTRLR,#2 ; QIO #PTXT,#3 ;Prompt MOV #CMD,R1 ;CURS pointer JMP G.RARW ; CANCEL: QIO #CTRLU,#2 ; BR PROMPT ;Prompt DEL1LF: CMP R1,#CMD ;Begin of bufr ? BEQ NEXT ;Yes DEC R1 ;CURS pointer MOV #1,R3 ;Backspace 1 place JSR PC,BKSP ;Position cursor ;Fall through DEL1AC: MOVB #40,(R2) ;Space at end MOV R2,R3 ;Calc chars to shift SUB R1,R3 ; BEQ NEXT ;None MOV R1,R0 ;Shift left 1$: MOVB 1(R0),(R0)+ ; SOB R3,1$ ; JSR PC,UPDT ;Display EOL JSR PC,BKSP ;Reposition cursor DEC R2 ;LMUU pointer BR NEXT ;Next character DELBOL: MOV R1,R3 ;Calc chars to delete SUB #CMD,R3 ; BEQ NEXT ;None PUSH R3 ;Remember 1$: MOVB #40,(R2)+ ;Append spaces SOB R3,1$ ; QIO #PTXT+1,#2 ;Reprompt JSR PC,UPDT ;Display EOL JSR PC,BKSP ;Reposition cursor MOV #CMD,R0 ;Shift left 2$: MOVB (R1)+,(R0)+ ; SOB R3,2$ ; MOV #CMD,R1 ;CURS pointer ASL (SP) ;LMUU pointer SUB (SP)+,R2 ; JMP NEXT ;Next character DELEOL: MOV R2,R3 ;Calc chars to delete SUB R1,R3 ; JEQ NEXT ;None MOV R1,R2 ;Overlay with spaces 1$: MOVB #40,(R2)+ ; SOB R3,1$ ; JSR PC,UPDT ;Display EOL JSR PC,BKSP ;Reposition cursor MOV R1,R2 ;LMUU pointer JMP NEXT ;Next character ESCAPE: DIR$ #RDDPB ;Read next byte CMPB ICH,#'[ ;"[" ? BEQ 1$ ;Yes CMPB ICH,#'O ;"O" ? BEQ 1$ ;Yes CMPB IOSB+1,#33 ; ? JEQ EXECUT ;Yes JMP NEXT ;Dunno then 1$: DIR$ #RDDPB ;Read next byte MOVB ICH,R0 ; BIC #177740,R0 ;Calc offset into jump table ASL R0 ; JMP @ETABL(R0) ;Jump accordingly .enabl lsb DARW: BITB #B.GOLD,STAT ;GOLD on ? BNE G.DARW ;Yes MOV CCPT,R0 ;Cur cmd pointer BEQ BEEP ;Empty MOV F.FOR(R0),R0 ;Advance 1 cmd BEQ BEEP ;None BR 1$ ;Common code PF3: G.DARW: MOV LCPT,R0 ;Last cmd pointer BEQ BEEP ;Empty BR 1$ ;Common code UARW: BITB #B.GOLD,STAT ;GOLD on ? BNE G.UARW ;Yes MOV CCPT,R0 ;Cur cmd pointer BEQ BEEP ;Empty MOV F.REV(R0),R0 ;Back up 1 cmd BEQ BEEP ;None BR 1$ ;Common code G.UARW: TST LCPT ;Empty ? BEQ BEEP ;Yes MOV R4,R0 ;TOP pointer 1$: MOV R0,CCPT ;Cur cmd pointer QIO #PTXT,#3 ;Prompt MOV #CMD,R1 ;Addr CMD bufr MOV R1,R2 ; 2$: MOVB (R0)+,(R2)+ ;Load CMD with FIFO cmd BNE 2$ ; DEC R2 ;Drop zero byte JSR PC,UPDT ;Display EOL MOV R2,R1 ;CURS pointer JMP NEXT ;Next character .dsabl lsb BEEP: QIO #DING,#1 ;Ring the bell JMP NEXT ; RARW: BITB #B.GOLD,STAT ;GOLD on ? BNE G.RARW ;Yes CMP R1,R2 ;At end ? JEQ NEXT ;Yes QIO R1,#1 ;Position cursor INC R1 ;CURS pointer JMP NEXT ; G.RARW: JSR PC,UPDT ;Display EOL MOV R2,R1 ;CURS pointer JMP NEXT ; LARW: BITB #B.GOLD,STAT ;GOLD on ? BNE G.LARW ;Yes CMP R1,#CMD ;At begin ? JEQ NEXT ;Yes DEC R1 ;CURS pointer MOV #1,R3 ;Backspace 1 place JSR PC,BKSP ;Position cursor JMP NEXT ; G.LARW: QIO #PTXT+1,#2 ;Reprompt MOV #CMD,R1 ;CURS pointer JMP NEXT ; PF1: BISB #B.GOLD,STAT ;GOLD on JMP NEXT1 ; PF2: DIR$ #DETDPB ;Detach TI: BICB #B.ATT,STAT ;Not attached MOV #HTXT,R0 ;Addr help cmd line MOV #CMD,R2 ;Addr cmd bufr 1$: MOVB (R0)+,(R2)+ ;Load bufr with cmd BNE 1$ ; QIO #PTXT+1,#1 ; SUB #CMD,R2 ;Calc length MOV R2,SPNDPB+S.PWCL ; DIR$ #SPNDPB ;Spawn to CLI STSE$S #1 ;Stop for CLI JMP PROMPT ; PF4: TST LCPT ;Empty ? BEQ BEEP ;Yes MOV R4,R0 ;TOP pointer 1$: QIO #PTXT,#2 ; MOV R0,R3 ;Find end of cmd 2$: TSTB (R3)+ ; BNE 2$ ; SUB R0,R3 ;Calc length QIO R0,R3 ;Display MOV F.FOR(R0),R0 ;Next forward BNE 1$ ; JMP PROMPT ; EXECUT: DIR$ #DETDPB ;Detach TI: BICB #B.ATT,STAT ;Not attached CMP R2,#CMD ;Anything ? JEQ PROMPT ;No MOV #CMD,R0 ;Addr cmd line MOV (R0)+,R3 ;Is it BYE ? BIC #120240,R3 ; CMP R3,#"BY ; BNE 1$ ;No MOVB (R0)+,R3 ;Maybe BIC #177640,R3 ; CMPB R3,#'E ; BNE 5$ ;No DIR$ #GCIDPB ;Get CLI name CMP CII,#^RMCR ;Is it MCR ? BNE 5$ ;No BR 2$ ; 1$: CMP R3,#"LO ;Is it LO ? BNE 5$ ;No DIR$ #GCIDPB ;Get CLI name CMP CII,#^RDCL ;Is it DCL ? BNE 5$ ;No 2$: BISB #B.BYE,STAT ; 5$: QIO #PTXT+1,#1 ; CLRB (R2) ;Terminate cmd SUB #CMD,R2 ;Calc length MOV R2,SPNDPB+S.PWCL ; DIR$ #SPNDPB ;Spawn to CLI BITB #B.BYE,STAT ;Logging off ? BNE EXIT ;Yes STSE$S #1 ;Stop for CLI MOV LCPT,R3 ;1st time ? BEQ 12$ ;Yes MOV R5,F.FOR(R3) ;Prev cmd's forward link CMP R5,R4 ;Is START > TOP ? BHI 12$ ;Yes, can't overrun MOV R5,R0 ;Start addr ADD R2,R0 ;Plus cmd length ADD #6,R0 ;Plus 4+2 BIC #1,R0 ;Or 4+1 to be even 11$: CMP R0,R4 ;Is END+1 <= TOP ? BLOS 12$ ;Yes, can't overrun MOV F.FOR(R4),R4 ;New TOP CLR F.REV(R4) ; CMP R5,R4 ;Is START <= TOP ? BLOS 11$ ;Yes, might overrun 12$: CLR F.FOR(R5) ;This cmd's forward link MOV R3,F.REV(R5) ;This cmd's reverse link MOV R5,LCPT ;Last cmd pointer MOV R5,CCPT ;Current cmd pointer MOV #CMD,R0 ;Addr cmd to copy 13$: MOVB (R0)+,(R5)+ ;Copy cmd to FIFO BNE 13$ ; BIT #1,R5 ;Even addr ? BEQ 14$ ;Yes CLRB (R5)+ ;Is now 14$: CMP R5,#FIFOV ;Overflow ? BLOS 15$ ;No MOV #FIFO,R5 ;Wrap around FIFO 15$: ADD #4,R5 ;Plus 4 for pointers JMP PROMPT ; EXIT: EXIT$S ;Exit to CLI ; UPDT to write & move cursor forward ; Input: R1 cursor position ; R2 left-most unused position ; Output: R1,R2 preserved ; R3 length of I/O ; UPDT: MOV R2,R3 ;Calc length SUB R1,R3 ; BEQ 1$ ;None QIO R1,R3 ;Display EOL 1$: RTS PC ; BKSP to backspace ; will reposition cursor if called following UPDT ; Input: R3 places to backspace ; Output: registers preserved ; BKSP: QIO #BS,R3 ;Reposition cursor RTS PC .PAGE .PDATA ; jump table ; CTABL: .WORD INSERT ;Single character .WORD NEXT ;^A .WORD DELBOL ;^B delete to begin of line .WORD NEXT ;^C .WORD DEL1AC ;^D delete 1 char at cursor .WORD DELEOL ;^E delete to end of line .WORD NEXT ;^F .WORD NEXT ;^G .WORD NEXT ;^H .WORD HORTAB ;^I horizontal tab .WORD NEXT ;^J .WORD NEXT ;^K .WORD NEXT ;^L .WORD EXECUT ;^M .WORD NEXT ;^N .WORD NEXT ;^O .WORD NEXT ;^P .WORD NEXT ;^Q .WORD RETYPE ;^R redisplay .WORD NEXT ;^S .WORD NEXT ;^T .WORD CANCEL ;^U cancel .WORD NEXT ;^V .WORD NEXT ;^W .WORD NEXT ;^X .WORD NEXT ;^Y .WORD EXIT ;^Z exit .WORD ESCAPE ;33 .WORD NEXT ;34 .WORD NEXT ;35 .WORD NEXT ;36 .WORD NEXT ;37 ; jump table ; ETABL: .WORD NEXT ; .WORD UARW ;A uparrow .WORD DARW ;B downarrow .WORD RARW ;C rightarrow .WORD LARW ;D leftarrow .WORD NEXT,NEXT,NEXT,NEXT ;E,F,G,H .WORD NEXT,NEXT,NEXT,NEXT ;I,J,K,L .WORD NEXT,NEXT,NEXT ;M,N,O .WORD PF1 ;P PF1 .WORD PF2 ;Q PF2 .WORD PF3 ;R PF3 .WORD PF4 ;S PF4 .WORD NEXT,NEXT,NEXT,NEXT ;T,U,V,W .WORD NEXT,NEXT,NEXT ;X,Y,Z .WORD NEXT,NEXT,NEXT,NEXT,NEXT ;33-37 .PAGE .IDATA ; Each command dispatched to the CLI is placed in FIFO, a first-in/first-out ; ring buffer with an overflow area. These are variable-length records, linked ; forward and reverse. CCPT is modified by uparrow, downarrow, PF1, & PF2. ; FIFO: .BLKB FIFOL ;FIFO bufr FIFOV: .BLKB CMDL+2/2*2+4 ;FIFO overflow CCPT: .WORD 0 ;Current cmd pointer LCPT: .WORD 0 ;Last cmd pointer SCP: .BYTE TC.SCP,0 ;GMC bufr CII: .BLKW 2 ;GCII bufr IOSB: .BLKW 2 ;I/O status block ICH: .BYTE 0 ;Input character STAT: .BYTE 0 ;Status byte CMD: .BLKB CMDL+2 ;Command line .EVEN .PDATA BS: .REPT CMDL ;Backspace bufr .BYTE 10 .ENDR PTXT: .ASCII <12><15>")" ;Prompt DING: .BYTE 7 ;Bell CTRLR: .ASCII "^R" ; CTRLU: .ASCII "^U" ; HTXT: .ASCII "HELP CLE" ;Help text .EVEN .END START