Whimusical
Whimusical

Reputation: 6629

Input with a default editable string in a BAT by using Powershell

I'm getting mad trying to get an editable input in a BAT script, similar to read -i in bash.

I saw all sort of workarounds but I found them too complicated or long or dependant of other files/non-native resources.

Is there any way to use powershell inside the bat in order to emulate an input with editable default string?

I found that this can be called from within a bat:

 powershell -Command "$input = read-host 'Enter Input: '"

Upvotes: 0

Views: 2706

Answers (3)

MC ND
MC ND

Reputation: 70923

Following the original idea from Aacini. I've not tested it under all the posible scenarios, but seems to work.

EDITED - Code updated to detect Ctrl+C key press while editing the line. Call to the subroutine returns error level to signal it.

@if (@this == @isBatch) @then
@echo off

    setlocal enableextensions

    call :prefilledSet/P data "Edit this:" "This is the data that must be edited"
    if not errorlevel 1 (
        echo(Data retrieved: [%data%]
    ) else (
        echo(
        echo( ---- Input has been canceled
    )

    endlocal
    exit /B

:prefilledSet/P variable "Prompt" "Prefill value"
    setlocal enableextensions disabledelayedexpansion
    set "line=" 
    <nul set /p "v=%~2"
    for /f "delims=" %%a in ('cscript //nologo //e:jscript "%~f0" "%~3"'
    ) do if not defined line ( set "line=%%a" & set "exitCode=0"
    ) else if "%%a"=="ERROR" ( set "line="    & set "exitCode=1" )
    endlocal & set "%~1=%line%" & exit /b %exitCode%

@end
    WScript.CreateObject("WScript.Shell").SendKeys(WScript.Arguments(0));
    try { 
        WScript.StdOut.WriteLine( WScript.StdIn.ReadLine() );
    } catch (e) { 
        WScript.StdOut.WriteLine('ERROR\r\nERROR'); WScript.Quit(1) 
    };

EDITED - Just to add another option. But sorry, not directly batch code. If you have the option to compile a simple tool (tested with mingw gcc compiler), this c code

#define  _WIN32_WINNT 0x0500
#include "windows.h"

int main(int argc, char **argv){

    HWND hWnd = NULL;
    int  i;

    if (argc < 2) return 1 ;
    hWnd = GetConsoleWindow();

    for (i=0;i<strlen(argv[1]);i++){ 
        PostMessage(hWnd, WM_CHAR, argv[1][i], 0);
    };

    return 0;
}

when compiled will generate a command line tool that will send the text given as first argument to the current console. So, it can be used as (ex. compiled as typetext.exe)

typetext.exe "this is the text to edit" & set /p "var=edit this text:"

As the text is directly sent to the console in where the tool is running, there is no interference with other window being active while this executes.

Upvotes: 0

Aacini
Aacini

Reputation: 67216

The solution below is a Batch-JScript hybrid script that uses SendKeys in order to fill the command-line input buffer with the default value, so the user may use the standard edition keys to edit it when the set /P command is executed. However, this method have the inconvenience that the filling of the buffer will always appear in the screen, so it must be cleared before the user enter the data. I am working trying to solve this point.

EDIT: After read MC ND's answer I realized that it is not necessary to prefill the input buffer before the actual input, because characters just entered may also be edited in the same way; this point leads to a much simpler solution.

The method below just prefill the input with an editable string; it does not try to modify the original set /P command behavior in any way.

@if (@CodeSection == @Batch) @then

@echo off
rem Enter the prefill value
CScript //nologo //E:JScript "%~F0" "Prefill value"
rem Read the variable
set /P "var=Prompt: "
echo var=%var%
goto :EOF

@end

WScript.CreateObject("WScript.Shell").SendKeys(WScript.Arguments(0));

For further details, see this post.

Upvotes: 1

Bill_Stewart
Bill_Stewart

Reputation: 24545

set /p INPUTSTRING=Enter Input:

Note that this does not let you edit a pre-existing variable. To do that requires a different program. My own program editv32.exe/editv64.exe lets you do this:

set INPUTSTRING=Test string
editv32 -p "Enter input: " INPUTSTRING

This will present the "Enter input:" prompt following by the existing content of the INPUTSTRING variable, which you can edit.

Download is here: http://www.westmesatech.com/editv.html

Unrestricted copyrighted freeware.

Upvotes: 2

Related Questions