wellle / tmux-complete.vim

Vim plugin for insert mode completion of words in adjacent tmux panes
MIT License
515 stars 21 forks source link

Feature suggestion: copy all visible lines in specified tmux pane to buffer (I included a working implemention as example) #94

Open Matt-A-Bennett opened 2 years ago

Matt-A-Bennett commented 2 years ago

I really like this plugin!

I ended up taking the tmuxcomplete script and modifying it to allow me to copy all the visible lines in a specified tmux pane to it's own buffer. Then I can edit/copy lines I want and paste them into other buffers using all of vim's power. I wonder if this would be useful to others? I haven't got much experience with writing vim plugins so I'm not sure I could create a useful pull request (but I'd be up for trying). In any case I'll include the changes here so anyone can make use of them and give feedback. Thanks.

Demo of what I've done

A vim session, with a couple of tmux panes on the side

before

Calling my command

pane_selection

After specifying pane 1

pane_1

Doing the above but specifying pane 2

pane_2

.vimrc functions to achieve the above (using altered tmuxcomplete script - see below)

When I want to pull in the contents of a tmux pane, I call a function that asks which pane I want, opens a split, and calls tmuxcomplete with instructions for which pane to target, and to give me a list of lines, and not to sort them:

function! TmuxPaneToBuffer()
    call DisplayTmuxPaneIndices("350")
    " get the input from user
    let targetpane = input("target_pane:")
    if targetpane =~ '\d\+'
        silent execute 'split .tmux_pane_'.targetpane
        silent execute '%!sh /path/to/tmuxcomplete -t '.targetpane.' -s lines -n'
        set filetype=bash
        setlocal buftype=nofile
        setlocal bufhidden=hide
        setlocal noswapfile
        setlocal nobuflisted
    endif
endfunction                             

To make it easier to know the indices of each pane, at the beginning of the function above, I issue a command to tmux to flash the pane indices on screen:

function! DisplayTmuxPaneIndices(duration)
    " bring up the pane numbers as a background job
    call job_start(["tmux", "display-pane", "-d", a:duration])
endfunction                             

Changes to tmuxcomplete script

First I created a new option to specify a particular pane (by it's index) to grab the contents from (I just show the lines that I changed/added in tmuxcomplete):

# Words visible in specified pane in current window
# (can't be used alongside the -e option)
#     sh tmuxcomplete -t <pane_idex>

TARGET='-1'
while getopts enp:s:t:l:c:g: name
    t) TARGET="$OPTARG";;
    *) echo "Usage: $0 [-t <pane_index>] [-p pattern] [-s splitmode] [-l listargs] [-c captureargs] [-g grepargs]\n"

I changed the 'excludecurrent()' function to 'targetpanes()' and added the case when a -t <pane_index> argument is made:

targetpanes() {
    if [ "$EXCLUDE" = "1" ]; then
        currentpane=$(tmux display-message -p '11-#{session_id} ')
        # echo 1>&2 'current' "$currentpane"
        # use -F to match $ in session id
        grep -v -F "$currentpane"
    elif ! [ "$TARGET" = "-1" ]; then
        targetpane=$(tmux display-message -p '01-#{session_id} ')$TARGET
        grep -F "$targetpane"
    else
        cat
    fi
}

Since I wanted the lines of the tmux pane transferred to a vim buffer exactly as they appeared (i.e. unsorted and retaining any line duplicates), I changed the existing 'sortu()' function to keep duplicate lines when not sorting:

# modified
sortu() {
    if [ "$NOSORT" = "1" ]; then
        cat
    else
        sort -u
    fi
}

Here I of course changed the 'excludecurrent' to 'targetpanes':

# list all panes
listpanes |
# filter out current pane
targetpanes |
# take the pane id
paneids |
...