-
Notifications
You must be signed in to change notification settings - Fork 256
Usage
RTags consists of three executables, rdm
, rc
and rp
. rdm
is the server
application, and monitors all your indexed files for changes, and reindexes,
using rp
, when a source file or one of its dependencies is modified. Since
clang is a fully compliant compiler it needs specific information about how
your sources are compiled to be able to properly index them. This is done
through telling rdm
about the compile line using rc
. First you need to
start rdm
. There are multiple ways to do so, either automatically
(Launchd/Systemd/Emacs) or manually. To manually start rdm
, just run rdm
in a shell. Call rdm
with the flag --help
to print all the options
available. We also provide manual pages for rdm
and rc
. If you always want
to start rdm
with specific options, put those options in the file
~/.rdmrc
, see Setting rdm
default options.
# Start rdm in the background
rdm &
# Index the file _foobar.c_
rc -c gcc -I... -fsomeflag -c foobar.c
# Load the compilation commands JSON file
rc -J /path/to/a/directory/containing/compile_commands.json
You can generate a compile_commands.json with various different tools, one might fit better than the other, depending on your project build system.
-
ninja
ninja -t compdb cxx cc > compile_commands.json rc -J
With
ninja
it’s also possible to pipe the commands directly torc
.ninja -t commands | rc -c - # Parse commands for a specific target only ninja -t commands rdm | rc -c -
-
cmake
cmake
can generate a compile_commands.json file as well.cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=1 . rc -J
-
Bear
For other projects you can use
bear
to generate a compile_commands.json file. However, if you are cross-compiling you probably need to adjust the command entries in the compile_commands.json file to match the correct compiler. Furthermore, make sure you clean your project before invokingbear
.make clean bear make rc -J # Parse commands for a specific target only make clean bear make rdm rc -J
-
make
You can ask
make
to only print the recipes without actually doing something. This way may be perfectly fine for not too complex Makefiles.make clean make -nk | rc -c -
There are very likely similar things you can do with other build systems that we’re unfamiliar with, please let us know if you do.
- A different approach to get your files indexed is the man-in-the-middle
This can be done like this:
ln -s /path/to/rtags/bin/gcc-rtags-wrapper.sh /somewhere/that/is/in/your/path/before/usr/bin/gcc ln -s /path/to/rtags/bin/gcc-rtags-wrapper.sh /somewhere/that/is/in/your/path/before/usr/bin/c++ ln -s /path/to/rtags/bin/gcc-rtags-wrapper.sh /somewhere/that/is/in/your/path/before/usr/bin/cc ln -s /path/to/rtags/bin/gcc-rtags-wrapper.sh /somewhere/that/is/in/your/path/before/usr/bin/g++
E.g.
$ which -a gcc | xargs file /home/abakken/bin/gcc: symbolic link to `/home/abakken/dev/rtags/bin/gcc-rtags-wrapper.sh' /usr/bin/gcc: symbolic link to `gcc-4.7'
Now every time you compile a file with
which gcc
rc
will get its grubby hands all over your command line and make sure RTags knows about it.
RTags will group source files into projects based on some heuristics.
Essentially it will look for certain files/dirs (like
configure/CMakeLists.txt/scons.1/.git) etc to try to determine the likely
project root for each source file. For generated source files that end up in
the build directory we try to find the source root based on similar heuristics
around config.status/CMakeCache.txt etc. Usually this works out reasonably
well. If it doesn’t for you, you can pass --project-root
/path/to/the/project/root
to rc
.
RTags only gives you information about current project when you ask for things by name. You can explicitly change the current project using:
rc -w foobar
We try to do it automatically for you by passing along information about the
current buffer when we call rc
from elisp so that rdm
can update its
current project on demand.
RTags keeps a cache of indexed data so you don’t have to reindex everything if
you restart it. The location of this data is by default ~/.cache/rtags
but
can be overridden by passing --data-dir /other/dir
to rdm
.
(rtags-start-process-unless-running)
Start the rdm
process unless the process is already running. You may create
hook to automatically call this function upon entering, e.g. c-mode or
c++mode.
E.g.
(add-hook 'c-mode-hook 'rtags-start-process-unless-running)
(add-hook 'c++-mode-hook 'rtags-start-process-unless-running)
(add-hook 'objc-mode-hook 'rtags-start-process-unless-running)
(rtags-restart-process)
Restart the rdm
process.
(rtags-find-symbol-at-point)
Follow symbol under cursor. For references this goes to the definition (or
declaration if no definition is known of the symbol. For declarations it goes
to the definition and vice versa. For definitions of variables/parameters with
constructors it goes to the constructor in question. If you pass a prefix
argument, limit to current source file, if you pass a prefix argument and have
narrowed the current file, limit to the narrowed region. This prefix argument
is the same for: rtags-find-references-at-point
, rtags-find-symbol
,
rtags-find-references
(rtags-find-references-at-point)
Find all references to symbol under cursor. If symbol is itself a reference it will find all references to the referenced symbol
(rtags-find-symbol)
Prompt for name of symbol to go to. Imagine the following code:
namespace N
{
class C
{
public:
int func(int);
};
};
using namespace N;
int C::func(int val)
{
return val * 2;
}
int N::C::func(int) will now be accessible by the following names:
- func
- func(int)
- C::func(int)
- C::func
- N::C::func(int)
- N::C::func
(rtags-find-references)
Prompt for name of symbol to find references to. Same as above but find references to symbol rather than declarations and definitions.
(rtags-diagnostics)
Start an async process in a buffer to receive warnings/errors from clang whenever a file gets reindexed. It integrates with flymake to put highlighting on code with warnings and errors
(rtags-enable-standard-keybindings)
Sets up a ton of standard keybindings under C-c r. If you pass a mode to the function it will set it up on that mode, otherwise it will use c-mode-base-map). You can choose a different prefix than C-c r like this:
(rtags-enable-standard-keybindings c-mode-base-map "\C-xr")
(rtags-find-file)
Lets you jump to file by name (partial or full, concept kinda stolen from gtags.el) with completion in the project. This includes all files under what we determine to be the root of the project, not just source files.
(rtags-find-virtuals-at-point)
For virtual functions, show the various reimplementations of the function at point
(rtags-fixit)
Apply clang’s automatic fixits in current file. If you pass a prefix arg use ediff to apply it. See (https://clang.llvm.org/diagnostics.html) for more info.
(rtags-imenu)
Provides an ido-based imenu like interface to a subset of the symbols in the current file. Note that it does not actually use imenu infrastructure.
(rtags-location-stack-back)
(rtags-location-stack-forward)
Whenever RTags jumps somewhere it pushes a location onto its stack. Jump back and forward in this stack
(rtags-next-match)
(rtags-previous-match)
For functions that return more than one match, jump to the next/previous one.
(rtags-preprocess-file)
Preprocess current file according to known C(XX)Flags and show the result in a buffer. If region is active only display the preprocessed output for that region.
(rtags-print-symbol-info)
Print some info about symbol under cursor
(rtags-symbol-type)
Print the type of the symbol under cursor.
(rtags-print-dependencies)
Open a buffer showing files that depend on current file/files that current file depends on.
(rtags-print-enum-value-at-point)
Print integral value of enum value at point
(rtags-quit-rdm)
Shut down rdm
(rtags-rename-symbol)
Rename symbol under cursor. Make sure all files are saved and fully indexed before using.
(rtags-reparse-file)
Explicitly trigger a reparse of current file. Mostly for debugging. Unless we have bugs it should not be necessary.
(rtags-show-rtags-buffer)
Switch to *RTags*
buffer. This is the buffer where a number of functions
display their alternatives when they have more than one match.
(rtags-include-file)
Insert selected or entered include, e.g. “string.h”/<string.h> in current
buffer, either at the top, after the first include statement or with prefix
argument (C-u
) at current point.
(rtags-get-include-file-for-symbol)
Insert include for entered symbol or symbol under courser in current buffer,
either at the top, after the first include statement or with prefix argument
(C-u
) at current point.
rtags-path
Path to rc/rdm
if they’re not in $PATH
.
rtags-jump-to-first-match
Similar to compilation-auto-jump-to-first-error
. Whether to jump to the
first match automatically when there’s more than one.
rtags-find-file-case-insensitive
Whether to match files case-insensitively
rtags-find-file-prefer-exact-match
Whether to exclude partial matches for file names when an exact match is
found. E.g. /foobar.cpp
/bar.cpp
If rtags-find-file-prefer-exact-match
is t
a query for bar.cpp
would only return /bar.cpp
, otherwise both
foobar.cpp
and bar.cpp
would be returned.
You can do something like the following to fall back to e.g. gtags if RTags doesn’t have a certain project indexed:
(defun use-rtags (&optional useFileManager)
(and (rtags-executable-find "rc")
(cond ((not (gtags-get-rootpath)) t)
((and (not (eq major-mode 'c++-mode))
(not (eq major-mode 'c-mode))) (rtags-has-filemanager))
(useFileManager (rtags-has-filemanager))
(t (rtags-is-indexed)))))
(defun tags-find-symbol-at-point (&optional prefix)
(interactive "P")
(if (and (not (rtags-find-symbol-at-point prefix)) rtags-last-request-not-indexed)
(gtags-find-tag)))
(defun tags-find-references-at-point (&optional prefix)
(interactive "P")
(if (and (not (rtags-find-references-at-point prefix)) rtags-last-request-not-indexed)
(gtags-find-rtag)))
(defun tags-find-symbol ()
(interactive)
(call-interactively (if (use-rtags) 'rtags-find-symbol 'gtags-find-symbol)))
(defun tags-find-references ()
(interactive)
(call-interactively (if (use-rtags) 'rtags-find-references 'gtags-find-rtag)))
(defun tags-find-file ()
(interactive)
(call-interactively (if (use-rtags t) 'rtags-find-file 'gtags-find-file)))
(defun tags-imenu ()
(interactive)
(call-interactively (if (use-rtags t) 'rtags-imenu 'idomenu)))
(define-key c-mode-base-map (kbd "M-.") (function tags-find-symbol-at-point))
(define-key c-mode-base-map (kbd "M-,") (function tags-find-references-at-point))
(define-key c-mode-base-map (kbd "M-;") (function tags-find-file))
(define-key c-mode-base-map (kbd "C-.") (function tags-find-symbol))
(define-key c-mode-base-map (kbd "C-,") (function tags-find-references))
(define-key c-mode-base-map (kbd "C-<") (function rtags-find-virtuals-at-point))
(define-key c-mode-base-map (kbd "M-i") (function tags-imenu))
(define-key global-map (kbd "M-.") (function tags-find-symbol-at-point))
(define-key global-map (kbd "M-,") (function tags-find-references-at-point))
(define-key global-map (kbd "M-;") (function tags-find-file))
(define-key global-map (kbd "C-.") (function tags-find-symbol))
(define-key global-map (kbd "C-,") (function tags-find-references))
(define-key global-map (kbd "C-<") (function rtags-find-virtuals-at-point))
(define-key global-map (kbd "M-i") (function tags-imenu))
To enable code completion in Emacs with company mode do the following:
- Enable completions in RTags:
(setq rtags-completions-enabled t)
- Enable company-mode
(require 'company)
(global-company-mode)
- Add company-rtags to company-backends:
(push 'company-rtags company-backends)
This minimal init.el configuration should be enough to get completion to work.
(require 'package)
(package-initialize)
(require 'rtags)
(require 'company)
(setq rtags-completions-enabled t)
(push 'company-rtags company-backends)
(global-company-mode)
(define-key c-mode-base-map (kbd "<C-tab>") (function company-complete))
To enable completion in Emacs with auto-complete-mode do the following: …TODO…
To turn on RTags Flycheck support you need to load the flycheck-rtags
package.
(require 'flycheck-rtags)
You may explicitly select the RTags Flycheck checker for some major modes for better experience.
At the moment there is no customize option available to choose between
rtags-diagnostics
overlays or Flycheck overlays, nor is it planned right
now.
We recommend setting flycheck-highlighting-mode
locally to nil
as the
RTags overlays are more accurate.
Further, Flycheck will trigger automatically, based on events, the syntax
checker for the current buffer, this is however, pretty useless in conjunction
with RTags. We trigger it manually because we find it gives you a better
experience.
To turn off the automatic Flycheck syntax checking, set the variable
flycheck-check-syntax-automatically
locally to nil
.
(setq rtags-autostart-diagnostics t)
(defun my-flycheck-rtags-setup ()
(flycheck-select-checker 'rtags)
(setq-local flycheck-highlighting-mode nil) ;; RTags creates more accurate overlays.
(setq-local flycheck-check-syntax-automatically nil))
(add-hook 'c-mode-hook #'my-flycheck-rtags-setup)
(add-hook 'c++-mode-hook #'my-flycheck-rtags-setup)
(add-hook 'objc-mode-hook #'my-flycheck-rtags-setup)
You can use Helm to view the result, to do so, set
rtags-display-result-backend
to helm
. You don’t need to load helm-rtags
,
we do it. If you have installed RTags through MELPA you need to install
helm-rtags
.
(setq rtags-display-result-backend 'helm)
You can use Ivy to view the result, to do so, set
rtags-display-result-backend
to ivy
. You don’t need to load ivy-rtags
,
we do it. If you have installed RTags through MELPA you need to install
ivy-rtags
.
(setq rtags-display-result-backend 'ivy)
There are several other projects integrating RTags with other editors.
Sublime Text:
Vim:
- https://github.com/lyuts/vim-rtags
- https://github.com/shaneharper/vim-rtags
- https://github.com/mattn/vim-rtags
Neovim:
Atom:
- https://github.com/artagnon/atomic-rtags
- https://github.com/rajendrant/atom-rtags
- https://github.com/sphaerophoria/atom-rtags-plus
Note to those maintainers. If you need RTags to behave differently or add features to make these other integration’s easier (like produce output in other formats etc), just drop us a note.
Here are some videos demonstrating how to use RTags with Emacs though some of these may be outdated:
Set up symlinks and run the daemon