Skip to content

Commit

Permalink
Merge pull request ocaml#1846 from Julow/vim-search-by-type
Browse files Browse the repository at this point in the history
vim: Expose the search-by-type feature
  • Loading branch information
voodoos authored Dec 13, 2024
2 parents c47b3c5 + e59881a commit 5b10e5c
Show file tree
Hide file tree
Showing 4 changed files with 98 additions and 16 deletions.
9 changes: 9 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,12 @@
unreleased
==========

+ vim plugin
- Added support for search-by-type (#1846)
This is exposed through the existing `:MerlinSearch` command, that
switches between search-by-type and polarity search depending on the
first character of the query.

merlin 5.3
==========
Tue Nov 26 17:30:42 CET 2024
Expand Down
39 changes: 27 additions & 12 deletions vim/merlin/autoload/merlin.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ def vim_value(v):
if isinstance(v, int):
return str(v)
if isinstance(v, str):
return "'%s'" % v.replace("'", "''")
return "'%s'" % v.replace("'", "''").replace("\n", "'.\"\\n\".'")
raise Exception("Failed to convert into a vim value: %s" % str(v))

# Format a dictionnary containing integer and string values into a Vim record.
Expand Down Expand Up @@ -362,27 +362,29 @@ def command_holes():

######## VIM FRONTEND

def vim_complete_prepare(str):
return re.sub(re_wspaces, " ", str).replace("'", "''").strip()

def vim_complete_prepare_preserve_newlines(str):
return re.sub(re_spaces_around_nl, "\n", re.sub(re_spaces, " ", str)).replace("'", "''").strip()

# Turns Merlin's search-by-polarity or complete-prefix entries into a Vim's completion-item list (:h complete-items)
def vim_fillentries(entries, vimvar):
prep = vim_complete_prepare
prep_nl = vim_complete_prepare_preserve_newlines
def prep(s):
return re.sub(re_wspaces, " ", s).strip()
def prep_nl(s):
return re.sub(re_spaces_around_nl, "\n", re.sub(re_spaces, " ", s)).strip()
for prop in entries:
vim.command("let tmp = {'word':'%s','menu':'%s','info':'%s','kind':'%s'}" %
(prep(prop['name']),prep(prop['desc']),prep_nl(prop['info']),prep(prop['kind'][:1])))
vim.command("let tmp = " + vim_record({
"word": prep(prop["name"]),
"menu": prep(prop["desc"]),
"info": prep_nl(prop["info"]),
"kind": prop["kind"][:1]
}))
vim.command("call add(%s, tmp)" % vimvar)

# Complete
def vim_complete_cursor(base, suffix, vimvar):
def prep(str):
return re.sub(re_wspaces, " ", str).replace("'", "''").strip()
vim.command("let %s = []" % vimvar)
try:
completions = command_complete_cursor(base,vim.current.window.cursor)
nb_entries = len(completions['entries'])
prep = vim_complete_prepare
if completions['context'] and completions['context'][0] == 'application':
app = completions['context'][1]
if not base or base == suffix:
Expand Down Expand Up @@ -432,6 +434,19 @@ def vim_polarity_search(query, vimvar):
except MerlinExc as e:
try_print_error(e)

# search-by-type is introduced in https://github.com/ocaml/merlin/pull/1828
def vim_search_by_type(query, vimvar):
def completion_item_of_result(e):
return { "word": e["name"], "menu": ": %s" % e["type"] }
vim.command("let %s = []" % vimvar)
try:
l = command("search-by-type", "-query", query, "-position", fmtpos(vim.current.window.cursor))
for r in l:
item = completion_item_of_result(r)
vim.command("call add(%s, %s)" % (vimvar, vim_record(item)))
except MerlinExc as e:
try_print_error(e)

# Error listing
def vim_loclist(vimvar, ignore_warnings):
vim.command("let %s = []" % vimvar)
Expand Down
28 changes: 24 additions & 4 deletions vim/merlin/autoload/merlin.vim
Original file line number Diff line number Diff line change
Expand Up @@ -284,15 +284,33 @@ function! merlin#PolaritySearch(debug,query)
let s:search_result = []
MerlinPy merlin.vim_polarity_search(vim.eval("a:query"), "s:search_result")
if a:debug != 1 && s:search_result != []
call feedkeys("i=merlin#PolarityComplete()\<CR>","n")
call feedkeys("i=merlin#SearchComplete()\<CR>","n")
endif
endfunction

function! merlin#PolarityComplete()
function! merlin#SearchComplete()
call complete(col('.'), s:search_result)
return ''
endfunction

function! merlin#SearchByType(debug,query)
let s:search_result = []
MerlinPy merlin.vim_search_by_type(vim.eval("a:query"), "s:search_result")
if a:debug != 1 && s:search_result != []
call feedkeys("i=merlin#SearchComplete()\<CR>","n")
endif
endfunction

" Do a polarity search or a search by type depending on the first character of
" the query.
function! merlin#Search(debug, query)
if a:query =~ "^[-+]"
call merlin#PolaritySearch(a:debug, a:query)
else
call merlin#SearchByType(a:debug, a:query)
endif
endfunction

function! s:StopHighlight()
if exists('w:enclosing_zone') && w:enclosing_zone != -1
call matchdelete(w:enclosing_zone)
Expand Down Expand Up @@ -813,8 +831,10 @@ function! merlin#Register()
command! -buffer -nargs=0 MerlinGotoDotMerlin call merlin#GotoDotMerlin()
command! -buffer -nargs=0 MerlinEchoDotMerlin call merlin#EchoDotMerlin()

""" Polarity search
command! -buffer -complete=customlist,merlin#ExpandTypePrefix -nargs=+ MerlinSearch call merlin#PolaritySearch(0,<q-args>)
""" Search
command! -buffer -complete=customlist,merlin#ExpandTypePrefix -nargs=+ MerlinSearchPolarity call merlin#PolaritySearch(0,<q-args>)
command! -buffer -complete=customlist,merlin#ExpandTypePrefix -nargs=+ MerlinSearchType call merlin#SearchByType(0,<q-args>)
command! -buffer -complete=customlist,merlin#ExpandTypePrefix -nargs=+ MerlinSearch call merlin#Search(0,<q-args>)

""" debug --------------------------------------------------------------------
command! -buffer -nargs=0 MerlinDebugLastCommands MerlinPy merlin.vim_last_commands()
Expand Down
38 changes: 38 additions & 0 deletions vim/merlin/doc/merlin.txt
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,44 @@ Act either as *:py* or *:py3* depending on the version of python is used
by the vim plugin.
This is only useful if you want to write custom merlin extensions.

:MerlinSearch *:MerlinSearch*

Act either as :MerlinSearchPolarity or :MerlinSearchType depending on the first
character of the query. If the query starts with '-' or '+', then
:MerlinSearchPolarity is used, otherwise, :MerlinSearchType is used.

>
:MerlinSearch -int +string
:MerlinSearch int -> string
<

:MerlinSearchPolarity *:MerlinSearchPolarity*

Search for values in the current scope that have a type matching the query.
The results are displayed in a completion menu.

The query language is simply a list of path identifiers prefixed by `+` or `-`,
e.g. `-int`, `-int +string`, `-Hashtbl.t +int`.

`-` is interpreted as "consuming" and `+` as "producing": `-int +string` looks
for functions consuming an `int` and producing a `string`.

>
:MerlinSearchPolarity -int +string
<

:MerlinSearchType *:MerlinSearchType*

Works similarly to :MerlinSearchPolarity but uses a different query language.
The results are displayed in a completion menu.

The query language is a list of type constructors separated by '->'.
Type parameters and functions are allowed: `('a -> bool) -> 'a list -> bool`.

>
:MerlinSearchType int -> string
<

==============================================================================
OPTIONS *merlin-options*

Expand Down

0 comments on commit 5b10e5c

Please sign in to comment.