copy to local clipboard in vscode terminal in ssh mode - visual-studio-code

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?

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.

Issue with PowerShell/Linode Terminal

I am accessing my linode (Ubuntu 16.04 LTS) with "LISH Console via SSH", using PowerShell to do the SSH. I do not know if this is a problem with PowerShell, or the LISH Console I am SSHing to. I can connect fine and am able to run commands fine, however there is a small annoyance when I try to type longer commands. Below is what a longer commmand should look like:
user#host:~# scp -r local.directory.that.i.want.to.copy other.directory.im.copying.to
OR
user#host:~# scp -r local.directory.that.i.want.to.copy ot
her.directory.im.copying.to
However, as I type that command out, I reach some sort of char limit...
user#host:~# scp -r local.directory.that.i.want.to.copy ot
Which then continues on the same line that I was typing on:
her.directory.im.copying.toirectory.that.i.want.to.copy ot
While it does still work, it gets a bit annoying that I can't really see what I've typed. Are there settings I can adjust within the LISH access terminal?

VSCode - remote SSH - can't find code executable in vscode-server directory

I'm using VSCode and the official remote-ssh extension.
I would like to be able to write code /path/to/file in an ssh terminal or in the vscode integrated terminal in a remote window in order to open a file/folder in vscode remote.
I am aware that I can use code --folder-uri=vscode-remote://ssh-remote+ADDRESS/path/to/file from the local machine's terminal, but I want to be able to run a command from within the integrated vscode terminal and any other terminal session where I've ssh'd into the remote machine)
Currently, if I run code from a remote terminal it opens up a new vscode window on the remote machine.
To achieve this goal, in the past I've used the following alias on the remote machine:
alias code="${VSCODE_GIT_ASKPASS_NODE%/*}/bin/code"
Which looks for the code executable in ~/.vscode-server/bin/<COMMIT_ID>/bin before defaulting to the local /bin/code.
I got that alias from this related stackoverflow question.
However, this doesn't seem to work right now.
Upon closer inspection, it appears that there is no code executable in the vscode-server directory.
How can I fix this?
Both machines are running MacOS and visual studio code version f80445acd5a3dadef24aa209168452a3d97cc326, if that's relevant.
I also wanted to be able to run code from the integrated terminal when running VSCode with the "remote ssh" extension. In my case, the "remote" is a Linux box (named "aorus" below), and I want to use VSCode from a laptop running macOS (named "mbp").
As for you, I used to use the VSCODE_GIT_ASKPASS_NODE trick. Recently, I had to change the alias since code (or code-insiders in my case) wasn't available in bin/ anymore. It seems it has been moved to bin/remote-cli. The correct alias (tested with vscode 1.64.2):
alias code="${VSCODE_GIT_ASKPASS_NODE%/*}/bin/remote-cli/code"
If you also want this to work from other ssh sessions (not just inside the integrated terminal), you can create a short script that I called coder (r for "remote") which I have in ~/bin on my remote ("aorus"). Note that you need to be able to reach the local machine from your remote (I do that with Tailscale). The script looks like this:
#! /bin/bash
set -ex
remotehost=$(hostname)
localhost=mbp
cmd="code"
while [ $# -gt 0 ]; do
if [ -f "$1" ]; then
cmd+=" --file-uri \"vscode-remote://ssh-remote+$remotehost$(readlink -f "$1")\""
elif [ -d "$1" ]; then
cmd+=" --folder-uri \"vscode-remote://ssh-remote+$remotehost$(readlink -f "$1")\""
else
cmd+=" $1"
fi
shift
done
exec ssh $localhost -q -t -x "exec bash -l -c '$cmd'"
On my Mac, when running VSCode connected remotely to my Linux box, I can type this in the integrated terminal to open the file main.go present on my remote Linux box:
coder main.go
The reason I have to wrap code in bash -l is due to the fact that ssh, by default, runs in a non-login shell, which means that the ~/.bashrc on my Mac isn't picked up, meaning code isn't in the PATH. The error message looks like this:
bash:1: command not found: code
Another note: there is a shorter syntax documented here:
ssh -q -t -x mbp bash -l -c "code --remote=ssh-remote+aorus main.go"
I don't use this syntax is because this method isn't able to know whether you are opening just a single file (which should be open in the most recent VSCode remote session) or a folder (which should be open as a new VSCode remote session).
Finally, if you are using VSCode Insiders, you can create a symlink so that the command code works on your local machine (in my case, on my Mac):
sudo ln -sf /usr/local/bin/code-insiders /usr/local/bin/code
As already explained by maelvls the path has been changed.
But if you use it outside integrated terminal you will got message
Command is only available in WSL or inside a Visual Studio Code terminal
To avoid this you need to export VSCODE_IPC_HOOK_CLI in your .bashrc .
Use this script in your .bashrc
export VSCODE_IPC_HOOK_CLI=`ls -t /run/user/1012/vscode-ipc-* | head -n1`
alias code="~/.vscode-server/bin/*/bin/remote-cli/code"
If you want to open your file in your current visual studio use -r option.
code -r tes.txt
Note :
I can't call VSCODE_GIT_ASKPASS_NODE so I use full path, it is working well
I don't know if VSCODE_IPC_HOOK_CLI will show in different location, just check it in your integrated terminal visual studio code
tested on remote server Centos 7
local macOS Monterey version 12.2
Visual Studio Code Version: 1.64.2 (Universal)
Commit: f80445acd5a3dadef24aa209168452a3d97cc326
extension : remote-ssh

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

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.

How can I make emacsclient just open a window for an existing emacs daemon without opening a new file

I use an emacs daemon to preserve my emacs session even if I have to reboot the machine that I run my X server on or if I want to access the same session from a different machine. This works very well but when restoring a session I'd quite like to just run "emacsclient --create-frame --no-wait" to connect to the daemon without opening a new file. It won't let me get away without specifying a filename.
I've tried using --eval to execute a function rather than open a file but the window just goes away when the evaluation is complete.
(Emacs 23.1 via backports on Debian GNU/Linux 5.0.)
From the help provided by emacsclient, you have a few options. First, is the one mentioned already which is emacsclient -c. That will try to create a frame associated with the emacs daemon. The advantage to this is that if DISPLAY is not set, then it will open emacs in the terminal.
Which brings us to the next best option (especially if you are logging in remotely): emacsclient -t which forces emacs to open up in terminal mode even if DISPLAY is set.
Also keep in mind that you can set the display from the command-line as well. I use this often when logging in remotely from VNC. The full command would be emacsclient -d DISPLAY -c
emacsclient -c works for me.
emacsclient -n -e "(make-frame)"
The -n flag means that the emacsclient doesn't wait, and the emacs instance doesn't destroy the frame.
If you are using emacs from the command line, you might also want to consider emacsclient -t