1

I have built an app which receives text input from the user in a command prompt. And I would like to allow the user to select text and use that text instead of requiring the user to type it in.

In linux/bash this is achieved by calling "xsel" (a bash utility) which outputs the currently selected text which I then pipe to my python script. In windows it seems there isn't a simple solution... Any idea how do I get currently selected command line text in python/batch/powershell/external utility in Windows?

Thanks!

rubmz
  • 1,947
  • 5
  • 27
  • 49
  • The simple solution is `Read-Host`. It'll prompt the user for input. Assigning the input to a variable makes it easier to work with as well. `$var = Read-host -Prompt 'what ya want'`, the input is saved to `$var`. – Abraham Zinala Apr 26 '21 at 12:49
  • @AbrahamZinala will it be using the mouse? – rubmz Apr 26 '21 at 12:50
  • 2
    In the typical console.exe enable Quick Edit. That makes it much easier to select copy then paste. Which, when combined with Read-Host, I think is very close to the request. – Steven Apr 26 '21 at 12:52
  • No, you would have to make a selection to choose from. There is an option to use the arrow keys using `$host.ui` but, that's a little more difficult to understand coming from a different cli. – Abraham Zinala Apr 26 '21 at 12:53
  • You can run my script/function here: https://community.spiceworks.com/scripts/show/4908-delete-userprofile. It's a good example on how you can make a selection from sub directories in *C:\Users* which then, prompts you to delete a single, or multiple profiles. Same logic can be applied to a lot of other things – Abraham Zinala Apr 26 '21 at 12:55
  • 1
    Does this answer your question? [How to get the word under the cursor in Windows?](https://stackoverflow.com/questions/4665045/how-to-get-the-word-under-the-cursor-in-windows) – Simon Mourier Apr 26 '21 at 13:28
  • @SimonMourier It might just be, but it is in C# and it's not clear to me if the automation class used there will be available for a regular script (and not in a testing scenario)? – rubmz Apr 26 '21 at 15:04
  • Hey @Steven, looks interesting, but please could you elaborate? What is Read-Host ? is it a powershell command? and how does it work? – rubmz Apr 26 '21 at 15:07
  • UI Automation is the Windows API technology. Powershell supports inline C# or you can simply build an exe from C#. – Simon Mourier Apr 26 '21 at 15:14
  • Thanks, Steven. @SimonMourier, please see the footnote I've just added to my answer for why I think your proposed solution won't work in this particular scenario. – mklement0 Apr 26 '21 at 15:28

1 Answers1

1

Note: I'm assuming you're only interested in text selected in the current console window.

There is no perfect solution on Windows that I'm aware of[1], but you can approximate one, which, however, requires the user's cooperation, in the form right-clicking after making a selection.

The solution below works in both regular console windows (conhost.exe) and Windows Terminal:

  • In regular console windows, "Quick Edit" mode should be enabled, so as to allow direct selection of text with the mouse.

  • To make the solution work, the user must copy the selection to the clipboard, which later allows you to retrieve the clipboard's content if no direct input was supplied. This is easily achieve by right-clicking (anywhere inside the window) after making a selection, which the prompt message must instruct the user to do.

Here's an example:

# Since the selection can only be obtained via the clipboard and we don't want preexisting
# clipboard content to interfere with the operation, we clear the clipboard first.
Set-Clipboard '' 

# Define the prompt string to use with Read-Host containing instructions.
$prompt = @'
Enter a value and press Enter 
 - OR -
Select a string in this console window, RIGHT-CLICK and then press Enter
'@

# Prompt for user input until it is non-blank, either by direct input or via the selection.
do {
  $userInput = Read-Host $prompt
  if (-not $userInput) { # No direct input, try to get the selection from the clipboard.
    $userInput = Get-Clipboard
  }
} while (-not $userInput.Trim())

Write-Verbose -Verbose @"
You entered or selected:

  «$userInput»

"@

[1] While (non-PowerShell-friendly) techniques exist in principle to query a Windows console's selection (involving the - "softly" deprecated - GetConsoleSelectionInfo WinAPI function), or, more generally the cross-application Windows Accessibility API that allows "spying on" UIs, as shown in this answer), these techniques cannot be used by code that directly, synchronously executes in the console window itself, because typing or submitting a command invariably involves automatic clearing of the selection before returning control to the shell / a running porgram. In regular console windows - but not in Windows Terminal - the first Enter keypress after having made a selection actually copies the selection to the clipboard and then clears the selection and returns control to the shell / running program, so that pressing Enter twice instead of right-clicking and then pressing Enter works too.
Terminals on macOS also clear the selection first.
By contrast, on Linux at least X-Window-based terminals retain the selection in this case (as verified with the Gnome Terminal that ships with Ubuntu 18.04), which, as your question suggests, can be combined with the (installable on demand) xsel utility to programmatically query the selection.

mklement0
  • 382,024
  • 64
  • 607
  • 775
  • Glad to hear it was helpful, @rubmz. The footnote I've added explains the challenges that prevent a better solution. There may be a way to overcome them, but it would require substantial effort. – mklement0 Apr 26 '21 at 15:29
  • 1
    I am not looking for a perfect solution. Clearing the selection is a problem on Linux too, I guess in any terminal. But it's suffice for my application. Thanks again! This was a harder issue to tackle than I thought it would be :-) – rubmz Apr 26 '21 at 15:32
  • @rubmz, yeah, it seems like there should be a simpler solution. The only terminal that does _not_ clear the selection when the shell / a program running in the shell regains controls is the Gnome Terminal that comes with Ubuntu, so using `xsel` (must be installed on demand) indeed works there; my guess is that all X-Windows-based terminals behave this way. – mklement0 Apr 26 '21 at 15:59
  • 1
    @IInspectable, you left out half of that sentence: "_We do not recommend using this content in new products_, but we will continue to support existing usages for the indefinite future." The term _deprecation_ is ambiguous: it can either refer to functionality _that will be removed in a future version_ or to functionality _that isn't recommended for new projects anymore_ but will be kept for backward compatibility. An informal way to refer to the latter form of deprecation is to call it "soft", and I've updated the footnote accordingly. – mklement0 Apr 26 '21 at 16:04