misc/vim: make Nitdoc a command
[nit.git] / misc / vim / plugin / nit.vim
index c9d54d0..9968b5e 100644 (file)
@@ -84,7 +84,7 @@ endfunction
 " Get path to the best metadata file named `name`
 "
 " Returns an empty string if not found.
-fun NitMetadataFile(name)
+fun s:NitMetadataFile(name)
        " Where are the generated metadata files?
        if empty($NIT_VIM_DIR)
                let metadata_dir = $HOME . '/.vim/nit'
@@ -110,15 +110,19 @@ endfun
 " Internal function to search for lines in `path` corresponding to the partial
 " word `base`. Adds found and formated match to `matches`.
 "
-" Will order the results in 3 levels:
+" Will order the results in 5 levels:
 " 1. Exact matches
 " 2. Common prefix matches
 " 3. Substring matches
+" 4. Synopsis matches
+" 5. Doc matches
 fun NitOmnifuncAddFromFile(base, matches, path)
        let prefix_matches = []
        let substring_matches = []
+       let synopsis_matches = []
+       let doc_matches = []
 
-       let path = NitMetadataFile(a:path)
+       let path = s:NitMetadataFile(a:path)
        if empty(path)
                return
        endif
@@ -130,23 +134,31 @@ fun NitOmnifuncAddFromFile(base, matches, path)
                " Add?
                if name == a:base
                        " Exact match
-                       call NitOmnifuncAddAMatch(a:matches, words, name)
-               elseif name =~ '^'.a:base
+                       call s:NitOmnifuncAddAMatch(a:matches, words, name)
+               elseif name =~? '^'.a:base
                        " Common-prefix match
-                       call NitOmnifuncAddAMatch(prefix_matches, words, name)
-               elseif name =~ a:base
+                       call s:NitOmnifuncAddAMatch(prefix_matches, words, name)
+               elseif name =~? a:base
                        " Substring match
-                       call NitOmnifuncAddAMatch(substring_matches, words, name)
+                       call s:NitOmnifuncAddAMatch(substring_matches, words, name)
+               elseif get(words, 2, '') =~? a:base
+                       " Match in the synopsis
+                       call s:NitOmnifuncAddAMatch(synopsis_matches, words, name)
+               elseif get(words, 3, '') =~? a:base
+                       " Match in the longer doc
+                       call s:NitOmnifuncAddAMatch(doc_matches, words, name)
                endif
        endfor
 
        " Assemble the final match list
        call extend(a:matches, sort(prefix_matches))
        call extend(a:matches, sort(substring_matches))
+       call extend(a:matches, sort(synopsis_matches))
+       call extend(a:matches, sort(doc_matches))
 endfun
 
 " Internal function to search parse the information from a metadata line
-fun NitOmnifuncAddAMatch(matches, words, name)
+fun s:NitOmnifuncAddAMatch(matches, words, name)
        let pretty = get(a:words, 1, '')
        let synopsis = get(a:words, 2, '')
        let desc = get(a:words, 3, '')
@@ -254,16 +266,20 @@ fun NitOmnifunc(findstart, base)
 endfun
 
 " Show doc for the entity under the cursor in the preview window
-fun Nitdoc()
-       " Word under cursor
-       let word = expand("<cword>")
+fun Nitdoc(...)
+       if a:0 == 0 || empty(a:1)
+               " Word under cursor
+               let word = expand("<cword>")
+       else
+               let word = join(a:000, ' ')
+       endif
 
        " All possible docs (there may be more than one entity with the same name)
        let docs = []
 
        " Search in all metadata files
        for file in ['modules', 'classes', 'properties']
-               let path = NitMetadataFile(file.'.txt')
+               let path = s:NitMetadataFile(file.'.txt')
                if empty(path)
                        continue
                endif
@@ -271,7 +287,7 @@ fun Nitdoc()
                for line in readfile(path)
                        let words = split(line, '#====#', 1)
                        let name = get(words, 0, '')
-                       if name =~ '^' . word
+                       if name =~ '^' . word . '\>'
                                " It fits our word, get long doc
                                let desc = get(words,3,'')
                                let desc = join(split(desc, '#nnnn#', 1), "\n")
@@ -310,7 +326,36 @@ fun Nitdoc()
        redraw!
 endfun
 
+" Call `git grep` on the word under the cursor
+"
+" Shows declarations first, then all matches, in the preview window.
+fun NitGitGrep()
+       let word = expand("<cword>")
+       let out = tempname()
+       execute 'silent !(git grep "\\(module\\|class\\|universal\\|interface\\|var\\|fun\\) '.word.'";'.
+               \'echo; git grep '.word.') > '.out
+
+       " Open the preview window on a temp file
+       execute "silent pedit " . out
+
+       " Change to preview window
+       wincmd P
+
+       " Set options
+       setlocal buftype=nofile
+       setlocal noswapfile
+       setlocal syntax=none
+       setlocal bufhidden=delete
+
+       " Change back to the source buffer
+       wincmd p
+       redraw!
+endfun
+
 " Activate the omnifunc on Nit files
 autocmd FileType nit set omnifunc=NitOmnifunc
 
+" Define the user command Nitdoc for ease of use
+command -nargs=* Nitdoc call Nitdoc("<args>")
+
 let s:script_dir = fnamemodify(resolve(expand('<sfile>:p')), ':h')