Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Yank to system clipboard #192

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open

Yank to system clipboard #192

wants to merge 1 commit into from

Conversation

brorbw
Copy link

@brorbw brorbw commented Sep 24, 2022

A very preliminary stab at using the system clipboard for cutting, deleting and yanking. This does contain code for getting the system clipboard but I think that requires a bit more thought than I want to pour into this ATM.

The code is more or less "borrowed (read: stolen)" from https://github.com/kutsan/zsh-system-clipboard/blob/master/zsh-system-clipboard.zsh#L13-L87

@niksingh710
Copy link

will this be merged?

Copy link
Owner

@jeffreytse jeffreytse left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi, @brorbw

Thanks for your contribution to the system clipboard implementation, I'd love for a more common and flexible implementation, and it would not involve code of other repositories in.

Thanks & Regards

@jeffreytse jeffreytse added the enhancement New feature or request label Dec 29, 2022
@brorbw
Copy link
Author

brorbw commented Jan 1, 2023

@jeffreytse I understand. I use this locally because otherwise it zsh-vi-mode breaks my workflow compared to other applications with a vim mode. I thought that if nothing else this could serve as an easy starting point for an implementation 🤷🏻

@asmodeus812
Copy link

@brorbw i mean we have this already - https://github.com/ohmyzsh/ohmyzsh/blob/master/lib/clipboard.zsh. Is it not possible to integrate it with this plugin ?

@brorbw
Copy link
Author

brorbw commented Jan 16, 2023

@asmodeus812 I didn't know that existed. Yes it should make this implementation much easier

@brorbw
Copy link
Author

brorbw commented Feb 20, 2023

@jeffreytse would using hmyzsh/ohmyzsh@master/lib/clipboard.zsh be the flexible solution you are looking for?

@effinsky
Copy link

@jeffreytse would using hmyzsh/ohmyzsh@master/lib/clipboard.zsh be the flexible solution you are looking for?

hope this sees some action sooon :)

@lukebmay
Copy link

I've added a very small monkey patch (27 additional lines) that implements system clipboard functionality with external commands xsel and wl-clipboard. It looks like a lot of code because I have to reimplement existing functions, but in each function only has less than a dozen lines added, in one or two places. My additions are labeled #### CLIPBOARD ADDITONS.

What currently works now is to just add the following to ~/.zshrc somewhere after the ZVM module has loaded:

if [[ $ZVM_NAME == 'zsh-vi-mode' ]]; then

    # Duplicated from source ZVM, but added clipboard support.
    function zvm_yank() {
        local ret=($(zvm_calc_selection $1))
        local bpos=$ret[1] epos=$ret[2] cpos=$ret[3]
        CUTBUFFER=${BUFFER:$bpos:$((epos-bpos))}
        if [[ ${1:-$ZVM_MODE} == $ZVM_MODE_VISUAL_LINE ]]; then
            CUTBUFFER=${CUTBUFFER}$'\n'
        fi
        #### CLIPBOARD ADDITIONS - begin
        if test "$XDG_SESSION_TYPE" = "x11"; then
            printf "%s" $CUTBUFFER | xsel -ib
        elif test "$XDG_SESSION_TYPE" = "wayland"; then
            printf "%s" $CUTBUFFER | wl-copy
        fi
        #### CLIPBOARD ADDITIONS - end
        CURSOR=$bpos MARK=$epos
    }

    # Duplicated from source ZVM, but added clipboard support.
    function zvm_replace_selection() {
        local ret=($(zvm_calc_selection))
        local bpos=$ret[1] epos=$ret[2] cpos=$ret[3]
        local cutbuf=$1
        #### CLIPBOARD ADDITIONS - begin
        if [[ -n $cutbuf ]]; then
            if test "$XDG_SESSION_TYPE" = "x11"; then
                cutbuf="$(xsel -ob)"
            elif test "$XDG_SESSION_TYPE" = "wayland"; then
                cutbuf="$(wl-paste)"
            fi
        fi
        #### CLIPBOARD ADDITIONS - end

        # If there's a replacement, we need to calculate cursor position
        if (( $#cutbuf > 0 )); then
            cpos=$(($bpos + $#cutbuf - 1))
        fi

        CUTBUFFER=${BUFFER:$bpos:$((epos-bpos))}

        # Check if it is visual line mode
        if [[ $ZVM_MODE == $ZVM_MODE_VISUAL_LINE ]]; then
            if (( $epos < $#BUFFER )); then
                epos=$epos+1
            elif (( $bpos > 0 )); then
                bpos=$bpos-1
            fi
            CUTBUFFER=${CUTBUFFER}$'\n'
        fi
        #### CLIPBOARD ADDITIONS - begin
        if test "$XDG_SESSION_TYPE" = "x11"; then
            printf "%s" $CUTBUFFER | xsel -ib
        elif test "$XDG_SESSION_TYPE" = "wayland"; then
            printf "%s" $CUTBUFFER | wl-copy
        fi
        #### CLIPBOARD ADDITIONS - end

        BUFFER="${BUFFER:0:$bpos}${cutbuf}${BUFFER:$epos}"
        CURSOR=$cpos
    }

    # Duplicated from source ZVM, but added clipboard support.
    function zvm_vi_put_after() {
        a="$a p"
        local head= foot=
        local content=${CUTBUFFER}
        local offset=1
        #### CLIPBOARD ADDITIONS - begin
        if test "$XDG_SESSION_TYPE" = "x11"; then
            content="$(xsel -ob)"
        elif test "$XDG_SESSION_TYPE" = "wayland"; then
            content="$(wl-paste)"
        fi
        #### CLIPBOARD ADDITIONS - end

        if [[ ${content: -1} == $'\n' ]]; then
            local pos=${CURSOR}

            # Find the end of current line
            for ((; $pos<$#BUFFER; pos++)); do
                if [[ ${BUFFER:$pos:1} == $'\n' ]]; then
                    pos=$pos+1
                    break
                fi
            done

            # Special handling if cursor at an empty line
            if zvm_is_empty_line; then
                head=${BUFFER:0:$pos}
                foot=${BUFFER:$pos}
            else
                head=${BUFFER:0:$pos}
                foot=${BUFFER:$pos}
                if [[ $pos == $#BUFFER ]]; then
                    content=$'\n'${content:0:-1}
                    pos=$pos+1
                fi
            fi

            offset=0
            BUFFER="${head}${content}${foot}"
            CURSOR=$pos
        else
            # Special handling if cursor at an empty line
            if zvm_is_empty_line; then
                head="${BUFFER:0:$((CURSOR-1))}"
                foot="${BUFFER:$CURSOR}"
            else
                head="${BUFFER:0:$CURSOR}"
                foot="${BUFFER:$((CURSOR+1))}"
            fi

            BUFFER="${head}${BUFFER:$CURSOR:1}${content}${foot}"
            CURSOR=$CURSOR+$#content
        fi

        # Reresh display and highlight buffer
        zvm_highlight clear
        zvm_highlight custom $(($#head+$offset)) $(($#head+$#content+$offset))
    }

    # Duplicated from source ZVM, but added clipboard support.
    # Put cutbuffer before the cursor
    function zvm_vi_put_before() {
        b="$b P"
        local head= foot=
        local content=${CUTBUFFER}
        #### CLIPBOARD ADDITIONS - begin
        if test "$XDG_SESSION_TYPE" = "x11"; then
            content="$(xsel -ob)"
        elif test "$XDG_SESSION_TYPE" = "wayland"; then
            content="$(wl-paste)"
        fi
        #### CLIPBOARD ADDITIONS - end

        if [[ ${content: -1} == $'\n' ]]; then
            local pos=$CURSOR

            # Find the beginning of current line
            for ((; $pos>0; pos--)); do
                if [[ "${BUFFER:$pos:1}" == $'\n' ]]; then
                    pos=$pos+1
                    break
                fi
            done

            # Check if it is an empty line
            if zvm_is_empty_line; then
                head=${BUFFER:0:$((pos-1))}
                foot=$'\n'${BUFFER:$pos}
                pos=$((pos-1))
            else
                head=${BUFFER:0:$pos}
                foot=${BUFFER:$pos}
            fi

            BUFFER="${head}${content}${foot}"
            CURSOR=$pos
        else
            head="${BUFFER:0:$CURSOR}"
            foot="${BUFFER:$((CURSOR+1))}"
            BUFFER="${head}${content}${BUFFER:$CURSOR:1}${foot}"
            CURSOR=$CURSOR+$#content
            CURSOR=$((CURSOR-1))
        fi

        # Reresh display and highlight buffer
        zvm_highlight clear
        zvm_highlight custom $#head $(($#head+$#content))
    }
fi

@jeffreytse Would something like this be reasonable to add? If you think I'm on the right track I can implement the changes and put a a pull request. I can add in xclip support too if you like.

@S1M0N38
Copy link

S1M0N38 commented Nov 22, 2024

@lukebmay, can it be extended to macOS pbcopy/pbpaste?

@lukebmay
Copy link

@S1M0N38 I don't know why not. I don't have a mac to test on though. All you need to do to test it is to add that snippent above to the end of your ~/.zshrc and then in each of the #### CLIPBOARD ADDITIONS sections add in an if check that will verify you're on mac, then add the line for mac in each function. It should only be 5 lines or so, assuming pbcopy and pbpaste work the same as the other clipboard utilities.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants