lh-tags
lh-tags copied to clipboard
ctags base updating, and browsing from vim
lh-tags : a ctags wrapper for Vim
Introduction
lh-tags is a ctags wrapper plugin for Vim.
This plugin has two main features:
- The generation of
tags
files is simplified, - and tag selection is simplified (the support for overloads (when
overloading is supported) is more ergonomic than what
:tselect
permits)
It also provides a feature aimed at plugin developpers:
- an API to request information on the current file -- local variables, information on an enumeration, function boundaries... In other Words, the API gives on-the-fly access to information that is not necesserally stored in the current tag database.
Features
Tags generation
- Is portable: the plugin is regularly used on nixes, windows (with or without
cygwin, and with
'shellslash'
on). - Is incremental: when a file under the watch of lh-tags is modified, only
this file is parsed -- its previous information is deleted from the current
tags
file. - Can be run on the whole project, when needed.
- Is, of course, parametrisable.
- Can be run asynchronously (this is the default starting from Vim 7.4-1980). When this happens, airline will display information about the background jobs -- if airline plugin is installed, of course.
- Can be done on a third-party project freshly cloned/checked out without a need to define any configuration file for a local_vimrc plugin.
- Doesn't have external dependencies other than
ctags
andcd
. BTW, I highly recommend universal ctags over exhuberant ctags. - Is project friendly: i.e. multiple projects can be opened simultaneously in
a single vim session, and we can run
ctags
on each of them with different specialized options to produced dedicaded tag files. - Tag files built can be used to (automatically) fill
'spellfile'
option with words to be ignored by vim spell checker. - Generated tags can also automatically be highlighted (see
g:tags_options.auto_highlight
)
Tags selection
- Presents all tags that match the selected text (
META-W-META-DOWN
), or the pattern used (:LHTags
). - Can hide, or show, functions signatures (on
s
). - Permits to sort the results by
K
ind,N
ame, orF
ilename. - Can filter the results on any (ctags) field (kind, name, filename, signature, namespace, ...)
- The selected tag can be jumped to in the current window (
CR
, double-click), or in a split window (o
) -- the tags stack is updated along the way.
Usage
In order to use lh-tags, I highly recommend to use a plugin like local_vimrc.
In the buffer local section, you can:
- set some
(bpg):tags_options....
if the default values don't suit you -- I use it to add exclusion lists in my projects. - force another root directory where to store the ctags database
- ...
Then, you'll have to generate the tags
database once (<C-X>ta
), then you
can enjoy lh-tags automagic update of the database, and improved tag selection.
Options
Regarding the conventions used in my plugins, and how to set options, see
the following
documentation.
I explain what I mean by (bpg)
, what each scope covers, and how (and where)
related variables can be set.
Directory and pathnames related options
lh-tags can distinguish the directory where a tag database is stored from the directory where the source files are. By default, both directories will be the same.
Dirname to source code: (bpg):paths.tags.src_dir
How ever this directory name is deduced, its value will be cached in the
project variable
p:paths.tags.src_dir
.
The heuristic to deduce where the source code to index is located consists in searching the first option which is set among:
-
(bpg):paths.tags.src_dir
-- cached, specific to lh-tags, permits to override(bpg):paths.sources
if need be -
(bpg):tags_dirname
-- old (deprecated) options previously used by lh-tags V2; kept for retro-compatibility -
(bpg):paths.sources
-- where sources files are supposed to be found according to lh-vim-lib Project feature. -
b:project_source_dir
-- old option used by previous versions of mu-template; kept for retro-compatibility -
(bpg):BTW_project_config._.paths.sources
-- internal information used by Build Tools Wrapper; not meant to be set from lh-tags -
If none of the previous options is set, lh-tags will search a parent directory which contains any sign of being under source control (
.git/
,.svn/
,.hg/
...) -
Ultimately, lh-tags asks to the end-user where the source files to index are stored (previous values are recorded in case several files from a same project are opened).
Note: At this time, we cannot say "never ask for this directory" as it's possible with lh-vim-lib Project feature. I'm likelly to change the current behaviour to the one used in lh-vim-lib.
Name of the tag database: (pbg):tags_filename
The name defaults to "tags"
with ctags indexers.
This option permits to have another name -- this can be useful when all tag
databases are stored with a policy such as projects/.tags/{projectname}.ctags
.
If you want to change the directory where the tag database is stored, it must
be done through this option. Relative pathnames are expressed relativelly to
the sources directory (bpg):paths.tags.src_dir
.
Filetypes and languages related options
Indexed filetype: lh#tags#add_indexed_ft()
This option helps managing the filetypes whose files will be indexed. Files of other types are ignored.
Internally, this updates the project option p:tags_options.indexed_ft
--
prefer this function when using
local_vimrc to configure a
project.
It's also possible to set the option g:tags_options.indexed_ft
that'll be
used instead. The global option is meant to be used when no project are
defined.
" In this project we index only C and C++ files
:call lh#tags#add_indexed_ft('c', 'cpp')
Language map: lh#tags#set_lang_map()
Manages the extensions associated to a filetype.
The point of this helper function is to set the options to the best possible value according to the current tag-indexer which could be exhuberant-ctags, universal-ctags, or eventually any other indexer like global.
:call lh#tags#set_lang_map('cpp', '+.txx')
Since version 3.0.0, it's best to avoid to directly set
b:tags_options.{ft}.flags
to either --langmap=C++:+.txx
or
--map-C++=+.txx
as it's not portable between the various flavours of ctags.
Option to highlight tags
-
g:tags_options.auto_highlight
boolean option that tells to automatically highlight tags withTagsGroup
style -- which is linked toSpecial
group.Defaults to 0.
This option is best set in your
.vimrc
. If you want to change or toggle its value, you'd best use the menuProject->Tags->Auto Highlight Tags
when running gvim, or the:Toggle
command::Toggle ProjectTagsAutoHighlightTags
Notes:
- At this point, there is a bug: the highlighting isn't propagated to all buffers.
- This feature can incur an observable slow down with current non-multithreaded implementations of Vim.
Options to add tags to the list of correctly spelled words
-
lh#tags#ignore_spelling()
option permits to add all the current tags to Vim spellchecker ignore list. If no parameter is passed to the function, it will assume the dictionary file to be namedcode-symbols-spell.{enc}.add
. If no file was specified in'spellfile'
, one is automatically added to contain words the end-user would want to manually register withzg
and all. -
g:tags_options.auto_spellfile_update
specifies whether spellfiles are automatically generated from updated tag files:-
0
: never, useCTRL-X_ts
instead. -
1
: always -
"all"
: only when tags are regenerated for the whole project, never when a file is saved.Indeed, updating spellfile may be very long on some projects, and we may not wish to see this task automated.
-
-
(bg):tags_to_spellfile
has been deprecated since Version 2.0.0. Uselh#tags#ignore_spelling()
instead.
Note:
- This feature can incur an observable slow down with current non-multithreaded implementations of Vim.
Tag selection (options)
-
(bpg):tags_select
defaults to'expand('<cword>')'
; this policy says how the current word under the cursor is selected by normal mode mappingMETA-W-META-DOWN
.
Indexer related options
Since V 3.0.0, lh-tags can support multiple indexers. At this time only
indexers for ctags are supported. I'm likelly to eventually support GNU
global. Any other indexer needs to be typically dropped into
{rtp}/autoload/lh/tags/indexers/{indexername}.vim
If you want to contribute another indexer, check
autoload/lh/tags/indexers/interface.vim
and the implementation of ctags
indexer.
-
lh#tags#set_indexer(indexer [,scope])
This function permits to change the current indexer. The indexer will be binded to the specified scope (the default value is
"p"
).
Options common to all indexers
-
(V3.0+)
(bpg):tags_options.excludes
List of excluded patterns, inctags
format. -
(V3.0+)
(bpg):tags_options._...
and(bpg):tags_options._.{&ft}....
dictionaries of options. This is the prefered way to specify ctags--fields
,--extra(s)
and--kinds
parameters. The supported suboptions are:- all field names and shortcut names that can be obtained with
ctags --list-field
. The plugin will try to find the best fit for each indexer supported. -
absolute_path
used to generate absolute path of tag locations -
extract_local_variables
-
extract_variables
- TODO: add generic support for other kinds
-
recursive_or_all
used internally to work on all files of a directory -
index_file
used internally to index a single file -
ft
to force a filetype
Note: these options can also be injected while calling
cmd_line()
method on indexers.Indexers other than ctags indexer are expected to translate the possible values to something they could understand.
- all field names and shortcut names that can be obtained with
Options specific to the ctags indexer
-
(bpg):tags_executable
defaults to"ctags"
; you should not need to change it unless you want to play with different flavours of ctags installed on a same system. -
(bpg):tags_must_go_recursive
defaults to 1; set it to 0 if you really want to not explore subdirectories. -
g:tags_options.explicit_cmdline'
-- default: 0; Tells to not rely on implicit options when indexing files. For instance, many fields are enabled or disabled by default with ctags; this options will procude command line 100% explicit about which fields should produced, or ignored. -
(wbpg):tags_options.flags
defaults to an empty string; It contains extra flags you could pass toctags
execution. You may have to adjust these options to your needs. Note that most options are already covered by the indexer generic options:(bpg):tags_options._...
and(bpg):tags_options._.{&ft}....
. -
(V2.0+)
(wbpg):tags_options.{ft}.flags
defaults to nothing since Version 3.0. It can be used to set anything specific to a filetype, yet prefer the new dedicated interface to specify ctags--fields
,--extra(s)
and--kinds
parameters.Note: This was renamed from
(bg):tags_options_{ft}
in version 2.0.0.
Other options
-
(bpg):tags_options.no_auto
defaults to 1; set it to 0 if you want to enable the automatic incremental update. IOW, if you want incremental update, force this option to 0. Note: this has changed in version 2.0.0; it used to be named(bg):LHT_no_auto
, and it had the opposite default value. -
g:tags_options.run_in_bg
; set to 1 by default, if |+job|s are supported. Tells to execute<Plug>CTagsUpdateCurrent
and<Plug>CTagsUpdateAll
in background (through |+job| feature).This option is best set in your
.vimrc
. If you want to change or toggle its value, you'd best use the menuProject->Tags->Generate
when running gvim, or the:Toggle
command::Toggle ProjectTagsGenerate
-
lh#tags#update_tagfiles()
instructs the plugin to automatically set'tags'
with the current tagfile. This may be deprecated in the future for something less cumbersome to use.
Example
A typical configuration file for local_vimrc will be:
" #### In _vimrc_local.vim
" Define the project
Project --define FooBar
...
" ======================[ tags generation {{{2
" Be sure tags are automatically updated on the current file
LetIfUndef p:tags_options.no_auto 0
" Declare the indexed filetypes
call lh#tags#add_indexed_ft('c', 'cpp')
" Files and directories to ignore
LetIfUndef p:tags_options.excludes = ['"tests/*"', 'aspecificdir']
" Update Vim &tags option w/ the tag file produced for the current project
" (the folowing line is the only one which is required in all projects)
call lh#tags#update_tagfiles() " uses b:project_sources_dir/BTW_project_config
" Register ITK/OTB extensions as C++ extensions
call lh#tags#set_lang_map('cpp', '+.txx')
" Instruct to ignore spelling of code constructs
call lh#tags#ignore_spelling()
" But automatically when a file has been saved (this is too slow on OTB!)
LetIfUndef g:tags_options.auto_spellfile_update 'all'
Mappings and commands
-
The tags for the current file can be explicitly updated with
CTRL-X_tc
-- this mappings defaults to<Plug>CTagsUpdateCurrent
-
All the tags for the current project can be explicitly updated with
CTRL-X_ta
-- this mappings defaults to<Plug>CTagsUpdateAll
-
The list of words to ignore with the spellchecker can be updated on demand with
CTRL-X_ts
-- bound by default to<Plug>CTagsUpdateSpell
This requireslh#tags#ignore_spelling()
to have been explicitly called. Otherwise nothing will be done. -
Tags matching the current word (or selection) will be presented on
META-W-META-DOWN
-- these two mappings default to<Plug>CTagsSplitOpen
-
We can also present the tags that match a pattern with
:LHTags
command (this command supports auto-completion on tag names)
To Do
- Tag selection
- Have behaviour similar to the one from the quickfix mode (possibility to close and reopen the search window; prev&next moves)
- Show/hide declarations -- merge declaration and definitions
- Pluggable filters (that will check the number of parameters, their type, etc)
- Tag generation
- Get rid of
lh#tags#update_tagfiles()
is possible. - Be able to specify a directory to store all spellfiles automatically.
{prjroot}/spell/
,{prjroot}/.spell/
? -
g:tags_options.auto_spellfile_update
should be overridable for each project. - See to update spellfile in the background thanks to Python.
- Auto-update on other events like
CursorHold
- Get rid of
- Auto-highlight tags
- Cache tag list generated for spell file (as long it's not generated in background in another vim instance)
-
g:tags_options.auto_highlight
should be overridable for each project. - Different highlighting for different Identifier kind (type, function, variable, ...)
- Specify syn hl.
- Incrementally add/remove highlighted keywords when tags are incrementally
updated.
- And do the same for ignored words
Design Choices
- 100% in Vim script language
- API usable from other plugins -- to extract function boundaries, local variables...
- Avoid dependencies other than lh-vim-lib
- Support project specific settings (options may differ from one project to the other)
Installation
-
Requirements: Vim 7.2-295, lh-vim-lib v5.0.0
-
With vim-addon-manager, install lh-tags (this is the preferred method because of the dependencies)
ActivateAddons lh-tags
-
or with vim-flavor which also supports dependencies
flavor 'LucHermitte/lh-tags'
-
or you can clone the git repositories
git clone [email protected]:LucHermitte/lh-vim-lib.git git clone [email protected]:LucHermitte/lh-tags.git
-
or with Vundle/NeoBundle:
Bundle 'LucHermitte/lh-vim-lib' Bundle 'LucHermitte/lh-tags'