Warning, /sdk/kde-dev-scripts/kde-emacs/sourcepair.el is written in an unsupported language. File is not indexed.
0001 ;; sourcepair.el --- Load the corresponding C/C++ header or source file for the current buffer. 0002 ;; 0003 ;; Copyright (C) 2007 Mohamed Hendawi 0004 ;; 0005 ;; Emacs Lisp Archive Entry 0006 ;; Filename: sourcepair.el 0007 ;; Version: 1.01 0008 ;; Keywords: c languages oop 0009 ;; Author: Mohamed Hendawi <moedev *AT* hendawi *DOT* com> 0010 ;; Description: Load the corresponding C/C++ header or source file for the current buffer. 0011 ;; URL: http://www.hendawi.com/emacs/sourcepair.el 0012 ;; Compatibility: Emacs20, Emacs21 0013 ;; 0014 ;; $Id: sourcepair.el,v 1.15 2007/10/22 11:41:24 moe Exp $ 0015 ;; 0016 ;; This program is free software; you can redistribute it and/or 0017 ;; modify it under the terms of the GNU General Public License as 0018 ;; published by the Free Software Foundation; either version 2 of 0019 ;; the License, or (at your option) any later version. 0020 ;; 0021 ;; This program is distributed in the hope that it will be useful, 0022 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of 0023 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 0024 ;; GNU General Public License for more details. 0025 ;; 0026 ;; You should have received a copy of the GNU General Public 0027 ;; License along with this program; if not, write to the Free 0028 ;; Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 0029 ;; MA 02110-1301 USA 0030 ;; 0031 ;; This code is inspired by a similar function written by Abiyu Diro. 0032 ;; Thanks to Jesper Pedersen for idea and initial implementation of 0033 ;; support for private header files. 0034 ;; 0035 ;;; Commentary: 0036 ;; 0037 ;; This Emacs lisp file provides the function "sourcepair-load" which will load 0038 ;; the corresponding header or source file for the current buffer. For example, 0039 ;; if you are looking at the file FooParser.cpp and enter M-x sourcepair-load 0040 ;; (or whatever keybinding you've set), the file FooParser.h will be loaded. 0041 ;; It also works the other way as well. To use it put this file somewhere 0042 ;; in your lisp library path and then add something like this to your .emacs 0043 ;; file: 0044 ;; 0045 ;; (load-file "sourcepair.el") 0046 ;; 0047 ;; KEYBINDINGS: 0048 ;; 0049 ;; You should set a keybinding to use this function easily. For example, I add 0050 ;; the following to my .emacs file: 0051 ;; 0052 ;; (define-key global-map "\C-xz" 'sourcepair-load) 0053 ;; 0054 ;; 0055 ;; GLOBAL VARIABLES: 0056 ;; 0057 ;; There are six global variables that can be used to adjust how the function 0058 ;; works: 0059 ;; 0060 ;; sourcepair-source-extensions : 0061 ;; 0062 ;; A list containing the recognized extensions for source files. By default 0063 ;; this is set to ( ".cpp" ".cxx" ".cc" ".c" ). For example: with the default 0064 ;; setting if you are looking at "foo.h", the function will look for 0065 ;; "foo.cpp", "foo.cxx", "foo.cc" or "foo.c" in that order in the 0066 ;; directories specified by sourcepair-source-path. 0067 ;; 0068 ;; sourcepair-header-extensions : 0069 ;; 0070 ;; A list containing the recognized extensions for header files. By default 0071 ;; this is set to ( ".h" ".hpp" ".hh" ). For example: with the default 0072 ;; setting if you are looking at "foo.cpp", the function will look for 0073 ;; "foo.h", "foo.hpp" or "foo.hh" in that order in the directories specified 0074 ;; by sourcepair-header-path. 0075 ;; 0076 ;; sourcepair-source-path : 0077 ;; 0078 ;; A list containing the path's to search for source files. By default this 0079 ;; is set to ( "." ) which means source files will only be searched for in 0080 ;; the current directory. Paths that end in "/*" will be searched 0081 ;; recursively. For example, if you specified sourcepair-source-path as 0082 ;; ( "." "../*" ) the function will look for source files first in the 0083 ;; current directory, and then in the parent directory, and then in any 0084 ;; subdirectories of the parent directory. 0085 ;; 0086 ;; sourcepair-header-path : 0087 ;; 0088 ;; Similar to sourcepair-source-path except for header files. 0089 ;; 0090 ;; sourcepair-recurse-ignore : 0091 ;; 0092 ;; A list containing directories to ignore when recursively searching 0093 ;; subdirectories for header or source files. By default this is set 0094 ;; to ( "CVS" ) 0095 ;; 0096 ;; sourcepair-private-header-suffixes : 0097 ;; 0098 ;; A list containing suffixes that will be ignored when searching 0099 ;; for the corresponding source file for a given header file. This 0100 ;; allows supporting "private header files". For example, Foo.cpp 0101 ;; has a public interface in "Foo.h" and a private interface in 0102 ;; "Foo_p.h". By default this is set to ( "_p" "_impl" ). 0103 ;; 0104 ;; For example, in my .emacs file I have the following: 0105 ;; 0106 ;; (setq sourcepair-source-path '( "." "../*" )) 0107 ;; (setq sourcepair-header-path '( "." "include" "../include" "../*")) 0108 ;; (setq sourcepair-recurse-ignore '( "CVS" "Obj" "Debug" "Release" )) 0109 0110 ;;; Code: 0111 0112 (defcustom sourcepair-source-extensions '( ".cpp" ".CPP" ".Cpp" ".cxx" ".CXX" ".cc" ".CC" ".c" ".C" ".c++" ".C++") 0113 "*List of recognized extensions for source files. 0114 0115 This variable is used by `sourcepair-load'. The value should be a list 0116 containing the recognized extensions for source files. For example: if the 0117 value is ( \".cpp\" \".cxx\" \".cc\" \".C\" \".c\" ), and you are looking at 0118 \"foo.h\", `sourcepair-load' will look for \"foo.cpp\", \"foo.cxx\", 0119 \"foo.cc\" or \"foo.c\" in that order in the directories specified by 0120 `sourcepair-source-path'." 0121 :type '(repeat string) 0122 :group 'sourcepair) 0123 0124 (defcustom sourcepair-header-extensions '( ".h" ".H" ".hpp" ".HPP" ".Hpp" ".hh" ".HH" ".hxx" ".HXX") 0125 "*List of recognized extensions for header files. 0126 0127 This variable is used by `sourcepair-load'. The value should be a list 0128 containing the recognized extensions for header files. For example: if the 0129 value is (\".h\" \".hpp\" \".hh\" ), and you are looking at \"foo.cpp\", 0130 `sourcepair-load' will look for \"foo.h\", \"foo.hpp\" or \"foo.hh\" in that 0131 order in the directories specified by `sourcepair-header-path'." 0132 :type '(repeat string) 0133 :group 'sourcepair) 0134 0135 (defcustom sourcepair-private-header-suffixes '( "_p" "_impl" ) 0136 "*List of recognized suffixes for 'private' header files. 0137 0138 This variable is used by `sourcepair-load' to help support 'private header 0139 files'. The value should be a list containing recognized suffixes that will 0140 be ignored when searching for the corresponding source file for a given 0141 header file. For example, Foo.cpp is an implementation of what is in 0142 Foo_p.h. If you set this variable to include (\"_p\") and you are looking 0143 at \"Foo_p.h\" or \"Foo.h\", `sourcepair-load' will load the file \"Foo.cpp\". 0144 0145 " 0146 :type '(repeat-string) 0147 :group 'sourcepair) 0148 0149 (defcustom sourcepair-source-path '( "." ) 0150 "*List of directories to search for corresponding source file. 0151 0152 This variable is used by `sourcepair-load'. The value should be a list 0153 containing the directories to search for source files. By default this is set 0154 to ( \".\" ) which means source files will only be searched for in the current 0155 directory. Paths that end in \"/*\" will be searched recursively. For 0156 example, if you specified `sourcepair-source-path' as ( \".\" \"../*\" ) 0157 `sourcepair-load' will look for source files first in the current directory, 0158 and then in the parent directory, and then in any subdirectories of the parent 0159 directory." 0160 :type '(repeat string) 0161 :group 'sourcepair) 0162 0163 (defcustom sourcepair-header-path '( "." ) 0164 "*List of directories to search for corresponding header file. 0165 0166 This is similar to `sourcepair-source-path' except for header files. See the 0167 documentation for `sourcepair-source-path' for more info." 0168 :type '(repeat string) 0169 :group 'sourcepair) 0170 0171 (defcustom sourcepair-recurse-ignore '( "CVS" ) 0172 "*List of directories to ignore when recursively searching subdirectories. 0173 0174 This variable is used by `sourcepair-load'. The value should be a list 0175 containing the names of directories to ignore when `sourcepair-load' is 0176 recursively searching subdirectories for header or source files. By default 0177 this is set to ( \"CVS\" )" 0178 :type '(repeat string) 0179 :group 'sourcepair) 0180 0181 (defun sourcepair-header-file-p (filename) 0182 "Return t if argument is a C/C++ header file, nil otherwise 0183 0184 This function returns t if the filename specified is a C/C++ header 0185 file, or nil otherwise. Header files are identified by extension via 0186 the variable `sourcepair-header-extensions'." 0187 0188 (let* ((extension (concat (member ?. (append filename nil)))) 0189 (basename (substring filename 0 (- 0 (length extension))))) 0190 (if (member extension sourcepair-header-extensions) 0191 t 0192 nil))) 0193 0194 0195 (defun sourcepair-source-file-p (filename) 0196 "Return t if argument is a C/C++ source file, nil otherwise 0197 0198 This function returns t if the filename specified is a C/C++ source file, 0199 or nil otherwise. Source files are identified by extension via the 0200 variable `sourcepair-source-extensions'." 0201 0202 (let* ((extension (concat (member ?. (append filename nil)))) 0203 (basename (substring filename 0 (- 0 (length extension))))) 0204 (if (member extension sourcepair-source-extensions) 0205 t 0206 nil))) 0207 0208 0209 (defun sourcepair-remove-private-suffixes (basename) 0210 (car (delete 'nil (append (mapcar '(lambda (suffix) 0211 (if (string= (substring basename (- (length basename) (length suffix))) suffix) 0212 (substring basename 0 (- (length basename) (length suffix))))) 0213 sourcepair-private-header-suffixes) 0214 (list basename))))) 0215 0216 (defun sourcepair-analyze-filename (filename) 0217 (let* ((extension (concat (member ?. (append filename nil)))) 0218 (basename (substring filename 0 (- 0 (length extension))))) 0219 0220 (if (member extension sourcepair-header-extensions) 0221 (progn (setq basename (sourcepair-remove-private-suffixes basename)) 0222 (cons sourcepair-source-path (mapcar '(lambda (arg) (concat basename arg)) sourcepair-source-extensions))) 0223 (if (member extension sourcepair-source-extensions) 0224 (cons sourcepair-header-path 0225 (apply 'append 0226 (mapcar '(lambda (suffix) (mapcar '(lambda (ext) (concat basename suffix ext)) sourcepair-header-extensions)) 0227 (append '("") sourcepair-private-header-suffixes)))))))) 0228 0229 (defun sourcepair-find-one-of (path choices recurse) 0230 (catch 'matching-filename 0231 (if (file-directory-p path) 0232 (let ((possible-filenames choices) 0233 (matching-filename nil) 0234 (files-in-directory nil)) 0235 0236 ;; Check if there's a match in this directory 0237 (while possible-filenames 0238 (let ((possible-filename (expand-file-name (car possible-filenames) path))) 0239 (if (file-exists-p possible-filename) 0240 (throw 'matching-filename possible-filename) 0241 (setq possible-filenames (cdr possible-filenames))))) 0242 0243 ;; Recursively search subdirectories 0244 (if (not (eq recurse nil)) 0245 (progn 0246 (setq files-in-directory (directory-files path nil "^[^\\.]")) 0247 (while files-in-directory 0248 (let ((possible-subdir (car files-in-directory))) 0249 (if (not (member possible-subdir sourcepair-recurse-ignore)) 0250 (progn 0251 (setq possible-subdir (expand-file-name possible-subdir path)) 0252 (if (file-directory-p possible-subdir) 0253 (progn 0254 (message "Checking %s" possible-subdir) 0255 (setq matching-filename 0256 (sourcepair-find-one-of possible-subdir choices t)) 0257 (if (not (eq matching-filename nil)) 0258 (throw 'matching-filename matching-filename)))))) 0259 (setq files-in-directory (cdr files-in-directory)))))))) 0260 ;; Return nil if nothing found 0261 nil)) 0262 0263 (defun sourcepair-matching-file-for-file (filename) 0264 (catch 'found-matching-file 0265 (let* ((temp (sourcepair-analyze-filename (file-name-nondirectory filename))) 0266 (search-path (car temp)) 0267 (possible-filenames (cdr temp))) 0268 (if (= (length possible-filenames) 0) 0269 (message "%s is not a recognized source or header file (consider updating sourcepair-source-extensions or sourcepair-header-extensions)" (buffer-name)) 0270 (progn 0271 (while search-path 0272 (let ((path-to-check (car search-path)) 0273 (matching-filename nil)) 0274 (if (and (> (length path-to-check) 3) 0275 (equal (substring path-to-check -2) "/*")) 0276 (setq matching-filename (sourcepair-find-one-of (substring path-to-check 0 -2) 0277 possible-filenames 0278 t)) 0279 (setq matching-filename 0280 (sourcepair-find-one-of path-to-check possible-filenames nil))) 0281 0282 (if (eq matching-filename nil) 0283 (setq search-path (cdr search-path)) 0284 (throw 'found-matching-file matching-filename)))) 0285 0286 nil))))) 0287 0288 (defun sourcepair-load () 0289 "Load the corresponding C/C++ header or source file for the current buffer. 0290 0291 This function can be invoked by \\[sourcepair-load]. It will load the the 0292 corresponding header or source file for the current buffer. For example, if 0293 you are looking at the file FooParser.cpp and press \\[sourcepair-load], the 0294 file FooParser.h will be loaded. It also works the other way as well. 0295 0296 There are six global variables that can be used to adjust how the function 0297 works: 0298 0299 `sourcepair-source-extensions' 0300 `sourcepair-header-extensions' 0301 `sourcepair-source-path' 0302 `sourcepair-header-path' 0303 `sourcepair-recurse-ignore' 0304 `sourcepair-private-header-suffixes' 0305 0306 See the documentation for these variables for more info. 0307 " 0308 0309 (interactive) 0310 0311 (let ((file (sourcepair-matching-file-for-file (buffer-file-name)))) 0312 (if file 0313 (find-file file) 0314 (message (concat "No matching file for " (buffer-name) 0315 " (consider updating sourcepair-source-path, sourcepair-header-path)"))))) 0316 0317 (defun sourcepair-jump-to-headerfile (prefix) 0318 "Jump to header file for class at point" 0319 (interactive "P") 0320 (save-excursion 0321 (let* ((word-at-point (if prefix 0322 (read-from-minibuffer "Class: ") 0323 (current-word))) 0324 (file1 (sourcepair-matching-file-for-file (concat word-at-point ".cpp" ))) 0325 (file (if file1 file1 (sourcepair-matching-file-for-file (concat (downcase word-at-point) ".cpp" ))))) 0326 (if file 0327 (find-file file) 0328 (message "Sorry couldn't find include file for class"))))) 0329 0330 (defun sourcepair-yank-advice () 0331 "Advice function called after a yank. 0332 0333 This function is called when advising the yank function. If you are 0334 looking at a header file and paste a method declaration that was copied 0335 from a source file, this function will remove the class prefix (e.g. 0336 \"Foo::\"), add a semicolon at the end of the declaration and reindent the 0337 region. If you paste something other than a method declaration this 0338 function will just reindent the region. 0339 " 0340 (if (member major-mode '(c-mode c++-mode)) 0341 (if (sourcepair-header-file-p (buffer-name)) 0342 (let* ((this-buffer-name (buffer-name)) 0343 (extension (concat (member ?. (append this-buffer-name nil)))) 0344 (basename (substring this-buffer-name 0 (- 0 (length extension)))) 0345 (class-prefix (concat basename "::")) 0346 (begin-point (region-beginning)) 0347 (end-point (region-end)) 0348 (region-len (- end-point begin-point))) 0349 (save-excursion 0350 (set-window-point nil (- (point) region-len)) 0351 (if (re-search-forward class-prefix end-point t) 0352 (progn 0353 (replace-match "" nil t) 0354 (set-window-point nil (- end-point (length class-prefix) 1)) 0355 (re-search-backward "[^ ]") 0356 (set-window-point nil (+ (point) 1)) 0357 (insert ";") 0358 (indent-region (region-beginning) (region-end) nil) 0359 (message "Removed class prefix when pasting")) 0360 (indent-region begin-point end-point nil)))) 0361 (indent-region (region-beginning) (region-end) nil)))) 0362 0363 ; This allows (require 'sourcepair) 0364 (provide 'sourcepair) 0365 0366 ;;; sourcepair.el ends here 0367