Warning, /sdk/kde-dev-scripts/kde-emacs/kde-emacs-utils.el is written in an unsupported language. File is not indexed.
0001 ;; kde-emacs-utils.el 0002 ;; 0003 ;; Copyright (C) 2002-2005 KDE Development Team <www.kde.org> 0004 ;; 0005 ;; This library is free software; you can redistribute it and/or 0006 ;; modify it under the terms of the GNU Lesser General Public 0007 ;; License as published by the Free Software Foundation; either 0008 ;; version 2.1 of the License, or (at your option) any later version. 0009 ;; 0010 ;; This library is distributed in the hope that it will be useful, 0011 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of 0012 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0013 ;; Lesser General Public License for more details. 0014 ;; 0015 ;; You should have received a copy of the GNU Lesser General Public 0016 ;; License along with this library; if not, write to the Free Software 0017 ;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 0018 ;; 02110-1301 USA 0019 0020 0021 (require 'kde-emacs-vars) 0022 (require 'kde-emacs-general) 0023 (require 'kde-emacs-compat) 0024 0025 (if (eq kde-emacs-type 'xemacs) 0026 (progn 0027 (require 'func-menu) 0028 (add-hook 'find-file-hooks 'fume-add-menubar-entry)) 0029 (require 'imenu)) 0030 0031 (defmacro c-safe-scan-lists (from count depth) 0032 "Like `scan-lists' but returns nil instead of signalling errors. 0033 This function does not do any hidden buffer changes." 0034 (if (featurep 'xemacs) 0035 `(scan-lists ,from ,count ,depth nil t) 0036 `(c-safe (scan-lists ,from ,count ,depth)))) 0037 0038 (if (not (eq kde-include-directory nil)) 0039 (setq sourcepair-header-path (list "." kde-include-directory "/*"))) 0040 0041 ;; returns non-nil if the given file has a using declaration 0042 ;; with the passed namespace 0043 (defun kde-file-has-using (namespace) 0044 (let (found) 0045 (save-excursion 0046 (beginning-of-buffer) 0047 (setq found (re-search-forward "^using" nil 1)) 0048 (if found 0049 (setq found (search-forward namespace (line-end-position) 1)) 0050 ) 0051 ) 0052 found) 0053 ) 0054 ;; returns non-nill if the given file has a "namespace SomeNM" declaration 0055 ;; where SomeNM is passed via the namespace argument 0056 (defun kde-file-is-in-namespace (namespace) 0057 (let (found) 0058 (save-excursion 0059 (beginning-of-buffer) 0060 (setq found (re-search-forward "^namespace" nil 1)) 0061 (if found 0062 (setq found (search-forward namespace (line-end-position) 1)) 0063 ) 0064 ) 0065 found) 0066 ) 0067 0068 ; Helper function for getting the baseclass of the current class - in a C++ header file 0069 ; Only supports single inheritance 0070 (defun baseclass-under-point () 0071 (let ((pos (c-safe-scan-lists (point) -1 1))) 0072 (save-excursion 0073 (goto-char (if pos pos (point-min))) 0074 (backward-word 2) ; move back over "public baseclass" 0075 (if (looking-at "public\\|protected\\|private[ \t]*") 0076 (progn 0077 (forward-word) 0078 (while (looking-at "[ \t]") 0079 (forward-char 1)) 0080 (let ((start (point))) 0081 (forward-word) 0082 (buffer-substring start (point)))) 0083 nil 0084 ))) 0085 ) 0086 0087 ; Helper function for parsing our current position in a C++ header file 0088 ; returns (namespace (class function)) where (a b) is a cons. 0089 (defun method-under-point () 0090 (let ((class nil) 0091 (namespace "") ; will contain A::B:: 0092 (function nil)) 0093 (save-excursion 0094 (backward-char) ; in case we're after the ';' 0095 (search-forward ";" nil t) ; look for the ';' 0096 (backward-char) 0097 (save-excursion 0098 ; Go up a level, skipping entire classes etc. 0099 ; This is a modified version of (backward-up-list) which doesn't 0100 ; throw an error when not found. 0101 (let ((pos (c-safe-scan-lists (point) -1 1))) 0102 ; +1 added here so that the regexp in the while matches the { too. 0103 (goto-char (if pos (+ pos 1) (point-min)))) 0104 (while (re-search-backward "^[ ]*\\(class\\|namespace\\|struct\\)[ \t][^};]*{" nil t) 0105 (save-excursion 0106 (forward-word 1) 0107 (when (looking-at "[ \t]*[A-Z_]*_EXPORT[A-Z_]*[ \t]") 0108 (forward-word 1) 0109 (re-search-forward "[ \t]" nil t)) 0110 (while (looking-at "[ \t]") 0111 (forward-char 1)) 0112 (setq start (point)) 0113 ; Parse class name ("Foo" or "Foo::Bar::Blah"). 0114 ; Beware of "Foo:" 0115 (while (or (looking-at "[A-Za-z0-9_]") (looking-at "::")) 0116 (while (looking-at "[A-Za-z0-9_]") 0117 (forward-char 1)) 0118 (while (looking-at "::") 0119 (forward-char 2)) 0120 ) 0121 (cond 0122 (class ; class found already, so the rest goes into the namespace 0123 (setq namespace (concat (buffer-substring start (point)) "::" namespace))) 0124 (t ; class==nil 0125 (setq class (buffer-substring start (point))))) 0126 ) 0127 ; Go up one level again 0128 (let ((pos (c-safe-scan-lists (point) -1 1))) 0129 (goto-char (if pos (+ pos 1) (point-min)))) 0130 )) 0131 0132 ; Back to where we were, parse function name 0133 (let ((end (point))) ; remember where the function decl ends 0134 (search-backward ")" nil t) ; look back for the end of the argument list 0135 (forward-char) 0136 (backward-sexp) ; brings us back to the '(' 0137 (backward-word 1) 0138 (when (looking-at "throw[ \t]") ; exception specification, look for () again 0139 (search-backward ")" nil t) 0140 (forward-char) 0141 (backward-sexp)) 0142 ; now that we moved back enough, go to beginning of line. 0143 ; (we assume that the return type, function name, and '(' are on the same line) 0144 (re-search-backward "^[ \t]*") 0145 (while (looking-at "[ \t]") 0146 (forward-char 1)) 0147 (when (looking-at "/\\*") ; C-style comment, like /*! \reimp */ 0148 (re-search-forward "\\*/" nil t)) 0149 (when (looking-at "Q_") ; Qt macro like Q_SCRIPTABLE 0150 (forward-sexp)) 0151 (while (looking-at "[ \t]") 0152 (forward-char 1)) 0153 (setq function (buffer-substring (point) end)) 0154 ) 0155 ) ; end of global save-excursion 0156 (cons namespace (cons class function)) ; the returned value 0157 ) 0158 ) 0159 0160 ; get rid of virtual, static, multiple spaces, default values. 0161 (defun canonical-function-sig (function) 0162 (and (string-match "[ \t]*\\<virtual\\>[ \t]*" function) 0163 (setq function (replace-match " " t t function))) 0164 (and (string-match "^\\(virtual\\>\\)?[ \t]*" function) 0165 (setq function (replace-match "" t t function))) 0166 (and (string-match "^\\(explicit\\>\\)?[ \t]*" function) 0167 (setq function (replace-match "" t t function))) 0168 (and (string-match "^\\(static\\>\\)?[ \t]*" function) 0169 (setq function (replace-match "" t t function))) 0170 (while (string-match " +" function) ; simplifyWhiteSpace 0171 (setq function (replace-match " " t t function))) 0172 (while (string-match "\t+" function) 0173 (setq function (replace-match " " t t function))) 0174 (while (string-match "^ " function) ; remove leading whitespace 0175 (setq function (replace-match "" t t function))) 0176 ; remove default values. complex case: void foo(p=QString()) 0177 (let ((startargs (string-match "(" function))) 0178 (while (string-match " ?=[^,()]+" function startargs) ; part 1 (stop at '(') 0179 (setq function (replace-match "" t t function))) 0180 (while (string-match "([^()]*)" function (+ startargs 1)) ; part 2, remove "(...)" 0181 (setq function (replace-match "" t t function)))) 0182 0183 (while (string-match " +," function) ; remove space before commas 0184 (setq function (replace-match "," t t function))) 0185 function ; the return value 0186 ) 0187 0188 ; Helper method which turns the function as seen in the header 0189 ; into the signature for its implementation 0190 ; Returns the fully-qualified signature of the function implementation 0191 (defun kde-function-impl-sig (namespace class _function) 0192 (let ( 0193 (function (canonical-function-sig _function)) 0194 (insertion-string nil)) 0195 (and (stringp class) 0196 (cond 0197 ((string-match (concat "^ *" class "[ \\t]*(") function) ; constructor 0198 (setq insertion-string 0199 (replace-match 0200 (concat namespace class "::" class "(") 0201 t t function) 0202 )) 0203 ((string-match (concat "^ *~" class "[ \\t]*(") function) ; destructor 0204 (setq insertion-string 0205 (replace-match 0206 (concat namespace class "::~" class "(") 0207 t t function) 0208 )) 0209 )) ; end of "class required" 0210 (if (not (stringp insertion-string)) ; no ctor nor dtor 0211 (if (or (string-match " *\\([a-zA-Z0-9_]+\\)[ \\t]*(" function) ; normal method 0212 (string-match " *\\(operator[^ \\t]+\\)[ \\t]*(" function)) ; operator 0213 (setq insertion-string 0214 (replace-match 0215 (if class 0216 (concat " " namespace class "::" "\\1(") ; c++ method 0217 (concat " " "\\1(")) ; c function 0218 t nil function) 0219 ) 0220 ; else 0221 (error (concat "Can't parse declaration ``" 0222 function "'' in class ``" class 0223 "'', aborting")))) 0224 insertion-string ; the return value 0225 ) 0226 ) 0227 0228 ;; Switch between the declaration of a class member in .cc/.cpp/.C, and its definition in the .h file 0229 ;; Written by David and Reggie after much hair tearing 0230 ;; Found since, might be worth looking at: http://www.hendawi.com/emacs/sourcepair.el 0231 (defun switch-to-function-def-xemacs () 0232 (interactive) 0233 (let ((n (buffer-file-name)) 0234 (namespace "") 0235 (class "") 0236 (function "") 0237 found 0238 ) 0239 (if (member (concat "." (file-name-extension n)) sourcepair-source-extensions) 0240 ; TODO replace fume-function-before-point, needed for emacs, 0241 ; and for better namespace support. 0242 ;(progn 0243 ; (let ((pos (kde-scan-lists (point) -1 1 nil t))) ; Go up a level 0244 ; (goto-char (if pos (+ pos 1) (point-min)))) 0245 (let ((a (fume-function-before-point)) 0246 (functionregexp "")) 0247 0248 (if (eq a nil) 0249 (progn 0250 (kde-switch-cpp-h) 0251 (message "point is not in a method")) 0252 (if (string-match "^\\(.*\\)::\\(.*\\)$" a) 0253 (progn 0254 (setq class (match-string 1 a)) 0255 (setq function (match-string 2 a)) 0256 (kde-switch-cpp-h) 0257 (goto-char 0) 0258 ; Look for beginning of class ("\\s-+" means whitespace including newlines) 0259 (re-search-forward 0260 (concat "\\(class\\|struct\\|namespace\\)\\s-+" 0261 "\\([A-Z_]+_EXPORT[A-Z_]*\\s-+\\)?" ; allow for optional EXPORT macro 0262 class "\\b" ; the classname - with word separator 0263 "[^;]+{" ; the optional inheritance and the '{' 0264 ) nil t) ; no error, just return nil if not found 0265 0266 ; Look for function - with \\b prepended, unless this is about ~Foo. 0267 (setq functionregexp (kde-function-regexp-quote function)) 0268 (and (not (string-match "^~" functionregexp)) 0269 (setq functionregexp (concat "\\b" functionregexp))) 0270 ;; TODO keep looking, until we find a match that's not inside a comment 0271 (re-search-forward (concat functionregexp "[ \t]*(") nil t)) 0272 ; else: not a member method, maybe just a c function 0273 (progn 0274 (setq function a) 0275 (kde-switch-cpp-h) 0276 (goto-char 0) 0277 (re-search-forward (concat "\\b" (kde-function-regexp-quote function) "[ \t]*(") nil t)) 0278 ) 0279 ) 0280 )) 0281 (if (member (concat "." (file-name-extension n)) sourcepair-header-extensions) 0282 (progn 0283 (let ((mup (method-under-point)) 0284 (sig "") 0285 (pos 0)) 0286 (setq namespace (car mup)) 0287 (setq class (cadr mup)) 0288 (setq function (cddr mup)) 0289 (kde-switch-cpp-h) 0290 0291 ;; First search with namespace prefixed 0292 (goto-char 0) 0293 (setq sig (kde-remove-newline (kde-function-impl-sig namespace class function))) 0294 (if (string-match "(.*" sig) ; remove args 0295 (setq sig (replace-match "" nil t sig))) 0296 (setq found (re-search-forward (concat "^[^()]*" (kde-function-regexp-quote sig) "[ \t]*(") nil t) ) 0297 0298 (if (not found) 0299 (progn 0300 ; Now search without name space prefix 0301 0302 (goto-char 0) 0303 (setq sig (kde-remove-newline (kde-function-impl-sig "" class function))) 0304 0305 (if (string-match "(.*" sig) ; remove args 0306 (setq sig (replace-match "" nil t sig))) 0307 (re-search-forward (concat "^[^()]*" (kde-function-regexp-quote sig) "[ \t]*(") nil t) ) ) 0308 ))))) 0309 0310 (defun switch-to-def-semanticdb (arg) 0311 ;; This below was shared by Emacs Wiki 0312 ;; user nschum (Nikolaj Schumacher; 0313 ;; https://www.emacswiki.org/emacs/nschum) on the Emacs Wiki page 0314 ;; https://www.emacswiki.org/emacs/JumpToDefinition 0315 ;; 0316 ;; The work is licensed under version 2 of the GNU General Public License. 0317 ;; 0318 ;; Incorporated into this file by Akarsh Simha. 0319 ;; 0320 ;; Note that this is a more general method that finds the definition 0321 ;; of any symbol, not just a function. 0322 0323 "Jump to the definition of the symbol, type or function at point. 0324 With prefix arg, find in other window." 0325 (interactive "P") 0326 (let* ((tag (or (semantic-idle-summary-current-symbol-info-context) 0327 (semantic-idle-summary-current-symbol-info-brutish) 0328 (error "No known tag at point"))) 0329 (pos (or (semantic-tag-start tag) 0330 (error "Tag definition not found"))) 0331 (file (semantic-tag-file-name tag))) 0332 (if file 0333 (if arg (find-file-other-window file) (find-file file)) 0334 (if arg (switch-to-buffer-other-window (current-buffer)))) 0335 (push-mark) 0336 (goto-char pos) 0337 (end-of-line)) 0338 ) 0339 0340 (defun switch-to-function-def-semanticdb (arg) 0341 0342 ;; Modified switch-to-def-semanticdb to only find the current 0343 ;; function -- asimha 0344 0345 "Jump to the definition of the function before point. 0346 With prefix arg, find in other window." 0347 (interactive "P") 0348 0349 (if 0350 ;; Check if we are in a header file 0351 (member (concat "." (file-name-extension (buffer-file-name))) 0352 sourcepair-header-extensions) 0353 0354 ;; If we are in a header file, simply use (which-function) to 0355 ;; find the function before point and (semantic-ia-fast-jump) to 0356 ;; jump 0357 (let* ((pos nil)) 0358 (save-excursion 0359 (setq pos (search-backward (which-function)))) 0360 (push-mark) 0361 (semantic-ia-fast-jump pos) 0362 ) 0363 0364 ;; We are in the source file. 0365 0366 ;; (semantic-stickyfunc-tag-to-stick) returns the sticky tag, 0367 ;; which is the function before point in a source file, but it 0368 ;; returns the tag in the same file, not in the header file.So 0369 ;; we hack this by going to the function definition and then using 0370 ;; (semantic-idle-summary-current-symbol-info-context) etc. 0371 (let* ((destpos nil) 0372 (desttag nil) 0373 (file nil)) 0374 (push-mark) 0375 (save-excursion 0376 (end-of-line) ; This ensures that being at the beginning of the line does not take us to the previous function's declaration 0377 (beginning-of-defun) 0378 (re-search-forward "(") 0379 (forward-char -1) 0380 (re-search-backward "\\S-") 0381 (setq desttag (or (semantic-idle-summary-current-symbol-info-context) 0382 (semantic-idle-summary-current-symbol-info-brutish) 0383 (error "No known tag at point"))) 0384 (setq destpos (or (semantic-tag-start desttag) 0385 (error "Tag definition not found"))) 0386 (setq file (semantic-tag-file-name desttag)) 0387 ) 0388 (if file 0389 (if arg (find-file-other-window file) (find-file file)) 0390 (if arg (switch-to-buffer-other-window (current-buffer)))) 0391 (goto-char destpos) 0392 (end-of-line) 0393 ) 0394 ) 0395 ) 0396 0397 0398 (if (eq kde-emacs-type 'xemacs) 0399 (defun switch-to-function-def () (interactive) (switch-to-function-def-xemacs) ) 0400 (defun switch-to-function-def (arg) (interactive "P") (switch-to-function-def-semanticdb arg)) 0401 ) 0402 0403 0404 (defun kde-remove-newline (str) 0405 (replace-in-string str "\n" " ")) 0406 ; quote for use as regexp, but replace spaces with "any whitespace" 0407 (defun kde-function-regexp-quote (str) 0408 (replace-in-string (regexp-quote str) "[ \n\t]" "[ \n\t]")) 0409 0410 ; Initial implementation by Arnt Gulbransen 0411 ; Current maintainer: David Faure 0412 (defun agulbra-make-member () 0413 "make a skeleton member function in the .cpp or .cc file" 0414 (interactive) 0415 (let* ( 0416 (mup (method-under-point)) 0417 (namespace (car mup)) ; will contain A::B:: 0418 (class (cadr mup)) 0419 (function (cddr mup)) 0420 (file (buffer-file-name)) 0421 (insertion-string (kde-function-impl-sig namespace class function)) 0422 (function-sig (canonical-function-sig function)) 0423 (msubstr nil) 0424 (start nil) 0425 (newcppfile nil) 0426 (baseclass nil) 0427 ) 0428 ; First, assemble the skeleton text into insertion-string 0429 ; At this point it already contains the method signature 0430 0431 ; If constructor: add call to base class 0432 (and (stringp class) 0433 (string-match (concat "^ *" class "[ \\t]*(") function-sig) ; constructor 0434 (setq baseclass (baseclass-under-point)) 0435 ; TODO: passing the parent parameter if baseclass starts with Q :) 0436 (setq insertion-string (concat insertion-string "\n : " baseclass "()" ))) 0437 0438 ; Method body 0439 (setq insertion-string 0440 (concat insertion-string "\n{\n" 0441 (replace-in-string kde-make-member-default-impl "FUNCTION" 0442 ; the function name and args, without newlines 0443 (replace-in-string insertion-string "\n" " " t) 0444 t) 0445 "}\n")) 0446 0447 ; Move to next method, to be ready for next call 0448 (backward-char) ; in case we're after the ';' 0449 (re-search-forward ";" nil t) ; end of this method decl 0450 (let ((moveToNext t)) 0451 (while moveToNext 0452 (re-search-forward ";" nil t) ; end of next method decl 0453 (save-excursion 0454 (forward-char -2) ; -1 goes to ';' itself, so go before that 0455 (while (looking-at "[ \t0=]") 0456 (forward-char -1)) 0457 (forward-char 1) 0458 ; move to next method again if we're at a pure virtual method 0459 (setq moveToNext (looking-at "[ \t]*=[ \t]*0;")) 0460 ) 0461 ) 0462 ) 0463 0464 ; Switch to .cpp if the declaration was in a header file 0465 (if (member (concat "." (file-name-extension file)) sourcepair-header-extensions) 0466 (kde-switch-cpp-h) 0467 ) 0468 ;(setq newcppfile (= (point-max) 1)) 0469 (goto-char (point-max)) 0470 (kde-comments-begin) 0471 (kde-skip-blank-lines) 0472 (setq msubstr (buffer-substring (point-at-bol) (point-at-eol))) 0473 ; TODO refine regexp 0474 (if (string-match "^#include.*moc.*" msubstr) 0475 (progn 0476 (while (string-match "^#include.*moc.*" msubstr) 0477 (forward-line -1) 0478 (setq msubstr (buffer-substring (point-at-bol) (point-at-eol))) 0479 ) 0480 (end-of-line) 0481 (insert "\n")) 0482 ; else 0483 (progn 0484 (end-of-line) 0485 (insert "\n") 0486 (forward-line 1) 0487 )) 0488 (insert insertion-string) 0489 (forward-char -3) 0490 (c-indent-defun) 0491 ; Insert #include for the header if necessary 0492 (save-excursion 0493 (and (string-match ".*/" file) 0494 (setq file (replace-match "" t nil file))) 0495 (and (string-match "\\.h$" file) 0496 (functionp 'kdab-insert-header-non-interactive) 0497 (kdab-insert-header-non-interactive (file-name-sans-extension file)))) 0498 (when (featurep 'fume-rescan-buffer) 0499 (fume-rescan-buffer)) 0500 )) 0501 0502 (defun add-file-to-buildsystem () 0503 "Add the current (C++) file to either Makefile.am or a .pro file, whichever exists." 0504 ; Author: David 0505 (interactive) 0506 (if (file-readable-p "Makefile.am") 0507 (add-file-to-makefile-am) 0508 ; else: find a .pro file and add it there 0509 (let* ((files (directory-files "." nil ".pro$" nil t)) 0510 (projfile (car files))) 0511 (if projfile 0512 (add-file-to-project projfile "^SOURCES[ \t]*") ; could be SOURCES= or SOURCES+= 0513 ; else: error 0514 (error "No build system file found") 0515 ))) 0516 ) 0517 0518 ; internal helper for add-file-to-* 0519 (defun add-file-to-project (makefile searchString) 0520 (let ((file (buffer-name))) 0521 (if (not (file-readable-p makefile)) 0522 (error (concat makefile " not found!")) 0523 ) 0524 (find-file makefile) 0525 (goto-char (point-min)) 0526 (if (re-search-forward searchString nil t) 0527 (progn 0528 (end-of-line) 0529 ; check if line ends with '\' [had to read make-mode.el to find this one!] 0530 (while (= (char-before) ?\\) 0531 (end-of-line 2)) ; moves to end of next line 0532 (insert " ") 0533 (insert file) 0534 ) 0535 (error (concat searchString " not found")) 0536 )) 0537 ) 0538 0539 (defun add-file-to-makefile-am () 0540 "Add the current file to the first _SOURCES line in the Makefile.am" 0541 ; Author: David 0542 (interactive) 0543 (add-file-to-project "Makefile.am" "_SOURCES") 0544 ) 0545 0546 0547 ; Inserts a kDebug statement showing the name of the current method. 0548 ; You need to create the empty line first. 0549 (defun insert-kDebug () 0550 (interactive) 0551 (if (and (boundp 'kdab-qt-version) (eq kdab-qt-version 4)) 0552 (progn ; KDE4 version 0553 (insert "kDebug() << this << ;") 0554 (backward-char 1) 0555 ) 0556 (progn ; KDE3 version 0557 (insert "kdDebug() << k_funcinfo ")) 0558 (insert "<< endl;") 0559 (backward-char 8) 0560 ) 0561 ) 0562 0563 ; finds a string to be used in the header-protection function ( see below ) 0564 (defun kde-header-protection-definable-string () 0565 (let* ((definablestring "") 0566 (f (buffer-file-name)) 0567 (parts (nreverse (split-string f "/"))) 0568 (i) 0569 (first-iter t) 0570 (iters (min (length parts) kde-header-protection-parts-to-show))) 0571 (dotimes (i iters) 0572 (let ((part (pop parts))) 0573 (setq definablestring 0574 (concat 0575 (upcase (replace-in-string part "[\\.-]" "_")) 0576 (if (not first-iter) "_" "") 0577 definablestring 0578 ) 0579 ) 0580 (setq first-iter nil) 0581 ) 0582 ) 0583 definablestring 0584 ) 0585 ) 0586 0587 ; Creates the ifndef/define/endif statements necessary for a header file 0588 (defun header-protection () 0589 (interactive) 0590 (let ((s (kde-header-protection-definable-string))) 0591 (save-excursion 0592 (goto-char (point-min)) 0593 (insert "#ifndef " s "\n#define " s "\n\n") 0594 (goto-char (point-max)) 0595 (insert "\n#endif\n") 0596 ) 0597 ) 0598 ) 0599 0600 ;; Add (setq magic-parens-mode nil) to your .emacs (before loading this file) 0601 ;; to disable the automatic spaces inside "( ... )" in C++ mode. 0602 ;; This can also be enabled/disabled per project using magic-parens-mode: t in .emacs-dirvars. 0603 0604 ; Makes '(' insert '(' or ' ( ' where appropiate 0605 (defun insert-parens (arg) (interactive "*P") 0606 (if (and (not (c-in-literal)) 0607 (boundp 'magic-parens-mode) magic-parens-mode) 0608 (let ((n nil) (except nil)) 0609 (save-excursion 0610 (setq n (or (progn (forward-char -2) (looking-at "\\bif")) 0611 (progn (forward-char -1) (looking-at "\\bfor")) 0612 (progn (forward-char -1) (looking-at "\\bcase")) 0613 (progn (forward-char -1) (looking-at "\\bwhile")) 0614 ) 0615 ) 0616 (setq except (or (progn (forward-char -2) (looking-at "kDebug")) 0617 (looking-at "kError") 0618 (progn (forward-char -2) (looking-at "kWarning")) 0619 ) 0620 ) 0621 ) 0622 (cond 0623 (n (progn 0624 (insert " ") 0625 (self-insert-command (prefix-numeric-value arg)) 0626 (insert kde-emacs-after-parent-string) 0627 )) 0628 (t ;else 0629 (self-insert-command (prefix-numeric-value arg)) 0630 (cond ((not except) (insert kde-emacs-after-parent-string))) 0631 ))) 0632 (self-insert-command (prefix-numeric-value arg))) 0633 ) 0634 0635 (defun insert-parens2 (arg) (interactive "*P") 0636 (if (and (not (c-in-literal)) 0637 (boundp 'magic-parens-mode) magic-parens-mode) 0638 (let ((remv nil) (nospac nil)) 0639 (forward-char -2) 0640 (setq remv (looking-at "( ")) ; () -> we'll have to remove that space 0641 (forward-char 1) 0642 (setq nospac ; no space to be added 0643 (or (looking-at " ") 0644 (looking-at "(") 0645 (save-excursion ; check for kDebug(123 0646 (while (looking-at "[0-9]") 0647 (forward-char -1)) 0648 (forward-char -7) 0649 (or (looking-at "kDebug(") 0650 (looking-at "kError(") 0651 (progn (forward-char -2) (looking-at "kWarning(")) 0652 ) 0653 ) 0654 ) 0655 ) 0656 (forward-char 1) 0657 (cond 0658 (remv (progn 0659 (delete-backward-char 1) 0660 (self-insert-command (prefix-numeric-value arg)))) ; the () case 0661 (nospac (self-insert-command (prefix-numeric-value arg))) ; no space to be added 0662 (t ;else 0663 (if abbrev-mode ; XEmacs 0664 (expand-abbrev)) 0665 (insert kde-emacs-after-parent-string) 0666 (self-insert-command (prefix-numeric-value arg)) 0667 ))) ; normal case, prepend a space 0668 ;;(blink-matching-open) ; show the matching parens 0669 (self-insert-command (prefix-numeric-value arg))) 0670 ) 0671 0672 ; Makes ',' insert ', ' 0673 (defun insert-comma (arg) 0674 (interactive "*P") 0675 (let* ((ch (char-after)) 0676 (spacep (not (or (eq ch ? ) 0677 (c-in-literal) 0678 arg)))) 0679 (self-insert-command (prefix-numeric-value arg)) 0680 (if spacep 0681 (insert " ")))) 0682 0683 (defun insert-semicolon (arg) 0684 (interactive "*P") 0685 (self-insert-command (prefix-numeric-value arg)) 0686 (newline-and-indent)) 0687 0688 (defun insert-curly-brace (arg) (interactive "*P") 0689 (if (not (c-in-literal)) 0690 (let ((n nil) (o nil) 0691 (spacep nil) (c nil) 0692 (oneliner nil) (cxxlambda nil) 0693 (clausekeyword nil) (dokeyword nil)) 0694 (save-excursion 0695 (save-excursion 0696 (if (re-search-forward "[a-zA-Z]" (point-at-eol) t) 0697 (setq oneliner t))) 0698 (forward-char -1) ; These three lines are for the situation where 0699 (if (not (looking-at " ")) ; the user already have inserted a space after 0700 (forward-char 1) ; the closing parenthesis 0701 (setq spacep t)) 0702 (forward-char -2) 0703 (setq o (looking-at "()")) 0704 (forward-char 1) 0705 (setq n (looking-at ")")) 0706 (save-excursion (if (and 0707 (not oneliner) 0708 (not (eq 0709 (count-lines (point-min) (point)) 0710 (count-lines (point-min) (point-max))))) 0711 (progn 0712 (next-line 1) 0713 (beginning-of-line) 0714 (if (re-search-forward "[a-zA-Z]" (point-at-eol) t) 0715 (setq c (eq (car (car (c-guess-basic-syntax))) 'substatement))) 0716 ) 0717 )) 0718 0719 ; The following lines handle keywords 'else' and 'do' to insert a matching brace 0720 ; if the keyword is 'do', we also insert a while. 0721 (forward-char -1) 0722 (setq dokeyword (looking-at "do")) 0723 (setq clausekeyword (or dokeyword 0724 (progn (forward-char -2) (looking-at "else")))) 0725 ) 0726 (setq cxxlambda (looking-back "\\[.*\\]\\s-*(.*)\\(\\s-*->.*\\)?\\s-*")) 0727 (cond 0728 ((or (or n clausekeyword) cxxlambda) (progn 0729 (if (not spacep) (insert " ")) 0730 (self-insert-command (prefix-numeric-value arg)) 0731 (if (not c) (newline-and-indent)) 0732 (if oneliner (end-of-line)) 0733 (save-excursion 0734 (if c 0735 (progn 0736 (next-line 1) 0737 (end-of-line) 0738 )) 0739 (newline-and-indent) 0740 (insert "}") 0741 (if cxxlambda (insert ";")) 0742 (if dokeyword (insert " while")) 0743 (c-indent-line)) 0744 (c-indent-line) 0745 )) 0746 (o (progn 0747 (newline) 0748 (self-insert-command (prefix-numeric-value arg)) 0749 (newline-and-indent))) 0750 (t (progn ;else 0751 (self-insert-command (prefix-numeric-value arg)) 0752 (save-excursion 0753 (beginning-of-line) 0754 (c-indent-command)))) 0755 )) 0756 (self-insert-command (prefix-numeric-value arg)) 0757 ) 0758 ) 0759 0760 ;; have PelDel mode work 0761 (put 'insert-parens 'pending-delete t) 0762 (put 'insert-parens2 'pending-delete t) 0763 (put 'insert-comma 'pending-delete t) 0764 (put 'insert-curly-brace 'pending-delete t) 0765 (put 'newline-and-indent 'pending-delete t) 0766 0767 ; A wheel mouse that doesn't beep, unlike mwheel-install 0768 (defun scroll-me-up () (interactive) (scroll-up 4)) 0769 (defun scroll-me-down () (interactive) (scroll-down 4)) 0770 (defun scroll-me-up-a-bit () (interactive) (scroll-up 1)) 0771 (defun scroll-me-down-a-bit () (interactive) (scroll-down 1)) 0772 0773 ; Compilation 0774 (defun makeclean () 0775 "Executes a \"make clean\" in the current directory" 0776 (interactive) 0777 (compile (concat kde-emacs-make " clean")) 0778 ) 0779 0780 (defun make () 0781 "Executes a \"make\" in the current directory" 0782 (interactive) 0783 (compile (concat kde-emacs-make " -k")) 0784 ) 0785 0786 (defun makeinstall () 0787 "Executes a \"make install\" in the current directory" 0788 (interactive) 0789 (compile (concat kde-emacs-make " -k install")) 0790 ) 0791 0792 (defun makeinstallexec () 0793 "Executes a \"make install-exec\" in the current directory" 0794 (interactive) 0795 (compile (concat kde-emacs-make " -k install-exec")) 0796 ) 0797 0798 (defun makethisfile () 0799 "Try to compile the currently opened file" 0800 (interactive) 0801 (let ((f (file-name-nondirectory (buffer-file-name))) 0802 (objext nil)) 0803 0804 (if (and (file-readable-p "Makefile.am") (not (file-readable-p "CMakeLists.txt"))) 0805 (setq objext "\.lo") 0806 (setq objext "\.o")) 0807 (if (string-match "\.cpp$" f) (setq f (replace-match objext t t f))) 0808 (if (string-match "\.cc$" f) (setq f (replace-match objext t t f))) 0809 (if (string-match "\.c$" f) (setq f (replace-match objext t t f))) 0810 (compile (concat kde-emacs-make " " f))) 0811 ) 0812 0813 ;; pc-like textmarking, deprecated in GNU Emacs 24+. 0814 (when (not (and (eq kde-emacs-type 'emacs) 0815 (>= emacs-major-version 24))) 0816 (when kde-use-pc-select 0817 (progn 0818 (load "pc-select") 0819 (if (eq kde-emacs-type 'xemacs) 0820 (funcall 'pc-select-mode) 0821 (funcall 'pc-selection-mode))))) 0822 0823 0824 ; Move in other window 0825 (defun scroll-other-up () (interactive) (scroll-other-window-down 1)) ; hehe :) 0826 (defun scroll-other-down () (interactive) (scroll-other-window 1)) 0827 0828 (defun match-paren () 0829 "Go to the matching parenthesis if on parenthesis otherwise do nothing." 0830 (interactive) 0831 (cond ((looking-at "[ \t]*[\({]") (forward-sexp) (backward-char)) 0832 ((looking-at "[\)}]") (forward-char) (backward-sexp)))) 0833 0834 (defun kde-start-c++-header () 0835 "Start a new C++ header by inserting include guards ( see \ 0836 header-protection function ), inserting a license statement \ 0837 and putting (point) at the correct position" 0838 (interactive) 0839 (header-protection) 0840 (insert "\n") 0841 (beginning-of-buffer) 0842 (kde-license-insert "GNU GPL") 0843 (next-line 1) 0844 (kill-line) 0845 (end-of-buffer) 0846 (next-line -3) 0847 (insert "\n") 0848 ) 0849 0850 (defun kde-year-range-parse-years-string (string) 0851 "parses something like \"2000, 2008-2010\" into a list of the form \ 0852 ((2008 . 2010)(2000 . 2000))" 0853 (let ((pos -1) 0854 (oldpos) 0855 (l (length string)) 0856 (currange "") 0857 (startyear) 0858 (endyear) 0859 (ret) 0860 ) 0861 (while (< pos l) 0862 (setq oldpos (+ pos 1)) 0863 (setq pos (string-match "[,]" string (+ pos 1))) 0864 (unless pos (setq pos l)) 0865 (setq currange (substring string oldpos pos)) 0866 (string-match "[0-9]+" currange) 0867 (setq startyear (string-to-int (match-string 0 currange))) 0868 (setq endyear 0869 (if (string-match "-" currange) 0870 (string-to-int (substring currange (match-end 0))) 0871 startyear)) 0872 (setq ret (cons (cons startyear endyear) ret)) 0873 ) 0874 ret 0875 ) 0876 ) 0877 0878 (defun kde-year-range-contains-year (ranges year) 0879 "checks whether year is in ranges.. ( ranges is a list as \ 0880 kde-year-range-parse-years-string returns.. " 0881 (let ((ret)) 0882 (dolist (range ranges ret) 0883 (when (and (>= year (car range)) (<= year (cdr range))) 0884 (setq ret t)) 0885 ))) 0886 0887 (defun kde-year-range-to-string (ranges) 0888 "converts ranges to a string.." 0889 (let ((ret "")) 0890 (dolist (range ranges) 0891 (setq ret 0892 (concat 0893 (int-to-string (car range)) 0894 (if (/= (cdr range) (car range)) 0895 (concat "-" (int-to-string (cdr range))) 0896 "") 0897 ", " 0898 ret) 0899 ) 0900 ) 0901 ; remove extraneous ", " 0902 (setq ret (substring ret 0 (- (length ret) 2))) 0903 ) 0904 ) 0905 0906 ; merges adjacent year ranges into one.. 0907 (defun kde-year-range-cleanup (range) 0908 (let ((origrange range)) 0909 (while (and range (cdr range)) 0910 (let ((years (car range)) (nyears (cadr range))) 0911 (when (>= (+ (cdr nyears) 1) (car nyears)) 0912 (setcar range (cons (car nyears) (cdr years))) 0913 (setcdr range (cddr range))) 0914 ) 0915 (setq range (cdr range)) 0916 ) 0917 origrange 0918 ) 0919 ) 0920 0921 ; adds year to range.. 0922 (defun kde-year-range-add-year (range year) 0923 (while range 0924 (let ((years (car range))) 0925 (cond 0926 ((and (>= year (car years)) (<= year (cdr years)) 0927 ; year is already in the range.. 0928 (setq range nil))) 0929 ((= year (+ (cdr years) 1)) 0930 (setcdr years year) 0931 (setq range nil)) 0932 ((= year (- (car years) 1)) 0933 (setcar years year) 0934 (setq range nil)) 0935 ) 0936 ) 0937 (setq range (cdr range)) 0938 ) 0939 (kde-year-range-cleanup range) 0940 ) 0941 0942 (defun kde-add-copyright () (interactive) 0943 "Tries to add your kde-full-name and kde-email to the Copyright \ 0944 statements at the top of a file... It tries to figure out \ 0945 if it's already there, and if so, updates the line to include the \ 0946 current year.. ( well, replaces it by a new one, anyway :) )" 0947 (let ((wascomment "")) 0948 (save-excursion 0949 (beginning-of-buffer) 0950 (if (re-search-forward (concat "Copyright ([Cc]) \\([0-9 ,-]*\\) " (regexp-quote kde-full-name)) nil t) 0951 (progn 0952 (beginning-of-line) 0953 (let ((years (kde-year-range-cleanup (kde-year-range-parse-years-string (match-string 1)))) 0954 (new-copyright-string "Copyright (C) ") 0955 (this-year (string-to-int (format-time-string "%Y")))) 0956 (when (not (kde-year-range-contains-year years this-year)) 0957 (kde-year-range-add-year years this-year)) 0958 (setq new-copyright-string 0959 (concat new-copyright-string (kde-year-range-to-string years))) 0960 ; finish new-copyright-string 0961 (setq new-copyright-string 0962 (concat new-copyright-string " " kde-full-name " <" kde-email ">")) 0963 (beginning-of-line) 0964 (re-search-forward "Copyright ([Cc])") 0965 (beginning-of-line) 0966 (setq wascomment 0967 (buffer-substring (point) 0968 (match-beginning 0) 0969 )) 0970 (kill-line nil) 0971 (insert new-copyright-string) 0972 ) 0973 ) 0974 (beginning-of-buffer) 0975 (let ((first-copyright-str (re-search-forward "Copyright ([Cc])" nil t))) 0976 (if first-copyright-str 0977 (progn 0978 (goto-char first-copyright-str) 0979 (beginning-of-line) 0980 (setq wascomment (buffer-substring (point) (match-beginning 0))) 0981 (forward-line 1) 0982 ) 0983 (goto-line 2)) 0984 ) 0985 (beginning-of-line) 0986 (insert "Copyright (C) " (format-time-string "%Y") " " 0987 kde-full-name " <" kde-email ">\n") 0988 (forward-line -1) 0989 ) 0990 (end-of-line) 0991 (let ((end (point))) 0992 (beginning-of-line) 0993 (insert wascomment) 0994 ) 0995 ) 0996 ) 0997 ) 0998 0999 (defun kde-emacs-file-style-update () 1000 "Updates the style header of this file" 1001 (interactive) 1002 (if (or (eq major-mode 'c++-mode) 1003 (eq major-mode 'c-mode)) 1004 (let ((startpoint) (endpoint) 1005 (firstline) (strings) 1006 (str) (m) (m2) (var) (value) 1007 (final)) 1008 (save-excursion 1009 (beginning-of-buffer) 1010 (setq startpoint (point)) 1011 (setq endpoint (point-at-eol))) 1012 (setq firstline (buffer-substring startpoint endpoint)) 1013 (if (string-match "-\*-\\([A-Za-z0-9\-\+\:\; ]+\\)-\*-" firstline) 1014 (delete-region startpoint endpoint)) 1015 (setq final (concat "-*- " 1016 "Mode: " mode-name "; " 1017 "c-basic-offset: " (prin1-to-string c-basic-offset) "; " 1018 "indent-tabs-mode: " (prin1-to-string indent-tabs-mode) "; " 1019 "tab-width: " (prin1-to-string tab-width) "; " 1020 "-*-")) 1021 (save-excursion 1022 (beginning-of-buffer) 1023 (insert final) 1024 (comment-region (point-at-bol) (point-at-eol)) 1025 (newline))))) 1026 1027 ; Helper for qt-open-header, for Qt 4. Opens a file if it says #include "../foo/bar.h", 1028 ; close it and open that file instead; recursively until finding a real file. 1029 (defun qt-follow-includes (file) 1030 (let ((line "") 1031 (begin nil) 1032 (buffer nil)) 1033 (find-file file) 1034 (goto-char 0) 1035 (if (looking-at "#include \"") 1036 (progn 1037 (forward-char 10) 1038 (setq begin (point)) 1039 (re-search-forward "\"" nil t) 1040 (backward-char 1) 1041 (setq file (buffer-substring begin (point))) 1042 (setq buffer (current-buffer)) 1043 (qt-follow-includes file) 1044 (kill-buffer buffer) 1045 ) 1046 ; else: this is the right file, skip the comments and go to the class 1047 (progn 1048 (re-search-forward "^class" nil t) 1049 (beginning-of-line)) 1050 ))) 1051 1052 (defun qt-open-header () 1053 "Open the Qt header file for the class under point" 1054 (interactive) 1055 (let* ((qtinc (concat (getenv "QTDIR") "/include/")) 1056 (class (thing-at-point 'word)) 1057 (f nil) 1058 (file nil) 1059 (files nil) 1060 ) 1061 (save-excursion 1062 ; The Qt3 case: the includes are directly in $QTDIR/include/, lowercased 1063 (setq f (concat qtinc (downcase class) ".h" )) 1064 (if (file-readable-p f) 1065 (setq file f) 1066 ; For some Qt3/e classes: add _qws 1067 (setq f (concat qtinc (downcase class) "_qws.h" )) 1068 (if (file-readable-p f) 1069 (setq file f) 1070 ; The Qt4 case: the includes are in $QTDIR/include/QSomething/, in original case 1071 (setq files (directory-files qtinc t nil "dirsonly")) 1072 (dolist (f files nil) 1073 (if (file-readable-p (concat f "/" class) ) 1074 (setq file (concat f "/" class)))) 1075 )) 1076 (and file 1077 (qt-follow-includes file)) 1078 ) 1079 )) 1080 1081 (provide 'kde-emacs-utils)