vim + COPY + mac over SSH
Asked Answered
A

19

88

I access a sever over ssh on which I run vim for editing files. When I try to yank text from vim into an editor locally on my mac (lion) either with y OR "+y it does not work. I end up with the text I copied last locally. It does work if I just use p within vim alright.

Allomerism answered 22/5, 2012 at 0:55 Comment(4)
are you using Terminal.app or another term program?Chic
Can you change the name to vim + COPY + mac over SSHMia
Seven years later.... The answer is to create ~./vimrc and add a single line: set clipboard = unnamed. This works with debian 10 in Mac Terminal.Hartle
you shouldn’t open large file with vim on server it will use a lot of memory, if you want to copy sth, like some answers, just cat and grep the file find what you need and copy it from the terminalLoxodrome
U
85

To expand on Ray's answer…

When you are using Vim on a remote server via SSH, everything you do in Vim is done on the remote server. The remote server and the remote Vim that you are running on it have zero practical knowledge of your local computer and its system clipboard.

Because of that, y will never put the yanked text in your local clipboard.

In order to copy a chunk of text from the remote Vim to your local machine's clipboard you have three options:

  • Select the text with your mouse and hit Cmd+C like in any Mac OS X application.

    Obviously, it seems to be the easiest but it has at least three limitations:

    1. It is limited to the current screen. If the text you want to yank is not displayed entirely you won't be able to copy all of it.

    2. It doesn't play well with set mouse=a. With this option, any attempt to select something with the mouse will result in a visual mode selection which can't be copied with Cmd+C. As a workaround, you can use Alt+mouse to select the text without entering visual mode or simply remove this setting from your remote ~/.vimrc.

    3. Line numbers are copied as well.

  • Put the yanked text in a temporary file, scp it to your local machine and use pbcopy to put it in your system clipboard.

    This solution seems to be a little convoluted but it works (and the problem itself is also a little bit convoluted). Over the years I've seen a lot of different implementations ranging from simple one liners to client/server setups. Here is one, feel free to google around for others.

  • Use X-forwarding to connect your local clipboard to the remote clipboard if available.

Unparliamentary answered 22/5, 2012 at 13:26 Comment(11)
Thanks Romaini - I think this was closest answer. Seems there really is no very good answer though. I DO have mouse=a. I wish to keep it. Since I also want to keep nerd tree open, by pressing down Alt I not only get line numbers but also the directory. Either is bad really. I happen to also use Expanddrive mac. I moved my .vimrc and .vim directory onto mac and access over sftp. Still yank did not work no matter what i tried - so I put in this hack "vmap y :w !pbcopy<CR><CR>". That works pretty close to perfect. Odd little bug is that you can only copy FULL lines ...Allomerism
Since expanddrive is pretty expectable I suppose my question now would be if someone could improve on .... "vmap y :w !pbcopy<CR><CR>" .... a solution where partial line copies were possible.Allomerism
Since you are now working locally there's nothing preventing you from using MacVim which does actually allow you to use "*y, "+y or even <kbd>Cmd</kbd>+<kbd>C</kbd> to yank to the system clipboard.Unparliamentary
Or the CLI Vim bundled with MacVim which, on my machine at least, syncs Vim's internal default register with the system's clipboard.Unparliamentary
ah MacVim was the missing element actaully. I was using normal Vim on my mac. Now I have cmd-c. SUPER.Allomerism
HELPFUL TIP: When going with the "Select the text with your mouse" option, you can toggle line numbers with :set nonum.Sholem
One other way, that is clunky but can work in a pinch: exit vim. "cat" file from command line (type "cat <filename>"). Now you can copy with mouse (and cmd-C).Schluter
Just want to add that on Mac OS X 10.13 (High Sierra), to make it work with :set mouse=a in your ~/.vimrc, you need to hold <kbd>fn</kbd>, rather than <kbd>option</kbd> (<kbd>alt</kbd> on MacOS) when using the mouse to select a block of code in your vim session.Ostraw
On some OS's you need to hold shift instead of alt when selecting text w/ mouse to override set mouse=aFatima
hold alt, use mouse selection, and Cmd+C works well on mac! Thanks!Involution
I normally find selecting from the screen itself is good enough in most cases, the issue as @Unparliamentary said is that it does not play nice with :set mouse=a When I am using the integrated keyboard in my macbook that's easy, however I am at a loss if I am using an external keyboard which only has Ctrl,Win,Alt layout I have been searching what is the equivalent to the Fn key in a "classic PC" keyboard but have had no luck... I see people here saying Alt or Option worked for them... I have tried all of them and none did the trick. I am running MontereyBarbarese
B
46

Had this problem - log in from OSX over SSH to a linux box and cannot copy text from a file, opened with vim.

My workaround is :set mouse=i

By default mouse is enabled in all modes. When you set it to be enabled only in Insert mode you can scroll around and copy when you are not editing (normal mode) but when you start editing (by hitting the I or Insert key) and enter insert mode the mouse acts as cursor placement and you cannot copy from terminal.

You can set that option in ~/.vimrc

See :help mouse for more information about the values you can set and the modes.

Baber answered 24/2, 2017 at 8:31 Comment(3)
Using :set mouse=i worked for me, too. Without specifying any mouse-related properties, using the mouse to select text enabled visual mode. Running :set by itself, this showed up as the only mouse thing: ttymouse=xterm2. Note that ttymouse=xterm2 is still present after I run :set mouse=i, but I am able to use the mouse to select text and copy using Mac clipboard.Mallissa
Thanks, this solves my issue. I have to toggle mouse=a|i if I want to adjust splits but it's easy and it works.Sama
@Sama it might be better then to use mouse=v, and switch to visual mode by pressing v when you want to adjust splits.Kellie
I
32

My first answer on stackoverflow, but I feel it's a cool (albeit tiny) trick and it's worth posting. So here's what I do :

cat <filename>

When the text is printed onto the terminal, I select all the text with my mouse (the mouse scroll works since we're on the terminal window). Then copy that text with Cmd+C and paste into my local text editor.

The only flaw with this trick is that it's impractical to use if your files are tens of thousands of lines long since selecting all the lines with your mouse would be a task in itself. But for a file of ~2k lines it works well.

Impetuous answered 26/5, 2017 at 22:8 Comment(3)
If anyone's looking to paste rather than copy, do !cat >> %, paste, and hit ctrl-C to stop cat. Run :e! and the contents should appear at the bottom of the file.Courante
And if you just want to copy, lets say lines 750 to 764 from a 2k line file you can do ! cat % | head -764 from the vim command line.Broadcasting
my work around is similar, from vim (i have set number on by default), you know which line numbers are of interest, then use sed -n 5,8p filename.txt, this will print lines 5 to 8 only; you can even pipe that into pbcopyHuh
C
24

My go-to solution is to edit the file with vim from your local machine via scp.

:e scp://[email protected]//path/to/document

This keeps your buffer local and makes it easy to copy to your local clipboard.

The other advantage is that you get to use your local vim setup (.vimrc settings, plugins, etc.)

Childress answered 25/3, 2013 at 18:45 Comment(1)
Great method, too bad it doesn't work when you're inside a docker container shell within an SSH session.Epideictic
O
14

iTerm2 Shell Utilities come with it2copy which allows copying from a remote server to a client clipboard. Install Shell Utilities on the remote server and make sure you have Applications in terminal may access clipboard checked. enter image description here

Then, go into visual mode, select the text and execute <,'>:w !it2copy

Oldham answered 24/3, 2019 at 6:28 Comment(6)
Interesting. I use now neovim instead of vim now, but haven't tried this recently. I'll look into it.Oldham
how do you install the command on a remote server though?Pearlene
@Pearlene a bit of a late response on my part... you need to install shell integration on the serverOldham
This doesn't seem to work! I get zsh:1: command not found: it2copyIritis
@MilodOrif did you install shell utilities on the server and then logout and login?Oldham
@Oldham sorry for really late response, yes I did that, but there are some success, but I am getting the test in base64 format. I have made a PR in the iterm repo, but not much help :\ github.com/gnachman/iterm2-website/issues/81Iritis
C
9

https://github.com/ojroques/vim-oscyank + iTerm2 + tmux worked in my case, this is my workflow:

Some parts of my .vimrc

Plug 'ojroques/vim-oscyank'  " clipboard over ssh through tmux

" yank operation don't need to use the *" register (system clipboard)
set clipboard+=unnamedplus

autocmd TextYankPost *
    \ if v:event.operator is 'y' && v:event.regname is '+' |
    \ execute 'OSCYankRegister +' |
    \ endif
Cutback answered 19/7, 2021 at 21:3 Comment(2)
hey this is brilliant, been looking for a solution for this for a while now, works perfectly on a mac running iTerm, ssh-ing to a linux server running vim inside tmux, perfect. Thanks!Thermogenesis
Unfortunately this doesn't work for me. I'm using tmux on the host and on the guest. It works if I reboot all systems for a moment, but it stops working all the time.Squeak
A
5

Yanking within vi in a terminal to which you ssh'd into copies the lines into vi's internal buffer on the remote machine, not into your Mac's clipboard.

Use your mouse. :)

Atalaya answered 22/5, 2012 at 0:57 Comment(5)
Seems there should be a way to use cmd+c, Actually tried the mouse but that doesn't really work too well and it is slow. I'm sure there must be a better way ...Allomerism
Yes, in the Terminal window, with vi running, drag the mouse to highlight the text you want to copy. Hit Command+C, then in your local application on the Mac, such as TextPad, hit Command+V.Atalaya
Doesn't work - that would be completely obvious. If it did i would not be asking here. Also with mouse when I highlight text and say right click it goes back to selecting just the particular work I am on. so i just copy one word.Allomerism
Sorry, I guess that would be obvious. We must have different configurations as this does work for me. Try romani's answer. Best.Atalaya
@Allomerism It works as long as set mouse=a isn't configured. The real issue is copying line numbers or having to turn them off each time to copy. Editing remote files works alright: vim.wikia.com/wiki/Editing_remote_files_via_scp_in_vimRuckman
D
5

On MacOS, when SSH from machine A to machine B and using vim in machine B, I add this to my .vimrc in machine B:

nmap yr :call system("ssh $machineA_IP pbcopy", @*)<CR>

That way, in normal mode, if you copy something to * register, then type yr, the content of * register in vim@machine_B is copied to machine A's local clipboard, assuming you have setup Vim correctly with +clipboard and * register

Dorey answered 21/3, 2019 at 9:5 Comment(0)
M
3

Here's an update on the solution #2 from romainl. It creates and alias of the ssh command and launches the remotecopyserver if it's not running and installs the remotecopy(rclip) in the remote server. In short, you don't have to do anything except paste the code snippet below into your bash_profile.

######################## For SSH Remote Copy #########################
export LC_SETUP_RC='command -v rclip >/dev/null 2>&1 || { echo "executing"; mkdir -p /usr/local/bin; if [ ! -f /usr/local/bin/rclip ];then wget https://raw.githubusercontent.com/justone/remotecopy/master/remotecopy -P /usr/local/bin/; ln -s /usr/local/bin/remotecopy /usr/local/bin/rclip; chmod +x /usr/local/bin/remotecopy; fi; if [[ \":\$PATH:\" == *\"/usr/local/bin:\"* ]]; then export PATH=/usr/local/bin:$PATH; fi } > /var/log/rclip.log 2>&1 || echo "Some error occured in setting up rclip. check /var/log/rclip.log"'

ssh_function() {
count="`ps -eaf | grep remotecopyserver | grep -v grep | wc -l`";
if [ "$count" -eq "0" ]; then 
   mkdir -p $HOME/bin;
   if [ ! -f $HOME/bin/remotecopyserver ]; then 
      wget https://raw.githubusercontent.com/justone/remotecopy/master/remotecopyserver -P $HOME/bin;
      chmod +x $HOME/bin/remotecopyserver;
   fi;
   nohup $HOME/bin/remotecopyserver & 
fi;
ssh_cmd=`which ssh`
PARAMS=""
for PARAM in "$@"
do
  PARAMS="${PARAMS} \"${PARAM}\""
done
bash -c "ssh ${PARAMS} -R 12345:localhost:12345 -t 'echo \$LC_SETUP_RC | sudo bash; bash -l'"
}
alias ssho=`which ssh`
alias ssh=ssh_function
alias ssh2=ssh_function

vssh_function() {
ssh_config=`vagrant ssh-config`;
if [ "$?" -eq "1" ]; then
echo "Problem with Vagrant config. run 'vagrant ssh-config' to debug"
return 1
fi
PORT=`echo "$ssh_config" | grep Port | grep -o "[0-9]\+"`; 
ID_FILE=`echo "$ssh_config" | grep IdentityFile | awk '{print $2}'`
ssh2 -q -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -o PasswordAuthentication=no -i $ID_FILE vagrant@localhost -p $PORT "$@"
}
alias vssh=vssh_function

Once the alias is activated, you can normally use ssh and whenever you need to copy to local clipboard from vim, use

:w !rclip 

to copy the whole file to clipboard

:'<,'> !rclip

to copy selected lines from visual mode. You have to press "Cmd+V" or "Ctrl+V" whenever it asks for the secret key.

Bonus

For those who work on Vagrant, there's a wrapper vssh which will execute vagrant ssh but also launches and install the necessary components.

Reference

Latest code snippet here - https://gist.github.com/ningsuhen/7933b206b92fc57364b2

http://endot.org/2011/12/04/remotecopy-copy-from-remote-terminals-into-your-local-clipboard/

https://github.com/justone/remotecopy

Caveats

The alias wraps the ssh command and there might be some unexpected issues. ssho is available if you need to execute ssh without the whole remotecopyserver thing. Alternatively, you can use the alias ssh2 and keep the ssh command as it is.

Mia answered 23/11, 2015 at 14:16 Comment(0)
K
3

One trick which i use often during copying vim text using mouse if number of lines get little over-flown my screen is to minimize (Cmd + '-') the text. :) Minimize so much that you can not see by eyes but you can copy all the text in one go.

Klinger answered 8/3, 2018 at 7:9 Comment(1)
Wow that's actually brilliantly pragmatic.Epideictic
H
3

Instructions for mac + ssh + iterm2 + neovim:

  1. Ssh to your server.
  2. Install iterm shell integration.
  3. Add ~/.iterm2 to the $PATH variable.
  4. Create a ttyup command in e.g. ~/.local/bin.
  5. Add ~/.local/bin to $PATH, if it's not already.
  6. Add the g:clipboard declaration to your init.vim.

ttyup:

#!/bin/bash
# @medgar's ttyup script for passing the output to the parent shell

parent() { awk '{print $4}' "/proc/$1/stat"; }
leader() { awk '{print $6}' "/proc/$1/stat"; }
it2copy > "/proc/$(parent $(leader $$))/fd/0"

init.vim:

let g:clipboard = {
\   'name': 'myClipboard',
\   'copy': {
\      '+': ['ttyup'],
\      '*': ['ttyup'],
\   },
\   'paste': {
\      '+': '+',
\      '*': '*',
\   },
\   'cache_enabled': 0,
\ }
Horizon answered 29/8, 2022 at 16:22 Comment(1)
This works really well! When I yank something with y, it fills the clipboard on my local Mac. The only caveat is that when I paste something in the remote vim using p, I get this error: Error detected while processing function provider#clipboard#Call[9]..function provider#clipboard#Call[6]..268[7]..<SNR>35_try_cmd: E475: Invalid value for argument cmd: '+' is not executable. For now I've just been ignoring the error.Confinement
O
2

Or, from the terminal, write less [filename] to get it written to the terminal. Then start by selecting with your mouse, while you hold down-arrow-key down. Then you can select the whole bunch.

Obe answered 28/6, 2017 at 11:36 Comment(1)
Thank you. Your tricks works with a large bunch of contents that needs scrolling. Unfortunately, it only work with arrow-key down. Not working with G key (till the end of file)Delirium
I
1

I found a solution that works perfectly in my case with macOS on a local machine and Ubuntu Linux on a remote server.

Setup X11 forwarding for macOS (local machine)

1. Install XQuatrz

brew install --cask xquartz

Check that clipboard synchronization is enabled in XQuartz -> Preferences window -> Clipboard tab

Note: You need to reboot your Mac for xquartz to work correctly.

2. Enable X11 forwarding

Use one of two options:

- Start ssh connection with -X flag:

ssh -X [email protected]

-- or --

- Set default settings for ssh connection.

Add the following line to ~/.ssh/config, create this file if not existing:

ForwardX11 yes 

This is equivalent to -X flag for all new ssh connections. Then start a regular ssh connection:

ssh [email protected]

Check and adjust clipboard access for Linux (remote server)

1. Verify X11 Forwarding

Login to remote machine via ssh as described above. Check the DISPLAY environment variable:

echo $DISPLAY

Should return a reply similar to localhost:10.0.

2. Verify clipboard integration

Install xclip for Linux if not installed:

sudo apt install xclip

Copy test text to the clipboard with the following command:

echo "test" | xclip -sel clip

Paste to macOS with cmd+V and check if it works.

3. Adjust clipboard for vim:

Check whether vim supports clipboard suitable for X11 forwarding:

vim --version | grep clipboard

It should have +clipboard feature enabled.

If this it is not enabled, run:

sudo apt install vim-gtk

Add the following line to ~/.vimrc , create this file if not existing:

set clipboard=unnamedplus

Copy text from vim with standard approach: v <arrow-keys-for-selection> y And paste the result to macOS with regular cmd+V shortcut.

Now your yanking in vim over shh should be easily pasted to any macOS app.

Illustrator answered 12/11, 2023 at 12:3 Comment(1)
Even though this approach is quite a few steps to setup initially, this gives the fastest workflow for me to copy text - a simple yank. Thanks for the detailed instructions! I just had to reboot my Mac after installing quartz for the copying to work correctly.Formaldehyde
L
0

I was hoping to improve on my solution here, but instead will share it as it seems on par with some of the others.

When using iTerm2 on a Mac, sshing into machines, running tmux, and then editing with Vim, I have a vertical split iTerm2 window on the Mac that I pull all the way off to the side to make it as skinny as possible.

Then when I want to copy text from Vim, I will click into the tiny slice of iTerm2 window, and go back over and highlight and then copy the text from Vim. This works the best for single lines of text.

If there is a tmux vertical split, highlighting multiple lines in the Vim buffer won't wrap properly, and will copy text from the other tmux window, but otherwise this is great for copying 90% of what I need, without having to exit Vim, cat a file, or do something else.

I also have ample horizontal window space, making the small iTerm2 window not a space hog.

Lorineloriner answered 6/6, 2019 at 21:20 Comment(0)
C
0

Just use MobaXterm.
I tried lots of ways and none of them is easy. So the only solution I could find is using MobaXterm. You can see all of the files and open them any way you want.

Cucullate answered 29/4, 2021 at 9:34 Comment(0)
D
0

The easiest way to copy to local machine is via selecting with mouse and then CMD + c to copy. As is noted in another answer this has a few limitations/drawbacks. Consequently, I sought out the alternatives, but after trying for hours (unsuccessfully) to get X11 forwarding working, I instead came up with the following simple workaround (at least for the line-numbering caveat) for aid in mouse copying.

Add the following to your .vimrc to easily toggle line numbers for mouse copying:

nnoremap L :set invnumber <CR>

You can easily change the L to any key of your choice that you wish to be the shortcut key.

Dorchester answered 19/2, 2022 at 17:2 Comment(0)
S
0

I had a similar problem of not being able to command + c (copy) out of nvim using kitty terminal on macOS.

After much fumbing, the only thing that worked was adding this to ~/.config/nvim/init.vim

set mouse=

I closed and reopened nvim and suddenly copy worked as expected.

Source: I found this info by right-clicking inside of nvim, and selecting the bottom option (How-to disable mouse):

enter image description here

If right clicking doesn't bring up that menu, it might mean your mouse is already disabled (so check your config file)

Additional info

FWIW, this is the info that comes up when you select 'How-to disable mouse'

DEFAULT MOUSE
                        *default-mouse* *disable-mouse*
By default the mouse is enabled, and <RightMouse> opens a |popup-menu| with
standard actions ("Cut", "Copy", "Paste", …). Mouse is NOT enabled in
|command-mode| or the |more-prompt|, so you can temporarily disable it just by
typing ":".

If you don't like this you can disable the mouse in your |config| using any of
the following:
- Disable mouse completely by unsetting the 'mouse' option: >vim
  set mouse=
- Pressing <RightMouse> extends selection instead of showing popup-menu: >vim
  set mousemodel=extend
- Pressing <A-LeftMouse> releases mouse until the cursor moves:  >vim
  nnoremap <A-LeftMouse> <Cmd>
    \ set mouse=<Bar>
    \ echo 'mouse OFF until next cursor-move'<Bar>
    \ autocmd CursorMoved * ++once set mouse&<Bar>
    \ echo 'mouse ON'<CR>
<
To remove the "How-to disable mouse" menu item and the separator above it: >vim
  aunmenu PopUp.How-to\ disable\ mouse
  aunmenu PopUp.-1-
<
DEFAULT MAPPINGS
                            *default-mappings*
Nvim creates the following default mappings at |startup|. You can disable any
of these in your config by simply removing the mapping, e.g. ":unmap Y".
>vim
    nnoremap Y y$
    nnoremap <C-L> <Cmd>nohlsearch<Bar>diffupdate<Bar>normal! <C-L><CR>
    inoremap <C-U> <C-G>u<C-U>
    inoremap <C-W> <C-G>u<C-W>
    xnoremap * y/\V<C-R>"<CR>
    xnoremap # y?\V<C-R>"<CR>
    nnoremap & :&&<CR>
<
DEFAULT AUTOCOMMANDS
                            *default-autocmds*
Default autocommands exist in the following groups. Use ":autocmd! {group}" to
remove them and ":autocmd {group}" to see how they're defined.

nvim_terminal:
- BufReadCmd: Treats "term://" buffers as |terminal| buffers. |terminal-start|

nvim_cmdwin:
- CmdwinEnter: Limits syntax sync to maxlines=1 in the |cmdwin|.

==============================================================================
Schnapp answered 22/3 at 3:39 Comment(0)
C
-1

@andrewgazelka had a great solution

I don't have it2copy script: https://github.com/gnachman/iTerm2-shell-integration/blob/main/utilities/it2copy

Here is the code I downloaded from :)

Hope someone will feel it is helpful :)

I moved it2copy in my /usr/bin directory for both my server and macbook

Centillion answered 25/10, 2022 at 20:54 Comment(0)
F
-3

Try the other clipboard register - "*y.

Fluorescence answered 22/5, 2012 at 9:25 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.