changeset 435:b7682004288d

Move Vim stuff to autoload, add FZF tags lister.
author Ludovic Chabant <ludovic@chabant.com>
date Wed, 04 Apr 2018 20:36:11 -0700
parents 44afdeba29bf
children 8986ec3a9c1c
files vim/autoload/ludo.vim vim/scripts/list_tags.py vim/vimrc
diffstat 3 files changed, 154 insertions(+), 34 deletions(-) [+]
line wrap: on
line diff
--- a/vim/autoload/ludo.vim	Wed Apr 04 20:35:50 2018 -0700
+++ b/vim/autoload/ludo.vim	Wed Apr 04 20:36:11 2018 -0700
@@ -1,5 +1,28 @@
 let g:ludo_trace = 0
 
+" Get the platform we're running on.
+if has("win32") || has("win64") || has("dos32")
+    let s:vim_platform = "windows"
+    let s:path_sep = "\\"
+elseif has("mac")
+    let s:vim_platform = "mac"
+    let s:path_sep = '/'
+else
+    let s:vim_platform = "unix"
+    let s:path_sep = '/'
+endif
+function! ludo#platform() abort
+    return s:vim_platform
+endfunction
+
+" Get our vim directory. 
+let s:vim_home = expand("<sfile>:h:h")
+
+" Get local path.
+function! ludo#localpath(...) abort
+    return s:vim_home.s:path_sep.join(a:000, s:path_sep)
+endfunction
+
 " Debug logging.
 function! ludo#trace(msg) abort
     if g:ludo_trace
@@ -74,6 +97,8 @@
     call ludo#trace("Exclude list: ".join(g:pathogen_disabled, ', '))
 endfunction
 
+" Goyo writing mode tweaks
+"
 let s:ludo_revert = {}
 
 function! ludo#on_goyo_enter()
@@ -114,3 +139,56 @@
     Goyo
 endfunction
 
+" Better tags browser using FZF
+"
+function! ludo#run_fzf_tags(args, bang) abort
+    let l:tag_files = tagfiles()
+    let l:tag_lister = 
+                \'python '.
+                \ludo#localpath('scripts', 'list_tags.py').' -a 24 '.
+                \join(map(l:tag_files, "shellescape(v:val)"))
+    let options = {
+                \'source': l:tag_lister,
+                \'sink': function('s:tags_sink'),
+                \'options': '--algo=v1 --tiebreak=begin --prompt "Tags> "'
+                \}
+    return fzf#run(fzf#wrap('tags', options, a:bang))
+endfunction
+
+function! s:tags_sink(line) abort
+	let l:tokens = matchlist(
+                \a:line, 
+                \'\v^(\S+)\s+([^\t]+)\t([^\t]{-1,})(;")?\t[a-z]+\tline\:([0-9]+)')
+    if len(l:tokens) < 5
+        call fb#warn("Couldn't parse line '".a:line."', got '".string(l:tokens)."'")
+        return
+    endif
+
+    let [l:tag, l:source_path, l:regex, l:line] = 
+                \[l:tokens[1], tolower(l:tokens[2]), l:tokens[3], l:tokens[4]]
+    let l:cur_path = fnamemodify(bufname('%'), ':p')
+    let l:candidates = taglist(l:tag, l:cur_path)
+
+    if len(l:candidates) == 0
+        call fb#warn("No candidates found for '".l:tag."'")
+        return
+    endif
+
+    if len(l:candidates) == 1
+        execute ':tjump '.l:tag
+        return
+    endif
+
+    let l:tagidx = 0
+    for cndd in l:candidates
+        let l:tagidx += 1
+        if tolower(cndd['filename']) != l:source_path
+            continue
+        endif
+        if cndd['cmd'] != l:regex
+            continue
+        endif
+        break
+    endfor
+    execute ':'.string(l:tagidx).'tag '.l:tag
+endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/scripts/list_tags.py	Wed Apr 04 20:36:11 2018 -0700
@@ -0,0 +1,57 @@
+import sys
+import argparse
+
+
+def main():
+    parser = argparse.ArgumentParser()
+    parser.add_argument('tagfiles', nargs='+',
+                        help="Tag files to list from.")
+    parser.add_argument('-a', '--align', default=0, type=int,
+                        help="Aligns tag names to the given width.")
+    parser.add_argument('-s', '--simple', action='store_true',
+                        help="Only show the tag name and file path.")
+    args = parser.parse_args()
+
+    outwrite = sys.stdout.write
+    tagfiles = list(args.tagfiles)
+
+    printer = _print_line
+    if args.align > 0 or args.simple:
+        printer = _make_aligning_line_printer(args.align, args.simple)
+
+    for tagfile in tagfiles:
+        with open(tagfile, 'r') as fp:
+            try:
+                for line in fp:
+                    if not line.startswith('!'):
+                        printer(line, outwrite)
+            except (IOError, KeyboardInterrupt):
+                # For Ctrl-C directly or through a pipe.
+                break
+    sys.stdout.flush()
+
+
+def _print_line(line, outwrite):
+    outwrite(line)
+
+
+def _make_aligning_line_printer(alignment, simple):
+    def _print_line_with_alignment(line, outwrite):
+        tokens = line.rstrip().split('\t')
+        tok0_len = len(tokens[0])
+        padding = alignment - tok0_len
+        outwrite(tokens[0])
+        if padding > 0:
+            outwrite(' ' * padding)
+        outwrite('\t')
+        if simple:
+            outwrite(tokens[1])
+        else:
+            outwrite('\t'.join(tokens[1:]))
+        outwrite("\n")
+
+    return _print_line_with_alignment
+
+
+if __name__ == '__main__':
+    main()
--- a/vim/vimrc	Wed Apr 04 20:35:50 2018 -0700
+++ b/vim/vimrc	Wed Apr 04 20:36:11 2018 -0700
@@ -19,23 +19,8 @@
 endif
 let g:sourced_vimrc = 1
 
-" Get the platform we're running on.
-if has("win32") || has("win64") || has("dos32")
-    let s:vim_platform = "windows"
-    let s:path_sep = "\\"
-elseif has("mac")
-    let s:vim_platform = "mac"
-    let s:path_sep = '/'
-else
-    let s:vim_platform = "unix"
-    let s:path_sep = '/'
-endif
-
-" Get our vim directory. 
-let s:vim_home = expand("<sfile>:h")
-
 " Local pre-override.
-let s:local_vimrc_pre = s:vim_home.'/vimrc-local-pre'
+let s:local_vimrc_pre = ludo#localpath('vimrc-local-pre')
 if filereadable(s:local_vimrc_pre)
     execute 'source' s:local_vimrc_pre
 endif
@@ -46,16 +31,16 @@
 
 " Disable some plugins.
 let g:pathogen_disabled = get(g:, 'pathogen_disabled', [])
-call ludo#setup_pathogen([s:vim_home.'/bundle', s:vim_home.'/local'])
+call ludo#setup_pathogen([ludo#localpath('bundle'), ludo#localpath('local')])
 
 " Load pathogen.
 runtime bundle/pathogen/autoload/pathogen.vim
 " Add the bundle directory, and potentially add the local one if it exists.
 " Note that we pass absolute paths to make pathogen prepend stuff before Vim's
 " system files otherwise stuff like indent plugins don't work.
-let s:pathogen_bundles = [s:vim_home.s:path_sep.'bundle'.s:path_sep.'{}']
-if isdirectory(s:vim_home.s:path_sep.'local')
-    call add(s:pathogen_bundles, s:vim_home.s:path_sep.'local'.s:path_sep.'{}')
+let s:pathogen_bundles = [ludo#localpath('bundle', '{}')]
+if isdirectory(ludo#localpath('local'))
+    call add(s:pathogen_bundles, ludo#localpath('local', '{}'))
 endif
 call call('pathogen#infect', s:pathogen_bundles)
 
@@ -143,8 +128,8 @@
 " we edit the file, and then get rid of it.
 set nobackup
 set writebackup
-execute('set backupdir='.s:vim_home.'/backup')
-execute('set directory='.s:vim_home.'/temp')
+execute('set backupdir='.ludo#localpath('backup'))
+execute('set directory='.ludo#localpath('temp'))
 
 " Better command-line completion, but don't show some
 " stuff we don't care about.
@@ -200,7 +185,7 @@
 
 " And now, for some system-dependent settings:
 " - font to use
-if s:vim_platform == "windows"
+if ludo#platform() == "windows"
     set guifont=InputMono:h11,Hack:h12,Consolas:h12
 else
     set guifont=InputMono:h11,Hack:h12,Monaco:h12
@@ -255,6 +240,8 @@
 endif
 
 nnoremap <Leader>a :Ack!<Space>
+nnoremap <leader>f :Ack! /<C-R><C-W>/ 
+vnoremap <leader>f "zy:Ack! /<C-R>z/ 
 
 " }}}
 
@@ -272,7 +259,7 @@
             \ }
 
 " Make Ctrl-P cache stuff in our temp directory.
-let g:ctrlp_cache_dir = s:vim_home.'/cache'
+let g:ctrlp_cache_dir = ludo#localpath('cache')
 
 " Remember things.
 let g:ctrlp_clear_cache_on_exit = 0
@@ -297,7 +284,7 @@
 
 " FZF {{{
 
-if s:vim_platform == 'mac'
+if ludo#platform() == 'mac'
     if filereadable('/usr/local/opt/fzf/plugin/fzf.vim')
         " FZF installed via Homebrew.
         source /usr/local/opt/fzf/plugin/fzf.vim
@@ -314,9 +301,9 @@
 
 " Gutentags {{{
 
-let g:gutentags_cache_dir = s:vim_home.'/tags'
+let g:gutentags_cache_dir = ludo#localpath('tags')
 let g:gutentags_ctags_exclude = ['venv', 'build', 'static', 'node_modules']
-let g:gutentags_ctags_extra_args = ['--options='.s:vim_home.'/ctagsrc']
+let g:gutentags_ctags_extra_args = ['--options='.ludo#localpath('ctagsrc')]
 let g:gutentags_ctags_exclude_wildignore = 0
 
 " }}}
@@ -656,9 +643,6 @@
 vnoremap * :<C-u>call <SID>VSetSearch()<CR>//<CR><c-o>
 vnoremap # :<C-u>call <SID>VSetSearch()<CR>??<CR><c-o>
 
-nnoremap <leader>fa :vimgrep /<C-R><C-W>/ 
-vnoremap <leader>fa "zy:vimgrep /<C-R>z/ 
-
 " Keep search matches in the middle of the window.
 nnoremap n nzvzz
 nnoremap N Nzvzz
@@ -733,6 +717,10 @@
         nnoremap <silent> <C-p> :Files<cr>
         nnoremap <silent> <C-o> :Buffers<cr>
         nnoremap <Tab> :History<cr>
+
+        " Replace the default `Tags` command, which requires Perl, with
+        " something I can use, based on Python.
+        command! -bang -nargs=* Tags call ludo#run_fzf_tags(<q-args>, <bang>0)
     else
         call ludo#error(
                     \"FZF is installed and enabled, but the Vim plugin ".
@@ -820,10 +808,7 @@
 
 " Local override {{{
 
-let s:local_vimrc = s:vim_home.'/vimrc-local'
-if filereadable(s:local_vimrc)
-    execute 'source' s:local_vimrc
-let s:local_vimrc = s:vim_home.'/vimrc-local'
+let s:local_vimrc = ludo#localpath('vimrc-local')
 if filereadable(s:local_vimrc)
     execute 'source' s:local_vimrc
 endif