"============================================================================= " FILE: line.vim " AUTHOR: Shougo Matsushita " t9md " License: MIT license {{{ " Permission is hereby granted, free of charge, to any person obtaining " a copy of this software and associated documentation files (the " "Software"), to deal in the Software without restriction, including " without limitation the rights to use, copy, modify, merge, publish, " distribute, sublicense, and/or sell copies of the Software, and to " permit persons to whom the Software is furnished to do so, subject to " the following conditions: " " The above copyright notice and this permission notice shall be included " in all copies or substantial portions of the Software. " " THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS " OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF " MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. " IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY " CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, " TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE " SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. " }}} "============================================================================= " original verion is http://d.hatena.ne.jp/thinca/20101105/1288896674 call unite#util#set_default( \ 'g:unite_source_line_enable_highlight', 0) let s:supported_search_direction = \ ['forward', 'backward', 'all', 'buffers', 'args'] function! unite#sources#line#define() abort "{{{ return s:source_line endfunction "}}} " line source. "{{{ let s:source_line = { \ 'name' : 'line', \ 'syntax' : 'uniteSource__Line', \ 'hooks' : {}, \ 'max_candidates': 100, \ 'default_kind' : 'jump_list', \ 'matchers' : 'matcher_regexp', \ 'sorters' : 'sorter_nothing', \ } function! s:source_line.hooks.on_init(args, context) abort "{{{ let a:context.source__linenr = line('.') let a:context.source__linemax = line('$') let a:context.source__is_bang = \ (get(a:args, 0, '') ==# '!') let options = filter(copy(a:args), "v:val != '!'") let direction = get(options, 0, '') if direction == '' let direction = 'all' endif let a:context.source__wrap = get(options, 1, \ (&wrapscan ? 'wrap' : 'nowrap')) ==# 'wrap' if index(s:supported_search_direction, direction) == -1 let direction = 'all' endif let a:context.source__bufnrs = \ (direction ==# 'buffers') ? \ filter(range(1, bufnr('$')), 'buflisted(v:val)') : \ (direction ==# 'args') ? \ filter(map(argv(), "bufnr(v:val)"), 'v:val > 0') : \ [bufnr('%')] " Dummy loading call s:dummy_loading(a:context.source__bufnrs) if len(a:context.source__bufnrs) == 1 let a:context.source__syntax = \ getbufvar(a:context.source__bufnrs[0], '&l:syntax') endif let a:context.source__input = a:context.input if a:context.source__linemax > 10000 && a:context.source__input == '' " Note: In huge buffer, you must input narrowing text. let a:context.source__input = unite#util#input('Narrowing text: ', '') endif if a:context.source__input != '' call unite#print_source_message( \ 'Narrowing text: ' . a:context.source__input, \ s:source_line.name) endif if len(a:context.source__bufnrs) == 1 call unite#print_source_message( \ 'Target: ' . bufname(a:context.source__bufnrs[0]), \ s:source_line.name) endif let a:context.source__direction = direction endfunction"}}} function! s:source_line.hooks.on_syntax(args, context) abort "{{{ let highlight = get(a:context, 'custom_line_enable_highlight', \ g:unite_source_line_enable_highlight) if len(a:context.source__bufnrs) > 1 syntax match uniteSource__LineFile /^[^:]*:/ contained \ containedin=uniteSource__Line \ nextgroup=uniteSource__LineSeparator highlight default link uniteSource__LineFile Comment endif syntax match uniteSource__LineLineNR /\d\+:/ contained \ containedin=uniteSource__Line syntax match uniteSource__LineSeparator /:/ contained conceal \ containedin=uniteSource__LineFile,uniteSource__LineLineNR highlight default link uniteSource__LineLineNR LineNR if !highlight || len(a:context.source__bufnrs) > 1 return endif let save_current_syntax = get(b:, 'current_syntax', '') unlet! b:current_syntax try execute 'silent! syntax include @LineSyntax' 'syntax/' \ . a:context.source__syntax . '.vim' syntax region uniteSource__Line_LineSyntax \ start='' end='$' \ contains=@LineSyntax \ containedin=uniteSource__Line contained finally let b:current_syntax = save_current_syntax endtry endfunction"}}} function! s:source_line.hooks.on_post_filter(args, context) abort "{{{ for candidate in a:context.candidates let candidate.is_multiline = 1 let candidate.action__col_pattern = a:context.source__input let candidate.action__buffer_nr = candidate.source__info[0] let candidate.action__line = candidate.source__info[1][0] let candidate.action__text = candidate.source__info[1][1] endfor endfunction"}}} function! s:source_line.gather_candidates(args, context) abort "{{{ let direction = a:context.source__direction let start = a:context.source__linenr let _ = s:get_context_lines(a:context, direction, start) let a:context.source__format = \ (len(a:context.source__bufnrs) > 1) ? \ '%s:%4s: %s' : \ '%' . strlen(len(_)) . 'd: %s' return direction ==# 'backward' ? reverse(_) : _ endfunction"}}} function! s:source_line.complete(args, context, arglead, cmdline, cursorpos) abort "{{{ return s:supported_search_direction endfunction"}}} function! s:source_line.source__converter(candidates, context) abort "{{{ if len(a:context.source__bufnrs) > 1 for candidate in a:candidates let candidate.abbr = printf(a:context.source__format, \ unite#util#substitute_path_separator( \ fnamemodify(bufname(candidate.source__info[0]), ':.')), \ candidate.source__info[1][0], \ substitute(candidate.source__info[1][1], '\s\+$', '', '')) endfor else for candidate in a:candidates let candidate.abbr = printf(a:context.source__format, \ candidate.source__info[1][0], \ substitute(candidate.source__info[1][1], '\s\+$', '', '')) endfor endif return a:candidates endfunction"}}} let s:source_line.converters = [s:source_line.source__converter] "}}} " Misc. "{{{ function! s:on_gather_candidates(direction, context, start, max) abort "{{{ let candidates = [] for bufnr in a:context.source__bufnrs " source__info = [bufnr, [line, text]] let candidates += map(s:get_lines(a:context, a:direction, \ bufnr, a:start, a:max), "{ \ 'word' : v:val[1], \ 'source__info' : [bufnr, v:val], \ }") endfor return candidates endfunction"}}} function! s:get_lines(context, direction, bufnr, start, max) abort "{{{ let [start, end] = \ a:direction ==# 'forward' ? \ [a:start, (a:max == 0 ? '$' : a:start + a:max - 1)] : \ [((a:max == 0 || a:start == a:max) ? \ 1 : a:start - a:max), a:start] let _ = [] let linenr = start let input = tolower(a:context.source__input) let is_expr = input =~ '[~\\.^$\[\]*]' for line in getbufline(a:bufnr, start, end) if input == '' \ || (!is_expr && stridx(tolower(line), input) >= 0) \ || line =~? input call add(_, [linenr, line]) endif let linenr += 1 endfor return _ endfunction"}}} function! s:get_context_lines(context, direction, start) abort "{{{ if a:direction !=# 'forward' && a:direction !=# 'backward' let lines = s:on_gather_candidates('forward', a:context, 1, 0) else let lines = s:on_gather_candidates(a:direction, a:context, a:start, 0) if a:context.source__wrap let start = ((a:direction ==# 'forward') ? \ 1 : a:context.source__linemax) let max = ((a:direction ==# 'forward') ? \ a:context.source__linenr-1 : \ a:context.source__linemax-a:context.source__linenr-1) if max != 0 let lines += s:on_gather_candidates(a:direction, a:context, start, max) endif endif endif return lines endfunction"}}} function! s:dummy_loading(bufnrs) abort "{{{ let load_bufnrs = filter(copy(a:bufnrs), '!bufloaded(v:val)') if empty(load_bufnrs) return endif let prev_bufnr = bufnr('%') try silent bufdo echo finally execute 'buffer' prev_bufnr endtry endfunction"}}} "}}} " vim: foldmethod=marker