X-Git-Url: http://nitlanguage.org diff --git a/misc/vim/plugin/nit.vim b/misc/vim/plugin/nit.vim index 23e557a..86d5e45 100644 --- a/misc/vim/plugin/nit.vim +++ b/misc/vim/plugin/nit.vim @@ -81,17 +81,10 @@ function ForceNitComplete() call NitComplete() endfunction -" Internal function to search for lines in `path` corresponding to the partial -" word `base`. Adds found and formated match to `matches`. +" Get path to the best metadata file named `name` " -" Will order the results in 3 levels: -" 1. Exact matches -" 2. Common prefix matches -" 3. Substring matches -fun NitOmnifuncAddFromFile(base, matches, path) - let prefix_matches = [] - let substring_matches = [] - +" Returns an empty string if not found. +fun s:NitMetadataFile(name) " Where are the generated metadata files? if empty($NIT_VIM_DIR) let metadata_dir = $HOME . '/.vim/nit' @@ -99,17 +92,41 @@ fun NitOmnifuncAddFromFile(base, matches, path) let metadata_dir = $NIT_VIM_DIR end - let path = metadata_dir . '/' . a:path + let path = metadata_dir . '/' . a:name + " Is there generated custom metadata files? if ! filereadable(path) - let path = s:script_dir . '/' . a:path + let path = s:script_dir . '/' . a:name " Is there standard metadata files? if ! filereadable(path) - return + return '' endif endif + return path +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 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 = s:NitMetadataFile(a:path) + if empty(path) + return + endif + for line in readfile(path) let words = split(line, '#====#', 1) let name = get(words, 0, '') @@ -117,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, '') @@ -159,10 +184,10 @@ fun NitOmnifunc(findstart, base) " find keyword matching with "a:base" let matches = [] - " Advanced suggestions + " advanced suggestions let cursor_line = getline('.') - " Content of the line before the partial word + " content of the line before the partial word let line_prev_cursor = cursor_line[:col('.')-1] let prev_char_at = strlen(line_prev_cursor) - 1 @@ -240,7 +265,127 @@ fun NitOmnifunc(findstart, base) endif endfun +" Show doc for the entity under the cursor in the preview window +fun Nitdoc(...) + if a:0 == 0 || empty(a:1) + " Word under cursor + let word = expand("") + else + let word = join(a:000, ' ') + endif + + " All possible docs (there may be more than one entity with the same name) + let docs = [] + let prefix_matches = [] + let substring_matches = [] + let synopsis_matches = [] + let doc_matches = [] + + " Search in all metadata files + for file in ['modules', 'classes', 'properties'] + let path = s:NitMetadataFile(file.'.txt') + if empty(path) + continue + endif + + for line in readfile(path) + let words = split(line, '#====#', 1) + let name = get(words, 0, '') + if name =~ '^'.word.'\>' + " Exact match + call s:NitdocAdd(docs, words) + elseif name =~? '^'.word + " Common-prefix match + call s:NitdocAdd(prefix_matches, words) + elseif name =~? word + " Substring match + call s:NitdocAdd(substring_matches, words) + elseif get(words, 2, '') =~? word + " Match in the synopsis + call s:NitdocAdd(synopsis_matches, words) + elseif get(words, 3, '') =~? word + " Match in the longer doc + call s:NitdocAdd(doc_matches, words) + endif + endfor + endfor + + " Unite all results in prefered order + call extend(docs, sort(prefix_matches)) + call extend(docs, sort(substring_matches)) + call extend(docs, sort(synopsis_matches)) + call extend(docs, sort(doc_matches)) + + " Found no doc, give up + if empty(docs) || !(join(docs, '') =~ '\w') + echo 'Nitdoc found nothing for "' . word . '"' + return + endif + + " Open the preview window on a temp file + execute "silent pedit " . tempname() + + " Change to preview window + wincmd P + + " Show all found doc one after another + for doc in docs + if doc =~ '\w' + silent put = doc + silent put = '' + endif + endfor + execute 0 + delete " the first empty line + + " Set options + setlocal buftype=nofile + setlocal noswapfile + setlocal syntax=none + setlocal bufhidden=delete + + " Change back to the source buffer + wincmd p + redraw! +endfun + +" Internal function to search parse the information from a metadata line +fun s:NitdocAdd(matches, words) + let desc = get(a:words, 3, '') + let desc = join(split(desc, '#nnnn#', 1), "\n") + call add(a:matches, desc) +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("") + 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("") + let s:script_dir = fnamemodify(resolve(expand(':p')), ':h')