2

My goal is to write a function which behaves similarily to what happens when invoking PsReadline's Ctrl-R functionality: insert text on the current command line, but don't accept the line, so that when the function returns the cursor is still on the same line. I tried the following

function Invoke-Foo() {
  [Microsoft.PowerShell.PSConsoleReadLine]::Insert('foo')
}

But when calling this, the result is:

PS> Invoke-Foo foo
PS> <cursor position>

What I want instead if that after inserting the text, the cursor stays on that line so

PS> Invoke-Foo foo<cursor position>

I looked into other PSConsoleReadLine functions (as I assume they are the way to go since PsReadline handles the console?) like AddLine/CancelLine/... but none of the combinations do the trick. What does work is calling the function as a PsReadline key handler using Set-PSReadlineKeyHandler -Key 'Ctrl+P' -ScriptBlock {Invoke-Foo} then hitting Ctrl-P does exactly what I want. So the question is probably: how to hook into PsReadline to mimic a function being called as it's key handler?

update Solution is fairly simple, thanks to Jason for the tip: just bind Enter, and don't accept the line if Invoke-Foo is being called

function DealWithEnterKey() {
  $line = $null
  $cursor = $null
  [Microsoft.PowerShell.PSConsoleReadline]::GetBufferState([ref]$line, [ref]$cursor)

  if($line -match 'Invoke-Foo') {
    Invoke-Foo
  } else {
    [Microsoft.PowerShell.PSConsoleReadLine]::AcceptLine()
  }
}

Set-PSReadlineKeyHandler -Key 'Enter' -ScriptBlock {DealWithEnterKey}
6
  • I'm not sure I understand the use case. Do you enter Invoke-Foo, hit Enter, and then want PowerShell to execute Invoke-Foo in such a way that the existing line becomes Invoke-Foo foo? What should happen if you hit Enter again -- do you get Invoke-Foo foo foo? It seems like a convoluted way to do custom argument completion, for which there are better solutions. Commented May 3, 2017 at 10:00
  • @JeroenMostert I kept the example as simple as possible, in practice I want to enter Invoke-Foo, PS executes it (which will call fzf.exe underneath allowing to select a directory or file) and the existing line becomes just the selected file/dir, so I can edit it further (e.g. insert 'cd' or 'cat' in front of it). So yes I could just use a function like Invoke-Foo -Command { cd $_ }, but since I saw Ctrl-R or any other PSReadLine keyhandler basically does what I want (edit commandline in-place) I thought maybe there's a way to have a function do that as well. Commented May 3, 2017 at 10:14
  • So you're really after a function that produces a new command line, ready for further editing, and it would be neat if it did that by replacing itself? Presumably you only care about the case where it exists on its own then? Because making cases like Copy-Item Invoke-Foo Invoke-Foo work would require altering the parser. Commented May 3, 2017 at 10:20
  • indeed, a new commandline which can be edited at will. Commented May 3, 2017 at 10:22
  • Seems very hard. The problem is not simply mimicking a key handler, because your function is actually already parsed and being executed. You're asking for a PowerShell function to manipulate the input buffer of a prompt that doesn't exist yet. If this is possible at all, it'll require some nasty groveling in internals. ...how was this better than setting a key handler again? Do you enjoy typing that much? :-) Commented May 3, 2017 at 10:33

1 Answer 1

1

You'll need to either use a custom key handler or simulate keyboard input I think.

I suggest rebinding Enter. If the command line matches your command, run your command and replace the command line. If not, just call the normal handler for Enter.

Sign up to request clarification or add additional context in comments.

3 Comments

Might work indeed; did you try it and/or do you have sample code?
Look at SamplePSReadlineProfile.ps1 in your PSReadline module directory or on GitHub. I included different samples that cover your scenario, look for AcceptLine and GetBufferState to give you some ideas.
Thanks, it was indeed as simple as rebinding Enter. And that SamplePSReadlineProfile was also a good read.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.