project/include/some-controller/some-aspect/something.h
and project/src/some-controller/some-aspect/something.cpp
). Quickly switching between both saves on keystrokes and sanity, so I wrote this little chunk of elisp, bound to ctrl-alt-g
(for no particular reason other than the combination is easy to mash):
(defun djw-c-toggle-impl-header-view (create-if-nonexistent)
(interactive "P")
(let* ((mode (if (string-equal (file-name-extension (buffer-file-name))
"h")
:switch-to-implementation :switch-to-header))
(toggle-tags (list (cons "/Include/" "/Src/")
(cons "/include/" "/src/")))
(from-fn (if (eq mode :switch-to-implementation)
#'car #'cdr))
(to-fn (if (eq mode :switch-to-implementation)
#'cdr #'car))
(source-file-name (buffer-file-name))
(case-fold-search nil)) ;; I want case-sensitive matching throughout this block.
(dolist (pair toggle-tags)
(setf source-file-name (replace-regexp-in-string (funcall from-fn pair)
(funcall to-fn pair)
source-file-name)))
(setf source-file-name
(replace-regexp-in-string
(if (eq mode :switch-to-implementation)
"h\$" "cpp\$")
(if (eq mode :switch-to-implementation)
"cpp" "h")
source-file-name))
(message (format "Looking for %s" source-file-name))
(if (or (file-exists-p source-file-name)
create-if-nonexistent)
(find-file source-file-name)
(message (format "Can't find '%s'" source-file-name)))))
If the counterpart file is missing, it won't be created unless the function is invoked with a prefix argument (
C-u C-M-g
).There's probably some extension to CC mode or the like that already does something like this, but in the absence of reading the manual, this works well for me.
Thank you very much!
ReplyDeleteI looked for something packaged with emacs (24) that does what you provided, but I couldn't find anything (just ff-find-other-file, which needs explicit search directories to switch between header/implementation). I had to adapt your source a bit since I use hpp instead of h for my header files, but apart from that, it's working very well. :-)