Can a command be send to VSCode, directly from the integrated terminal (integrated terminal -> VSCode API)? - visual-studio-code

Hi I would like to know whether one could call a VSCode command from the integrated terminal. So basically is the terminal aware of VSCode and can they communicate (at least from terminal => VSCode)
My Usecase: I would like to have H and L, to move to editor tab left / right of the terminal (I am using the terminal in an editor tab). Additionally, I would like that to happen when I am in vim normal mode in my zsh.
So I would like, when I am in normal mode and press H that the terminal sends an editor.tabNext (or whatever the command is) to VSCode.

I think I found a workaround at least. There is an extension called Remote Control (https://marketplace.visualstudio.com/items?itemName=eliostruyf.vscode-remote-control&ssr=false#review-details), with which I can send arbitrary commands to VSCode, so this seems to work. Proabably natively this is not possible, but maybe someone knows something.
EDIT1:
Here is my setup now:
if [ ! -z $VSCODE ]; then
_sendcmd() { echo "{ \"command\": \"workbench.action.$1\" }" | websocat ws://localhost:4242 }
# define commands and register them in zsh
editor_left() { _sendcmd previousEditor }; zle -N editor_left;
editor_right() { _sendcmd nextEditor }; zle -N editor_right;
bindkey -a H editor_left
bindkey -a L editor_right
fi
where $VSCODE is defined in VSCode through terminal.integrated.env = { "VSCODE": "1" }. May this make you as happy as it makes me happy.

Yes you can do this but it will require writing a simple extension and there is one flaw with it.
If you write a VSCode extension there is an API that will set environment variables in new terminals.
export function activate(context: ExtensionContext) {
...
context.environmentVariableCollection.replace("REMOTE_CONTROLL_EXTENSION_IPC_PATH", ipcPath);
What you do is create a Unix socket (or named pipe on Windows) and pass it into that environment variable. Then in your shell you can just send data to that socket.
This is much better than the approach used by the Remote Control extension that Dimfred mentioned - it's more secure and doesn't rely on known fixed ports, which means you're going to run into issues e.g. if they don't get closed properly or you run multiple copies of VSCode.
The only downside I've found with this approach is that if restart VSCode, then the socket will be closed but VSCode will try to restore shell sessions. Those shell sessions will be left with an old REMOTE_CONTROLL_EXTENSION_IPC_PATH value which points at a non-existent socket.
I'm not sure of a way around that yet.
Edit: Actually all you need to do is ensure your Unix socket path is tied to a workspace. At least this is what the built in Git extension does. See createIPCServer(). It uses storagePath which is specific to a workspace. It also unlinks the socket at that path (if any) when it starts.
I initially thought that might cause issues if you open the same workspace twice in two windows, but VSCode won't let you do that.

Related

Editing WSL2 instance of Ubuntu Crontab using Windows VSCode

My question is whether it is possible to edit the crontab of a WSL2-based instance of Ubuntu with my Windows VSCode that is connected via WSL remote SSH.
If I type export EDITOR=code inside my WSL instance and then crontab -e, I am able to see a /tmp/crontab.sygFAU file load inside my VSCode instance.
The problem is that once I make edits to this file, it will save the file to /tmp/crontab.sysFAU but it doesn't actually take the next step of replacing the the real crontab file in /var/spool/cron/crontabs.
So once I re-open the crontab, it will just show what I had previously, and not my saved edits.
It would be nice to know if this is not possible or if there are any alternative ways to run a GUI editor because using nano is a pain!
An interesting question that I haven't considered before, myself. Here's what's happening:
You set your editor to code
You crontab -e, which properly loads VSCode with the temporary crontab.
However, because this is a Windows GUI application, it returns control to the parent Linux application (crontab) immediately after starting VSCode. You can see the same result if you just start notepad.exe from your shell in WSL -- Once Notepad starts (rather than exits) control is returned to the shell.
If you switch back to your terminal at this point, you'll see that crontab detected that the editor that it launched exited (returned), and so it has already tried to copy the temporary file to the permanent location.
However, since the temporary files doesn't yet have any changes, crontab decides there's nothing to do.
Editing the file in VSCode and saving it has no effect, other than to leave a dangling /tmp/... file hanging around (since crontab isn't there to clean up).
So what's the solution? We need a way to launch a Windows GUI application and prevent it from returning control to crontab until you are done editing.
I originally thought something from this question might work, but the problem is that the actual command that launches the Windows process is embedded in a shell script, which you can see with less "$(which code)" (or code "$(which code)"), but it's probably not a great idea to edit this.
So the next-best thing I came up with is a simple "wrapper" script around the (already-a-wrapper) code command. Create ~/.local/bin/code_no_fork.sh (could be anywhere) with:
#!/usr/bin/env bash
code $* > /dev/null
echo Press Spacebar to continue
read -r -s -d ' '
Credit: This answer for the Spacebar approach
Then:
EDITOR=~/.local/bin/code_no_fork crontab -e
After you make your edits in VSCode, simply press Space to allow the script to continue/exit, at which point crontab will (assuming no errors were detected) install the new Crontab.
Alternatives
This is should typically only be a problem with Windows GUI applications, so the other possible avenue is to simply use any Linux editor that doesn't fork. If you want a GUI editor, that's entirely possible as long as you are running a WSL release that includes WSLg support (now available for Windows 10 and 11).
I won't offer any individual editor suggestions since that would get into "opinion" and "software recommendation" territory, which is off-topic here.

How are keyboard inputs transmitted through Windows terminal and WSL2

I'm using WSL (WSL2 in fact) for a few days and I'm a bit confuse about keyboard combination redirection and/or interception.
I have to say that my favorite tool to edit text is emacs, that use a lot of keyword combinations.
My stack is this one :
Under windows, I run Windows terminal (WT.exe)
In this terminal I open a tab which (afaik magically) is a shell on a linux subsystem. This subsystem is a Debian
In this shell I run emacs.
The whole thing looks like that :
At this point, when I enter a key combination, it may be passed to emacs, or it may be intercepted/interpreted by any other layer of the stack.
For instance :
ctrl-e is interpreted by emacs : it move the caret to the end of file
ctrl-z is interpreted by wsl2 (afaik) : it pauses emacs as a background job
ctrl-tab is interpreted by windows terminal : it changes tab
alt-f4 is interpreted by windows : it closes windows terminal
And some of them are a mystery for me. For instance ctrl-_ (ctrl underscore), which is very useful on default emacs configuration, is not interpreted by emacs. It is translated at some point as "delete". In this configuration typing "delete" or "ctrl-_" is the very same thing : it removes the first character before the caret.
Very specifically and synthetically stated, my question would be : "How do I configure this stack to make emacs receive ctrl-_ ?"
Of course more generally, I really would like to know, how each layer works and is parameterized. For instance, is there a configuration file for WT and/or WSL2, that says which combination are forwarded, which one are interpreted and which one are ignored.
Additional Data :
If I run WSL2 through WT, but don't start emacs, ctrl-_ is also interpreted as "delete"
If I run another type of "tab" in WT, like cmd.exe or powershell, ctrl-_ is not interpreted as "delete". I don't know if it is interpreted at all
If I run WSL2 without WT, Ctrl-_ is not interpreted at all.
I didn't found any mention of ctrl-_ in WT config shortcuts.
Additional Data :
I tried to run following python program in both stacks : WT/WSL and WT/CMD.EXE
import keyboard
while(True):
c = keyboard.read_key()
print(c)
On WT/CMD.EXE, the output is :
ctrl
_
_
ctrl
Which means it receive the keyboard info.
On WT/WSL2, it fails to run. Apparently "keyboard" is not compatible with WSL2. But this is not the question here.
A useful tool for debugging input on linux is showkey -a. You can use that to help debug what keys the client application is receiving. If you press a key and it doesn't display anything in the output, then there's a good chance it's being intercepted by the Terminal.
There's probably an open issue for this on the Terminal repo. #8458 looks similar.
is there a configuration file for WT and/or WSL2, that says which combination are forwarded, which one are interpreted and which one are ignored.
defaults.json is the file that contains all the keybindings that the Windows Terminal binds by default.
What WSL does is more complicated. IIRC, the inputrc file on linux is used readline (for bash, etc) to specify how certain keys are handled by the shell. But then there are also keys configured in stty that control other parts of the TTY interface. That part I understand less.
alt-f4 is interpreted by windows : it closes windows terminal
FWIW That's actually a application-level keybinding. The Terminal handles that key manually, so that people can optionally disable it. See defaults.json

copy to local clipboard in vscode terminal in ssh mode

I have some utility scripts that copy text to my clipboard using pyperclip (python library).
When I use vscode in ssh mode to develop on my remote server, I want to still be able to run these scripts in the integrated terminal of the remote server, but make it copy text to my local clipboard.
I suspect there might be a way to do this, since running code <dirname> in the remote terminal, for example, opens a vscode window in my local machine, so I assume there's a way to intercept the commands to make them do something locally even if they run on the remote machine. Any suggestions?
xsel might help you.
I'm trying to get a similar result using a dev container, although I could use some help myself. My problem is that I can't configure X11 forwarding. If you can set that up, then the following might move you forward a bit:
copy-to-clipboard-file() {
[[ "$REGION_ACTIVE" -ne 0 ]] && zle copy-region-as-kill
print -rn -- $CUTBUFFER > xsel --clipboard
}
zle -N copy-to-clipboard-file
bindkey "^X" copy-to-clipboard-file
I don't know if zle is available in your shell; I'm using zsh. This binds Ctrl-X to copy the selected text. You'll need to install xsel.
You'll know if X11 forwarding is working because this will output something:
echo $DISPLAY
Also see:
How do I highlight text for copying and pasting in the VS Code terminal?

How can I handle user input in VS Code?

I'm trying to test code that runs off user input in VS Code.
When I use 'prompt' I get:
ReferenceError: prompt is not defined
I googled that and found this page saying I need to use node.js - makes sense!
I tried the node.js example code here:
var readline = require('readline');
var rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
rl.question("What do you think of node.js? ", function(answer) {
// TODO: Log the answer in a database
console.log("Thank you for your valuable feedback:", answer);
rl.close();
});
When I run it in VS Code I can see the output in the terminal asking for the input:
[Running] node "C:\Users\jon_d\AppData\Local\Temp\tempCodeRunnerFile.javascript"
What do you think of node.js?
But I can see anyway to input a value in VS Code? Someone mentioned I need to use an external terminal - but I can't find any info on how to do that on a PC only OSX? Can someone explain how i use cmd for this?
Cheers,
Jon
Since Windows PCs don't have a real "terminal", a common solution is to use vscode with WSL (Windows Subsystem for Linux). This replicates the workspace of a linux machine in vscode - you have access to a real terminal (which is built into vscode) and this is where you would enter your user input.
I'm not sure if what you want to do is possible with only cmd/powershell, but since WSL is so common and convenient, I thought I'd put it out there.

Send tmux command to tmuxinator

Specifically, I need to create a profile that by default will have a small pain displaying the clock, which can be triggered with C-b t. However, I couldn't find the way to do that.
In this GitHub issue comment, a Collaborator of the project said it could be defined like a regular command, but on my ZSH setup, it just didn't work, saying "zsh: Command not found: C-b".
Does anyone happen to know how I can achieve this?
Thanks!!!
windows:
- work:
panes:
- tmux clock-mode
- ipython
Below is what happens when typing tmux clock-mode inside tmux session:
current tmux client connect to tmux server
attach to current(or the most recently) session
since the -t argument is omitted, the currently active pane in the current window is used for the clock-mode command.
Checkout the session in $man tmux for more detail.
COMMANDS
This section contains a list of the commands supported by tmux. Most commands accept the optional -t argument with one of target-client, target-session
target-window, or target-pane. These specify the client, session, window or pane which a command should affect. target-client is the name of the pty(7)
file to which the client is connected, for example either of /dev/ttyp1 or ttyp1 for the client attached to /dev/ttyp1. If no client is specified, the
current client is chosen, if possible, or an error is reported. Clients may be listed with the list-clients command.