Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Make a keybinding to run previous or last shell commands

I frequently want to quickly re-run the last shell command that I used.

I know you can shift focus to the terminal, up arrow and enter but I thought there must be a better way than these three steps.

The sendSequence command in vscode is getting more powerful and so I looked for a way to create a keybinding that will run the last shell command quickly.

From sendSequence documentation:

Send text from a keybinding

The workbench.action.terminal.sendSequence command can be used to send a specific sequence of text to the terminal, including escape sequences. This enables things like sending arrow keys, enter, cursor moves, etc. The example below shows the sorts of things you can achieve with this feature, it jumps over the word to the left of the cursor (Ctrl+Left arrow) and presses backspace:

{
  "key": "ctrl+u",
  "command": "workbench.action.terminal.sendSequence",
  "args": { "text": "\u001b[1;5D\u007f" }
}

This feature supports variable substitution.

Note that the command only works with the \u0000 format for using characters via their character code (not \x00).

See terminal supports variables substitution:

{
  "key": "ctrl+shift+t",
  "command": "workbench.action.terminal.sendSequence",
  "args": { "text": ". ${file}" }
}

For example, see run files in terminal:

{
    "key": "ctrl+shift+t",
    "command": "workbench.action.terminal.sendSequence",
    "args": { "text": "node '${file}'\u000D" }
}
like image 330
Mark Avatar asked Dec 13 '22 12:12

Mark


1 Answers

With vscode v1.69 and shell integration enabled, there is now a built-in command to do this (for supported shells).

  1. Eanble the setting Terminal > Integrated > Shell Integration: Enabled
  2. Set a shortcut for the command Terminal: Run Recent Command from the Keyboard Shortcuts editor.

You should end up with a keybinding like this (in your keybindings.json):

{
  "key": "alt+x",         // whatever you chose as a keybinding
  "command": "workbench.action.terminal.runRecentCommand"
}

Supported shells are limited to Windows: pwsh and Linux/Mac: bash, pwsh and zsh.

This setting applies only when terminals are created, so you will need to restart your terminals for it to take effect.


Also see https://stackoverflow.com/a/70900927/836330 for how to see a QuickPick of recent terminal commands (in preview as of v1.64) for certain supported shells and OS's.


I came up with this keybinding:

{
  "key": "alt+x",

  "command": "workbench.action.terminal.sendSequence",
      
  "args": { "text": "\u001b[A\u000d" }
},
  1. \u001b is an escape sequence to indicate the following characters have special meaning.

  2. [A is an up arrow. See, e.g., xterm function keys:

    Cursor Up    | CSI A
    Cursor Down  | CSI B
    Cursor Right | CSI C
    Cursor Left  | CSI D
    

(the "CSI" refers to ESC or \u001b or followed by a [ and stands for "Control Sequence Introducer" (CSI is 0x9b).)

So "CSI A" is \u001b[A which is equal to an up arrow which should cycle your terminal command list to the previous command.

  1. \u000d is a return, so the command runs immediately.

Now Alt-x or whatever keybinding you choose will run the last shell command used, focus can be in the editor or the terminal.

For fun I put together this command:

"args": { "text": "\u0012watch\u001b[1;5C" }    

That will send a Ctrl-R to the terminal which searches previous commands.

Then it will search for "watch", and then Ctrl-rightArrow to go to the end of "watch" where you could modify arguments if need be.

Or skip the Ctrl-rightArrow part (\u001b[1;5C) and do a return (\u000d) to run the command that was found anywhere in your history. Obviously, you will need a unique search term for that to work.

[Tested in powershell and git bash. Not tested elsewhere.]

like image 97
Mark Avatar answered Dec 30 '22 14:12

Mark