I use vim, and I'd like to be able to navigate to function and type definitions spread across multiple Elm projects. My understanding is that the easiest way to go about this is to use ctags.
There is an existing open issue from January 2016 with various suggestions, including a link to ctags-elm which provides:
--langdef=Elm
--langmap=Elm:.elm
--regex-Elm=/^ *([[:lower:]][[:alnum:]_]+)[[:blank:]]*:[^:].*->.*/\1/f,function,functions/
--regex-Elm=/^ *([[:lower:]][[:alnum:]_]+)[[:blank:]]*:[^:][^-]+$/\1/c,constant,constants/
--regex-Elm=/^port +([[:lower:]][[:alnum:]_]+)[[:blank:]]*:[^:]/\1/p,port,ports/
--regex-Elm=/^type +([[:upper:]][[:alnum:]_]+)/\1/t,type,types/
--regex-Elm=/^type[[:blank:]]+alias[[:blank:]]+([[:upper:]][[:alnum:]_]+)/\1/a,type-alias,type-aliases/
If you install this in ~/.ctags, you can scan all your sources:
$ ctags -R --languages=-all,+Elm
However this approach still has problems:
- It ignores qualified names, so an attempt to navigate to the definition of
List.mapwill offer all the definitions ofDict.map,Set.map,Random.mapetc. - It scans all the
*.elmfiles in all my directories, including tests and old dependencies.
Basically I'd like a solution that:
- Can follow qualified names☨ to their definition: navigating to
List.mapshould prefer definitions ofmapin files namedList.elm. - Scans all the
*.elmfiles in each project'ssource-directories - Ignores everything in each project's
testsdirectory - Ignores all the built
*.jsfiles - Optionally scans the latest versions☨ of library sources in each project's
elm-stuff/packagesdirectory
Is this possible with ctags, or with a ctags wrapper that parses each project's elm-packages.json file?
[☨] Regarding qualified names: I'm aware that some people abbreviate qualifiers, like:
import Math.Vector3 as V3
and I wouldn't expect a ctags regex to look for V3.add in Math/Vector3.
The longer-term solution would be a tool that understands Elm modules and imports, like hasktags does for Haskell. For now I could live with ctags not understanding abbreviated qualifiers.
[☨] Regarding latest versions: Sources of dependencies are downloaded into elm-stuff/packages/GITHUB-USERNAME/GITHUB-PROJECTNAME/VERSION-TAG, and over time it is possible to accumulate multiple versions, eg:
elm-stuff/packages/kfish/elm-gamepad/3.0.0
elm-stuff/packages/kfish/elm-gamepad/3.1.0
elm-stuff/packages/kfish/elm-gamepad/3.2.0
elm-stuff/packages/kfish/elm-gamepad/3.4.0
I can't answer on the Elm-specific points but…
Add this to
~/.ctags:Add this to
~/.ctagsif they are not compiled in a specific directory:or exclude the directory/directories in which they are compiled.
How do you define "latest"?The only way I could think of to reach that goal would be to pre-compile the list of places to look in and feed it to
ctagsvia the-Lflag:Actually, writing a shell script to generate a proper
list-of-files.txtcould probably fix all your pain points. Maybe someone already thought about that…See
$ man ctags.