" Vim global plugin for quickly and easily jumping to positions on screen " Maintainer: Barry Arthur " Version: 0.3 " Description: Jump to the object you're looking at! " Last Change: 2014-08-11 " License: Vim License (see :help license) " Location: plugin/kweasy.vim " Website: https://github.com/dahu/kweasy " " See kweasy.txt for help. This can be accessed by doing: " " :helptags ~/.vim/doc " :help kweasy let g:kweasy_version = '0.3' " Vimscript Setup: {{{1 " Allow use of line continuation. let s:save_cpo = &cpo set cpo&vim " load guard " uncomment after plugin development. " XXX The conditions are only as examples of how to use them. Change them as " needed. XXX "if exists("g:loaded_kweasy") " \ || v:version < 700 " \ || v:version == 703 && !has('patch338') " \ || &compatible " let &cpo = s:save_cpo " finish "endif "let g:loaded_kweasy = 1 " Plugin Options : {{{1 if !exists('g:kweasy_nolist') let g:kweasy_nolist = 0 endif if !exists('g:kweasy_hints') let g:kweasy_hints = 'asdfg;lkjh' endif " Private Functions: {{{1 " a-z A-Z 0-9 punct let s:index = map(range(97,97+25) + range(65,65+25) +range(48,48+9) + \ range(33,47) + range(58,64) + range(123,126), \ 'nr2char(v:val)') " move g:kweasy_hints to the beginning (filtering them out of s:index) let s:index = split(kweasy_hints, '\zs') \ + split(substitute(tr(join(s:index, ''), \ kweasy_hints, \ repeat(' ', len(kweasy_hints))), \ ' ', '', 'g'), \ '\zs') let s:len = len(s:index) function! s:trim(str) return substitute(a:str, '\s\+$', '', '') endfunction function! s:with_jump_marks(lines, pattern) let lines = a:lines let pattern = a:pattern let counter = Series() let newlines = [] let mask = "\n" let fill = pattern == ' ' ? "\r" : ' ' let lnum = line('w0') - 1 for l in lines let lnum += 1 " add a single empty line to newlines for each fold group if foldclosed(lnum) > 0 if foldclosed(lnum) == lnum call add(newlines, '') endif continue endif " mark the start of matches with the 'mask' and erasing with 'fill' let ms = match(l, pattern) while ms != -1 " use strchars() instead of len() to account for multibyte (wide) chars let fill_len = len(substitute(matchstr(l, pattern), '.', \ '\=repeat("x", strchars(submatch(0)))', 'g')) - 1 let l = substitute(l, pattern, mask . repeat(fill, fill_len), '') let ms = match(l, pattern) endwhile " clear stuff that isn't the 'mask' (or tabs to keep alignment) let l = substitute(l, '[^\t' . mask . ']', \ '\=repeat(" ", strchars(submatch(0)))', 'g') " replace 'mask's with jump-mark let ms = match(l, mask) while ms != -1 let c = counter.next() if c >= s:len break endif let l = substitute(l, '\m' . mask, escape(s:index[c], '&~'), '') let ms = match(l, mask) endwhile " we'd only have residual mask chars if there were too many to replace " with jump hints; erase these unreachable extras let l = substitute(l, mask, ' ', 'g') call add(newlines, s:trim(l)) endfor return newlines endfunction function! s:jump_marks_overlay(lines, cur_pos) let altbuf = bufnr('#') let cur_pos = a:cur_pos normal! 0 let first_col = wincol() let ts = &l:tabstop hide noautocmd enew setlocal buftype=nofile setlocal bufhidden=hide setlocal noswapfile let &l:numberwidth = first_col - 1 let &l:tabstop = ts call append(0, a:lines) $ delete _ redraw 1 let jump = escape(nr2char(getchar()), '^$.*~]\\') if jump == '' || jump == "\" || jump == "\" let jump_pos = cur_pos elseif search(jump . '\C', 'cW') == 0 let jump_pos = cur_pos else let jump_pos = getpos('.') " fix offset if there are tabs before jump target let jump_pos[2] = virtcol('.') endif buffer # bwipe # if buflisted(altbuf) exe 'buffer ' . altbuf silent! buffer # endif return jump_pos endfunction function! s:show_jump_marks_for(pattern) let lines = s:with_jump_marks(getline('w0', 'w$'), a:pattern) let top_of_window = line('w0') let cur_pos = getpos('.') let jump_pos = s:jump_marks_overlay(lines, cur_pos) " re-centre screen to pre-overlay view exe "normal! " . top_of_window . 'zt' call setpos('.', cur_pos) " jump to relative line,col exe 'normal! H' . jump_pos[1] . '_' exe 'normal! ' . jump_pos[2] . '|' endfunction function! s:check_dependencies() " Nexus is used for the Series() number generator if !exists('g:nexus_version') echohl Warn echom "vim-KWEasy depends on https://github.com/dahu/Nexus" echohl none return 0 endif return 1 endfunction "}}} " Public Interface: {{{1 function! KWEasyJump(char) if !s:check_dependencies() return endif let char = '\C' . escape(nr2char(a:char), '^$.*~]\\') if char == "\\C\" || char == "\\C\" || char == '\C' return endif call histadd('input', char) return KWEasySearch(char) endfunction function! KWEasySearch(pattern) if !s:check_dependencies() return endif let pattern = a:pattern if pattern == "\" || pattern == "\" || pattern == '' return endif if g:kweasy_nolist let save_list = &list set nolist endif let save_scrolloff = &so set so=0 call s:show_jump_marks_for(pattern) let &so = save_scrolloff if g:kweasy_nolist let &list = save_list endif endfunction function! KWEasySearchCmd() let g:kweasy_cmdline = getcmdline() return "\e:call KWEasySearch(g:kweasy_cmdline)\r" endfunction " Maps: {{{1 " nnoremap KweasyJump :call KWEasy(getchar()) nnoremap KweasyJump :call KWEasyJump(getchar()) if !hasmapto('KweasyJump') nmap k KweasyJump endif nnoremap KweasySearch :call KWEasySearch(input('/')) if !hasmapto('KweasySearch') nmap s KweasySearch endif nmap KweasyAgain KweasySearch if !hasmapto('KweasyAgain') nmap n KweasyAgain endif " Teardown:{{{1 "reset &cpo back to users setting let &cpo = s:save_cpo " Template From: https://github.com/dahu/Area-41/ " vim: set sw=2 sts=2 et fdm=marker: