From fc7cdb443df436c1865673c0d752469226b3e780 Mon Sep 17 00:00:00 2001 From: Jules Aguillon Date: Fri, 27 Sep 2024 16:42:00 +0200 Subject: [PATCH 1/3] vim: Expose the search-by-type feature This adds the :MerlinSearchType command to query for a value with a matching type. It works exactly like the previous :MerlinSearch, the search results are shown in the completion menu. --- vim/merlin/autoload/merlin.py | 39 +++++++++++++++++++++++----------- vim/merlin/autoload/merlin.vim | 15 +++++++++++-- 2 files changed, 40 insertions(+), 14 deletions(-) diff --git a/vim/merlin/autoload/merlin.py b/vim/merlin/autoload/merlin.py index 5d79cba9b9..581c0aed51 100644 --- a/vim/merlin/autoload/merlin.py +++ b/vim/merlin/autoload/merlin.py @@ -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. @@ -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: @@ -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) diff --git a/vim/merlin/autoload/merlin.vim b/vim/merlin/autoload/merlin.vim index 3d925b9daf..67f5c03592 100644 --- a/vim/merlin/autoload/merlin.vim +++ b/vim/merlin/autoload/merlin.vim @@ -284,15 +284,23 @@ 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()\","n") + call feedkeys("i=merlin#SearchComplete()\","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()\","n") + endif +endfunction + function! s:StopHighlight() if exists('w:enclosing_zone') && w:enclosing_zone != -1 call matchdelete(w:enclosing_zone) @@ -816,6 +824,9 @@ function! merlin#Register() """ Polarity search command! -buffer -complete=customlist,merlin#ExpandTypePrefix -nargs=+ MerlinSearch call merlin#PolaritySearch(0,) + """ Search by type + command! -buffer -complete=customlist,merlin#ExpandTypePrefix -nargs=+ MerlinSearchType call merlin#SearchByType(0,) + """ debug -------------------------------------------------------------------- command! -buffer -nargs=0 MerlinDebugLastCommands MerlinPy merlin.vim_last_commands() command! -buffer -nargs=0 MerlinDebugDisable call merlin#DebugDisable() From c742accf8279a3f3d5c81ff52fd310441161d3dc Mon Sep 17 00:00:00 2001 From: Jules Aguillon Date: Fri, 27 Sep 2024 17:18:59 +0200 Subject: [PATCH 2/3] vim: Type search in :MerlinSearch and update the doc ':MerlinSearch' switches between polarity search and search by type depending on the first character of the query, like is done in the emacs plugin. Documentation about the three search functions is added. --- vim/merlin/autoload/merlin.vim | 17 +++++++++++---- vim/merlin/doc/merlin.txt | 38 ++++++++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+), 4 deletions(-) diff --git a/vim/merlin/autoload/merlin.vim b/vim/merlin/autoload/merlin.vim index 67f5c03592..caa3959331 100644 --- a/vim/merlin/autoload/merlin.vim +++ b/vim/merlin/autoload/merlin.vim @@ -301,6 +301,16 @@ function! merlin#SearchByType(debug,query) 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) @@ -821,11 +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,) - - """ Search by type + """ Search + command! -buffer -complete=customlist,merlin#ExpandTypePrefix -nargs=+ MerlinSearchPolarity call merlin#PolaritySearch(0,) command! -buffer -complete=customlist,merlin#ExpandTypePrefix -nargs=+ MerlinSearchType call merlin#SearchByType(0,) + command! -buffer -complete=customlist,merlin#ExpandTypePrefix -nargs=+ MerlinSearch call merlin#Search(0,) """ debug -------------------------------------------------------------------- command! -buffer -nargs=0 MerlinDebugLastCommands MerlinPy merlin.vim_last_commands() diff --git a/vim/merlin/doc/merlin.txt b/vim/merlin/doc/merlin.txt index b1c571d5d7..3d23b100c4 100644 --- a/vim/merlin/doc/merlin.txt +++ b/vim/merlin/doc/merlin.txt @@ -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* From e59881aef0cfee059742a959ff41915b26e78b17 Mon Sep 17 00:00:00 2001 From: Jules Aguillon Date: Tue, 10 Dec 2024 11:10:50 +0100 Subject: [PATCH 3/3] Update CHANGES --- CHANGES.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/CHANGES.md b/CHANGES.md index ff31880a3f..f3ca754ebf 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -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