jeffreytse / zsh-vi-mode

💻 A better and friendly vi(vim) mode plugin for ZSH.
MIT License
3.13k stars 109 forks source link

clipboard workaround #19

Open ngmariusz opened 3 years ago

ngmariusz commented 3 years ago

While we wait for final solution you can patch zsh-vi-mode plugin if it's deal breaker for you.

For those not very familiar with bash just find plugin file ~/.oh-my-zsh/custom/plugins/zsh-vi-mode/zsh-vi-mode.zsh and then function zvm_yank(); In my case for windows wsl2 ubuntu20 it's like so:

image

brutal, but does the job.

dm9pZCAq commented 2 years ago

i just redefine zvm_vi_yank in zshrc:

zvm_vi_yank () {
    zvm_yank
    printf %s "${CUTBUFFER}" | xclip -sel c
    zvm_exit_visual_mode
}
tormodatt commented 2 years ago

similarly for macOS:

function zvm_vi_yank() {
    zvm_yank
    echo ${CUTBUFFER} | pbcopy
    zvm_exit_visual_mode
}

(printf also works)

jeffreytse commented 2 years ago

@tormodatt Thanks for your tips. Hope you have a good day! : )

vanarok commented 2 years ago

Also for wayland (need is wl-clipboard)

zvm_vi_yank () {
    zvm_yank
    printf %s "${CUTBUFFER}" |  wl-copy -n
    zvm_exit_visual_mode
}
reaz1995 commented 2 years ago

also you can make p/P paste from the windows clipboard by changing zvm_vi_put_after and zvm_vi_put_before as follow:

function zvm_vi_put_after() {
  local head= foot=
  local content=$(win32yank.exe -o)
...
}

would be great to add one variable which will decide if use custom clipboards, if yes then left the user specify yank/past command

anderslundstedt commented 2 years ago

FWIW, here is my solution for getting zsh-vi-mode to play nicely—given my preferences¹—with system clipboards. I have not done any thorough testing but I have not noticed any problems since I started using this solution some weeks ago. (cbread and cbprint are custom functions I have for writing and reading to and from the system clipboard, respectively.²)

my_zvm_vi_yank() {
  zvm_vi_yank
  echo -en "${CUTBUFFER}" | cbread
}

my_zvm_vi_delete() {
  zvm_vi_delete
  echo -en "${CUTBUFFER}" | cbread
}

my_zvm_vi_change() {
  zvm_vi_change
  echo -en "${CUTBUFFER}" | cbread
}

my_zvm_vi_change_eol() {
  zvm_vi_change_eol
  echo -en "${CUTBUFFER}" | cbread
}

my_zvm_vi_put_after() {
  CUTBUFFER=$(cbprint)
  zvm_vi_put_after
  zvm_highlight clear # zvm_vi_put_after introduces weird highlighting for me
}

my_zvm_vi_put_before() {
  CUTBUFFER=$(cbprint)
  zvm_vi_put_before
  zvm_highlight clear # zvm_vi_put_before introduces weird highlighting for me
}

zvm_after_lazy_keybindings() {
  zvm_define_widget my_zvm_vi_yank
  zvm_define_widget my_zvm_vi_delete
  zvm_define_widget my_zvm_vi_change
  zvm_define_widget my_zvm_vi_change_eol
  zvm_define_widget my_zvm_vi_put_after
  zvm_define_widget my_zvm_vi_put_before

  zvm_bindkey visual 'y' my_zvm_vi_yank
  zvm_bindkey visual 'd' my_zvm_vi_delete
  zvm_bindkey visual 'x' my_zvm_vi_delete
  zvm_bindkey vicmd  'C' my_zvm_vi_change_eol
  zvm_bindkey visual 'c' my_zvm_vi_change
  zvm_bindkey vicmd  'p' my_zvm_vi_put_after
  zvm_bindkey vicmd  'P' my_zvm_vi_put_before
}

¹ I only work with one clipboard, which is shared between my local system and any (trusted) remote system I am logged on to.

² Here are cbread and cbprint:

if [[ $(uname) = "Darwin" ]]; then
  on_mac_os=0
else
  on_mac_os=1
fi

cbread() {
  if [[ $on_mac_os -eq 0 ]]; then
    pbcopy
  else
    xclip -selection primary -i -f | xclip -selection secondary -i -f | xclip -selection clipboard -i
  fi
}

cbprint() {
  if [[ $on_mac_os -eq 0 ]]; then
    pbpaste
  else
    if   x=$(xclip -o -selection clipboard 2> /dev/null); then
      echo -n $x
    elif x=$(xclip -o -selection primary   2> /dev/null); then
      echo -n $x
    elif x=$(xclip -o -selection secondary 2> /dev/null); then
      echo -n $x
    fi
  fi
}
Acumane commented 1 year ago

For anyone on WSL2 for Windows:

zvm_vi_yank () {
    zvm_yank
    echo "$CUTBUFFER" | clip.exe
    zvm_exit_visual_mode
}
raph90 commented 1 year ago

Thanks for your solution @anderslundstedt

phortonssf commented 1 year ago

Any idea how to stop deleting lines or characters from replacing what is in the clipboard?

Shuraken007 commented 1 year ago

Loved idea with cbprint, cpread from @anderslundstedt https://github.com/jeffreytse/zsh-vi-mode/issues/19#issuecomment-1268057812

rewrite it via functions overriding

for f in zvm_backward_kill_region zvm_yank zvm_replace_selection zvm_change_surround_text_object zvm_vi_delete zvm_vi_change zvm_vi_change_eol; do
  eval "$(echo "_$f() {"; declare -f $f | tail -n +2)"
  eval "$f() { _$f; echo -en \$CUTBUFFER | cbread }"
done

for f in zvm_vi_put_after zvm_vi_put_before; do
  eval "$(echo "_$f() {"; declare -f $f | tail -n +2)"
  eval "$f() { CUTBUFFER=\$(cbprint); _$f; zvm_highlight clear }"
done
uduse commented 8 months ago

Sharing my version for macOs that covers more commands.

my_zvm_vi_yank() {
    zvm_vi_yank
    echo -en "${CUTBUFFER}" | pbcopy
}

my_zvm_vi_delete() {
    zvm_vi_delete
    echo -en "${CUTBUFFER}" | pbcopy
}

my_zvm_vi_change() {
    zvm_vi_change
    echo -en "${CUTBUFFER}" | pbcopy
}

my_zvm_vi_change_eol() {
    zvm_vi_change_eol
    echo -en "${CUTBUFFER}" | pbcopy
}

my_zvm_vi_substitute() {
    zvm_vi_substitute
    echo -en "${CUTBUFFER}" | pbcopy
}

my_zvm_vi_substitute_whole_line() {
    zvm_vi_substitute_whole_line
    echo -en "${CUTBUFFER}" | pbcopy
}

my_zvm_vi_put_after() {
    CUTBUFFER=$(pbpaste)
    zvm_vi_put_after
    zvm_highlight clear # zvm_vi_put_after introduces weird highlighting
}

my_zvm_vi_put_before() {
    CUTBUFFER=$(pbpaste)
    zvm_vi_put_before
    zvm_highlight clear # zvm_vi_put_before introduces weird highlighting
}

my_zvm_vi_replace_selection() {
    CUTBUFFER=$(pbpaste)
    zvm_vi_replace_selection
    echo -en "${CUTBUFFER}" | pbcopy
}

zvm_after_lazy_keybindings() {
    zvm_define_widget my_zvm_vi_yank
    zvm_define_widget my_zvm_vi_delete
    zvm_define_widget my_zvm_vi_change
    zvm_define_widget my_zvm_vi_change_eol
    zvm_define_widget my_zvm_vi_put_after
    zvm_define_widget my_zvm_vi_put_before
    zvm_define_widget my_zvm_vi_substitute
    zvm_define_widget my_zvm_vi_substitute_whole_line
    zvm_define_widget my_zvm_vi_replace_selection

    zvm_bindkey vicmd 'C' my_zvm_vi_change_eol
    zvm_bindkey vicmd 'P' my_zvm_vi_put_before
    zvm_bindkey vicmd 'S' my_zvm_vi_substitute_whole_line
    zvm_bindkey vicmd 'p' my_zvm_vi_put_after

    zvm_bindkey visual 'p' my_zvm_vi_replace_selection
    zvm_bindkey visual 'c' my_zvm_vi_change
    zvm_bindkey visual 'd' my_zvm_vi_delete
    zvm_bindkey visual 's' my_zvm_vi_substitute
    zvm_bindkey visual 'x' my_zvm_vi_delete
    zvm_bindkey visual 'y' my_zvm_vi_yank
}
d9k commented 3 months ago

https://github.com/jeffreytse/zsh-vi-mode/issues/19#issuecomment-1268057812:

in Linux for these cool bindings to work set aliases before:

alias cbread='xclip -selection c'
alias cbprint='xclip -o -selection clipboard'
joihn commented 2 months ago

I applied it on linux. it works well when I first select the word via visual mode, then y however

edit: solved it !

I had to edit the source, https://github.com/jeffreytse/zsh-vi-mode/blob/master/zsh-vi-mode.zsh#L1829 to call my_zvm_vi_yank instead

d9k commented 2 months ago

@joihn, thanks!

permanent link:

y*) zvm_vi_yank false; cursor=;;

My little bit more accurate patch: 1) at the beginning of .zsh-vi-mode.zsh:

# see https://unix.stackexchange.com/questions/332005/test-for-functions-existence-that-can-work-on-both-bash-and-zsh
fn_exists()
{
  typeset -f $1 >/dev/null 2>&1;
}

2) at that line:

    # y*) zvm_vi_yank false; cursor=;;
    y*) fn_exists my_zvm_vi_yank && my_zvm_vi_yank false || zvm_vi_yank false; cursor=;;

It fixes yy but seems Y still not working :thinking: