1 title: You Should Be Using Tags In Vim 2 author: Daniel Moch 3 copyright: 2018, Daniel Moch 4 date: 2018-12-02 17:33:09 UTC-05:00 5 category: technology 6 description: You may not know it, but Vim already does what you installed a Jedi plugin to do 7 8 <em>Note: This is a crosspost of an entry I wrote in this year's 9 <ahref="http://vimways.org">vimways.org</a> advent calendar. If 10 you'reinterested in Vim, I recommend you pop on over there and read 11 theother articles too.</em> 12 13 > I love you; you complete me. 14 > 15 > - Dr. Evil 16 17 I first came to Vim by recommendation. I was looking for a good Python 18 IDE (at the time I was new to the language) and one recommendation was 19 to use Vim with a variety of plugins added on top. That Vim could do a 20 lot of the things I thought only an IDE could do came as a bit of a 21 shock. I spent a summer as an intern using Emacs at a Unix terminal, but 22 didn't have enough curiosity at the time to use it any differently from 23 `notepad.exe`. I spent that summer wishing I had automatic features for 24 completion, indentation, and all the things that made me appreciate 25 the IDE's I used in college. How naive I was! 26 27 So how was I directed to achieve powerful programming completions in 28 Vim? By the use of a plugin called YouCompleteMe. My experience with it 29 was okay, at least to start with. It took a while to install and get 30 working, but that didn't bother me at the time since I was just playing 31 around with it at home and the stakes were low if it suddenly broke. I 32 did notice it slowed Vim down. Like a lot. But that was mainly when it 33 was starting up and I didn't know enough to find it frustrating. 34 Probably the first thing that really bothered me about the plugin was 35 that the embedded Jedi language server used more memory than Vim itself. 36 The other recommended plugins were similarly laggy, and I eventually 37 went in search of something better. 38 39 What I found was Vim itself. 40 41 Did you know that Vim has built-in facilities for completions? It works 42 admirably well out of the box too, but with a little bit of additional 43 setup it can be great. Let's take a look at what Vim has on offer 44 regarding completion and see what it takes to fully leverage it. 45 46 Completion in Vim 47 ----------------- 48 49 Completion in Vim is powerful, but not necessarily straightforward. 50 Read [:h 51 ins-completion](http://vimdoc.sourceforge.net/htmldoc/insert.html#ins-completion) 52 and you'll see what I mean: 53 54 Completion can be done for: 55 56 1. Whole lines |i_CTRL-X_CTRL-L| 57 2. keywords in the current file |i_CTRL-X_CTRL-N| 58 3. keywords in 'dictionary' |i_CTRL-X_CTRL-K| 59 4. keywords in 'thesaurus', thesaurus-style |i_CTRL-X_CTRL-T| 60 5. keywords in the current and included files |i_CTRL-X_CTRL-I| 61 6. tags |i_CTRL-X_CTRL-]| 62 7. file names |i_CTRL-X_CTRL-F| 63 8. definitions or macros |i_CTRL-X_CTRL-D| 64 9. Vim command-line |i_CTRL-X_CTRL-V| 65 10. User defined completion |i_CTRL-X_CTRL-U| 66 11. omni completion |i_CTRL-X_CTRL-O| 67 12. Spelling suggestions |i_CTRL-X_s| 68 13. keywords in 'complete' |i_CTRL-N| |i_CTRL-P| 69 70 Vim is smart enough to pull completion data from a variety of sources, 71 but in turn expects users to know which source will provide the best 72 answer and to invoke the correct keymap to draw the desired completions. 73 It's not a huge hurdle in terms of a learning curve, but it's not as 74 simple as hitting tab either. 75 76 The first thing one should do when trying to learn Vim's completion 77 system is to disable any completion plugins and learn these keymaps. 78 Getting comfortable with them will also help you learn and remember 79 where Vim can pull completion information from. You should also read 80 [:h 81 'completefunc'](http://vimdoc.sourceforge.net/htmldoc/options.html#'completefunc') 82 and [:h 83 'complete'](http://vimdoc.sourceforge.net/htmldoc/options.html#'complete') 84 for more information on user-defined completion and the `complete` 85 option. 86 87 Now that we have a cursory understanding of completion in Vim, let's 88 take a deeper look at tags and how they figure into completion. 89 90 Introduction to `tags` in Vim 91 ----------------------------- 92 93 One source of completion in Vim is tag completion, which pulls from a 94 special file called–appropriately—a tags file. Tags files are collections 95 of identifiers (e.g., function names) that are compiled into a single 96 file along with references to their location in a source tree. Vim is 97 capable of using a (properly formatted) tags file for a variety of use 98 cases, among them navigating your source code à la Visual Studio and 99 completion. 100 101 By default Vim doesn't do anything with a tags file except read it. 102 See [:h 103 'tags'](http://vimdoc.sourceforge.net/htmldoc/options.html#'tags') to 104 learn how to configure where Vim looks for tags files. Vimdoc also 105 contains a very good 106 [introduction](http://vimdoc.sourceforge.net/htmldoc/usr_29.html#29.1) 107 to tags more generally, so I won't spend any more time here 108 introducing them. Let's move on and take a look at how we generate 109 tags files. 110 111 Introduction to `ctags` 112 ----------------------- 113 114 Tags files solve the problem of navigating and completing code in a 115 given project, but they also create a problem: how do we create the 116 tags file, and how do we keep it up to date? It would be a pain to 117 manually maintain the tags file even for a small project; it would be 118 all but impossible to do it for a large project like the Linux kernel. 119 Luckily no one has to maintain a tags file. There are plenty of 120 utilities to do that for you, usually bearing the name ctags, or some 121 variant. One very popular choice is called [Exuberant 122 Ctags](http://ctags.sourceforge.net/), which has the virtue of being 123 extendable via regular expressions placed into a `.ctags` file, but 124 the drawback of not having been updated since 2009. Another 125 increasingly popular option is [Universal Ctags](https://ctags.io/), 126 which functions as a drop-in replacement for Exuberant Ctags and is 127 actively maintained. I've had good luck with both. 128 129 Tags files and the tools that generate them have a long history 130 alongside advanced text editors. The history-of-computing nerd in me 131 likes knowing that I'm using the same tool programmers have used since 132 the early days of BSD Unix. It's also a testament to how strong of a 133 solution they provide that folks are still using them 40 years later. 134 135 Generating `tags` Files 136 ----------------------- 137 138 ### Manually 139 140 When we speak of manually generating tags files, we're talking about 141 using any one of the aforementioned tags utilities to generate the tags 142 file. If you're the type of person who takes pleasure in at least 143 understanding how to do things from the command line, you should consult 144 the manual page for your selected tags utility. Take special note of the 145 flags necessary to recurse through all of the subdirectories if you want 146 to generate a tags file for an entire project in one shot. 147 148 ### Automatically 149 150 You can always use your ctags utility to generate your tags files from 151 the command line, but that's a heck of a lot of back and forth between 152 your text editor and your shell, and I doubt anyone who tries to do that 153 will enjoy the experience for long. So let's look at ways to generate 154 them automatically. 155 156 If you only ever see yourself using tags files with Vim, then maybe a 157 plugin will interest you. I used 158 [Gutentags](https://bolt80.com/gutentags/) for a long time, and found 159 it "just works" as advertised. It has sane defaults, but lots of 160 opportunities to customize its behavior, which you'll see if you visit 161 the above link. 162 163 In spite of that, I ended up moving in a different direction with 164 managing my tags files. There were several reasons, but the main one 165 is that I like to think of tags files as separate from Vim, something 166 the text editor consumes without having to manage. It's an opinionated 167 view of things, but I increasingly didn't like to configure my text 168 editor to manage my tags files. So I went in search of another method, 169 and what I found was the [Tim 170 Pope](https://tbaggery.com/2011/08/08/effortless-ctags-with-git.html) 171 method, which I've since implemented myself. Rather than using Vim 172 itself to manage tags files, this method uses local [Git 173 hooks](https://git-scm.com/docs/githooks) to rebuild the tags whenever 174 any of a handful of common Git operations are performed. The result is 175 a system that also just works, but does so in a half-a-dozen lines of 176 shell script rather than a few *hundred* lines of Vimscript. Gotta 177 keep that Vim config tight. 178 179 As a bonus, if you already use Tim Pope's [Fugitive Git 180 plugin](https://github.com/tpope/vim-fugitive) (and you should), this 181 method handily places your tags file where that plugin tells Vim to 182 look for it—in the `.git` folder. Of course the shell-script 183 approach is infinitely configurable, so you can ultimately place the 184 tags file wherever you want. One could also tailor this for other 185 distributed SCM tools (e.g., Mercurial). 186 187 Generically speaking, there are other options as well. You could set a 188 filesystem watcher to watch your project tree and run ctags any time a 189 file changes. A task runner like [Grunt](https://gruntjs.com/) might 190 be a viable option too, especially for web developers. The goal is to 191 automate the task of (re)generating your tags file, so there is likely 192 to be no shortage of options. 193 194 Tying It All Together 195 --------------------- 196 197 That brings us back to where we started, to the issue of code 198 completion in Vim. Yes, Vim does offer native code completion 199 (completing from tags is done with `C-x, C-]` in insert mode). No, 200 it's probably not as powerful as what you could get with something 201 like a Jedi plugin à la YouCompleteMe, but I've found it satisfies my 202 needs more often than not, with `:grep` (or my own 203 [:GrepJob](https://git.danielmoch.com/vim-makejob.git) filling the gap 204 nicely in a more native fashion. 205 206 There's more you can do here too. For instance, if you find yourself 207 instinctively reaching for the tab key in order to complete a word, 208 there is [VimCompletesMe](https://github.com/ajh17/VimCompletesMe), 209 which takes advantage of all of Vim's built-in completions through the 210 clever use of an [omni completion 211 function](http://vimdoc.sourceforge.net/htmldoc/options.html#'omnifunc'). 212 It works, but users do give up some control over selecting what data 213 source Vim uses for a particular completion. I used this plugin for a 214 while after I gave up on YouCompleteMe, but ultimately removed it 215 because it effectively made the tab key ambiguous in Insert mode. 216 Sometimes I wanted to insert an actual tab character, but got a 217 completion instead. 218 219 With all of this in place, it's natural to ask whether a language server 220 is even necessary with Vim. I don't intend here to suggest an answer to 221 that question, but I will say that many of the solutions to date for 222 language server integration in Vim have seemed like more trouble than 223 they're worth. That said, with the advent of Vim 8 and its asynchronous 224 capabilities, there is headroom for these solutions to improve, and I 225 expect the best among them to become more compelling in the near future. 226 227 I do not recommend coming to Vim with a mindset of creating an IDE in 228 your terminal. That said, Vim is a very powerful tool and if you invest 229 the time to learn how it works it will take you very far. In other 230 words, use Vim for all it's worth *before* looking for a plugin to help 231 you out. Anyone who (like me) jumps right to installing a bunch of 232 plugins—whether in a spree of grabbing anything that looks interesting 233 or just to copy someone else's configuration—will likely end up with an 234 unmaintainable mess of a tool that doesn't work consistently, may not 235 work at all, or works about as slow as the IDE you wanted to break free 236 of.