Skip to content
Open
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
10 changes: 10 additions & 0 deletions README
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,13 @@ then :bp(revious) in the last buffer (B) would open up buffer A, where C is
preferable. This plugin supplies the user with the commands :BufSurfForward
and :BufSurfBack to navigate buffers forwards and backwards according to the
navigation history.

Plugin also provides Unite [1] source for displaying bufsurf history for last
accessed window as a list of buffer candidates. Usage: `:Unite bufsurf`.
This source is actually a thin wrapper over stock Unite buffer source made
with using sorter_bufsurf filter. Filter accesses bufsurf history (list of
buffers' numbers) and converts it into buffers list consisting of matching
candidates got from list of candidates passed to filter, also preselecting
current buffer in Unite UI (by default).

[1] https://github.com/Shougo/unite.vim
94 changes: 94 additions & 0 deletions autoload/unite/filters/sorter_bufsurf.vim
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
" sorter_bufsurf.vim
"
" MIT license applies, see LICENSE for licensing details.

let s:save_cpo = &cpo
set cpo&vim

function! unite#filters#sorter_bufsurf#define() "{{{
return s:sorter
endfunction"}}}

let s:sorter = {
\ 'name': 'sorter_bufsurf',
\ 'description': 'sorts buffers to match with bufsurf history',
\}

" bufsurf filter implementation.
"
" Filter expects candidate containing key `action__buffer_nr` (any other
" candidates are filtered out). Filter converts `w:history` variable
" mantained by bufsurf into list of matching candidates (matched by
" value of `candidate.action__buffer_nr`). Any buffer from `w:history`
" missing in candidates list is filtered out.
"
" Filter also preselects current buffer in resulting list (if selection
" wasn't explicitly set by user through `:Unite` option) according to variable
" `w:history_index` maintained by bufsurf.
function! s:sorter.filter(candidates, context) "{{{
let l:window = winnr('#')
let l:history = getwinvar(l:window, 'history', [])
let l:history_index = getwinvar(l:window, 'history_index')
let l:history_buffers =
\ s:history_buffers(l:history, a:candidates, l:history_index)
call s:preselect_current_buffer(l:history_buffers, a:context)
" Get only those buffers from history that existed in candidates.
return filter(map(l:history_buffers, 'v:val[0]'), 'v:val isnot 0')
endfunction"}}}

" Convert `w:history` variable into list of tuples consisting of buffer
" candidate and flag showing whether `w:history_index` points to this buffer.
function! s:history_buffers(history, candidates, history_index) "{{{
" Make dictionary where number of buffer is mapped to candidate from
" candidates list.
let l:numbered_buffers = {}
for l:candidate in a:candidates
" If it doesn't have `action__buffer_nr`, it's not a buffer candidate (or,
" at least, it's not a candidate from stock buffer source).
if has_key(l:candidate, 'action__buffer_nr')
let l:numbered_buffers[candidate.action__buffer_nr] = candidate
endif
endfor
" Map `w:history` element to
" `[matching_buffer_candidate_or_zero, element_is_the_current_buffer]`.
return map(
\ copy(a:history),
\ '[get(l:numbered_buffers, v:val), (v:key == a:history_index)]')
endfunction"}}}

" Set `context.select` to index of current buffer.
function! s:preselect_current_buffer(history_buffers, context) "{{{
" Context passed in arguments could be either a reference to real context or
" a reference to its' copy. We need to change real context, so take
" a guaranteed reference to it.
let l:ctx = unite#get_context()
" If `context.select` is set to 0 or positive number, it was probably
" already explicitly set by user through `-select` Unite option, so default
" behavior should be skipped.
if l:ctx.select >= 0 | return | endif
" Try to find current buffer amongst candidates and preselect it by setting
" `context` value.
let l:ctx.select = 0
for [l:_, l:is_current_buffer] in a:history_buffers
unlet! l:_ " because it could be of different types
if !l:is_current_buffer
let l:ctx.select += 1
continue
endif
" When Unite is invoked with `-no-split` option, it shows up as a buffer
" in current window and this Unite buffer is put in `w:history`. However,
" this buffer isn't included in candidates returned by stock buffer
" source. Here this situation is handled by selecting previous buffer in
" history.
while (l:ctx.select > -1) && (a:history_buffers[l:ctx.select][0] is 0)
let l:ctx.select -= 1
endwhile
" Selection is set, so return early.
return
endfor
endfunction"}}}

let &cpo = s:save_cpo
unlet s:save_cpo

" vim: foldmethod=marker
21 changes: 21 additions & 0 deletions autoload/unite/sources/bufsurf.vim
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
" bufsurf.vim
"
" MIT license applies, see LICENSE for licensing details.

let s:save_cpo = &cpo
set cpo&vim

function! unite#sources#bufsurf#define()
return s:source
endfunction

" Basically, just stock Unite buffer source with changed sorter.
let s:source = deepcopy(unite#get_all_sources('buffer'))
let s:source.name = 'bufsurf'
let s:source.description = 'candidates from bufsurf history'
let s:source.sorters = ['sorter_bufsurf']

let &cpo = s:save_cpo
unlet s:save_cpo

" vim: foldmethod=marker
17 changes: 17 additions & 0 deletions doc/bufsurf.txt
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,23 @@ The following is a list of all available options:

Indicates whether BufSurf (warning) messages should be displayed.

UNITE SOURCE *bufsurf-unite-source-bufsurf*

bufsurs provides |unite| source for displaying bufsurf history for last
accessed window as a list of buffer candidates. Usage example:
>
:Unite bufsurf
<


*bufsurf-unite-filter-sorter_bufsurf*
bufsurf's Unite source is actually a thin wrapper over stock Unite buffer
source made with using sorter_bufsurf Unite filter (also provided by bufsurf).
Filter accesses bufsurf history (list of buffers' numbers) and converts it
into buffers list consisting of matching candidates got from list of
candidates passed to filter. Filter also preselects current buffer in Unite UI
(by default).


LICENSE *bufsurf-license*

Expand Down