-
Notifications
You must be signed in to change notification settings - Fork 233
vim from scratch
This document is a work in progress, any feedback or addition is welcomed.
To successfully use merlin from vim, you need to have an already configured
vim setup. The bare vim installation from your system won't do (a bunch of stuff
need to be activated: syntax on
, filetype plugin on
, etc.).
If it's your first time with vim, you should probably document yourself somewhere else before reading the rest of this page. If however you wish to continue in a hurry, you can still start by installing Tim Pope's vim-sensible.
Note that we encourage everyone to install merlin through opam, for two reasons:
- it's a lot easier
- you should then have a version of merlin that is known to work
That being said, it might make sense to install it from git:
- you want to help improve it (you're very welcome!)
- you noticed a bug in the opam version which is fixed on git
- you're cool and no one tells you what to do
With that in mind, feel free to choose the option you prefer.
Just run (should work on 4.00.1 and 4.01.0):
opam install merlin
And add the following to your .vimrc:
let g:opamshare = substitute(system('opam config var share'),'\n$','','''')
execute "set rtp+=" . g:opamshare . "/merlin/vim"
That not only adds merlin to your runtime path, but will always pick the version corresponding to your opam switch without you needing to modify your config (assuming you install merlin on each of your switches).
Note that you need to run :
:execute "helptags " . substitute(system('opam config var share'),'\n$','','''') . "/merlin/vim/doc"
manually to update the documentation.
Thanks to Gabriel Kerneis for this contribution.
Once you have cloned you must run the following commands:
# You can run the following with -help to have more informations
./configure
make
make install
The configure step will have printed you where the vim mode is installed. If it
is in /some/path/merlin/vim/
then you need to add:
set rtp+=/some/path/merlin/vim
set rtp+=/some/path/merlin/vimbufsync
To your .vimrc.
You can the generate the documentation using:
:helptags /some/path/merlin/vim/doc
Note: although you can use pathogen here, we strongly recommend not using Vundle. The reason for that being that you need to keep your vim plugin synchronized with the ocamlmerlin executable (they need to understand the same protocol), which probably won't be the case if you fetch the plugin from github.
Follows a non-ordered list of the features merlin provides, and an explaination on how to access them from vim.
Merlin knows about the syntax and type errors of your code. And it can tell vim about it.
We recommend using Syntastic for displaying these errors. Add this to your .vimrc to integrate it with merlin:
let g:syntastic_ocaml_checkers = ['merlin']
Once you have it, syntastic should ask merlin for errors in your buffer every time you save your file. So little signs should appear on the border of your window when you save and your code contains errors and disappear once you've fixed them.
Merlin offers completion as you would find in other IDEs: given a prefix, it will suggest all the elements of the current environment matching the given prefix and display their type.
Completion should be available out of the box using the omnicompletion facility
of vim, you need only type <C-x><C-o>
and a popup like the one in the previous
screenshot should appear.
Several plugins exists out there to make completion nicer to use in vim, they should all work with merlin; at the cost of a small configuration.
More information about such plugins is available in the documentation shipped
with merlin's vim plugin (so: :h merlin.txt
or directly from
github).
While coding, you can query Merlin for the type of expressions. You just need
to place your cursor on the expression you want type, and call :TypeOf
(which
is bound by default en <Localleader>t
, see :h localleader
) and vim should
then display the type in the command line, and highlight the considered
expression.
For example:
Notice here that the cursor is on map
, if it were on Option
then the
signature of the Option
module would have been printed.
Note also that you can grow (or shrink!) the expression you want to type, for example on my previous code:
And you can do that several times (until there's nowhere left to grow).
The TypeOf command also works in visual mode:
And accepts arguments! So :TypeOf 23 + 42
would have given the same result as
on the last screenshot.
There are mainly two ways Merlin can help you browse the source of you project.
One, which one can find in nearly every IDE on the planet, is a jump to
definition facility, accessible through the :Locate
command.
That command is to be used in the same way as :TypeOf
: either you give it an
argument (an arbitatry identifier, but no expressions, for obvious reasons) or
you place it on a word of your buffer and call it without arguments.
Note that it might happen that merlin fails to find the definition location of the identifier you gave him, several things might explain that:
- you are asking him for the definition of something defined in an other file
and:
- either that file is not in the load path of merlin (you need to setup a .merlin!)
- or you didn't compile with -bin-annot.
- you are asking him for the definition of something local to your file but the place where that thing is defined doesn't parse or doesn't typecheck, and the identifier is not present in the environment
If it doesn't work, but none of the above explains why, open an issue!
The other way of browsing your project is through the commands :ML
and :MLI
which expect a module name as an argument (completion is provided!) and open the
corresponding file.
Or " why doesn't merlin know about my other files? "
By default, when you edit a file in a directory foo/
merlin will add foo/
to
its load path. As your projects grow however, your files will often be spread
among several (sub)directories, at this point you will need to inform merlin
about the structure of your project.
To do that, you need to create a .merlin
file at the root of your project.
A .merlin
file will look something like :
# structure of my awesome project
S src
S src/foo
S src/bar
B _build/src
B _build/src/foo
B _build/src/bar
The S
directive tells merlin where to find source files (for you use with the
:ML
and :MLI
commands) and the B
tells it where to find cmi (used for
basically everything) and cmt (used for :Locate) files.
There is a lot more to .merlin
files than just S
and B
. Have a look at
the power guide to .merlin to know more.
Or " merlin complains about 'Unbound module Core' "
When you want to use external libraries that you installed with findlib (that's the case when you install them with opam) you need to tell merlin which ones you use.
You can do that on a per-session basis using the :Use
command followed by the
name of the package (completion on packages name is provided, but you can always
call ocamlfind list
from a shell to have the list of installed packages).
Or you can set it once and for all for your project by adding the directive
PKG
followed by packages name to the .merlin of your project.
For example :
PKG core lwt
Or " merlin complains about 'Unbound value lwt' "
Merlin has specifics support for syntax extensions, however not all are enabled by default. Those who aren't enabled are the one introducing new keywords, lwt for example.
Again you can choose to enable/disable these on a per-session basis with
:ExtEnable
and :ExtDisable
again followed by a name (completion is once more
provided).
Or you can set them in your .merlin with the EXT
directive.
To force merlin to refresh it's internal buffer afterwards just use :e %
.
Or " I've changed the interface of a module of my project, why doesn't merlin pick it up? "
If you have changed the interface of an other module of your project, and want
merlin to know about it, you need to call :Reload
after having recompiled your
project (the cmi needs to be updated!).
Note that this is done automatically if you call you compile through the :make
vim command.
For people using OMake or jenga's polling, wrapper scripts are provided to
notify merlin at the end of each successful compilation cycle.
They are called omake-merlin
and jenga-merlin
respectively.
If merlin doesn't seem to work for you, here are a few things you can do to understand what's going wrong :
Ensure merlin (the executable, named "ocamlmerlin") is indeed running, and if
it's not make sure that the merlin plugin is loaded. You can use :scriptnames
to have a list of the loaded script files.
If it's not, then check that it indeed is in vim's path (:set rtp?
)
That should be enough to ensure that merlin is indeed running (or to identify the problem, if it wasn't).
TODO: continue.