Skip to content

Commit 5b10e5c

Browse files
authored
Merge pull request #1846 from Julow/vim-search-by-type
vim: Expose the search-by-type feature
2 parents c47b3c5 + e59881a commit 5b10e5c

File tree

4 files changed

+98
-16
lines changed

4 files changed

+98
-16
lines changed

CHANGES.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,12 @@
1+
unreleased
2+
==========
3+
4+
+ vim plugin
5+
- Added support for search-by-type (#1846)
6+
This is exposed through the existing `:MerlinSearch` command, that
7+
switches between search-by-type and polarity search depending on the
8+
first character of the query.
9+
110
merlin 5.3
211
==========
312
Tue Nov 26 17:30:42 CET 2024

vim/merlin/autoload/merlin.py

Lines changed: 27 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ def vim_value(v):
9090
if isinstance(v, int):
9191
return str(v)
9292
if isinstance(v, str):
93-
return "'%s'" % v.replace("'", "''")
93+
return "'%s'" % v.replace("'", "''").replace("\n", "'.\"\\n\".'")
9494
raise Exception("Failed to convert into a vim value: %s" % str(v))
9595

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

363363
######## VIM FRONTEND
364364

365-
def vim_complete_prepare(str):
366-
return re.sub(re_wspaces, " ", str).replace("'", "''").strip()
367-
368-
def vim_complete_prepare_preserve_newlines(str):
369-
return re.sub(re_spaces_around_nl, "\n", re.sub(re_spaces, " ", str)).replace("'", "''").strip()
370-
365+
# Turns Merlin's search-by-polarity or complete-prefix entries into a Vim's completion-item list (:h complete-items)
371366
def vim_fillentries(entries, vimvar):
372-
prep = vim_complete_prepare
373-
prep_nl = vim_complete_prepare_preserve_newlines
367+
def prep(s):
368+
return re.sub(re_wspaces, " ", s).strip()
369+
def prep_nl(s):
370+
return re.sub(re_spaces_around_nl, "\n", re.sub(re_spaces, " ", s)).strip()
374371
for prop in entries:
375-
vim.command("let tmp = {'word':'%s','menu':'%s','info':'%s','kind':'%s'}" %
376-
(prep(prop['name']),prep(prop['desc']),prep_nl(prop['info']),prep(prop['kind'][:1])))
372+
vim.command("let tmp = " + vim_record({
373+
"word": prep(prop["name"]),
374+
"menu": prep(prop["desc"]),
375+
"info": prep_nl(prop["info"]),
376+
"kind": prop["kind"][:1]
377+
}))
377378
vim.command("call add(%s, tmp)" % vimvar)
378379

379380
# Complete
380381
def vim_complete_cursor(base, suffix, vimvar):
382+
def prep(str):
383+
return re.sub(re_wspaces, " ", str).replace("'", "''").strip()
381384
vim.command("let %s = []" % vimvar)
382385
try:
383386
completions = command_complete_cursor(base,vim.current.window.cursor)
384387
nb_entries = len(completions['entries'])
385-
prep = vim_complete_prepare
386388
if completions['context'] and completions['context'][0] == 'application':
387389
app = completions['context'][1]
388390
if not base or base == suffix:
@@ -432,6 +434,19 @@ def vim_polarity_search(query, vimvar):
432434
except MerlinExc as e:
433435
try_print_error(e)
434436

437+
# search-by-type is introduced in https://github.com/ocaml/merlin/pull/1828
438+
def vim_search_by_type(query, vimvar):
439+
def completion_item_of_result(e):
440+
return { "word": e["name"], "menu": ": %s" % e["type"] }
441+
vim.command("let %s = []" % vimvar)
442+
try:
443+
l = command("search-by-type", "-query", query, "-position", fmtpos(vim.current.window.cursor))
444+
for r in l:
445+
item = completion_item_of_result(r)
446+
vim.command("call add(%s, %s)" % (vimvar, vim_record(item)))
447+
except MerlinExc as e:
448+
try_print_error(e)
449+
435450
# Error listing
436451
def vim_loclist(vimvar, ignore_warnings):
437452
vim.command("let %s = []" % vimvar)

vim/merlin/autoload/merlin.vim

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -284,15 +284,33 @@ function! merlin#PolaritySearch(debug,query)
284284
let s:search_result = []
285285
MerlinPy merlin.vim_polarity_search(vim.eval("a:query"), "s:search_result")
286286
if a:debug != 1 && s:search_result != []
287-
call feedkeys("i=merlin#PolarityComplete()\<CR>","n")
287+
call feedkeys("i=merlin#SearchComplete()\<CR>","n")
288288
endif
289289
endfunction
290290

291-
function! merlin#PolarityComplete()
291+
function! merlin#SearchComplete()
292292
call complete(col('.'), s:search_result)
293293
return ''
294294
endfunction
295295

296+
function! merlin#SearchByType(debug,query)
297+
let s:search_result = []
298+
MerlinPy merlin.vim_search_by_type(vim.eval("a:query"), "s:search_result")
299+
if a:debug != 1 && s:search_result != []
300+
call feedkeys("i=merlin#SearchComplete()\<CR>","n")
301+
endif
302+
endfunction
303+
304+
" Do a polarity search or a search by type depending on the first character of
305+
" the query.
306+
function! merlin#Search(debug, query)
307+
if a:query =~ "^[-+]"
308+
call merlin#PolaritySearch(a:debug, a:query)
309+
else
310+
call merlin#SearchByType(a:debug, a:query)
311+
endif
312+
endfunction
313+
296314
function! s:StopHighlight()
297315
if exists('w:enclosing_zone') && w:enclosing_zone != -1
298316
call matchdelete(w:enclosing_zone)
@@ -813,8 +831,10 @@ function! merlin#Register()
813831
command! -buffer -nargs=0 MerlinGotoDotMerlin call merlin#GotoDotMerlin()
814832
command! -buffer -nargs=0 MerlinEchoDotMerlin call merlin#EchoDotMerlin()
815833

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

819839
""" debug --------------------------------------------------------------------
820840
command! -buffer -nargs=0 MerlinDebugLastCommands MerlinPy merlin.vim_last_commands()

vim/merlin/doc/merlin.txt

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,44 @@ Act either as *:py* or *:py3* depending on the version of python is used
158158
by the vim plugin.
159159
This is only useful if you want to write custom merlin extensions.
160160

161+
:MerlinSearch *:MerlinSearch*
162+
163+
Act either as :MerlinSearchPolarity or :MerlinSearchType depending on the first
164+
character of the query. If the query starts with '-' or '+', then
165+
:MerlinSearchPolarity is used, otherwise, :MerlinSearchType is used.
166+
167+
>
168+
:MerlinSearch -int +string
169+
:MerlinSearch int -> string
170+
<
171+
172+
:MerlinSearchPolarity *:MerlinSearchPolarity*
173+
174+
Search for values in the current scope that have a type matching the query.
175+
The results are displayed in a completion menu.
176+
177+
The query language is simply a list of path identifiers prefixed by `+` or `-`,
178+
e.g. `-int`, `-int +string`, `-Hashtbl.t +int`.
179+
180+
`-` is interpreted as "consuming" and `+` as "producing": `-int +string` looks
181+
for functions consuming an `int` and producing a `string`.
182+
183+
>
184+
:MerlinSearchPolarity -int +string
185+
<
186+
187+
:MerlinSearchType *:MerlinSearchType*
188+
189+
Works similarly to :MerlinSearchPolarity but uses a different query language.
190+
The results are displayed in a completion menu.
191+
192+
The query language is a list of type constructors separated by '->'.
193+
Type parameters and functions are allowed: `('a -> bool) -> 'a list -> bool`.
194+
195+
>
196+
:MerlinSearchType int -> string
197+
<
198+
161199
==============================================================================
162200
OPTIONS *merlin-options*
163201

0 commit comments

Comments
 (0)