Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

vim: Expose the search-by-type feature #1846

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 20 additions & 7 deletions vim/merlin/autoload/merlin.py
Original file line number Diff line number Diff line change
Expand Up @@ -365,15 +365,15 @@ def command_holes():
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
def vim_fillentries(entries, vimvar):
prep = vim_complete_prepare
prep_nl = vim_complete_prepare_preserve_newlines
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({
Copy link
Collaborator

@voodoos voodoos Oct 9, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's unclear to me that vim_record behaves similarly as the previous use of prep and prep_nl. Does it "preserve newlines" ? And only for the "info" field ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are right, there was a problem here!
I've fixed vim_record to properly encode newlines and added back the prep and prep_nl functions. I'm not sure in which cases these are useful.
I've just learnt from this "info" feature and I find it awesome. I tested that completion works fine with these settings:

let g:merlin_completion_with_doc = 1
set completeopt+=popup

"word": prop["name"],
"menu": prop["desc"],
"info": prop["info"],
"kind": prop["kind"][:1]
}))
vim.command("call add(%s, tmp)" % vimvar)

# Complete
Expand Down Expand Up @@ -432,6 +432,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
Comment on lines +304 to +312
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@xvw this detection is also made on Merlin side isn't it ?
Maybe we could have a simpler interface in both emacs and vim:

  • Keep the existing PolaritySearch
  • Add a new SearchByType or Search, that does indeed also support the polarity search syntax.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, in Emacs I've moved the original search behaviour into a search-by-polarity command and then the search command relies on the merlin search-by-type command (which classifies the query)


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