Skip to content

Navigating Project Files

Alastair Rankine edited this page Mar 13, 2014 · 4 revisions

Obviously for large projects it is necessary to quickly and easily navigate to another file within a project. I have several methods available to do this.

Firstly, the standard Emacs find-file commands work perfectly well, but I find that the ido mode is a most valuable addition.

Header/Source switching

ff-get-other-file is a standard Emacs command but by default it is not bound to any key. The idea is that it can switch from a header file to its corresponding source file by using some customizable rules to locate the “other” file. This is very valuable, as switching from header to source is a very common thing to do in C++. Hence I have this command bound to @<kbd>M-o@</kbd>, which is easy to type.

;; set up our own c++ extension mappings for ff-other-file support
(defvar my-cpp-other-file-alist
  '(("\\.cpp\\'" (".hpp" ".ipp"))
    ("\\.ipp\\'" (".hpp" ".cpp"))
    ("\\.hpp\\'" (".ipp" ".cpp"))
    ("\\.cxx\\'" (".hxx" ".ixx"))
    ("\\.ixx\\'" (".cxx" ".hxx"))
    ("\\.hxx\\'" (".ixx" ".cxx"))
    ("\\.c\\'" (".h"))
    ("\\.h\\'" (".c"))
    ))

(setq-default ff-other-file-alist 'my-cpp-other-file-alist)

(defun my-c-initialization-hook ()
  ;; ...

  (define-key c-mode-base-map [(meta o)] 'ff-get-other-file)

  ;; ...
)
(add-hook 'c-initialization-hook 'my-c-initialization-hook)

In general my projects tend to have source files and corresponding header files located in the same directory, hence the ff-other-file-alist configuration is fairly simple, and consists of associating file extensions. Should more complicated associations be needed, per-project configuration can be set up using a .dir-locals.el file. To date I haven’t needed this.

Opening Project Source Files

find-file-in-project is a library which allows selection of files within the current project that conform to a pre-determined pattern. I have this set up to look for common C++ file extensions only. This works well for smaller projects but is less useful for larger ones. I have it configured as follows:

;; Add our file extensions to enable project searching using find-file-in-project
(require 'find-file-in-project)
(setq ffip-patterns (append '("*.cpp" "*.hpp" "*.cxx" "*.hxx") ffip-patterns))

(global-set-key (kbd "C-x f") 'find-file-in-project)

Navigating #include Declarations

Also convenient for navigation is the semantic-decoration-include-visit function. When the cursor is placed on an #include declaration, I can hit @<kbd>C-c =@</kbd>, and the corresponding include file will be opened. This is generally correctly parsed from the include file path for the project, as read from the compilation database.

(defun my-cedet-c-hook ()
  (local-set-key [(control c) (=)] 'semantic-decoration-include-visit)

  ;; ..
  )
(add-hook 'c-mode-common-hook 'my-cedet-c-hook)