Charles Dye
Super Moderator
- May
- 5,334
- 161
Staff member
What features do you think are missing from TCC's command-line editor? What do you want to do with a keystroke that you can't do with a key alias?
By registering with us, you'll be able to discuss, share and private message with other members of our community.
SignUp Now!ON KEY LABEL F1 DO Show_Acct
ON KEY LABEL F4 DO Zoom
ON KEY LABEL F6 DO Report
EDIT NOORGANIZE
ON KEY LABEL F1
ON KEY LABEL F4
ON KEY LABEL F6
ON KEY LABEL F1 DO Show_Acct
ON KEY LABEL F4 DO Zoom
ON KEY LABEL F6 DO Report
input /k"[0-9]-()" Enter your phone number: %%var
ON KEY LABEL F1
ON KEY LABEL F4
ON KEY LABEL F6
v:\> help _inkey
waiting keystroke or 0 if none
unset string
do forever
set k=%_inkey
switch %k
case 0
delay /m 1
case @13
leave
case @59
echo you pressed F1
case @60
echo you pressed F2
default
set string=%[string]%k
endswitch
enddo
echo you entered %string
v:\> swinkey.btm
you pressed F1
you pressed F2
you entered 123456
Translated to TCC;
Code:ON KEY LABEL F1 DO Show_Acct ON KEY LABEL F4 DO Zoom ON KEY LABEL F6 DO Report input /k"[0-9]-()" Enter your phone number: %%var ON KEY LABEL F1 ON KEY LABEL F4 ON KEY LABEL F6
I used to have a key alias tied to Ctrl-L that would clear the screen (executing cls), as bash and most other CLIs in Unix do, but I ended up taking it out because it did not work if something had been typed into the command line already (producing stuff like "dir *.txt@cls").
It'd be nice to copy the Ctrl-L feature from the Unix CLI.
Does that work if you've done a cls/c right before? (also, does it work with prompt lines taller than one line?)
The only way I can think of to determine where the last prompt was issued is to use the POST_EXEC alias, which (I think) can be implemented in a plugin. Charles, can you think of another way?As for the multiline prompt, in this case all but the last line is scrolled out view. TCC reports the line where text entry begins, which is usually the last line of the prompt text. If there are multiple lines, I don't think there is any good way of distinguishing the prompt text from any other text which happens to be in the screen buffer.
Kind of a kludge, but easy to implement: Get the value of %PROMPT, and count instances of $_ .The only way I can think of to determine where the last prompt was issued is to use the POST_EXEC alias, which (I think) can be implemented in a plugin. Charles, can you think of another way?
There's wrapping too. There's enough stuff that can be put in the prompt to make it use many lines even without $_.Kind of a kludge, but easy to implement: Get the value of %PROMPT, and count instances of $_ .
INT WINAPI POST_EXEC (LPWSTR psz)
{
if ( g.hConOut != INVALID_HANDLE_VALUE )
{
CONSOLE_SCREEN_BUFFER_INFO csbi;
GetConsoleScreenBufferInfo(g.hConOut, &csbi);
g.nLastPromptRow = csbi.dwCursorPosition.Y + 1;
}
return 0;
}
else if ( !lstrcmp(lpki->pszKey, L"Ctrl-L") )
{
if ( g.hConOut != INVALID_HANDLE_VALUE )
{
CONSOLE_SCREEN_BUFFER_INFO csbi;
GetConsoleScreenBufferInfo(g.hConOut, &csbi);
INT nLinesToScroll = g.nLastPromptRow - csbi.srWindow.Top - 2;
while ( nLinesToScroll-- >= 0 )
{
SendMessage(g.hWndConsole, WM_VSCROLL, SB_LINEDOWN, NULL);
}
}
lpki->pszKey[0] = 0;
}
You can get rid of the error mentioned above by prefixing the alias with '^e". That will erase the command line in progress but it won't restore it.I used to have a key alias tied to Ctrl-L that would clear the screen (executing cls), as bash and most other CLIs in Unix do, but I ended up taking it out because it did not work if something had been typed into the command line already (producing stuff like "dir *.txt@cls").
It'd be nice to copy the Ctrl-L feature from the Unix CLI.
v:\> alias @@ctrl-l
^e@cls /s
ALIAS command - create new command names
To insure that a keystroke alias, esp. an autoexecute one, is on the command line by itself, use the character defined by the EraseLine key directive option (by default, the Esc key, represented as ^e) as the first character of the alias value.
^e[2J^e[H
will do it (not exactly in keeping with what the docs say).<ESC>exit<Return>
hardware-assigned to a key for as long as I can remember.@Charles Dye, you mentioned experimenting a bit with restoring a command line in progress. Did you have any success and, if so, can you give me any tips?
FWIW, barehandedly scrolling the console (as I did way above) isn't necessary. Issuing^e[2J^e[H
will do it (not exactly in keeping with what the docs say).
Yipes! Scrolling the console with SendMessage is a lot easier; it preserves anything in progress. The only problem with that is knowing the row on which the prompt begins. I decided my POST_EXEC alias was OTT. Idea ... I wonder if a static variable in the keyhandler itself could keep track of where the last prompt was issued (the keyhandler gets nKey = 0 and pszKey = NULL (or maybe it's "") when the prompt is issued.
Too many cryptic croswords from the Times (of London).OTT ?
INT WINAPI KEYHANDLER( LPKEYINFO lpki )
{
CONOUT con;
static INT nLastPromptRow;
if ( lpki->pszKey == nullptr && lpki->nKey == 0 )
{
con.GetInfo();
nLastPromptRow = con.csbi.dwCursorPosition.Y;
}
else if ( !lstrcmp(lpki->pszKey, L"Ctrl-L") )
{
con.GetInfo();
INT nRowsToScroll = nLastPromptRow - con.csbi.srWindow.Top - 1;
WCHAR sz[32];
wsprintf(sz, L"SCROLL v+%d", nRowsToScroll);
Command(sz, 0);
lpki->pszKey[0] = 0;
}
Too many cryptic croswords from the Times (of London).
Over The Top
INT WINAPI KEYHANDLER( LPKEYINFO lpki )
{
CONOUT con;
static INT nLastPromptRow;
if ( lpki->pszKey == nullptr && lpki->nKey == 0 )
{
con.GetInfo();
nLastPromptRow = con.csbi.dwCursorPosition.Y
}
e:\utils>editline.btm
This_is_a_test
┌───────────────────────────────┐
│ │
│ │
│ │
│ │
│ │
└───────────────────────────────┘
F4\utils>editline.btm
This_is_a_test_
July 2022
Su Mo Tu We Th Fr Sa
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
31
F5\utils>editline.btm
This_is_a_test_
:: _inkey is from 4UTILS plugin
:: Ref: https://jpsoft.com/forums/threads/_inkey-from-4utils.11225/post-63721
::
@setlocal
@echo off
set MaxInput=15
if defined theInput unset theInput
set InputRow=%_row
set InputColumn=0
:: I use Sysinternals DebugView to capture debugstring output.
:: (Ref: https://docs.microsoft.com/en-us/sysinternals/downloads/debugview)
debugstring %InputRow %InputColumn
Gosub EraseLine
do forever
set theKey=%_inkey
switch %theKey
case 0
delay /m 100
case @8
Gosub Backspace
case @9
::Tab
case @13
set theInput=%@replace[_, ,%theInput]
leave
case @27
Gosub EraseInput
case @32
Gosub Spacebar
case @62
Gosub F4
case @63
Gosub F5
case @71
::Home
case @72
::Up Arrow
case @73
::PageUp
case @75
::Left Arrow
case @77
::Right Arrow
case @79
::End
case @80
::Down Arrow
case @81
::Page Down
case @83
::Delete
default
set theInput=%theInput``%theKey
Gosub DisplayInput
endswitch
enddo
endlocal theInput
quit
:Backspace
set theLen=%@len[%theInput]
set theLen=%@dec[%theLen]
set theInput=%@left[%theLen,%theInput]
Gosub EraseLine
Gosub DisplayInput
Return
:DisplayInput
screen %InputRow %InputColumn %theInput
Return
:DrawBox
set bl=%@eval[%InputRow-2]
set tl=%@eval[%bl-6]
set tr=%@eval[%tl+6]
set br=%@eval[(%InputRow-2)+6]
debugstring bl=%bl tl=%tl tr=%tr br=%br
drawbox %tl 0 %bl %br 1 bri whi on blu fill blu
Return
:EraseInput
set theInput=``
Gosub EraseLine
Return
:EraseLine
screen %InputRow %InputColumn %@repeat[%@char[95],%MaxInput]
screen %InputRow %InputColumn``_
Return
:F4
set PrevRow=%_row
set PrevColumn=%_column
scrput %@eval[%InputRow-1] %InputColumn bri whi on blu F4
Gosub DrawBox
screen %PrevRow %PrevColumn``
Return
:F5
set PrevRow=%_row
set PrevColumn=%_column
scrput %@eval[%InputRow-1] %InputColumn bri whi on blu F5
screen %@eval[%InputRow-11] %InputColumn
:: qcal is from the ISO8601 Plugin
:: http://prospero.unm.edu/plugins/iso8601.html
qcal
screen %PrevRow %PrevColumn``
Return
:Spacebar
set theInput=%theInput`_`
Gosub DisplayInput
Return