Skip to content

Commit

Permalink
Merge pull request ocaml#1359 from voodoos/locate-type-editor-suppor
Browse files Browse the repository at this point in the history
`merlin-locate-type` editor support
  • Loading branch information
voodoos committed Jul 20, 2021
1 parent 857e085 commit 135a1d2
Show file tree
Hide file tree
Showing 7 changed files with 97 additions and 31 deletions.
3 changes: 3 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,11 @@ git version
- vim: add a simple interface to the new `construct` command:
`MerlinConstruct`. When several results are suggested, `<c-i>` and `<c-u>`
to show more or less deep results. (#1318)
- vim: add support for the `merlin-locate-type` command:
`MerlinLocateType` (#1359)
- emacs: add a simple interface to the new `construct` command:
`merlin-construct`. (#1352)
- emacs: add support for the `merlin-locate-type` command. (#1359)
+ test suite
- cover the new `construct` command (#1318)
Expand Down
11 changes: 11 additions & 0 deletions emacs/merlin.el
Original file line number Diff line number Diff line change
Expand Up @@ -1512,6 +1512,17 @@ loading"
(interactive)
(merlin--locate-result (merlin-call-locate)))

(defun merlin-locate-type ()
"Locate the type of the expression under point."
(interactive)
(let ((result (merlin/call "locate-type"
"-position" (merlin/unmake-point (point)))))
(unless result
(error "Not found. (Check *Messages* for potential errors)"))
(unless (listp result)
(error "%S" result))
(merlin--goto-file-and-point result)))

(defun merlin-pop-stack ()
"Go back to the last position where the user did a locate."
(interactive)
Expand Down
4 changes: 4 additions & 0 deletions tests/test-dirs/locate-type.t/a.ml
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,7 @@ end
module Y = struct
let y = T.X 1
end

let z = Y.y

let z2 = B.x
2 changes: 2 additions & 0 deletions tests/test-dirs/locate-type.t/b.ml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
type foo = string option
let x : foo = None
27 changes: 27 additions & 0 deletions tests/test-dirs/locate-type.t/run.t
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
$ $OCAMLC b.ml -bin-annot -c

$ $MERLIN single locate-type -position 6:6 -filename ./a.ml < ./a.ml
{
Expand All @@ -11,3 +12,29 @@
},
"notifications": []
}

$ $MERLIN single locate-type -workdir . -position 9:11 -filename a.ml < ./a.ml
{
"class": "return",
"value": {
"file": "$TESTCASE_ROOT/a.ml",
"pos": {
"line": 2,
"col": 2
}
},
"notifications": []
}

$ $MERLIN single locate-type -position 11:12 -filename ./a.ml < ./a.ml
{
"class": "return",
"value": {
"file": "$TESTCASE_ROOT/b.ml",
"pos": {
"line": 1,
"col": 0
}
},
"notifications": []
}
75 changes: 45 additions & 30 deletions vim/merlin/autoload/merlin.py
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,38 @@ def differs_from_current_file(path):
def vim_fnameescape(s):
return vim.eval("fnameescape('%s')" % s.replace("'","''"))

def goto_file_and_point(pos_or_err):
if not isinstance(pos_or_err, dict):
print(pos_or_err)
else:
l = pos_or_err['pos']['line']
c = pos_or_err['pos']['col']
split_method = vim.eval('g:merlin_split_method')
# save the current position in the jump list
vim.command("normal! m'")
if "file" in pos_or_err and differs_from_current_file(pos_or_err['file']):
fname = vim_fnameescape(pos_or_err['file'])
if split_method == "never":
vim.command(":keepjumps e %s" % fname)
elif "tab" in split_method:
if "always" in split_method:
vim.command(":keepjumps tab split %s" % fname)
else:
vim.command(":keepjumps tab drop %s" % fname)
elif "vertical" in split_method:
vim.command(":keepjumps vsplit %s" % fname)
else:
vim.command(":keepjumps split %s" % fname)
elif "always" in split_method:
if "tab" in split_method:
vim.command(":tab split")
elif "vertical" in split_method:
vim.command(":vsplit")
else:
vim.command(":split")
# TODO: move the cursor using vimscript, so we can :keepjumps?
vim.current.window.cursor = (l, c)

def command_locate(path, pos):
try:
choice = vim.eval('g:merlin_locate_preference')
Expand All @@ -260,36 +292,16 @@ def command_locate(path, pos):
pos_or_err = command("locate", "-look-for", choice, "-position", fmtpos(pos))
else:
pos_or_err = command("locate", "-prefix", path, "-look-for", choice, "-position", fmtpos(pos))
if not isinstance(pos_or_err, dict):
print(pos_or_err)
else:
l = pos_or_err['pos']['line']
c = pos_or_err['pos']['col']
split_method = vim.eval('g:merlin_split_method')
# save the current position in the jump list
vim.command("normal! m'")
if "file" in pos_or_err and differs_from_current_file(pos_or_err['file']):
fname = vim_fnameescape(pos_or_err['file'])
if split_method == "never":
vim.command(":keepjumps e %s" % fname)
elif "tab" in split_method:
if "always" in split_method:
vim.command(":keepjumps tab split %s" % fname)
else:
vim.command(":keepjumps tab drop %s" % fname)
elif "vertical" in split_method:
vim.command(":keepjumps vsplit %s" % fname)
else:
vim.command(":keepjumps split %s" % fname)
elif "always" in split_method:
if "tab" in split_method:
vim.command(":tab split")
elif "vertical" in split_method:
vim.command(":vsplit")
else:
vim.command(":split")
# TODO: move the cursor using vimscript, so we can :keepjumps?
vim.current.window.cursor = (l, c)
goto_file_and_point(pos_or_err)
except MerlinExc as e:
try_print_error(e)


def command_locate_type(pos):
try:
pos_or_err = command("locate-type", "-position", fmtpos(pos))
goto_file_and_point(pos_or_err)

except MerlinExc as e:
try_print_error(e)

Expand Down Expand Up @@ -444,6 +456,9 @@ def vim_locate_at_cursor(path):
def vim_locate_under_cursor():
vim_locate_at_cursor(None)

def vim_locate_type_at_cursor():
command_locate_type(vim.current.window.cursor)

# Jump and Phrase motion
def vim_jump_to(target):
command_motion("jump", target, vim.current.window.cursor)
Expand Down
6 changes: 5 additions & 1 deletion vim/merlin/autoload/merlin.vim
Original file line number Diff line number Diff line change
Expand Up @@ -393,6 +393,10 @@ function! merlin#Locate(...)
endif
endfunction

function! merlin#LocateType()
MerlinPy merlin.vim_locate_type_at_cursor()
endfunction

function! merlin#LocateImpl(...)
let l:pref = g:merlin_locate_preference
let g:merlin_locate_preference = 'implementation'
Expand Down Expand Up @@ -711,7 +715,7 @@ function! merlin#Register()
command! -buffer -complete=customlist,merlin#ExpandPrefix -nargs=? MerlinLocateImpl call merlin#LocateImpl(<q-args>)
command! -buffer -complete=customlist,merlin#ExpandPrefix -nargs=? MerlinLocateIntf call merlin#LocateIntf(<q-args>)
command! -buffer -nargs=0 MerlinILocate call merlin#InteractiveLocate()

command! -buffer -nargs=0 MerlinLocateType call merlin#LocateType()

if !exists('g:merlin_disable_default_keybindings') || !g:merlin_disable_default_keybindings
nmap <silent><buffer> gd :MerlinLocate<return>
Expand Down

0 comments on commit 135a1d2

Please sign in to comment.