Skip to content
 
 

Repository files navigation

#+OPTIONS: ^:nil
[[https://travis-ci.org/Andersbakken/rtags][https://travis-ci.org/Andersbakken/rtags.svg?branch=master]]
[[http://www.gnu.org/licenses/gpl-3.0.txt][https://img.shields.io/badge/license-GPL%203-brightgreen.svg]]
[[http://melpa.org/#/rtags][file:http://melpa.org/packages/rtags-badge.svg]]

* Introduction
RTags is a client/server application that indexes C/C++ code and keeps a
persistent file-based database of references, declarations, definitions,
symbolnames etc. There's also limited support for ObjC/ObjC++. It allows you
to find symbols by name (including nested class and namespace scope). Most
importantly we give you proper follow-symbol and find-references support. We
also have neat little things like rename-symbol, integration with clang's
"fixits" (http://clang.llvm.org/diagnostics.html). We also integrate with
flymake using clang's vastly superior errors and warnings. Since RTags
constantly will reindex "dirty" files you get live updates of compiler errors
and warnings. Since we already know how to compile your sources we have a way
to quickly bring up the preprocessed output of the current source file in a
buffer.

While existing taggers like gnu global, cscope, etags, ctags etc do a decent
job for C they often fall a little bit short for C++. With its incredible
lexical complexity, parsing C++ is an incredibly hard task and we make no
bones about the fact that the only reason we are able to improve on the
current tools is because of clang (http://clang.llvm.org/). RTags is named
RTags in recognition of Roberto Raggi on whose C++ parser we intended to base
this project but he assured us clang was the way to go. The name stuck though.

* TLDR Quickstart
Build RTags

#+BEGIN_SRC sh
git clone --recursive https://github.com/Andersbakken/rtags.git
cd rtags
cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=1 .
make
#+END_SRC

Start the RTags daemon (=rdm=)

#+BEGIN_SRC sh
./bin/rdm &
#+END_SRC

Index the RTags project, and wait until =rdm= is silent

#+BEGIN_SRC sh
./bin/rc -J .
#+END_SRC

Open source file in =emacs=

#+BEGIN_SRC sh
emacs +72:34 src/rdm.cpp
#+END_SRC

Load =rtags.el=

#+BEGIN_EXAMPLE
M-: (load-file "rtags.el") RET
#+END_EXAMPLE

Call =rtags-find-symbol-at-point=

#+BEGIN_EXAMPLE
M-x rtags-find-symbol-at-point RET
#+END_EXAMPLE

Your location is now on the definition of =Server::instance()=

* Installing RTags
** Prerequisites
There are a few prerequisites you need to have in order to build RTags

- =LLVM/Clang= >= 3.3

  On Linux you may be able to use your distribution package manager to install
  this. On OS X you can use homebrew or possibly other package managers,
  though see below for details if you plan to tag projects that use C++11
  features (such as RTags itself). Alternatively you can grab the sources from
  [[http://llvm.org/releases/download.html][llvm.org]] and build it yourself.

- =GCC/Clang= >= 4.7/3.2

  A modern compiler to build RTags. RTags makes extensive use of C++11
  features such as variadic templates and threading utility classes from the
  C++ standard library.

- =cmake= >= 2.8

  The meta-built system used by RTags.
-----
- =emacs= >= 24.3 is recommended

  RTags might very well work with much older =emacs= versions but the oldest
  version we have tested with is 23.4.1. There's no particular effort made to
  support older versions, but patches that make it work are welcome. Having
  said that, completion ([[https://github.com/auto-complete/auto-complete][ac]], [[https://github.com/company-mode/company-mode][company]]) as well as [[https://github.com/flycheck/flycheck][Flycheck]] integration only
  works, and has been tested with =emacs= >= 24.3.

  *NOTE:* Emacs is no real prerequisite. That implies you can compile RTags
  without =emacs= installed. This may be of interest to you, if you want use
  RTags as back-end for a different editor like vim, see section [[#support-for-other-editors][Support for
  other editors]]. You explicitly can tell =cmake= to ignore the elisp files by
  passing =-DRTAGS_NO_ELISP_FILES=1= to =cmake=.

*** Optional
- =pkg-config= and =bash-completion=

  RTags comes with bash completion support. If you want the bash completion
  files to be installed, you either have to make sure that =pkg-config= and
  =bash-completion= package is installed or you can manually force the
  installation by setting the variable =FORCE_BASH_COMPLETION_INSTALLATION=
  to =TRUE= or =ON=.

  The default installation path is
  =CMAKE_INSTALL_PREFIX/share/bash-completion/completions=. You can adjust the
  path with the =cmake= variable =BASH_COMPLETION_COMPLATIONSDIR=
  variable. However, if the bash completions files are not installed in the
  default completion path, i.e. =/usr/share/bash-completion/completions= on
  GNU/Linux, you have to make sure the RTags bash completion file gets
  sourced to get completion support.

- =lua= version >= 5.3

  TODO(Andersbakken): Add some notes why we optionally require Lua, whats the
  purpose of it.

  If your system does not provide a suitable version you can download Lua from
  [[https://www.lua.org/download.html][here]]. We recommend downloading the pre-built binaries. If you have compiled
  Lua from scratch (the build will only create an archive =liblua.a= and no
  shared library) or you have installed the headers/library to a non standard
  place you need to tell =cmake= where the headers/library is located.

  E.g.
  #+BEGIN_SRC sh
  cmake -DLUA_INCLUDE_DIR=/opt/lua/include -DLUA_LIBRARY=/opt/lua/lib/liblua.a
  # or liblua53.so or liblua53.a if you have downloaded, e.g. lua-5.3.2 binaries
  cmake -DLUA_INCLUDE_DIR=/opt/lua/include -DLUA_LIBRARY=/opt/lua/lib/liblua53.so
  #+END_SRC

- =ZLIB=

- =OpenSSL=

** C++11 on OS X

If you plan to tag projects using C++11 features on OS X then you'll
need a libclang linked with LLVM's [[http://libcxx.llvm.org/][libc++]].
For LLVM 3.6 the following works:

#+BEGIN_SRC sh
brew install llvm --with-libcxx --with-clang --without-assertions --with-rtti
#+END_SRC

or you can install clang and llvm from mac ports

#+BEGIN_SRC sh
sudo port install clang-3.5
#+END_SRC

** Building RTags
- Get the code

  To build RTags, you need to checkout RTags and the repository's sub-modules,
  this can be done in one step. After that, you need to run =cmake=, =make= and
  =make install=, in that order.

  #+BEGIN_SRC sh
  git clone --recursive https://github.com/Andersbakken/rtags.git
  #+END_SRC

  You can also download the sources from here:

  http://andersbakken.github.io/rtags-releases/rtags.tar.bz2

  or

  http://andersbakken.github.io/rtags-releases/rtags.tar.gz

- Building RTags

  We recommend building in a separate directory to keep the build files separate
  from the source, but you can run =cmake= in the source tree if you prefer.

  #+BEGIN_SRC sh
  cd rtags
  mkdir build
  cd build
  cmake ..
  make
  make install
  #+END_SRC

  *TIP:* You can run =ccmake= (CMake with an ncurses UI) instead of =cmake= to
  interactively configure the RTags build.

* Finding clang
** Use Your System's version
Unless you define RTAGS_BUILD_CLANG in cmake (or configure), the build system will try to
locate the required llvm/clang libraries and options automatically from what is
installed on your system.

RTags needs three pieces of information about =libclang=. All of these can be
provided to =cmake= by way of an environment variable or a =cmake= variable. If
not provided we will try to find =llvm-config= and interrogate it for the
information. You can tell RTags which =llvm-config= to use like this:

#+BEGIN_SRC sh
LIBCLANG_LLVM_CONFIG_EXECUTABLE=/path/to/llvm-config cmake .
#+END_SRC

or

#+BEGIN_SRC sh
cmake -DLIBCLANG_LLVM_CONFIG_EXECUTABLE=/path/to/llvm-config .
#+END_SRC

If you don't, we will look for variations of the =llvm-config= executable name
in your =$PATH=. If llvm is installed at a different place, you could set the
cmake variable =CMAKE_PREFIX_PATH= to the install prefix path of llvm.

The three things we need are:

1. =LIBCLANG_CXXFLAGS=

   Usually something like this:

   #+BEGIN_SRC sh
   $ llvm-config --cxxflags
   # Max OS X
   -I/usr/local/Cellar/llvm36/3.6.0/lib/llvm-3.6/include  -DNDEBUG -D_GNU_SOURCE -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -O3  -std=c++11 -fvisibility-inlines-hidden -fno-exceptions -fno-common -Woverloaded-virtual -Wcast-qual
   # Fedora 23 64 bit
   -I/usr/include -DNDEBUG -D_GNU_SOURCE -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -O3  -std=c++11 -fvisibility-inlines-hidden -fno-exceptions -fno-common -Woverloaded-virtual -Wcast-qual
   #+END_SRC

2. =LIBCLANG_LIBDIR=

   Usually something like this:

   #+BEGIN_SRC sh
   $ llvm-config --libdir
   # Mac OS X
   /usr/local/Cellar/llvm36/3.6.0/lib/llvm-3.6/lib
   # Fedora 23 64 bit
   /usr/lib64/llvm
   #+END_SRC

   We need this to locate clang's system headers, and we will assume that they
   are located in: =${LIBCLANG_LIBDIR}/clang/CLANG_VERSION_STRING/include
   (/usr/local/Cellar/llvm36/3.6.0/lib/llvm-3.6/lib/clang/3.6.0/include)=. There
   should be headers like stdarg.h and limits.h in this directory.

3. =LIBCLANG_LIBRARIES=

   Usually something like this:

   #+BEGIN_EXAMPLE
   # Mac OS X
   /usr/local/Cellar/llvm36/3.6.0/lib/llvm-3.6/lib/libclang.so
   # Fedora 23 64 bit
   /usr/lib64/llvm/libclang.so
   #+END_EXAMPLE

   Unless otherwise specified, we will try to find the clang library using
   =cmake='s =find_library= feature and/or assuming that they there will be a
   libclang.(so|dylib) in =${LIBCLANG_LIBDIR}=

Like with =LIBCLANG_LLVM_CONFIG_EXECUTABLE= these variables can be overwritten
as a =cmake= variable =(cmake -DLIBCLANG_LIBDIR =...)= or an environment variable
=(LIBCLANG_LIBDIR =... cmake)=

** Let the Build System Download and Compile LLVM/Clang
By default, cmake searches for a system libclang. If you want it to
download and build the required llvm/clang libraries, either call
cmake with -DRTAGS_BUILD_CLANG=1 or configure with --build-clang

Note that if you use ninja to build RTags you might run into the
following error:

#+BEGIN_SRC sh
ninja: error: '/usr/local/rtags-llvmclang/lib/libclang.dylib', needed by 'bin/rdm', missing and no known rule to make it
#+END_SRC

In that case you need to do this:

#+BEGIN_SRC sh
ninja llvmclang && ninja && ninja install
#+END_SRC

RTags uses C++11 features, and requires a relatively new compiler. GCC
version >= 4.8 or clang >= 3.2 should work.

* Setup

=rdm= runs in the background and monitors all your indexed files for changes,
and reindexes 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 like this:

#+BEGIN_SRC sh
rc -c gcc -I... -fsomeflag -c foobar.c
rc -J /path/to/a/directory/containing/compile_commands.json
#+END_SRC sh

You can generate a compile_commands.json with various different tools, one
might fit better than the other, depending on your project build system.

- [[https://ninja-build.org/manual.html][ninja]]

  #+begin_src sh
  ninja -t compdb cxx cc > compile_commands.json
  rc -J
  #+end_src

  With =ninja= it's also possible to pipe the commands directly to =rc=.

  #+BEGIN_SRC sh
  ninja -t commands | rc -c -
  # Parse commands for a specific target only
  ninja -t commands rdm | rc -c -
  #+END_SRC

- =cmake=

  =cmake= can generate a compile_commands.json file as well.

  #+BEGIN_SRC sh
  cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=1 .
  rc -J
  #+END_SRC

- [[https://github.com/rizsotto/Bear][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 invoking
  =bear=.

  #+BEGIN_SRC sh
  make clean
  bear make
  rc -J
  # Parse commands for a specific target only
  make clean
  bear make rdm
  rc -J
  #+END_SRC

- =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.

  #+BEGIN_SRC sh
  make clean
  make -nk | rc -c -
  #+END_SRC

  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:

  #+BEGIN_SRC sh
  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++
#+END_SRC

  E.g.

  #+BEGIN_EXAMPLE
  $ 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'
  #+END_EXAMPLE

  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:

#+BEGIN_SRC sh
rc -w foobar
#+END_SRC

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 =~/.rtags= but can be overridden by
passing =--data-dir /other/dir= to =rdm= or putting something like this in
your ~/.rdmrc:

#+BEGIN_EXAMPLE
$ cat ~/.rdmrc
--data-dir=/other/dir
#+END_EXAMPLE

** Integration with =launchd= /(Mac OS X)/

On Mac OS X, you can set =rdm= can be run on demand, on your behalf, by
=launchd=, and have it exit cleanly after a period of inactivity. This isn't
quite plug-and-play, but should be worth the small amount of effort.

1. Create a file, e.g., in emacs, with the following contents:

   #+BEGIN_SRC xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
  <dict>
    <key>Label</key>
    <string>com.andersbakken.rtags.agent</string>
    <key>ProgramArguments</key>
    <array>
      <string>sh</string>
      <string>-c</string>
      <string>$RDM -v --launchd --inactivity-timeout 300 --log-file ~/Library/Logs/rtags.launchd.log</string>
    </array>
    <key>Sockets</key>
    <dict>
      <key>Listener</key>
      <dict>
    <key>SockPathName</key>
    <string>$HOME/.rdm</string>
      </dict>
    </dict>
  </dict>
</plist>
   #+END_SRC

2. Replace =$HOME= with the absolute path to your home folder. Replace
   =$RDM= with the path to your copy of =rdm=, and add any command line
   parameters you might usually use.

   (The =SockPathName= entry relates to the name of the domain socket that
   =rdm= uses. The settings above are for the default value; if your command
   line options direct it to use some other name, please modify it to
   suit. Unfortunately =launchd='s configuration files are a bit naff, so
   you'll have to repeat yourself.)

3. Save the result as
   =~/Library/LaunchAgents/com.andersbakken.rtags.agent.plist=.

4. Run the following command from the terminal:

   : launchctl load ~/Library/LaunchAgents/com.andersbakken.rtags.agent.plist

   (This will happen automatically next time you log back in.)

5. Try using RTags, and you should find =rdm= will spring into life!

*** Notes

- =rdm= will automatically quit after 5 minutes of inactivity (this is
  what the =--inactivity-timeout 300= command line option is for), so
  it won't stick around hogging memory. But =launchd= will still be
  watching its socket for activity, and will relaunch it if necessary.

- You can watch =launchd='s logging by tailing
  =~/Library/Logs/rtags.launchd.log=.

** Integration with =systemd= /(GNU Linux)/

On GNU/Linux distributions based on the =systemd= service manager, =rdm= can
also be socket acivated.

 1. Add the following to =~/.config/systemd/user/rdm.socket=

   #+BEGIN_EXAMPLE
   [Unit]
   Description=RTags daemon socket

   [Socket]
   ListenStream=%h/.rdm

   [Install]
   WantedBy=multi-user.target
   #+END_EXAMPLE

 2. Add the following to =~/.config/systemd/user/rdm.service=

   #+BEGIN_EXAMPLE
   [Unit]
   Description=RTags daemon

   Requires=rdm.socket

   [Service]
   Type=simple
   ExecStart=$RDM -v --inactivity-timeout 300
   #+END_EXAMPLE

 3. Replace =$RDM= with the path to your copy of =rdm=, and add any command
    line parameters you might usually use.

    You have to use absolute paths here. =%h= is expanded to your home
    directory.  Environment variables are not expanded inside strings.

 4. Run the following command from the terminal:

    #+BEGIN_SRC sh
    systemctl --user enable rdm.socket
    systemctl --user start rdm.socket
    #+END_SRC

    =Systemd= will create the =rdm= socket automatically.
* Usage

Now that your files are indexed you can start using RTags. Normally you
would do this from your editor but the way to extract this information from
=rdm= is to use the command line tool =rc=.

E.g.

#+BEGIN_EXAMPLE
$ rdm &
$ ninja -t commands | rc -c
$ rc --follow-location Job.cpp:20:10
/home/abakken/dev/rtags/src/Job.h:10:18      List<RegExp> *mPathFiltersRegExp;
#+END_EXAMPLE

A location has the format of file:line:column.

For Emacs we maintain a set of elisp bindings that allows you to control RTags
from your editor. There are projects that provide integration for other
editors out there.

Vim: https://github.com/lyuts/vim-rtags and https://github.com/shaneharper/vim-rtags

Sublime Text: https://github.com/rampage644/sublime-rtags

Atom: https://github.com/artagnon/atomic-rtags and https://github.com/rajendrant/atom-rtags

=rc= has a vast number of commands and options and we intend to write a man
page at some point. Most users will have limited interest in ever calling them
manually and would rather just use the interactive elisp functions.

* Elisp
** Functions

#+BEGIN_SRC emacs-lisp
(rtags-start-process-unless-running)
#+END_SRC

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.

#+BEGIN_SRC emacs-lisp
(add-hook 'c-mode-common-hook 'rtags-start-process-unless-running)
(add-hook 'c++-mode-common-hook 'rtags-start-process-unless-running)
#+END_SRC

#+begin_src emacs-lisp
(rtags-restart-process)
#+end_src

Restart the =rdm= process.

#+BEGIN_SRC emacs-lisp
(rtags-find-symbol-at-point)
#+END_SRC

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=

#+BEGIN_SRC emacs-lisp
(rtags-find-references-at-point)
#+END_SRC

Find all references to symbol under cursor. If symbol is itself a reference it
will find all references to the referenced symbol

#+BEGIN_SRC emacs-lisp
(rtags-find-symbol)
#+END_SRC

Prompt for name of symbol to go to. Imagine the following code:

#+BEGIN_SRC C++

namespace N
{
class C
{
public:
    int func(int);
};
};

using namespace N;
int C::func(int val)
{
    return val * 2;
}
#+END_SRC
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

#+BEGIN_SRC emacs-lisp
(rtags-find-references)
#+END_SRC

Prompt for name of symbol to find references to. Same as above but find
references to symbol rather than declarations and definitions.

#+BEGIN_SRC emacs-lisp
(rtags-diagnostics)
#+END_SRC

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

#+BEGIN_SRC emacs-lisp
(rtags-enable-standard-keybindings)
#+END_SRC
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:

#+BEGIN_SRC emacs-lisp
(rtags-enable-standard-keybindings c-mode-base-map "\C-xr")
#+END_SRC

#+BEGIN_SRC emacs-lisp
(rtags-find-file)
#+END_SRC

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.

#+BEGIN_SRC emacs-lisp
(rtags-find-virtuals-at-point)
#+END_SRC
For virtual functions, show the various reimplementations of the function at
point

#+BEGIN_SRC emacs-lisp
(rtags-fixit)
#+END_SRC
Apply clang's automatic fixits in current file. If you pass a prefix arg use
ediff to apply it. See (http://clang.llvm.org/diagnostics.html) for more info.

#+BEGIN_SRC emacs-lisp
(rtags-imenu)
#+END_SRC
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.

#+BEGIN_SRC emacs-lisp
(rtags-location-stack-back)
(rtags-location-stack-forward)
#+END_SRC

Whenever RTags jumps somewhere it pushes a location onto its stack. Jump back
and forward in this stack

#+BEGIN_SRC emacs-lisp
(rtags-next-match)
(rtags-previous-match)
#+END_SRC

For functions that return more than one match, jump to the next/previous one.

#+BEGIN_SRC emacs-lisp
(rtags-preprocess-file)
#+END_SRC

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.

#+BEGIN_SRC emacs-lisp
(rtags-print-symbol-info)
#+END_SRC

Print some info about symbol under cursor

#+BEGIN_SRC emacs-lisp
(rtags-symbol-type)
#+END_SRC

Print the type of the symbol under cursor.

#+BEGIN_SRC emacs-lisp
(rtags-print-dependencies)
#+END_SRC

Open a buffer showing files that depend on current file/files that current
file depends on.

#+BEGIN_SRC emacs-lisp
(rtags-print-enum-value-at-point)
#+END_SRC

Print integral value of enum value at point

#+BEGIN_SRC emacs-lisp
(rtags-quit-rdm)
#+END_SRC

Shut down =rdm=

#+BEGIN_SRC emacs-lisp
(rtags-rename-symbol)
#+END_SRC

Rename symbol under cursor. Make sure all files are saved and fully indexed
before using.

#+BEGIN_SRC emacs-lisp
(rtags-reparse-file)
#+END_SRC

Explicitly trigger a reparse of current file. Mostly for debugging. Unless we
have bugs it should not be necessary.

#+BEGIN_SRC emacs-lisp
(rtags-show-rtags-buffer)
#+END_SRC

Switch to =*RTags*= buffer. This is the buffer where a number of functions
display their alternatives when they have more than one match.

#+BEGIN_SRC emacs-lisp
(rtags-include-file)
#+END_SRC

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.

#+BEGIN_SRC emacs-lisp
(rtags-get-include-file-for-symbol)
#+END_SRC

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.

** Variables

#+BEGIN_SRC emacs-lisp
rtags-path
#+END_SRC

Path to =rc/rdm= if they're not in =$PATH=.

#+BEGIN_SRC emacs-lisp
rtags-jump-to-first-match
#+END_SRC

Similar to =compilation-auto-jump-to-first-error=. Whether to jump to the
first match automatically when there's more than one.

#+BEGIN_SRC emacs-lisp
rtags-find-file-case-insensitive
#+END_SRC

Whether to match files case-insensitively

#+BEGIN_SRC emacs-lisp
rtags-find-file-prefer-exact-match
#+END_SRC

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.

** Fall back to other taggers
You can do something like the following to fall back to e.g. gtags
if RTags doesn't have a certain project indexed:

#+BEGIN_SRC emacs-lisp
(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))

#+END_SRC

* Code Completion in Emacs:
To enable code completion in Emacs with company mode do the following:

- Enable rtags-diagnostics. The easiest way is to:

#+BEGIN_SRC emacs-lisp
(setq rtags-autostart-diagnostics t)
#+END_SRC

but you can also explicitly start it with

#+BEGIN_EXAMPLE
M-x rtags-diagnostics <RET>
#+END_EXAMPLE

- Enable completions in RTags:

#+BEGIN_SRC emacs-lisp
(setq rtags-completions-enabled t)
#+END_SRC

- Enable company-mode

#+BEGIN_SRC emacs-lisp
(require 'company)
(global-company-mode)
#+END_SRC

- Add company-rtags to company-backends:

#+BEGIN_SRC emacs-lisp
(push 'company-rtags company-backends)
#+END_SRC

This minimal init.el configuration should be enough to get completion to work.

#+BEGIN_SRC emacs-lisp
(require 'package)
(package-initialize)
(require 'rtags)
(require 'company)

(setq rtags-autostart-diagnostics t)
(rtags-diagnostics)
(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))
#+END_SRC

To enable completion in Emacs with auto-complete-mode do the following:
...TODO...
* RTags Flycheck integration
To turn on RTags Flycheck support you need to load the =flycheck-rtags=
package.

#+BEGIN_SRC emacs-lisp
(require 'flycheck-rtags)
#+END_SRC

** Optional
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=.

#+BEGIN_SRC emacs-lisp
(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))
;; c-mode-common-hook is also called by c++-mode
(add-hook 'c-mode-common-hook #'my-flycheck-rtags-setup)
#+END_SRC

* Videos
Here are some videos demonstrating how to use RTags with Emacs though some of
these may be outdated:

[[http://www.youtube.com/watch?v=Z4g05SjkQzM&list=PLAL6K6Ycnt4IwjIjWcYV9bFgcTG_4T1Y_&index=10][Set up RTags]]

[[http://www.youtube.com/watch?v=J2B-z0LBL_s&list=PLAL6K6Ycnt4IwjIjWcYV9bFgcTG_4T1Y_&index=6][Set up symlinks and run the daemon]]

[[http://www.youtube.com/watch?v=bD6Rlycn1RU&list=PLAL6K6Ycnt4IwjIjWcYV9bFgcTG_4T1Y_&index=5][Project setup using make]]

[[http://www.youtube.com/watch?v=Zivoc5DH_II&list=PLAL6K6Ycnt4IwjIjWcYV9bFgcTG_4T1Y_&index=9][Project setup using ninja]]

[[http://www.youtube.com/watch?v=IfenCEuOqOs&list=PLAL6K6Ycnt4IwjIjWcYV9bFgcTG_4T1Y_&index=2][Navigation/references]]

[[http://www.youtube.com/watch?v=wVoaE3Pj4oU&list=PLAL6K6Ycnt4IwjIjWcYV9bFgcTG_4T1Y_&index=1][Fixits]]

[[http://www.youtube.com/watch?v=mnQPz5J7gN0&list=PLAL6K6Ycnt4IwjIjWcYV9bFgcTG_4T1Y_&index=3]["IMenu" / virtuals / filenames]]

[[http://www.youtube.com/watch?v=p6JHriYmVuY&list=PLAL6K6Ycnt4IwjIjWcYV9bFgcTG_4T1Y_&index=4][Rename symbol]]

[[http://www.youtube.com/watch?v=9CsoJTs58q8&list=PLAL6K6Ycnt4IwjIjWcYV9bFgcTG_4T1Y_&index=8][Enums and cursor info]]

* Debugging RTags
If you find that =rp= is crashing (leading to output like this: "job crashed
191 9698036154370 0x331e7e30"). You should be able to do the following:

#+BEGIN_SRC sh
rdm --suspend-rp-on-crash
#+END_SRC

When =rp= crashes the =rp= process will stay alive, enabling you to debug it
with something like this:

#+BEGIN_SRC sh
gdb -p `pidof rp`
#+END_SRC

* Support for other editors
There are several other projects integrating RTags with other editors.

Sublime Text:
https://github.com/rampage644/sublime-rtags

Vim:
https://github.com/lyuts/vim-rtags
https://github.com/shaneharper/vim-rtags
https://github.com/mattn/vim-rtags

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.

* Disclaimer
RTags is still under development and is not the most stable piece of software
you'll ever find. We're constantly working to improve on it.

About

A c/c++ client/server indexer for c/c++/objc[++] with integration for Emacs based on clang.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages