This function does exactly what ff-find-other-file does, and less. I did not know about ff-find-other-file when I wrote and posted this code. I wish I could delete this page, but PagePruning seems to say I'm stuck with it. Oh, well. This page can serve as a reminder to look *really* hard in emacs before you implement a new function. Odds are it's already there. -ScottDe
Ha! I wrote that a version of that function too. I didn't know about ff-find-other-file. BTW, my version of emacs (XEmacs 20.4) doesn't seem to have ff-find-other-file. Is it part of a particular package? -- JimWeirich
Don't worry about it, the same is true for just about any emacs feature. I once wrote a CORBA ORB in emacs lisp, and was shocked to find a few days later that there was already a (much) better one around. -- LukeGorrie
Here is some elisp to switch between twins [.h and .cpp files for the same class]. The entry point is "load-twin". It works if the files are stored in the same directory or if you have parallel "src" and "include" directories for your files.
I am not really a lisp person, hope this code isn't too ugly. If you try it and it doesn't work, let me know, I may have forgotten to include a helper function (I extracted this code from a couple of .el files I wrote, hopefully I got it all). You need to get the AnaphoricLispMacros before this code will work.
(defun my-file-exists-p (file-name)
(if (file-exists-p file-name) file-name nil))
(defun twin-file-name-helper (cur-file cur-ext twin-ext cur-dir twin-dir)
(if (string-match (concat ".*" cur-ext) cur-file)
(aif (my-file-exists-p
(my-replace-lisp-string cur-ext twin-ext
(my-replace-lisp-string cur-dir twin-dir
cur-file)))
it
(my-file-exists-p (my-replace-lisp-string
cur-ext
twin-ext cur-file)))))
(defun twin-file-name (cur-file)
(cond
((twin-file-name-helper cur-file "cpp$" "h" "/src/" "/include/"))
((twin-file-name-helper cur-file "inc$" "h" "/src/" "/include/"))
((twin-file-name-helper cur-file "h$" "cpp" "/include/" "/src/"))
((twin-file-name-helper cur-file "h$" "inc" "/include/" "/src/"))))
;; keep find-file-noselect from creating redundent buffers for same file
(setq find-file-existing-other-name t)
(defun load-twin ()
"Load the twin of the header or implementation file"
(interactive)
(let ((file-name (twin-file-name (buffer-file-name))))
(cond ((not file-name) (ding t))
((file-exists-p file-name)
(find-file file-name))
(t (ding t)))))
;; you also need the following helper functions
(defun my-lisp-substring (str from to)
(let ((last-char (1- (length str))))
(cond ((<= from last-char) (substring str from to))
(t nil))))
(defun my-replace-lisp-string (f-str r-str str)
(if (string-match f-str str)
(let ((first-part (my-lisp-substring str 0 (match-beginning 0)))
(last-part (my-lisp-substring str (match-end 0) nil)))
(concat first-part r-str last-part))
str))