Skip to content

Commit

Permalink
v1.6.1
Browse files Browse the repository at this point in the history
  • Loading branch information
Bill-Stewart committed Nov 3, 2021
1 parent 0192aa4 commit 10d0228
Show file tree
Hide file tree
Showing 8 changed files with 148 additions and 115 deletions.
23 changes: 19 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,10 @@ https://github.com/Bill-Stewart/editenv/releases
| **--disallowchars=**... | **-D** ... | Disallows input of specified characters
| **--disallowquotes** | **-d** | Disallows input of `"` character
| **--emptyinputallowed** | **-e** | Empty input is allowed to remove variable
| **--getmaxlength** | | Outputs maximum possible input length
| **--help** | **-h** | Displays usage information
| **--minlength=**_n_ | **-n** _n_ | Input must be at least _n_ character(s)
| **--maxlength=**_n_ | **-x** _n_ | Input cannot be longer than _n_ character(s)
| **--maxlength=**_n_ | **-x** _n_ | Limit input length to _n_ character(s)
| **--maskinput**[**=**_x_] | **-m** _x_ | Masks input using character _x_ (default=`*`)
| **--overtypemode** | **-o** | Starts line editor in overtype mode
| **--prompt=**... | **-p** ... | Specifies an input prompt
Expand All @@ -48,7 +49,9 @@ https://github.com/Bill-Stewart/editenv/releases

* You cannot specify the **--minlength** (**-n**) parameter with either the **--emptyinputallowed** (**-e**) or **--timeout** (**-t**) parameters.

* An argument of `0` for **--maxlength** (**-x**) means "no maximum length" (up to maximum allowed length: See **Notes/Limitations** section, below).
* An argument of `0` for **--maxlength** (**-x**) means "maximum allowable length" (see **Notes/Limitations** section, below).

* The **--getmaxlength** parameter outputs the maximum possible input length (see **Maximum Input Length** section, below).

* It is recommended to specify parameters at the beginning of the command line (in any order) and the environment variable name at the end of the command line.

Expand Down Expand Up @@ -95,14 +98,22 @@ The `Enter` key does nothing if you use the **--minlength** (**-n**) parameter a

* In PowerShell, you can check the exit code using the `$LASTEXITCODE` variable.

## Maximum Input Length

The maximum possible number of input characters depends on whether the current session is a standard Windows console or a Windows Terminal (WT) console. A WT console is detected by the presence of the `WT_SESSION` environment variable.

* In a standard Windows console, the maximum possible number of input characters is the number of rows * the number of columns in the console buffer or 16383, whichever is less. The standard Windows console allows the cursor to move back past the top of the current screenful into the scrollback buffer, which means it is possible to edit an environment variable that has a value longer than will fit in the current screenful.

* In a WT console, the maximum possible number of inputt characters is the number of rows * the number of columns or 16383 (whichever is less) in the current screenful only. WT does not allow the cursor to move "backwards" past the top of the current screenful into the scrollback buffer, which means it is not possible to edit an environment variable that has a value longer than will fit in the current screenful. (You can work around this limitation in a WT session by expanding the WT window such that it has a larger number of rows and/or columns before running **editenv**).

* The **--getmaxlength** parameter outputs the maximum possible input length.

## Notes/Limitations

* The environment variable's name cannot contain the `=` character.

* The environment variable's name is limited to 127 characters.

* The environment variable's value is limited to 16383 characters.

* The **--timeout** (**-t**) parameter does not use a high-precision timer.

* The **--maskinput** (**-m**) parameter is not encrypted or secure.
Expand All @@ -113,6 +124,10 @@ The `Enter` key does nothing if you use the **--minlength** (**-n**) parameter a

* **editenv** does not work from the PowerShell ISE.

* **editenv** does not detect window size changes while it is running.

* The maximum possible input length depends on whether **editenv** is running in a standard Windows console or a Windows Terminal (WT) console (see the **Maximum Input Length** section, above).

## Examples

1. Edit the `Path` environment variable for the current console:
Expand Down
14 changes: 0 additions & 14 deletions build.cmd

This file was deleted.

102 changes: 75 additions & 27 deletions editenv.pp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
uses
getopts,
Windows,
wsWinConsole,
wsWinEnvVar,
wsWinLineEditor,
wsWinMessage,
Expand All @@ -47,6 +48,7 @@
Debug: Boolean; // --debug
DisallowChars: AnsiString; // --disallowchars and --disallowquotes
EmptyInputAllowed: Boolean; // --emptyinputallowed
GetMaxLength: Boolean; // --getmaxlength
Help: Boolean; // --help
MaxLength: Word; // --maxlength
MaskInput: Boolean; // --maskinput
Expand All @@ -57,6 +59,7 @@
Quiet: Boolean; // --quiet
Timeout: Word; // --timeout
EnvVarName: UnicodeString; // name of env var to edit
MaxWindowChars: LongInt; // maximum # of characters we can edit
function IsValidCharList(const S: AnsiString): boolean;
function LongIntToUnicodeString(const N: LongInt): UnicodeString;
function AnsiStringToLongInt(const S: AnsiString; var N: LongInt): Boolean;
Expand Down Expand Up @@ -91,10 +94,11 @@ procedure Usage();
WriteLn('--disallowchars=... -D ... Disallows input of specified characters');
WriteLn('--disallowquotes -d Disallows input of " character');
WriteLn('--emptyinputallowed -e Empty input is allowed to remove variable');
WriteLn('--getmaxlength Outputs maximum possible input length');
WriteLn('--help -h Displays usage information');
WriteLn('--maskinput[=x] -m x Masks input using character x (default=*)');
WriteLn('--minlength=n -n n Input must be at least n character(s)');
WriteLn('--maxlength=n -x n Input cannot be longer than n character(s)');
WriteLn('--maxlength=n -x n Limit input length to n character(s)');
WriteLn('--overtypemode -o Starts line editor in overtype mode');
WriteLn('--prompt=... -p ... Specifies an input prompt');
WriteLn('--quiet -q Suppresses error messages');
Expand Down Expand Up @@ -143,11 +147,12 @@ procedure Usage();
WriteLn();
WriteLn('* The environment variable''s name cannot contain the = character');
WriteLn('* The environment variable''s name is limited to ', MAX_ENVVAR_NAME_LENGTH, ' characters');
WriteLn('* The environment variable''s value is limited to ', MAX_ENVVAR_VALUE_LENGTH, ' characters');
WriteLn('* The --timeout (-t) parameter does not use a high-precision timer');
WriteLn('* The --maskinput (-m) parameter is not encrypted or secure');
WriteLn('* There is no visual indication of insert vs. overtype mode');
WriteLn('* Does not work from the PowerShell ISE');
WriteLn('* Window size changes are not detected while the program is running');
WriteLn('* Input length in Windows Terminal is limited to the current screen');
end;

function TCommandLine.IsValidCharList(const S: AnsiString): boolean;
Expand Down Expand Up @@ -184,7 +189,7 @@ function TCommandLine.AnsiStringToLongInt(const S: AnsiString; var N: LongInt):
// Parse the command line
procedure TCommandLine.Parse();
var
LongOpts: array[1..16] of TOption;
LongOpts: array[1..17] of TOption;
Opt: Char;
I, IntArg: LongInt;
begin
Expand Down Expand Up @@ -233,70 +238,77 @@ procedure TCommandLine.Parse();
Value := 'e';
end;
with LongOpts[7] do
begin
Name := 'getmaxlength';
Has_arg := No_Argument;
Flag := nil;
Value := #0;
end;
with LongOpts[8] do
begin
Name := 'help';
Has_arg := No_Argument;
Flag := nil;
Value := 'h';
end;
with LongOpts[8] do
with LongOpts[9] do
begin
// --limitlength (-l) deprecated in favor of --maxlength (-x)
Name := 'limitlength';
Has_arg := Required_Argument;
Flag := nil;
Value := 'l';
end;
with LongOpts[9] do
with LongOpts[10] do
begin
Name := 'maskinput';
Has_arg := Optional_Argument;
Flag := nil;
Value := 'm';
end;
with LongOpts[10] do
with LongOpts[11] do
begin
Name := 'maxlength';
Has_arg := Required_Argument;
Flag := nil;
Value := 'x';
end;
with LongOpts[11] do
with LongOpts[12] do
begin
Name := 'minlength';
Has_arg := Required_Argument;
Flag := nil;
Value := 'n';
end;
with LongOpts[12] do
with LongOpts[13] do
begin
Name := 'overtypemode';
Has_arg := No_Argument;
Flag := nil;
Value := 'o';
end;
with LongOpts[13] do
with LongOpts[14] do
begin
Name := 'prompt';
Has_arg := Required_Argument;
Flag := nil;
Value := 'p';
end;
with LongOpts[14] do
with LongOpts[15] do
begin
Name := 'quiet';
Has_arg := No_Argument;
Flag := nil;
Value := 'q';
end;
with LongOpts[15] do
with LongOpts[16] do
begin
Name := 'timeout';
Has_arg := Required_Argument;
Flag := nil;
Value := 't';
end;
with LongOpts[16] do
with LongOpts[17] do
begin
Name := '';
Has_arg := No_Argument;
Expand All @@ -310,6 +322,7 @@ procedure TCommandLine.Parse();
BeginningOfLine := false;
DisallowChars := '';
EmptyInputAllowed := false;
GetMaxLength := false;
Help := false;
MaxLength := 0;
MaskInput := false;
Expand All @@ -320,6 +333,7 @@ procedure TCommandLine.Parse();
Quiet := false;
Timeout := 0;
EnvVarName := '';
MaxWindowChars := 0;
OptErr := false; // no error outputs from getopts
repeat
Opt := GetLongOpts('a:bD:dehm::n:x:l:op:qt:', @LongOpts, I);
Expand Down Expand Up @@ -414,6 +428,7 @@ procedure TCommandLine.Parse();
begin
case LongOpts[I].Name of
'debug': Debug := true;
'getmaxlength': GetMaxLength := true;
end; //case
end;
'?':
Expand All @@ -425,17 +440,27 @@ procedure TCommandLine.Parse();
until Opt = EndOfOptions;
if ErrorCode <> 0 then
exit();
EnvVarName := StringToUnicodeString(ParamStr(OptInd), CP_ACP);
if EnvVarName = '' then
begin
ErrorCode := ERROR_INVALID_PARAMETER;
ErrorMessage := 'Environment variable name not specified';
exit();
// Get upper limit of number of characters we can edit; if running Windows
// Terminal, max # characters is what is visible in the viewport
// (https://github.com/microsoft/terminal/issues/10191#issuecomment-897345862)
if not IsWindowsTerminal() then
MaxWindowChars := GetConsoleRows() * GetConsoleCols()
else
MaxWindowChars := GetConsoleRowsViewport() * GetConsoleColsViewport();
MaxWindowChars := MaxWindowChars - Length(Prompt) - 1;
if MaxLength = 0 then
begin
if MaxWindowChars > MAX_ENVVAR_VALUE_LENGTH then
MaxLength := MAX_ENVVAR_VALUE_LENGTH
else
begin
MaxLength := MaxWindowChars;
end;
end;
if Pos('=', EnvVarName) > 0 then
if MaxLength > MaxWindowChars then
begin
ErrorCode := ERROR_INVALID_PARAMETER;
ErrorMessage := 'Environment variable name cannot contain = character';
ErrorCode := ERROR_INSUFFICIENT_BUFFER;
ErrorMessage := '--maxlength (-x) parameter cannot exceed ' + LongIntToUnicodeString(MaxWindowChars) + ' characters';
exit();
end;
if MinLength > 0 then
Expand All @@ -458,6 +483,21 @@ procedure TCommandLine.Parse();
exit();
end;
end;
if GetMaxLength then
exit();
EnvVarName := StringToUnicodeString(ParamStr(OptInd), CP_ACP);
if EnvVarName = '' then
begin
ErrorCode := ERROR_INVALID_PARAMETER;
ErrorMessage := 'Environment variable name not specified';
exit();
end;
if Pos('=', EnvVarName) > 0 then
begin
ErrorCode := ERROR_INVALID_PARAMETER;
ErrorMessage := 'Environment variable name cannot contain = character';
exit();
end;
if Length(EnvVarName) > MAX_ENVVAR_NAME_LENGTH then
begin
ErrorCode := ERROR_INSUFFICIENT_BUFFER;
Expand All @@ -477,10 +517,11 @@ function IsOSVersionNewEnough(): Boolean;
end;

begin
ExitCode := 0;

if (ParamCount = 0) or (ParamStr(1) = '/?') then
begin
Usage();
ExitCode := 0;
exit();
end;

Expand All @@ -498,6 +539,11 @@ function IsOSVersionNewEnough(): Boolean;
begin
Usage();
ExitCode := 0;
end;

if CommandLine.GetMaxLength then
begin
WriteLn(CommandLine.MaxLength);
exit();
end;

Expand Down Expand Up @@ -537,8 +583,9 @@ function IsOSVersionNewEnough(): Boolean;
exit();
end;

// fail if environment variable value is too long
VarValue := GetEnvVar(CommandLine.EnvVarName);

// fail if environment variable value is too long
if Length(VarValue) > MAX_ENVVAR_VALUE_LENGTH then
begin
ExitCode := ERROR_INSUFFICIENT_BUFFER;
Expand All @@ -556,9 +603,6 @@ function IsOSVersionNewEnough(): Boolean;
exit();
end;

if CommandLine.Prompt <> '' then
Write(CommandLine.Prompt);

// Create instance
Editor := TLineEditor.Create();

Expand All @@ -575,9 +619,10 @@ function IsOSVersionNewEnough(): Boolean;
Editor.Timeout := CommandLine.Timeout;

{$IFDEF DEBUG}
// Handy for viewing effects of code page differences
if CommandLine.Debug then
begin
WriteLn('MaxWindowChars [', CommandLine.MaxWindowChars, ']');
WriteLn('MaxLength [', CommandLine.MaxLength, ']');
if Editor.AllowedChars <> '' then
WriteLn('--allowedchars [', Editor.AllowedChars, ']');
if Editor.DisallowChars <> '' then
Expand All @@ -588,6 +633,9 @@ function IsOSVersionNewEnough(): Boolean;
end;
{$ENDIF}

if CommandLine.Prompt <> '' then
Write(CommandLine.Prompt);

// Start the editor
NewValue := Editor.EditLine(UnicodeStringToString(VarValue, CP_ACP));

Expand Down
8 changes: 4 additions & 4 deletions editenv.rc
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
1 VERSIONINFO
FILEVERSION 1,6,0,0
PRODUCTVERSION 1,6,0,0
FILEVERSION 1,6,1,0
PRODUCTVERSION 1,6,1,0
FILEOS 0x4
FILETYPE 1
{
Expand All @@ -10,12 +10,12 @@ FILETYPE 1
{
VALUE "CompanyName", "Bill Stewart (bstewart at iname.com)"
VALUE "FileDescription", "editenv.exe"
VALUE "FileVersion", "1.6.0.0"
VALUE "FileVersion", "1.6.1.0"
VALUE "InternalName", "editenv.exe"
VALUE "LegalCopyright", "(C) 2020-2021 by Bill Stewart (bstewart at iname.com)"
VALUE "OriginalFilename", "editenv.exe"
VALUE "ProductName", "editenv.exe"
VALUE "ProductVersion", "1.6.0.0"
VALUE "ProductVersion", "1.6.1.0"
}
}

Expand Down
Loading

0 comments on commit 10d0228

Please sign in to comment.