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

26 Complete full lines #39

Merged
merged 6 commits into from
Jul 7, 2014
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 10 additions & 8 deletions autoload/tmuxcomplete.vim
Original file line number Diff line number Diff line change
Expand Up @@ -6,28 +6,30 @@ function! tmuxcomplete#init()
endif
endfunction

function! tmuxcomplete#words(scrollback)
function! tmuxcomplete#list(mode, scrollback)
let capture_args = s:capture_args . ' -S -' . a:scrollback
return tmuxcomplete#completions('', capture_args)
return tmuxcomplete#completions('', capture_args, a:mode)
endfunction

let s:script = expand('<sfile>:h:h') . "/sh/tmuxwords.sh"
let s:script = expand('<sfile>:h:h') . "/sh/tmuxcomplete"

function! tmuxcomplete#completions(base, capture_args)
function! tmuxcomplete#completions(base, capture_args, mode)
let base_pattern = '^' . escape(a:base, '*^$][.\') . '.'
let list_args = get(g:, 'tmuxcomplete#list_args', '-a')

let command = 'sh ' . shellescape(s:script)
let command .= ' ' . shellescape(a:mode)
let command .= ' ' . shellescape(base_pattern)
let command .= ' ' . shellescape(list_args)
let command .= ' ' . shellescape(a:capture_args)
echom command
Copy link
Contributor

Choose a reason for hiding this comment

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

I forgot to remove this.

Copy link
Owner Author

Choose a reason for hiding this comment

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

Will do.


let completions = system(command)
if v:shell_error == 0
return split(completions)
else
if v:shell_error != 0
return []
endif

return split(completions, '\n')
endfunction

function! tmuxcomplete#complete(findstart, base)
Expand All @@ -41,7 +43,7 @@ function! tmuxcomplete#complete(findstart, base)
endif
endif
" find words matching with "a:base"
return tmuxcomplete#completions(a:base, s:capture_args)
return tmuxcomplete#completions(a:base, s:capture_args, 'words')
endfun

function! tmuxcomplete#findstartword(line, max)
Expand Down
29 changes: 21 additions & 8 deletions autoload/unite/sources/tmuxcomplete.vim
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@ let s:save_cpo = &cpo
set cpo&vim

function! unite#sources#tmuxcomplete#define()
return s:s
return [ s:words, s:lines ]
endfunction

" define the tmuxcomplete source
let s:s = {
" tmuxcomplete WORDS source
let s:words = {
\ 'name' : 'tmuxcomplete',
\ 'description' : 'strings from tmux sessions',
\ 'description' : 'words in the current tmux session',
\ 'hooks' : {},
\ 'max_candidates' : 0,
\ 'default_kind' : 'word',
Expand All @@ -17,13 +17,26 @@ let s:s = {
\ 'source__maxstrings' : 0,
\ }

" function! s:s.hooks.on_init(args, context)
" call unite#print_source_message('tmux content', s:s.name)
" function! s:words.hooks.on_init(args, context)
" call unite#print_source_message('tmux content', s:words.name)
" endfunction

" provides the results for unite to search/filter/sort.
function! s:s.gather_candidates(args, context)
return map(tmuxcomplete#words(s:s.source__maxstrings), "{
function! s:words.gather_candidates(args, context)
return map(tmuxcomplete#list('words', 0), "{
\ 'word' : v:val,
\ 'is_multiline' : 0,
\ 'action__text' : v:val,
\ }")
endfunction

" tmuxcomplete LINES source
let s:lines = deepcopy(s:words)
let s:lines.name = 'tmuxcomplete/lines'
let s:lines.description = 'lines in the current tmux session'

function! s:lines.gather_candidates(args, context)
return map(tmuxcomplete#list('lines', 0), "{
\ 'word' : v:val,
\ 'is_multiline' : 0,
\ 'action__text' : v:val,
Expand Down
37 changes: 26 additions & 11 deletions sh/tmuxwords.sh → sh/tmuxcomplete
Original file line number Diff line number Diff line change
@@ -1,16 +1,21 @@
#!/bin/sh

# Usage: Get a list of all currently visible words:
# sh tmuxwords.sh '' -a
# sh tmuxcomplete words '' -a
#
# Get all visible words beginning with `foo`:
# sh tmuxwords.sh ^foo -a
# sh tmuxcomplete words ^foo -a
#
# Get all visible lines beginning with `foo`:
# sh tmuxcomplete lines ^foo -a ''

if [ -z "$TMUX_PANE" ]; then
echo "Not running inside tmux!" 1>&2
exit 1
fi

MODE="$1" PATTERN="$2" LISTARGS="$3" CAPTUREARGS="$4"

capturepane() {
if [ tmux capture-pane -p &> /dev/null ]; then
# tmux capture-pane understands -p -> use it
Expand All @@ -22,21 +27,31 @@ capturepane() {
fi
}

splitwords() {
# copy lines and split words
sed -e 'p;s/[^a-zA-Z0-9_]/ /g' |
# split on spaces
tr -s '[:space:]' '\n' |
# remove surrounding non-word characters
grep -o "\\w.*\\w"
}

splitlines() {
# remove surrounding whitespace
grep -o "\\S.*\\S"
}
Copy link
Contributor

Choose a reason for hiding this comment

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

It's odd that this is \S but the words equivalent is \w. Maybe I made a mistake here.

Copy link
Owner Author

Choose a reason for hiding this comment

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

Good point. The behavior differs when there are trailing non-space non-word characters. Given this line

    "foo" -> "bar;
grep -o "\\S.*\\S"

would capture

"foo" -> "bar;

Because we always start completion at a word character it might make more sense to use

grep -o "\\w.*\\S"

which would capture

foo" -> "bar;

That might not be wanted for the lines presented in Unite, though.

What do you think?

Copy link
Contributor

Choose a reason for hiding this comment

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

Actually my original concern is not valid. But the problem you bring up is definitely tricky. I'd say that for full lines, the user really does want the entire line, including non-word chars. This would be a problem for any completion engine that does not do partial matches (I'm guessing the built-in omni complete), but it shouldn't be a problem for Neocomplete and definitely not for Unite.

Copy link
Owner Author

Choose a reason for hiding this comment

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

I'm actually leaning towards different modes (like lines and LINES) to capture the respective versions. The former would be used for insert mode completion and the latter for Unite.

Copy link
Contributor

Choose a reason for hiding this comment

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

Ok. In the meantime whatever gets it merged is fine with me :)


# list all panes
tmux list-panes $2 -F '#{pane_active}#{window_active}-#{session_id} #{pane_id}' |
tmux list-panes $LISTARGS -F '#{pane_active}#{window_active}-#{session_id} #{pane_id}' |
# filter out current pane (use -F to match $ in session id)
grep -v -F "$(tmux display-message -p '11-#{session_id} ')" |
# take the pane id
cut -d' ' -f2 |
# capture panes
capturepane "$3" |
# copy lines and split words
sed -e 'p;s/[^a-zA-Z0-9_]/ /g' |
# split on spaces
tr -s '[:space:]' '\n' |
# remove surrounding non-word characters
grep -o "\\w.*\\w" |
capturepane "$CAPTUREARGS" |
# split words or lines depending on mode
( [ "$MODE" = "lines" ] && splitlines || splitwords ) |
# filter out words not beginning with pattern
grep "$1" |
grep "$PATTERN" |
# sort and remove duplicates
sort -u