diff options
Diffstat (limited to 'scripts/kde-emacs')
-rw-r--r-- | scripts/kde-emacs/HACKING | 7 | ||||
-rw-r--r-- | scripts/kde-emacs/dirvars.el | 200 | ||||
-rw-r--r-- | scripts/kde-emacs/kde-emacs-bindings.el | 185 | ||||
-rw-r--r-- | scripts/kde-emacs/kde-emacs-compat.el | 77 | ||||
-rw-r--r-- | scripts/kde-emacs/kde-emacs-core.el | 3823 | ||||
-rw-r--r-- | scripts/kde-emacs/kde-emacs-doc.el | 322 | ||||
-rw-r--r-- | scripts/kde-emacs/kde-emacs-general.el | 179 | ||||
-rw-r--r-- | scripts/kde-emacs/kde-emacs-semantic.el | 456 | ||||
-rw-r--r-- | scripts/kde-emacs/kde-emacs-tips.texi | 257 | ||||
-rw-r--r-- | scripts/kde-emacs/kde-emacs-utils.el | 894 | ||||
-rw-r--r-- | scripts/kde-emacs/kde-emacs-vars.el | 147 | ||||
-rw-r--r-- | scripts/kde-emacs/kde-emacs.el | 66 | ||||
-rw-r--r-- | scripts/kde-emacs/klaralv.el | 422 |
13 files changed, 7035 insertions, 0 deletions
diff --git a/scripts/kde-emacs/HACKING b/scripts/kde-emacs/HACKING new file mode 100644 index 00000000..d3a87f22 --- /dev/null +++ b/scripts/kde-emacs/HACKING @@ -0,0 +1,7 @@ +Rules are simple: +1) Make sure that your functions work both on GNU/Emacs and XEmacs. +2) Put general variables in kde-emacs-vars.el, file related variables +inside the related file. +3) Export general functions to kde-emacs-general.el. +4) Always provide documentation for both variables and functions that +you're adding. diff --git a/scripts/kde-emacs/dirvars.el b/scripts/kde-emacs/dirvars.el new file mode 100644 index 00000000..5fba18e7 --- /dev/null +++ b/scripts/kde-emacs/dirvars.el @@ -0,0 +1,200 @@ +;;; -*- local-enable-local-variables: nil -*- +;;; dirvars.el --- Local variables that apply to an entire directory + +;; Copyright (C) 2002 Matt Armstrong + +;; Author: Matt Armstrong <matt@lickey.com> +;; Location: http://www.lickey.com/env/elisp/dirvars.el +;; Keywords: files +;; Version: 1.2 +;; Obscure: matt@squeaker.lickey.com|elisp/dirvars.el|20021213043855|48166 + +;; This file is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 2, or (at your option) +;; any later version. + +;; This file is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with GNU Emacs; see the file COPYING. If not, write to +;; the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor, +;; Boston, MA 02110-1301, USA. + +;;; Commentary: + +;; Emacs allows you to specify local variable values for use when +;; editing a file either in the first line or in a local variables +;; list. +;; +;; This file provides similar functionality, but for an entire +;; directory tree. +;; +;; You simply place an .emacs-dirvars file in the root of your +;; project's tree, and you can then set emacs variables like you would +;; in a Local Variables: section at the end of a file. E.g. the +;; contents of a typical dirvars file might look like this: +;; +;; ;; -*- emacs-lisp -*- +;; ;; +;; ;; This file is processed by the dirvars emacs package. Each variable +;; ;; setting below is performed when this dirvars file is loaded. +;; ;; +;; indent-tabs-mode: nil +;; tab-width: 8 +;; show-trailing-whitespace: t +;; indicate-empty-lines: t +;; +;; Much of this code is stolen and modified from the standard Emacs +;; files.el +;; +;; This code refuses to set any symbol that meets any of these +;; criteria (this criteria is stolen from files.el): +;; +;; - the symbol is in the ignored-local-variables list +;; - the symbol has the risky-local-variable property. +;; - the symbol name ends in -hook(s), -function(s), -form(s), +;; -program, -command, or -predicate. + +;;; Todo: + +;; Implement the following changes to keep in line with elisp coding +;; conventions: When a package provides a modification of ordinary +;; Emacs behavior, it is good to include a command to enable and +;; disable the feature, Provide a command named `WHATEVER-mode' which +;; turns the feature on or off, and make it autoload (*note +;; Autoload::). Design the package so that simply loading it has no +;; visible effect--that should not enable the feature.(2) Users will +;; request the feature by invoking the command. +;; +;; Support customize? + +;;; Code: + +(defvar dirvars-enable-flag t + "*Control use of directory variables in files you visit. +The meaningful values are nil and non-nil.") + +(defun dirvars-find-upwards (file-name) + "Find a file in the current directory or one of its parents. + +Returns the fully qualified file name, or nil if it isn't found. + +The FILE-NAME specifies the file name to search for." + ;; Chase links in the source file and search in the dir where it + ;; points. + (setq dir-name (or (and buffer-file-name + (file-name-directory (file-chase-links + buffer-file-name))) + default-directory)) + ;; Chase links before visiting the file. This makes it easier to + ;; use a single file for several related directories. + (setq dir-name (file-chase-links dir-name)) + (setq dir-name (expand-file-name dir-name)) + ;; Move up in the dir hierarchy till we find a change log file. + (let ((file1 (concat dir-name file-name)) + parent-dir) + (while (and (not (file-exists-p file1)) + (progn (setq parent-dir + (file-name-directory + (directory-file-name + (file-name-directory file1)))) + ;; Give up if we are already at the root dir. + (not (string= (file-name-directory file1) + parent-dir)))) + ;; Move up to the parent dir and try again. + (setq file1 (expand-file-name file-name parent-dir))) + ;; If we found the file in a parent dir, use that. Otherwise, + ;; return nil + (if (or (get-file-buffer file1) (file-exists-p file1)) + file1 + nil))) + +(defun dirvars-eat-comment () + (while (looking-at "[ \t\n]*;") + (let ((begin (point))) + (skip-chars-forward " \t\n") + (if (looking-at ";") + (progn + (end-of-line) + (delete-region begin (point))))))) + +(defun dirvars-hack-local-variables (dirvars-file) + (save-excursion + (let ((original-buffer (current-buffer)) + (temp-buffer (get-buffer-create "*dirvars-temp*")) + (enable-local-variables (and ;local-enable-local-variables -- doesn't exist! + enable-local-variables + dirvars-enable-flag)) + (continue t) + (parse-sexp-ignore-comments t) + (lisp-mode-hook nil) + beg) + (set-buffer temp-buffer) + (erase-buffer) + (lisp-mode) + (insert-file dirvars-file) + (goto-char (point-min)) + (catch 'done + (while continue + (if (null (scan-sexps (point) 1)) + (throw 'done nil)) + (goto-char (scan-sexps (point) 1)) + (goto-char (scan-sexps (point) -1)) + (if (eobp) + (throw 'done nil)) + (setq beg (point)) + (skip-chars-forward "^:\n") + (if (not (looking-at ":")) + (error (format "Missing colon in directory variables entry at %d" + (point)))) + (skip-chars-backward " \t") + (let* ((str (buffer-substring beg (point))) + (var (read str)) + val) + ;; Read the variable value. + (skip-chars-forward "^:") + (forward-char 1) + (setq val (read (current-buffer))) + (save-excursion + (set-buffer original-buffer) + (dirvars-hack-one-local-variable dirvars-file + var val)))))))) + +(defun dirvars-hack-one-local-variable (dirvars-file var val) + "\"Set\" one variable in a local variables spec. +A few variable names are treated specially." + (cond ((memq var ignored-local-variables) + nil) + ;; Trap risky variables and such. This is the same logic + ;; that files.el uses. + ((or (get var 'risky-local-variable) + (and + (string-match "-hooks?$\\|-functions?$\\|-forms?$\\|-program$\\|-command$\\|-predicate$" + (symbol-name var)) + (not (get var 'safe-local-variable)))) + (message (format "Ignoring %s in %s" + (symbol-name var) dirvars-file))) + ;;check whether the var should be evaluated + ((eq var 'evaluate) + (eval val)) + ;; Ordinary variable, really set it. + (t (make-local-variable var) + (set var val)))) + +(defun dirvars-hack-local-variables-before () + (let ((dirvars-file (dirvars-find-upwards ".emacs-dirvars"))) + (if dirvars-file + (dirvars-hack-local-variables dirvars-file)))) + +(defadvice hack-local-variables + (before dirvars-hack-local-variables-before) + "Process dirvars before a file's local variables are processed." + (dirvars-hack-local-variables-before)) +(ad-activate 'hack-local-variables) + +(provide 'dirvars) +;;; dirvars.el ends here diff --git a/scripts/kde-emacs/kde-emacs-bindings.el b/scripts/kde-emacs/kde-emacs-bindings.el new file mode 100644 index 00000000..84202dfb --- /dev/null +++ b/scripts/kde-emacs/kde-emacs-bindings.el @@ -0,0 +1,185 @@ +;; kde-emacs-bindings.el +;; +;; Copyright (C) 2002 KDE Development Team +;; +;; This library is free software; you can redistribute it and/or +;; modify it under the terms of the GNU Lesser General Public +;; License as published by the Free Software Foundation; either +;; version 2.1 of the License, or (at your option) any later version. +;; +;; This library is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +;; Lesser General Public License for more details. +;; +;; You should have received a copy of the GNU Lesser General Public +;; License along with this library; if not, write to the Free Software +;; Foundation, Inc., 51 Franklin Steet, Fifth Floor, Boston, MA +;; 02110-1301 USA + +; currently no binding for header-protection and add-file-to-makefile-am, +; you need to call them from M-x + +; ----------------------------------------------------------------- +; The list below defines the following bindings: +; +; F2 : offer a grep command (use C-u F2 if you need to specify options, like -i or -w) +; Shift-F2 : offer a grep command to search in directories below the current too.. +; +; F3/Shift-F3/F8/Shift-RMB : different ways to see the list of methods in the current buffer +; +; F4 : make +; Shift-F4 : make clean +; F5 : make install +; Shift-F5 : make install-exec +; +; Shift-F6 : compile this file [assumes libtool is being used] +; F6 : Switch from .cpp/.cc to .h and vice-versa +; F7 : The same, but try to find the current method in the other file +; F9 : Create a member method in the .cpp, the cursor being on the definition in the .h +; F10: Place point on a class name, and the respective (Qt) include file will be inserted. +; This works with all Qt classes but can easily be extended to KDE classes. +; Shift-F10: Place point on a class name, and "class Blah" will be inserted near the top. +; Meta-F10: Place point on a class name, and press Meta-F10, and konqueror will load +; Qt documentation. Customize the location of the Qt documentation with the +; variable kdab-qt-documentation. XXX will be replace with the class name. +; Example (setq kdab-qt-location "file:/packages/kde-src/qt-copy/doc/html/XXX.html") +; +; M-n: jump to the next error (after compiling) or grep matches +; +; Ctrl+Meta+D : insert a kdDebug statement with the name of the current method +; [the new hide-all-windows shortcut conflicts with that, you may have to +; change it, or use Ctrl+Meta+Shift+D (!!)] +; +; Meta Up/Down : scroll the other window (when window is split) + +; Other very useful keybindings to know about: +; C-x r m to set a named bookmark in the buffer +; C-x r b to jump to a named bookmark in the buffer +; To save bookmarks to a file type: +; M-x bookmark-write +; and to load bookmarks from a file write: +; M-x bookmark-load + +(require 'kde-emacs-core) +(require 'kde-emacs-general) +(require 'kde-emacs-utils) +(require 'klaralv) +(require 'kde-emacs-utils) +(when (featurep 'semantic) + (require 'kde-emacs-semantic) + (require 'kde-emacs-doc)) + +;; Wheelmouse support +(define-key global-map [(button4)] 'scroll-me-down) +(define-key global-map [(button5)] 'scroll-me-up) +(define-key global-map [(shift button4)] 'scroll-me-down-a-bit) +(define-key global-map [(shift button5)] 'scroll-me-up-a-bit) + +;; Some example bindings, feel free to customize :) +(define-key global-map [(meta up)] 'scroll-other-up) +(define-key global-map [(meta down)] 'scroll-other-down) +(define-key global-map [(control j)] 'goto-line) +(global-set-key [(control %)] 'match-paren) ;;for all buffers :) + +(if (featurep 'igrep) + (progn + (setq igrep-find-prune-clause + (format "-type d %s -name CVS -o -name .libs -o -name .deps %s" + (shell-quote-argument "(") + (shell-quote-argument ")"))) + (setq igrep-find-file-clause + (format "-type f %s -name %s %s -name %s %s -name %s %s -name %s" ; -type l + (shell-quote-argument "!") + (shell-quote-argument "*~") ; Emacs backup + (shell-quote-argument "!") + (shell-quote-argument "*,v") ; RCS file + (shell-quote-argument "!") + (shell-quote-argument "s.*") ; SCCS file + (shell-quote-argument "!") + (shell-quote-argument "*.o") ; compiled object + (shell-quote-argument "!") + (shell-quote-argument ".#*") ; Emacs temp file + ) + ) + (define-key global-map [(f2)] 'igrep) + (define-key global-map [(shift f2)] 'igrep-find) + (define-key global-map [(f12)] 'igrep-find) ; on the console, shift f2 gives f12 for some reason.. + ;(setq igrep-files-default 'ignore) ; too hard to use *.cc *.h with it, because of the full path + ) + (define-key global-map [(f2)] 'grep)) +(define-key global-map [(shift backspace)] 'kde-delete-backward-ws) + +;; FIXME: remember to get these working on Gnu/Emacs (Zack) +(when (eq kde-emacs-type 'xemacs) + (define-key c++-mode-map [(f8)] 'function-menu) + (define-key c++-mode-map [(f3)] 'fume-prompt-function-goto) + (define-key c++-mode-map [(shift f3)] 'fume-list-functions) + ) + +(define-key global-map [(shift button3)] 'mouse-function-menu) +(define-key global-map [(shift f4)] 'makeclean) +(define-key global-map [(f4)] 'make) +(define-key global-map [(f5)] 'makeinstall) +(define-key global-map [(shift f5)] 'makeinstallexec) +(define-key global-map [(shift f6)] 'makethisfile) +(if kde-emacs-newline-semicolon + (define-key c++-mode-map "\;" 'insert-semicolon)) +(define-key c++-mode-map [(f6)] 'kde-switch-cpp-h) +(define-key c-mode-map [(f6)] 'kde-switch-cpp-h) +(define-key c++-mode-map [(f7)] 'switch-to-function-def) +(define-key c++-mode-map [(f9)] 'agulbra-make-member) +(define-key c-mode-map [(f9)] 'agulbra-make-member) +(define-key global-map [(meta n)] 'next-error) + +; kde-emacs-headers: +(define-key c++-mode-map [(f10)] 'kdab-insert-header) +(define-key c++-mode-map [(shift f10)] 'kdab-insert-forward-decl) +(define-key c++-mode-map [(meta f10)] 'kdab-lookup-qt-documentation) +(define-key c++-mode-map [(control meta d)] 'insert-kdDebug) + +; Standard Qt/KDE shortcuts: Ctrl+Backspace, Ctrl+Delete +(define-key global-map [(control backspace)] 'backward-kill-word) +(define-key global-map [(control delete)] 'kill-word) + +; Standard Qt/KDE shortcuts: Control Pageup and Pagedown +(define-key global-map [(control prior)] 'beginning-of-buffer) +(define-key global-map [(control next)] 'end-of-buffer) + +; kde-emacs-semantic : +; no binding for kde-license-insert; call it via M-x +(when (featurep 'semantic) + (define-key c++-mode-map [(control c)(control k)(d)] 'kde-doc-function-insert) + (define-key c++-mode-map [(control c)(control k)(m)] 'kde-doc-multiline-insert) + (define-key c++-mode-map [(control c)(control k)(o)] 'kde-doc-oneliner-insert) + (define-key c++-mode-map [(control c)(control k)(e)] 'kde-function-expand-at-point) + (define-key c++-mode-map [(control c)(control k)(s)] 'kde-create-skeletons)) + +(modify-frame-parameters (selected-frame) '((menu-bar-lines . 2))) +(define-key c++-mode-map [menu-bar KDE] + (cons "KDE" c++-mode-map)) +(when (featurep 'semantic) + (define-key c++-mode-map [menu-bar KDE kde-doc-function-insert] + '("kde-doc-function-insert" . kde-doc-function-insert)) + (define-key c++-mode-map [menu-bar KDE kde-function-expand-at-point] + '("kde-function-expand-at-point" . kde-function-expand-at-point)) + (define-key c++-mode-map [menu-bar KDE kde-create-skeletons] + '("kde-create-skeletons" . kde-create-skeletons)) + (define-key c++-mode-map [menu-bar KDE kde-doc-multiline-insert] + '("kde-doc-multiline-insert" . kde-doc-multiline-insert))) +(define-key c++-mode-map [menu-bar KDE makeclean] + '("make clean" . makeclean)) +(define-key c++-mode-map [menu-bar KDE make] + '("make" . make)) +(define-key c++-mode-map [menu-bar KDE makeinstall] + '("make install" . makeinstall)) +(define-key c++-mode-map [menu-bar KDE makethisfile] + '("make this file" . makethisfile)) +(define-key c++-mode-map [menu-bar KDE kdeswitchcpph] + '("Switch to .h/.cpp file" . kde-switch-cpp-h)) +(define-key c++-mode-map [menu-bar KDE insert-kdDebug] + '("Insert kdDebug" . insert-kdDebug)) + + +(provide 'kde-emacs-bindings) + diff --git a/scripts/kde-emacs/kde-emacs-compat.el b/scripts/kde-emacs/kde-emacs-compat.el new file mode 100644 index 00000000..1ff1fe7a --- /dev/null +++ b/scripts/kde-emacs/kde-emacs-compat.el @@ -0,0 +1,77 @@ +;; kde-emacs-compat.el - contains compatibility functions +;; +;; Copyright (C) 2003 Zack Rusin <zack@kde.org> +;; 2003 KDE Developlment team +;; 2003 XEmacs developers +;; +;; This program is free software; you can redistribute it and/or +;; modify it under the terms of the GNU General Public License +;; as published by the Free Software Foundation; either version 2 +;; of the License, or (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with this program; if not, write to the Free Software +;; Foundation, Inc., 51 Franklin Steet, Fifth Floor, Boston, MA +;; 02110-1301, USA. + +(require 'kde-emacs-vars) + +;;GNU/Emacs does not have this one +(if (not (fboundp 'replace-in-string)) + (defun replace-in-string (str regexp newtext &optional literal) + "Replace all matches in STR for REGEXP with NEWTEXT string, + and returns the new string. +Optional LITERAL non-nil means do a literal replacement. +Otherwise treat `\\' in NEWTEXT as special: + `\\&' in NEWTEXT means substitute original matched text. + `\\N' means substitute what matched the Nth `\\(...\\)'. + If Nth parens didn't match, substitute nothing. + `\\\\' means insert one `\\'. + `\\u' means upcase the next character. + `\\l' means downcase the next character. + `\\U' means begin upcasing all following characters. + `\\L' means begin downcasing all following characters. + `\\E' means terminate the effect of any `\\U' or `\\L'." + (if (> (length str) 50) + (with-temp-buffer + (insert str) + (goto-char 1) + (while (re-search-forward regexp nil t) + (replace-match newtext t literal)) + (buffer-string)) + (let ((start 0) newstr) + (while (string-match regexp str start) + (setq newstr (replace-match newtext t literal str) + start (+ (match-end 0) (- (length newstr) (length str))) + str newstr)) + str))) + + ) + +(if (not (fboundp 'read-shell-command)) + (progn + (defvar read-shell-command-map + (let ((map (make-sparse-keymap 'read-shell-command-map))) + (if (eq kde-emacs-type 'xemacs) + (set-keymap-parents map (list minibuffer-local-map)) + (set-keymap-parent map minibuffer-local-map)) + (define-key map "\t" 'comint-dynamic-complete) + (define-key map "\M-\t" 'comint-dynamic-complete) + (define-key map "\M-?" 'comint-dynamic-list-completions) + map) + "Minibuffer keymap used by `shell-command' and related commands.") + (defun read-shell-command (prompt &optional initial-input history default-value) + "Just like read-string, but uses read-shell-command-map: +\\{read-shell-command-map}" + (let ((minibuffer-completion-table nil)) + (read-from-minibuffer prompt initial-input read-shell-command-map + nil (or history 'shell-command-history) + nil default-value))) + )) + +(provide 'kde-emacs-compat) diff --git a/scripts/kde-emacs/kde-emacs-core.el b/scripts/kde-emacs/kde-emacs-core.el new file mode 100644 index 00000000..a954dfa0 --- /dev/null +++ b/scripts/kde-emacs/kde-emacs-core.el @@ -0,0 +1,3823 @@ +;; kde-emacs-core.el - core functionality,e.g. syntax & c++-mode-hook +;; +;; Copyright (C) 2002 KDE Development Team <www.kde.org> +;; +;; This library is free software; you can redistribute it and/or +;; modify it under the terms of the GNU Lesser General Public +;; License as published by the Free Software Foundation; either +;; version 2.1 of the License, or (at your option) any later version. +;; +;; This library is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +;; Lesser General Public License for more details. +;; +;; You should have received a copy of the GNU Lesser General Public +;; License along with this library; if not, write to the Free Software +;; Foundation, Inc., 51 Franklin Steet, Fifth Floor, Boston, MA +;; 02110-1301 USA + +(require 'kde-emacs-vars) +;*---------------------------------------------------------------------*/ +;* Variables ... */ +;*---------------------------------------------------------------------*/ + +(defcustom kde-tab-behavior 'default + "Specifies the current tab behavior. default will expand try to complete +the symbol at point if at the end of something that looks like an indentifier else +it will indent the current line if the pointer is at the beginning of the line it will +be moved the the start of the indention. abbrev-indent behaves like default, but the +cursor isn't moved to the beginning of the indention with tab is pressed when the cursor +is at the beginning of the line. indent simply indents the line without trying to +complete the symbol" + :group 'kde-devel + :version "0.1" + :type `(choice (const default) (const abbrev-indent) (const indent))) + +;*---------------------------------------------------------------------*/ +;* Functions ... */ +;*---------------------------------------------------------------------*/ + + +;; ------- First part, from Arnt's "c++ stuff" - slightly modified for our needs :) + +(defun agulbra-c++-tab (arg) + "Do the right thing about tabs in c++ mode. +Try to finish the symbol, or indent the line." + (interactive "*P") + (cond + ((and (not (looking-at "[A-Za-z0-9]")) + (save-excursion + (forward-char -1) + (looking-at "[A-Za-z0-9:>_\\-\\&\\.(){}\\*\\+/]"))) + (dabbrev-expand arg)) + (t + (if (eq kde-tab-behavior 'default) + (c-indent-command) + (save-excursion + (beginning-of-line) + (c-indent-command)))))) + +(defun agulbra-clean-out-spaces () + "Remove spaces at ends of lines." + (interactive) + (and (not buffer-read-only) + (save-excursion + (goto-char (point-min)) + (let ((count 0) + (bmp (buffer-modified-p))) + (while (re-search-forward "[ \t]+$" nil t) + (setq count (1+ count)) + (replace-match "" t t)) + (set-buffer-modified-p bmp) + nil + )))) + +; the above used to contain (untabify (point-min) (point-max)) too + +(defun agulbra-c++-clean-out-spaces () + "Remove spaces at ends of lines, only in c++ mode." + (interactive) + (if (eq major-mode 'c++-mode) + (agulbra-clean-out-spaces) + ) + ) + +(defun agulbra-delete-into-nomenclature (&optional arg) + "Delete forward until the end of a nomenclature section or word. +With arg, do it arg times." + (interactive "p") + (save-excursion + (let ((b (point-marker))) + (c-forward-into-nomenclature arg) + (delete-region b (point-marker))))) + + +(if (not (fboundp 'font-lock-add-keywords)) + (defun font-lock-add-keywords (mode keywords &optional append) + "XEmacs doesn't have font-lock-add-keywords so we provide it." + (font-lock-set-defaults) + (if (eq append 'set) + (setq font-lock-keywords keywords) + ; NOTE: write this function for XEmacs - Zack + ;(font-lock-remove-keywords nil keywords) ;to avoid duplicates + (let ((old (if (eq (car-safe font-lock-keywords) t) + (cdr font-lock-keywords) + font-lock-keywords))) + (setq font-lock-keywords (if append + (append old keywords) + (append keywords old)))))) + ) + +(c-add-style "kde-c" '("stroustrup" + (c-basic-offset . 4) + (c-offsets-alist + (case-label . 4) + (access-label . -) + (label . 0) + (statement-cont . c-lineup-math) + ))) + +; ( we use Backquote ( '`' ) instead of "'" because we want +; kde-access-labels to be evaluated... ) +(c-add-style "kde-c++" `("kde-c" + ;;FIXME: 1) fume functions not available on GNU/Emacs + ;; 2) insert-tab-mode no longer present (free variable) + ;; 3) c-hangin-commment-under-p no longer present (free variable) + (if (not (eq kde-tab-behavior 'indent)) + (c-tab-always-indent . nil)) + ; (insert-tab-mode nil) + (indent-tabs-mode . nil) + (if (eq kde-emacs-type 'xemacs) + (fume-auto-rescan-buffer-p nil)) + (c-access-key . ,kde-access-labels) + (c-opt-access-key . ,kde-access-labels) + ; (c-hanging-comment-under-p nil) + (c-offsets-alist . ((case-label . 0) + (inline-open . 0))) + )) + +;; KDE C++ mode +;; Not a "(setq c++-mode-hook ..." because this way we would +;; prune all other hooks! +(defun kde-c++-mode-hook () + (font-lock-mode) + (c-set-style kde-c++-style) + (define-key c++-mode-map "\C-m" 'c-context-line-break) + (when (or + (eq kde-tab-behavior 'default) + (eq kde-tab-behavior 'abbrev-indent)) + (define-key c++-mode-map "\C-i" 'agulbra-c++-tab)) + (define-key c++-mode-map "\ef" 'c-forward-into-nomenclature) + (define-key c++-mode-map "\ed" 'agulbra-delete-into-nomenclature) + (define-key c++-mode-map "\eb" 'c-backward-into-nomenclature) + ;; fontify "public|protected|private slots" with one and the same face :) + ;; NOTE: write face-at-point function to fontify those just like other + ;; access specifiers + (font-lock-add-keywords nil '(("\\<\\(\\(public\\|protected\\|private\\) slots\\)\\>" + . font-lock-reference-face))) + ;; Add (setq magic-keys-mode nil) to your .emacs (before loading this file) + ;; to disable the magic keys in C++ mode. + (and (boundp 'magic-keys-mode) magic-keys-mode + (progn + (define-key c++-mode-map "\(" 'insert-parens) + (define-key c++-mode-map "\)" 'insert-parens2) + (define-key c++-mode-map "\," 'insert-comma) + (define-key c++-mode-map "\{" 'insert-curly-brace) + )) + ) + +(defun kde-c-mode-hook () + (font-lock-mode) + (c-set-style kde-c-style)) + +;; NOTE : This is a completely new c-guess-basic-syntax, it's faster, +;; better, meaner, harder, covers more cases, more c++ syntax, +;; and is in general cooler ;) You have to have the new cc-mode +;; to use it ( 5.30 at least, check it with "M-x c-version") +;; If you don't have 5.30 comment out the following c-guess-basic-syntax +;; and uncomment the one underneath. +(cond + ((string-match "^5\\.30\\." c-version) + (defun c-guess-basic-syntax () + "Return the syntactic context of the current line. +This function does not do any hidden buffer changes." + (save-excursion + (save-restriction + (beginning-of-line) + (c-save-buffer-state + ((indent-point (point)) + (case-fold-search nil) + (paren-state (c-parse-state)) + literal containing-sexp char-before-ip char-after-ip lim + c-syntactic-context placeholder c-in-literal-cache step-type + tmpsymbol keyword injava-inher special-brace-list + ;; narrow out any enclosing class or extern "C" block + (inclass-p (c-narrow-out-enclosing-class paren-state + indent-point)) + ;; `c-state-cache' is shadowed here so that we don't + ;; throw it away due to the narrowing that might be done + ;; by the function above. That means we must not do any + ;; changes during the execution of this function, since + ;; `c-invalidate-state-cache' then would change this local + ;; variable and leave a bogus value in the global one. + (c-state-cache (if inclass-p + (c-whack-state-before (point-min) paren-state) + paren-state)) + (c-state-cache-start (point-min)) + inenclosing-p macro-start in-macro-expr + ;; There's always at most one syntactic element which got + ;; a relpos. It's stored in syntactic-relpos. + syntactic-relpos + (c-stmt-delim-chars c-stmt-delim-chars)) + ;; Check for meta top-level enclosing constructs such as + ;; extern language definitions. + (save-excursion + (save-restriction + (widen) + (when (and inclass-p + (progn + (goto-char (aref inclass-p 0)) + (looking-at c-other-decl-block-key))) + (setq inenclosing-p (match-string 1)) + (if (string-equal inenclosing-p "extern") + ;; Compatibility with legacy choice of name for the + ;; extern-lang syntactic symbols. + (setq inenclosing-p "extern-lang"))))) + + ;; Init some position variables: + ;; + ;; containing-sexp is the open paren of the closest + ;; surrounding sexp or nil if there is none that hasn't been + ;; narrowed out. + ;; + ;; lim is the position after the closest preceding brace sexp + ;; (nested sexps are ignored), or the position after + ;; containing-sexp if there is none, or (point-min) if + ;; containing-sexp is nil. + ;; + ;; c-state-cache is the state from c-parse-state at + ;; indent-point, without any parens outside the region + ;; narrowed by c-narrow-out-enclosing-class. + ;; + ;; paren-state is the state from c-parse-state outside + ;; containing-sexp, or at indent-point if containing-sexp is + ;; nil. paren-state is not limited to the narrowed region, as + ;; opposed to c-state-cache. + (if c-state-cache + (progn + (setq containing-sexp (car paren-state) + paren-state (cdr paren-state)) + (if (consp containing-sexp) + (progn + (setq lim (cdr containing-sexp)) + (if (cdr c-state-cache) + ;; Ignore balanced paren. The next entry + ;; can't be another one. + (setq containing-sexp (car (cdr c-state-cache)) + paren-state (cdr paren-state)) + ;; If there is no surrounding open paren then + ;; put the last balanced pair back on paren-state. + (setq paren-state (cons containing-sexp paren-state) + containing-sexp nil))) + (setq lim (1+ containing-sexp)))) + (setq lim (point-min))) + + ;; If we're in a parenthesis list then ',' delimits the + ;; "statements" rather than being an operator (with the + ;; exception of the "for" clause). This difference is + ;; typically only noticeable when statements are used in macro + ;; arglists. + (when (and containing-sexp + (eq (char-after containing-sexp) ?\()) + (setq c-stmt-delim-chars c-stmt-delim-chars-with-comma)) + + ;; cache char before and after indent point, and move point to + ;; the most likely position to perform the majority of tests + (goto-char indent-point) + (c-backward-syntactic-ws lim) + (setq char-before-ip (char-before)) + (goto-char indent-point) + (skip-chars-forward " \t") + (setq char-after-ip (char-after)) + + ;; are we in a literal? + (setq literal (c-in-literal lim)) + + ;; now figure out syntactic qualities of the current line + (cond + ;; CASE 1: in a string. + ((eq literal 'string) + (c-add-syntax 'string (c-point 'bopl))) + ;; CASE 2: in a C or C++ style comment. + ((and (memq literal '(c c++)) + ;; This is a kludge for XEmacs where we use + ;; `buffer-syntactic-context', which doesn't correctly + ;; recognize "\*/" to end a block comment. + ;; `parse-partial-sexp' which is used by + ;; `c-literal-limits' will however do that in most + ;; versions, which results in that we get nil from + ;; `c-literal-limits' even when `c-in-literal' claims + ;; we're inside a comment. + (setq placeholder (c-literal-limits lim))) + (c-add-syntax literal (car placeholder))) + ;; CASE 3: in a cpp preprocessor macro continuation. + ((and (save-excursion + (when (c-beginning-of-macro) + (setq macro-start (point)))) + (/= macro-start (c-point 'boi)) + (progn + (setq tmpsymbol 'cpp-macro-cont) + (or (not c-syntactic-indentation-in-macros) + (save-excursion + (goto-char macro-start) + ;; If at the beginning of the body of a #define + ;; directive then analyze as cpp-define-intro + ;; only. Go on with the syntactic analysis + ;; otherwise. in-macro-expr is set if we're in a + ;; cpp expression, i.e. before the #define body + ;; or anywhere in a non-#define directive. + (if (c-forward-to-cpp-define-body) + (let ((indent-boi (c-point 'boi indent-point))) + (setq in-macro-expr (> (point) indent-boi) + tmpsymbol 'cpp-define-intro) + (= (point) indent-boi)) + (setq in-macro-expr t) + nil))))) + (c-add-syntax tmpsymbol macro-start) + (setq macro-start nil)) + ;; CASE 11: an else clause? + ((looking-at "else\\>[^_]") + (c-beginning-of-statement-1 containing-sexp) + (c-add-stmt-syntax 'else-clause nil t nil + containing-sexp paren-state)) + ;; CASE 12: while closure of a do/while construct? + ((and (looking-at "while\\>[^_]") + (save-excursion + (prog1 (eq (c-beginning-of-statement-1 containing-sexp) + 'beginning) + (setq placeholder (point))))) + (goto-char placeholder) + (c-add-stmt-syntax 'do-while-closure nil t nil + containing-sexp paren-state)) + ;; CASE 13: A catch or finally clause? This case is simpler + ;; than if-else and do-while, because a block is required + ;; after every try, catch and finally. + ((save-excursion + (and (cond ((c-major-mode-is 'c++-mode) + (looking-at "catch\\>[^_]")) + ((c-major-mode-is 'java-mode) + (looking-at "\\(catch\\|finally\\)\\>[^_]"))) + (and (c-safe (c-backward-syntactic-ws) + (c-backward-sexp) + t) + (eq (char-after) ?{) + (c-safe (c-backward-syntactic-ws) + (c-backward-sexp) + t) + (if (eq (char-after) ?\() + (c-safe (c-backward-sexp) t) + t)) + (looking-at "\\(try\\|catch\\)\\>[^_]") + (setq placeholder (point)))) + (goto-char placeholder) + (c-add-stmt-syntax 'catch-clause nil t nil + containing-sexp paren-state)) + ;; CASE 18: A substatement we can recognize by keyword. + ((save-excursion + (and c-opt-block-stmt-key + (if (c-mode-is-new-awk-p) + (c-awk-prev-line-incomplete-p containing-sexp) ; ACM 2002/3/29 + (not (eq char-before-ip ?\;))) + (not (memq char-after-ip '(?\) ?\] ?,))) + (or (not (eq char-before-ip ?})) + (c-looking-at-inexpr-block-backward c-state-cache)) + (> (point) + (progn + ;; Ought to cache the result from the + ;; c-beginning-of-statement-1 calls here. + (setq placeholder (point)) + (while (eq (setq step-type + (c-beginning-of-statement-1 lim)) + 'label)) + (if (eq step-type 'previous) + (goto-char placeholder) + (setq placeholder (point)) + (if (and (eq step-type 'same) + (not (looking-at c-opt-block-stmt-key))) + ;; Step up to the containing statement if we + ;; stayed in the same one. + (let (step) + (while (eq + (setq step + (c-beginning-of-statement-1 lim)) + 'label)) + (if (eq step 'up) + (setq placeholder (point)) + ;; There was no containing statement afterall. + (goto-char placeholder))))) + placeholder)) + (if (looking-at c-block-stmt-2-key) + ;; Require a parenthesis after these keywords. + ;; Necessary to catch e.g. synchronized in Java, + ;; which can be used both as statement and + ;; modifier. + (and (zerop (c-forward-token-2 1 nil)) + (eq (char-after) ?\()) + (looking-at c-opt-block-stmt-key)))) + (if (eq step-type 'up) + ;; CASE 18A: Simple substatement. + (progn + (goto-char placeholder) + (cond + ((eq char-after-ip ?{) + (c-add-stmt-syntax 'substatement-open nil nil nil + containing-sexp paren-state)) + ((save-excursion + (goto-char indent-point) + (back-to-indentation) + (looking-at c-label-key)) + (c-add-stmt-syntax 'substatement-label nil nil nil + containing-sexp paren-state)) + (t + (c-add-stmt-syntax 'substatement nil nil nil + containing-sexp paren-state)))) + ;; CASE 18B: Some other substatement. This is shared + ;; with case 10. + (c-guess-continued-construct indent-point + char-after-ip + placeholder + lim + paren-state))) + ;; CASE 4: In-expression statement. C.f. cases 7B, 16A and + ;; 17E. + ((and (or c-opt-inexpr-class-key + c-opt-inexpr-block-key + c-opt-lambda-key) + (setq placeholder (c-looking-at-inexpr-block + (c-safe-position containing-sexp paren-state) + containing-sexp))) + (setq tmpsymbol (assq (car placeholder) + '((inexpr-class . class-open) + (inexpr-statement . block-open)))) + (if tmpsymbol + ;; It's a statement block or an anonymous class. + (setq tmpsymbol (cdr tmpsymbol)) + ;; It's a Pike lambda. Check whether we are between the + ;; lambda keyword and the argument list or at the defun + ;; opener. + (setq tmpsymbol (if (eq char-after-ip ?{) + 'inline-open + 'lambda-intro-cont))) + (goto-char (cdr placeholder)) + (back-to-indentation) + (c-add-stmt-syntax tmpsymbol nil t nil + (c-most-enclosing-brace c-state-cache (point)) + (c-whack-state-after (point) paren-state)) + (unless (eq (point) (cdr placeholder)) + (c-add-syntax (car placeholder)))) + ;; CASE 5: Line is at top level. + ((null containing-sexp) + (cond + ;; CASE 5A: we are looking at a defun, brace list, class, + ;; or inline-inclass method opening brace + ((setq special-brace-list + (or (and c-special-brace-lists + (c-looking-at-special-brace-list)) + (eq char-after-ip ?{))) + (cond + ;; CASE 5A.1: Non-class declaration block open. + ((save-excursion + (goto-char indent-point) + (skip-chars-forward " \t") + (and (c-safe (c-backward-sexp 2) t) + (looking-at c-other-decl-block-key) + (setq keyword (match-string 1) + placeholder (point)) + (if (string-equal keyword "extern") + ;; Special case for extern-lang-open. The + ;; check for a following string is disabled + ;; since it doesn't disambiguate anything. + (and ;;(progn + ;; (c-forward-sexp 1) + ;; (c-forward-syntactic-ws) + ;; (eq (char-after) ?\")) + (setq tmpsymbol 'extern-lang-open)) + (setq tmpsymbol (intern (concat keyword "-open")))) + )) + (goto-char placeholder) + (c-add-syntax tmpsymbol (c-point 'boi))) + ;; CASE 5A.2: we are looking at a class opening brace + ((save-excursion + (goto-char indent-point) + (skip-chars-forward " \t{") + (let ((decl (c-search-uplist-for-classkey (c-parse-state)))) + (and decl + (setq placeholder (aref decl 0))) + )) + (c-add-syntax 'class-open placeholder)) + ;; CASE 5A.3: brace list open + ((save-excursion + (c-beginning-of-decl-1 lim) + (while (looking-at c-specifier-key) + (goto-char (match-end 1)) + (c-forward-syntactic-ws indent-point)) + (setq placeholder (c-point 'boi)) + (or (consp special-brace-list) + (and (or (save-excursion + (goto-char indent-point) + (setq tmpsymbol nil) + (while (and (> (point) placeholder) + (zerop (c-backward-token-2 1 t)) + (/= (char-after) ?=)) + (and c-opt-inexpr-brace-list-key + (not tmpsymbol) + (looking-at c-opt-inexpr-brace-list-key) + (setq tmpsymbol 'topmost-intro-cont))) + (eq (char-after) ?=)) + (looking-at c-brace-list-key)) + (save-excursion + (while (and (< (point) indent-point) + (zerop (c-forward-token-2 1 t)) + (not (memq (char-after) '(?\; ?\())))) + (not (memq (char-after) '(?\; ?\())) + )))) + (if (and (not c-auto-newline-analysis) + (c-major-mode-is 'java-mode) + (eq tmpsymbol 'topmost-intro-cont)) + ;; We're in Java and have found that the open brace + ;; belongs to a "new Foo[]" initialization list, + ;; which means the brace list is part of an + ;; expression and not a top level definition. We + ;; therefore treat it as any topmost continuation + ;; even though the semantically correct symbol still + ;; is brace-list-open, on the same grounds as in + ;; case B.2. + (progn + (c-beginning-of-statement-1 lim) + (c-add-syntax 'topmost-intro-cont (c-point 'boi))) + (c-add-syntax 'brace-list-open placeholder))) + ;; CASE 5A.4: inline defun open + ((and inclass-p (not inenclosing-p)) + (c-add-syntax 'inline-open) + (c-add-class-syntax 'inclass inclass-p paren-state)) + ;; CASE 5A.5: ordinary defun open + (t + (goto-char placeholder) + (if (or inclass-p macro-start) + (c-add-syntax 'defun-open (c-point 'boi)) + ;; Bogus to use bol here, but it's the legacy. + (c-add-syntax 'defun-open (c-point 'bol))) + ))) + ;; CASE 5B: first K&R arg decl or member init + ((c-just-after-func-arglist-p lim) + (cond + ;; CASE 5B.1: a member init + ((or (eq char-before-ip ?:) + (eq char-after-ip ?:)) + ;; this line should be indented relative to the beginning + ;; of indentation for the topmost-intro line that contains + ;; the prototype's open paren + ;; TBD: is the following redundant? + (if (eq char-before-ip ?:) + (forward-char -1)) + (c-backward-syntactic-ws lim) + ;; TBD: is the preceding redundant? + (if (eq (char-before) ?:) + (progn (forward-char -1) + (c-backward-syntactic-ws lim))) + (if (eq (char-before) ?\)) + (c-backward-sexp 1)) + (setq placeholder (point)) + (save-excursion + (and (c-safe (c-backward-sexp 1) t) + (looking-at "throw[^_]") + (c-safe (c-backward-sexp 1) t) + (setq placeholder (point)))) + (goto-char placeholder) + (c-add-syntax 'member-init-intro (c-point 'boi)) + ;; we don't need to add any class offset since this + ;; should be relative to the ctor's indentation + ) + ;; CASE 5B.2: K&R arg decl intro + (c-recognize-knr-p + (c-beginning-of-statement-1 lim) + (c-add-syntax 'knr-argdecl-intro (c-point 'boi)) + (if inclass-p + (c-add-class-syntax 'inclass inclass-p paren-state))) + ;; CASE 5B.3: Inside a member init list. + ((c-beginning-of-member-init-list lim) + (c-forward-syntactic-ws) + (c-add-syntax 'member-init-cont (point))) + ;; CASE 5B.4: Nether region after a C++ or Java func + ;; decl, which could include a `throws' declaration. + (t + (c-beginning-of-statement-1 lim) + (c-add-syntax 'func-decl-cont (c-point 'boi)) + ))) + ;; CASE 5C: inheritance line. could be first inheritance + ;; line, or continuation of a multiple inheritance + ((or (and (c-major-mode-is 'c++-mode) + (progn + (when (eq char-after-ip ?,) + (skip-chars-forward " \t") + (forward-char)) + (looking-at c-opt-postfix-decl-spec-key))) + (and (or (eq char-before-ip ?:) + ;; watch out for scope operator + (save-excursion + (and (eq char-after-ip ?:) + (c-safe (forward-char 1) t) + (not (eq (char-after) ?:)) + ))) + (save-excursion + (c-backward-syntactic-ws lim) + (if (eq char-before-ip ?:) + (progn + (forward-char -1) + (c-backward-syntactic-ws lim))) + (back-to-indentation) + (looking-at c-class-key))) + ;; for Java + (and (c-major-mode-is 'java-mode) + (let ((fence (save-excursion + (c-beginning-of-statement-1 lim) + (point))) + cont done) + (save-excursion + (while (not done) + (cond ((looking-at c-opt-postfix-decl-spec-key) + (setq injava-inher (cons cont (point)) + done t)) + ((or (not (c-safe (c-forward-sexp -1) t)) + (<= (point) fence)) + (setq done t)) + ) + (setq cont t))) + injava-inher) + (not (c-crosses-statement-barrier-p (cdr injava-inher) + (point))) + )) + (cond + ;; CASE 5C.1: non-hanging colon on an inher intro + ((eq char-after-ip ?:) + (c-beginning-of-statement-1 lim) + (c-add-syntax 'inher-intro (c-point 'boi)) + ;; don't add inclass symbol since relative point already + ;; contains any class offset + ) + ;; CASE 5C.2: hanging colon on an inher intro + ((eq char-before-ip ?:) + (c-beginning-of-statement-1 lim) + (c-add-syntax 'inher-intro (c-point 'boi)) + (if inclass-p + (c-add-class-syntax 'inclass inclass-p paren-state))) + ;; CASE kde hack: + ((and inclass-p + c-access-key + (looking-at c-access-key)) + (c-add-syntax 'access-label (c-point 'bonl)) + (c-add-class-syntax 'inclass inclass-p paren-state) + ) + ;; CASE 5C.3: in a Java implements/extends + (injava-inher + (let ((where (cdr injava-inher)) + (cont (car injava-inher))) + (goto-char where) + (cond ((looking-at "throws\\>[^_]") + (c-add-syntax 'func-decl-cont + (progn (c-beginning-of-statement-1 lim) + (c-point 'boi)))) + (cont (c-add-syntax 'inher-cont where)) + (t (c-add-syntax 'inher-intro + (progn (goto-char (cdr injava-inher)) + (c-beginning-of-statement-1 lim) + (point)))) + ))) + ;; CASE 5C.4: a continued inheritance line + (t + (c-beginning-of-inheritance-list lim) + (c-add-syntax 'inher-cont (point)) + ;; don't add inclass symbol since relative point already + ;; contains any class offset + ))) + ;; CASE 5D: this could be a top-level initialization, a + ;; member init list continuation, or a template argument + ;; list continuation. + ((c-with-syntax-table (if (c-major-mode-is 'c++-mode) + c++-template-syntax-table + (syntax-table)) + (save-excursion + ;; Note: We use the fact that lim is always after any + ;; preceding brace sexp. + (while (and (zerop (c-backward-token-2 1 t lim)) + (not (looking-at "[;<,=]")))) + (or (memq (char-after) '(?, ?=)) + (and (c-major-mode-is 'c++-mode) + (zerop (c-backward-token-2 1 nil lim)) + (eq (char-after) ?<))))) + (goto-char indent-point) + (setq placeholder + (c-beginning-of-member-init-list lim)) + (cond + ;; CASE 5D.1: hanging member init colon, but watch out + ;; for bogus matches on access specifiers inside classes. + ((and placeholder + (save-excursion + (setq placeholder (point)) + (c-backward-token-2 1 t lim) + (and (eq (char-after) ?:) + (not (eq (char-before) ?:)))) + (save-excursion + (goto-char placeholder) + (back-to-indentation) + (or + (/= (car (save-excursion + (parse-partial-sexp (point) placeholder))) + 0) + (and + (if c-opt-access-key + (not (looking-at c-opt-access-key)) t) + (not (looking-at c-class-key)) + (if c-opt-bitfield-key + (not (looking-at c-opt-bitfield-key)) t)) + ))) + (goto-char placeholder) + (c-forward-syntactic-ws) + (c-add-syntax 'member-init-cont (point)) + ;; we do not need to add class offset since relative + ;; point is the member init above us + ) + ;; CASE 5D.2: non-hanging member init colon + ((progn + (c-forward-syntactic-ws indent-point) + (eq (char-after) ?:)) + (skip-chars-forward " \t:") + (c-add-syntax 'member-init-cont (point))) + ;; CASE 5D.3: perhaps a template list continuation? + ((and (c-major-mode-is 'c++-mode) + (save-excursion + (save-restriction + (c-with-syntax-table c++-template-syntax-table + (goto-char indent-point) + (setq placeholder (c-up-list-backward (point))) + (and placeholder + (eq (char-after placeholder) ?<)))))) + ;; we can probably indent it just like an arglist-cont + (goto-char placeholder) + (c-beginning-of-statement-1 lim t) + (c-add-syntax 'template-args-cont (c-point 'boi))) + ;; CASE 5D.4: perhaps a multiple inheritance line? + ((and (c-major-mode-is 'c++-mode) + (save-excursion + (c-beginning-of-statement-1 lim) + (setq placeholder (point)) + (if (looking-at "static\\>[^_]") + (c-forward-token-2 1 nil indent-point)) + (and (looking-at c-class-key) + (zerop (c-forward-token-2 2 nil indent-point)) + (if (eq (char-after) ?<) + (c-with-syntax-table c++-template-syntax-table + (zerop (c-forward-token-2 1 t indent-point))) + t) + (eq (char-after) ?:)))) + (goto-char placeholder) + (c-add-syntax 'inher-cont (c-point 'boi))) + ;; CASE 5D.5: Continuation of the "expression part" of a + ;; top level construct. + (t + (while (and (eq (car (c-beginning-of-decl-1 containing-sexp)) + 'same) + (save-excursion + (c-backward-syntactic-ws) + (eq (char-before) ?})))) + (c-add-stmt-syntax + (if (eq char-before-ip ?,) + ;; A preceding comma at the top level means that a + ;; new variable declaration starts here. Use + ;; topmost-intro-cont for it, for consistency with + ;; the first variable declaration. C.f. case 5N. + 'topmost-intro-cont + 'statement-cont) + nil nil nil containing-sexp paren-state)) + )) + ;; CASE 5E: we are looking at a access specifier + ((and inclass-p + c-opt-access-key + (looking-at c-opt-access-key)) + (setq placeholder (c-add-class-syntax 'inclass inclass-p + paren-state)) + ;; Append access-label with the same anchor point as inclass gets. + (c-append-syntax 'access-label placeholder)) + ;; CASE 5F: Close of a non-class declaration level block. + ((and inenclosing-p + (eq char-after-ip ?})) + (c-add-syntax (intern (concat inenclosing-p "-close")) + (aref inclass-p 0))) + ;; CASE 5G: we are looking at the brace which closes the + ;; enclosing nested class decl + ((and inclass-p + (eq char-after-ip ?}) + (save-excursion + (save-restriction + (widen) + (forward-char 1) + (and (c-safe (c-backward-sexp 1) t) + (= (point) (aref inclass-p 1)) + )))) + (c-add-class-syntax 'class-close inclass-p paren-state)) + ;; CASE 5H: we could be looking at subsequent knr-argdecls + ((and c-recognize-knr-p + (not (eq char-before-ip ?})) + (save-excursion + (setq placeholder (cdr (c-beginning-of-decl-1 lim))) + (and placeholder + ;; Do an extra check to avoid tripping up on + ;; statements that occur in invalid contexts + ;; (e.g. in macro bodies where we don't really + ;; know the context of what we're looking at). + (not (and c-opt-block-stmt-key + (looking-at c-opt-block-stmt-key))))) + (< placeholder indent-point)) + (goto-char placeholder) + (c-add-syntax 'knr-argdecl (point))) + ;; CASE 5I: ObjC method definition. + ((and c-opt-method-key + (looking-at c-opt-method-key)) + (c-beginning-of-statement-1 lim) + (c-add-syntax 'objc-method-intro (c-point 'boi))) + ;; CASE 5P: AWK pattern or function or continuation + ;; thereof. + ((c-mode-is-new-awk-p) + (setq placeholder (point)) + (c-add-stmt-syntax + (if (and (eq (c-beginning-of-statement-1) 'same) + (/= (point) placeholder)) + 'topmost-intro-cont + 'topmost-intro) + nil nil nil + containing-sexp paren-state)) + ;; CASE 5N: At a variable declaration that follows a class + ;; definition or some other block declaration that doesn't + ;; end at the closing '}'. C.f. case 5D.5. + ((progn + (c-backward-syntactic-ws lim) + (and (eq (char-before) ?}) + (save-excursion + (let ((start (point))) + (if paren-state + ;; Speed up the backward search a bit. + (goto-char (car (car paren-state)))) + (c-beginning-of-decl-1 containing-sexp) + (setq placeholder (point)) + (if (= start (point)) + ;; The '}' is unbalanced. + nil + (c-end-of-decl-1) + (>= (point) indent-point)))))) + (goto-char placeholder) + (c-add-stmt-syntax 'topmost-intro-cont nil nil nil + containing-sexp paren-state)) + ;; CASE 5J: we are at the topmost level, make + ;; sure we skip back past any access specifiers + ((progn + (while (and inclass-p + c-opt-access-key + (not (bobp)) + (save-excursion + (c-safe (progn (c-backward-sexp 1) t)) + (and (looking-at "slots:") + (c-backward-sexp 1)) + (looking-at c-opt-access-key))) + (c-backward-sexp 1) + (c-backward-syntactic-ws lim)) + (or (bobp) + (if (c-mode-is-new-awk-p) + (not (c-awk-prev-line-incomplete-p)) + (memq (char-before) '(?\; ?}))) + (and (c-major-mode-is 'objc-mode) + (progn + (c-beginning-of-statement-1 lim) + (eq (char-after) ?@))))) + ;; real beginning-of-line could be narrowed out due to + ;; enclosure in a class block + (save-restriction + (widen) + (c-add-syntax 'topmost-intro (c-point 'bol)) + ;; Using bol instead of boi above is highly bogus, and + ;; it makes our lives hard to remain compatible. :P + (if inclass-p + (progn + (goto-char (aref inclass-p 1)) + (or (= (point) (c-point 'boi)) + (goto-char (aref inclass-p 0))) + (if inenclosing-p + (c-add-syntax (intern (concat "in" inenclosing-p)) + (c-point 'boi)) + (c-add-class-syntax 'inclass inclass-p paren-state)) + )) + (when (and c-syntactic-indentation-in-macros + macro-start + (/= macro-start (c-point 'boi indent-point))) + (c-add-syntax 'cpp-define-intro) + (setq macro-start nil)) + )) + ;; CASE 5K: we are at an ObjC method definition + ;; continuation line. + ((and c-opt-method-key + (progn + (c-beginning-of-statement-1 lim) + (beginning-of-line) + (looking-at c-opt-method-key))) + (c-add-syntax 'objc-method-args-cont (point))) + ;; CASE 5L: we are at the first argument of a template + ;; arglist that begins on the previous line. + ((eq (char-before) ?<) + (c-beginning-of-statement-1 (c-safe-position (point) paren-state)) + (c-add-syntax 'template-args-cont (c-point 'boi))) + ;; CASE 5M: we are at a topmost continuation line + (t + (c-beginning-of-statement-1 (c-safe-position (point) paren-state)) + (c-add-syntax 'topmost-intro-cont (c-point 'boi))) + )) + ;; (CASE 6 has been removed.) + ;; CASE 7: line is an expression, not a statement. Most + ;; likely we are either in a function prototype or a function + ;; call argument list + ((not (or (and c-special-brace-lists + (save-excursion + (goto-char containing-sexp) + (c-looking-at-special-brace-list))) + (eq (char-after containing-sexp) ?{))) + (cond + ;; CASE 7A: we are looking at the arglist closing paren. + ;; C.f. case 7F. + ((memq char-after-ip '(?\) ?\])) + (goto-char containing-sexp) + (setq placeholder (c-point 'boi)) + (if (and (c-safe (backward-up-list 1) t) + (> (point) placeholder)) + (progn + (forward-char) + (skip-chars-forward " \t")) + (goto-char placeholder)) + (c-add-stmt-syntax 'arglist-close (list containing-sexp) t nil + (c-most-enclosing-brace paren-state (point)) + (c-whack-state-after (point) paren-state))) + ;; CASE 7B: Looking at the opening brace of an + ;; in-expression block or brace list. C.f. cases 4, 16A + ;; and 17E. + ((and (eq char-after-ip ?{) + (progn + (setq placeholder (c-inside-bracelist-p (point) + c-state-cache)) + (if placeholder + (setq tmpsymbol '(brace-list-open . inexpr-class)) + (setq tmpsymbol '(block-open . inexpr-statement) + placeholder + (cdr-safe (c-looking-at-inexpr-block + (c-safe-position containing-sexp + paren-state) + containing-sexp))) + ;; placeholder is nil if it's a block directly in + ;; a function arglist. That makes us skip out of + ;; this case. + ))) + (goto-char placeholder) + (back-to-indentation) + (c-add-stmt-syntax (car tmpsymbol) nil t nil + (c-most-enclosing-brace paren-state (point)) + (c-whack-state-after (point) paren-state)) + (if (/= (point) placeholder) + (c-add-syntax (cdr tmpsymbol)))) + ;; CASE 7C: we are looking at the first argument in an empty + ;; argument list. Use arglist-close if we're actually + ;; looking at a close paren or bracket. + ((memq char-before-ip '(?\( ?\[)) + (goto-char containing-sexp) + (setq placeholder (c-point 'boi)) + (when (and (c-safe (backward-up-list 1) t) + (> (point) placeholder)) + (forward-char) + (skip-chars-forward " \t") + (setq placeholder (point))) + (c-add-syntax 'arglist-intro placeholder)) + ;; CASE 7D: we are inside a conditional test clause. treat + ;; these things as statements + ((progn + (goto-char containing-sexp) + (and (c-safe (c-forward-sexp -1) t) + (looking-at "\\<for\\>[^_]"))) + (goto-char (1+ containing-sexp)) + (c-forward-syntactic-ws indent-point) + (if (eq char-before-ip ?\;) + (c-add-syntax 'statement (point)) + (c-add-syntax 'statement-cont (point)) + )) + ;; CASE 7E: maybe a continued ObjC method call. This is the + ;; case when we are inside a [] bracketed exp, and what + ;; precede the opening bracket is not an identifier. + ((and c-opt-method-key + (eq (char-after containing-sexp) ?\[) + (progn + (goto-char (1- containing-sexp)) + (c-backward-syntactic-ws (c-point 'bod)) + (if (not (looking-at c-symbol-key)) + (c-add-syntax 'objc-method-call-cont containing-sexp)) + ))) + ;; CASE 7F: we are looking at an arglist continuation line, + ;; but the preceding argument is on the same line as the + ;; opening paren. This case includes multi-line + ;; mathematical paren groupings, but we could be on a + ;; for-list continuation line. C.f. case 7A. + ((progn + (goto-char (1+ containing-sexp)) + (skip-chars-forward " \t") + (and (not (eolp)) + (not (looking-at "\\\\$")))) + (goto-char containing-sexp) + (setq placeholder (c-point 'boi)) + (if (and (c-safe (backward-up-list 1) t) + (> (point) placeholder)) + (progn + (forward-char) + (skip-chars-forward " \t")) + (goto-char placeholder)) + (c-add-stmt-syntax 'arglist-cont-nonempty (list containing-sexp) + t nil + (c-most-enclosing-brace c-state-cache (point)) + (c-whack-state-after (point) paren-state))) + ;; CASE 7G: we are looking at just a normal arglist + ;; continuation line + (t (c-forward-syntactic-ws indent-point) + (c-add-syntax 'arglist-cont (c-point 'boi))) + )) + ;; CASE 8: func-local multi-inheritance line + ((and (c-major-mode-is 'c++-mode) + (save-excursion + (goto-char indent-point) + (skip-chars-forward " \t") + (looking-at c-opt-postfix-decl-spec-key))) + (goto-char indent-point) + (skip-chars-forward " \t") + (cond + ;; CASE 8A: non-hanging colon on an inher intro + ((eq char-after-ip ?:) + (c-backward-syntactic-ws lim) + (c-add-syntax 'inher-intro (c-point 'boi))) + ;; CASE 8B: hanging colon on an inher intro + ((eq char-before-ip ?:) + (c-add-syntax 'inher-intro (c-point 'boi))) + ;; CASE 8C: a continued inheritance line + (t + (c-beginning-of-inheritance-list lim) + (c-add-syntax 'inher-cont (point)) + ))) + ;; CASE 9: we are inside a brace-list + ((and (not (c-mode-is-new-awk-p)) ; Maybe this isn't needed (ACM, 2002/3/29) + (setq special-brace-list + (or (and c-special-brace-lists + (save-excursion + (goto-char containing-sexp) + (c-looking-at-special-brace-list))) + (c-inside-bracelist-p containing-sexp paren-state)))) + (cond + ;; CASE 9A: In the middle of a special brace list opener. + ((and (consp special-brace-list) + (save-excursion + (goto-char containing-sexp) + (eq (char-after) ?\()) + (eq char-after-ip (car (cdr special-brace-list)))) + (goto-char (car (car special-brace-list))) + (skip-chars-backward " \t") + (if (and (bolp) + (assoc 'statement-cont + (setq placeholder (c-guess-basic-syntax)))) + (setq c-syntactic-context placeholder) + (c-beginning-of-statement-1 + (c-safe-position (1- containing-sexp) paren-state)) + (c-forward-token-2 0) + (while (looking-at c-specifier-key) + (goto-char (match-end 1)) + (c-forward-syntactic-ws)) + (c-add-syntax 'brace-list-open (c-point 'boi)))) + ;; CASE 9B: brace-list-close brace + ((if (consp special-brace-list) + ;; Check special brace list closer. + (progn + (goto-char (car (car special-brace-list))) + (save-excursion + (goto-char indent-point) + (back-to-indentation) + (or + ;; We were between the special close char and the `)'. + (and (eq (char-after) ?\)) + (eq (1+ (point)) (cdr (car special-brace-list)))) + ;; We were before the special close char. + (and (eq (char-after) (cdr (cdr special-brace-list))) + (zerop (c-forward-token-2)) + (eq (1+ (point)) (cdr (car special-brace-list))))))) + ;; Normal brace list check. + (and (eq char-after-ip ?}) + (c-safe (goto-char (c-up-list-backward (point))) t) + (= (point) containing-sexp))) + (if (eq (point) (c-point 'boi)) + (c-add-syntax 'brace-list-close (point)) + (setq lim (c-most-enclosing-brace c-state-cache (point))) + (c-beginning-of-statement-1 lim) + (c-add-stmt-syntax 'brace-list-close nil t t lim + (c-whack-state-after (point) paren-state)))) + (t + ;; Prepare for the rest of the cases below by going to the + ;; token following the opening brace + (if (consp special-brace-list) + (progn + (goto-char (car (car special-brace-list))) + (c-forward-token-2 1 nil indent-point)) + (goto-char containing-sexp)) + (forward-char) + (let ((start (point))) + (c-forward-syntactic-ws indent-point) + (goto-char (max start (c-point 'bol)))) + (c-skip-ws-forward indent-point) + (cond + ;; CASE 9C: we're looking at the first line in a brace-list + ((= (point) indent-point) + (if (consp special-brace-list) + (goto-char (car (car special-brace-list))) + (goto-char containing-sexp)) + (if (eq (point) (c-point 'boi)) + (c-add-syntax 'brace-list-intro (point)) + (setq lim (c-most-enclosing-brace c-state-cache (point))) + (c-beginning-of-statement-1 lim) + (c-add-stmt-syntax 'brace-list-intro nil t t lim + (c-whack-state-after (point) paren-state)))) + ;; CASE 9D: this is just a later brace-list-entry or + ;; brace-entry-open + (t (if (or (eq char-after-ip ?{) + (and c-special-brace-lists + (save-excursion + (goto-char indent-point) + (c-forward-syntactic-ws (c-point 'eol)) + (c-looking-at-special-brace-list (point))))) + (c-add-syntax 'brace-entry-open (point)) + (c-add-syntax 'brace-list-entry (point)) + )) + )))) + ;; CASE 10: A continued statement or top level construct. + ((and (if (c-mode-is-new-awk-p) + (c-awk-prev-line-incomplete-p containing-sexp) ; ACM 2002/3/29 + (and (not (memq char-before-ip '(?\; ?:))) + (or (not (eq char-before-ip ?})) + (c-looking-at-inexpr-block-backward c-state-cache)))) + (> (point) + (save-excursion + (c-beginning-of-statement-1 containing-sexp) + (setq placeholder (point)))) + (/= placeholder containing-sexp)) + ;; This is shared with case 18. + (c-guess-continued-construct indent-point + char-after-ip + placeholder + containing-sexp + paren-state)) + ;; CASE 14: A case or default label + ((looking-at c-label-kwds-regexp) + (goto-char containing-sexp) + (setq lim (c-most-enclosing-brace c-state-cache containing-sexp)) + (c-backward-to-block-anchor lim) + (c-add-stmt-syntax 'case-label nil t nil + lim paren-state)) + ;; CASE 15: any other label + ((looking-at c-label-key) + (goto-char containing-sexp) + (setq lim (c-most-enclosing-brace c-state-cache containing-sexp)) + (save-excursion + (setq tmpsymbol + (if (and (eq (c-beginning-of-statement-1 lim) 'up) + (looking-at "switch\\>[^_]")) + ;; If the surrounding statement is a switch then + ;; let's analyze all labels as switch labels, so + ;; that they get lined up consistently. + 'case-label + 'label))) + (c-backward-to-block-anchor lim) + (c-add-stmt-syntax tmpsymbol nil t nil + lim paren-state)) + ;; CASE 16: block close brace, possibly closing the defun or + ;; the class + ((eq char-after-ip ?}) + ;; From here on we have the next containing sexp in lim. + (setq lim (c-most-enclosing-brace paren-state)) + (goto-char containing-sexp) + (cond + ;; CASE 16E: Closing a statement block? This catches + ;; cases where it's preceded by a statement keyword, + ;; which works even when used in an "invalid" context, + ;; e.g. a macro argument. + ((c-after-conditional) + (c-backward-to-block-anchor lim) + (c-add-stmt-syntax 'block-close nil t nil + lim paren-state)) + ;; CASE 16A: closing a lambda defun or an in-expression + ;; block? C.f. cases 4, 7B and 17E. + ((setq placeholder (c-looking-at-inexpr-block + (c-safe-position containing-sexp paren-state) + nil)) + (setq tmpsymbol (if (eq (car placeholder) 'inlambda) + 'inline-close + 'block-close)) + (goto-char containing-sexp) + (back-to-indentation) + (if (= containing-sexp (point)) + (c-add-syntax tmpsymbol (point)) + (goto-char (cdr placeholder)) + (back-to-indentation) + (c-add-stmt-syntax tmpsymbol nil t nil + (c-most-enclosing-brace paren-state (point)) + (c-whack-state-after (point) paren-state)) + (if (/= (point) (cdr placeholder)) + (c-add-syntax (car placeholder))))) + ;; CASE 16B: does this close an inline or a function in + ;; a non-class declaration level block? + ((setq placeholder (c-search-uplist-for-classkey paren-state)) + (c-backward-to-decl-anchor lim) + (back-to-indentation) + (if (save-excursion + (goto-char (aref placeholder 0)) + (looking-at c-other-decl-block-key)) + (c-add-syntax 'defun-close (point)) + (c-add-syntax 'inline-close (point)))) + ;; CASE 16F: Can be a defun-close of a function declared + ;; in a statement block, e.g. in Pike or when using gcc + ;; extensions. Might also trigger it with some macros + ;; followed by blocks, and this gives sane indentation + ;; then too. Let it through to be handled below. + ;; C.f. cases B.3 and 17G. + ((and (not inenclosing-p) + lim + (save-excursion + (and (not (c-looking-at-bos)) + (eq (c-beginning-of-statement-1 lim nil nil t) 'same) + (setq placeholder (point))))) + (back-to-indentation) + (if (/= (point) containing-sexp) + (goto-char placeholder)) + (c-add-stmt-syntax 'defun-close nil t nil + lim paren-state)) + ;; CASE 16C: if there an enclosing brace that hasn't + ;; been narrowed out by a class, then this is a + ;; block-close. C.f. case 17H. + ((and (not inenclosing-p) lim) + ;; If the block is preceded by a case/switch label on + ;; the same line, we anchor at the first preceding label + ;; at boi. The default handling in c-add-stmt-syntax is + ;; really fixes it better, but we do like this to keep + ;; the indentation compatible with version 5.28 and + ;; earlier. + (while (and (/= (setq placeholder (point)) (c-point 'boi)) + (eq (c-beginning-of-statement-1 lim) 'label))) + (goto-char placeholder) + (if (looking-at c-label-kwds-regexp) + (c-add-syntax 'block-close (point)) + (goto-char containing-sexp) + ;; c-backward-to-block-anchor not necessary here; those + ;; situations are handled in case 16E above. + (c-add-stmt-syntax 'block-close nil t nil + lim paren-state))) + ;; CASE 16D: find out whether we're closing a top-level + ;; class or a defun + (t + (save-restriction + (narrow-to-region (point-min) indent-point) + (let ((decl (c-search-uplist-for-classkey (c-parse-state)))) + (if decl + (c-add-class-syntax 'class-close decl paren-state) + (goto-char containing-sexp) + (c-backward-to-decl-anchor lim) + (back-to-indentation) + (c-add-syntax 'defun-close (point))))) + ))) + ;; CASE 17: Statement or defun catchall. + (t + (goto-char indent-point) + ;; Back up statements until we find one that starts at boi. + (while (let* ((prev-point (point)) + (last-step-type (c-beginning-of-statement-1 + containing-sexp))) + (if (= (point) prev-point) + (progn + (setq step-type (or step-type last-step-type)) + nil) + (setq step-type last-step-type) + (/= (point) (c-point 'boi))))) + (cond + ;; CASE 17B: continued statement + ((and (eq step-type 'same) + (/= (point) indent-point)) + (c-add-stmt-syntax 'statement-cont nil nil nil + containing-sexp paren-state)) + ;; CASE 17A: After a case/default label? + ((progn + (while (and (eq step-type 'label) + (not (looking-at c-label-kwds-regexp))) + (setq step-type + (c-beginning-of-statement-1 containing-sexp))) + (eq step-type 'label)) + (c-add-stmt-syntax (if (eq char-after-ip ?{) + 'statement-case-open + 'statement-case-intro) + nil t nil containing-sexp paren-state)) + ;; CASE 17D: any old statement + ((progn + (while (eq step-type 'label) + (setq step-type + (c-beginning-of-statement-1 containing-sexp))) + (eq step-type 'previous)) + (c-add-stmt-syntax 'statement nil t nil + containing-sexp paren-state) + (if (eq char-after-ip ?{) + (c-add-syntax 'block-open))) + ;; CASE 17I: Inside a substatement block. + ((progn + ;; The following tests are all based on containing-sexp. + (goto-char containing-sexp) + ;; From here on we have the next containing sexp in lim. + (setq lim (c-most-enclosing-brace paren-state containing-sexp)) + (c-after-conditional)) + (c-backward-to-block-anchor lim) + (c-add-stmt-syntax 'statement-block-intro nil t nil + lim paren-state) + (if (eq char-after-ip ?{) + (c-add-syntax 'block-open))) + ;; CASE 17E: first statement in an in-expression block. + ;; C.f. cases 4, 7B and 16A. + ((setq placeholder (c-looking-at-inexpr-block + (c-safe-position containing-sexp paren-state) + nil)) + (setq tmpsymbol (if (eq (car placeholder) 'inlambda) + 'defun-block-intro + 'statement-block-intro)) + (back-to-indentation) + (if (= containing-sexp (point)) + (c-add-syntax tmpsymbol (point)) + (goto-char (cdr placeholder)) + (back-to-indentation) + (c-add-stmt-syntax tmpsymbol nil t nil + (c-most-enclosing-brace c-state-cache (point)) + (c-whack-state-after (point) paren-state)) + (if (/= (point) (cdr placeholder)) + (c-add-syntax (car placeholder)))) + (if (eq char-after-ip ?{) + (c-add-syntax 'block-open))) + ;; CASE 17F: first statement in an inline, or first + ;; statement in a top-level defun. we can tell this is it + ;; if there are no enclosing braces that haven't been + ;; narrowed out by a class (i.e. don't use bod here). + ((save-excursion + (save-restriction + (widen) + (c-narrow-out-enclosing-class paren-state containing-sexp) + (not (c-most-enclosing-brace paren-state)))) + (c-backward-to-decl-anchor lim) + (back-to-indentation) + (c-add-syntax 'defun-block-intro (point))) + ;; CASE 17G: First statement in a function declared inside + ;; a normal block. This can occur in Pike and with + ;; e.g. the gcc extensions. Might also trigger it with + ;; some macros followed by blocks, and this gives sane + ;; indentation then too. C.f. cases B.3 and 16F. + ((save-excursion + (and (not (c-looking-at-bos)) + (eq (c-beginning-of-statement-1 lim nil nil t) 'same) + (setq placeholder (point)))) + (back-to-indentation) + (if (/= (point) containing-sexp) + (goto-char placeholder)) + (c-add-stmt-syntax 'defun-block-intro nil t nil + lim paren-state)) + ;; CASE 17H: First statement in a block. C.f. case 16C. + (t + ;; If the block is preceded by a case/switch label on the + ;; same line, we anchor at the first preceding label at + ;; boi. The default handling in c-add-stmt-syntax is + ;; really fixes it better, but we do like this to keep the + ;; indentation compatible with version 5.28 and earlier. + (while (and (/= (setq placeholder (point)) (c-point 'boi)) + (eq (c-beginning-of-statement-1 lim) 'label))) + (goto-char placeholder) + (if (looking-at c-label-kwds-regexp) + (c-add-syntax 'statement-block-intro (point)) + (goto-char containing-sexp) + ;; c-backward-to-block-anchor not necessary here; those + ;; situations are handled in case 17I above. + (c-add-stmt-syntax 'statement-block-intro nil t nil + lim paren-state)) + (if (eq char-after-ip ?{) + (c-add-syntax 'block-open))) + )) + ) + ;; now we need to look at any modifiers + (goto-char indent-point) + (skip-chars-forward " \t") + ;; are we looking at a comment only line? + (when (and (looking-at c-comment-start-regexp) + (/= (c-forward-token-2 0 nil (c-point 'eol)) 0)) + (c-append-syntax 'comment-intro)) + ;; we might want to give additional offset to friends (in C++). + (when (and c-opt-friend-key + (looking-at c-opt-friend-key)) + (c-append-syntax 'friend)) + + ;; Set syntactic-relpos. + (let ((p c-syntactic-context)) + (while (and p + (if (integerp (car-safe (cdr-safe (car p)))) + (progn + (setq syntactic-relpos (car (cdr (car p)))) + nil) + t)) + (setq p (cdr p)))) + + ;; Start of or a continuation of a preprocessor directive? + (if (and macro-start + (eq macro-start (c-point 'boi)) + (not (and (c-major-mode-is 'pike-mode) + (eq (char-after (1+ macro-start)) ?\")))) + (c-append-syntax 'cpp-macro) + (when (and c-syntactic-indentation-in-macros macro-start) + (if in-macro-expr + (when (or + (< syntactic-relpos macro-start) + (not (or + (assq 'arglist-intro c-syntactic-context) + (assq 'arglist-cont c-syntactic-context) + (assq 'arglist-cont-nonempty c-syntactic-context) + (assq 'arglist-close c-syntactic-context)))) + ;; If inside a cpp expression, i.e. anywhere in a + ;; cpp directive except a #define body, we only let + ;; through the syntactic analysis that is internal + ;; in the expression. That means the arglist + ;; elements, if they are anchored inside the cpp + ;; expression. + (setq c-syntactic-context nil) + (c-add-syntax 'cpp-macro-cont macro-start)) + (when (and (eq macro-start syntactic-relpos) + (not (assq 'cpp-define-intro c-syntactic-context)) + (save-excursion + (goto-char macro-start) + (or (not (c-forward-to-cpp-define-body)) + (<= (point) (c-point 'boi indent-point))))) + ;; Inside a #define body and the syntactic analysis is + ;; anchored on the start of the #define. In this case + ;; we add cpp-define-intro to get the extra + ;; indentation of the #define body. + (c-add-syntax 'cpp-define-intro))))) + ;; return the syntax + c-syntactic-context))))) + ((>= (string-to-number c-version) 5.29) + (defun c-guess-basic-syntax () + "Return the syntactic context of the current line." + (save-excursion + (save-restriction + (beginning-of-line) + (let* ((indent-point (point)) + (case-fold-search nil) + (paren-state (c-parse-state)) + literal containing-sexp char-before-ip char-after-ip lim + syntax placeholder c-in-literal-cache step-type + tmpsymbol keyword injava-inher special-brace-list + ;; narrow out any enclosing class or extern "C" block + (inclass-p (c-narrow-out-enclosing-class paren-state + indent-point)) + ;; c-state-cache is shadowed here. That means we must + ;; not do any changes during the execution of this + ;; function, since c-check-state-cache then would change + ;; this local variable and leave a bogus value in the + ;; global one. + (c-state-cache (if inclass-p + (c-whack-state-before (point-min) paren-state) + paren-state)) + (c-state-cache-start (point-min)) + inenclosing-p macro-start in-macro-expr + ;; There's always at most one syntactic element which got + ;; a relpos. It's stored in syntactic-relpos. + syntactic-relpos + (c-stmt-delim-chars c-stmt-delim-chars)) + ;; check for meta top-level enclosing constructs, possible + ;; extern language definitions, possibly (in C++) namespace + ;; definitions. + (save-excursion + (save-restriction + (widen) + (if (and inclass-p + (progn + (goto-char (aref inclass-p 0)) + (looking-at c-other-decl-block-key))) + (let ((enclosing (match-string 1))) + (cond + ((string-equal enclosing "extern") + (setq inenclosing-p 'extern)) + ((string-equal enclosing "namespace") + (setq inenclosing-p 'namespace)) + ))))) + + ;; Init some position variables: + ;; + ;; containing-sexp is the open paren of the closest + ;; surrounding sexp or nil if there is none that hasn't been + ;; narrowed out. + ;; + ;; lim is the position after the closest preceding brace sexp + ;; (nested sexps are ignored), or the position after + ;; containing-sexp if there is none, or (point-min) if + ;; containing-sexp is nil. + ;; + ;; c-state-cache is the state from c-parse-state at + ;; indent-point, without any parens outside the region + ;; narrowed by c-narrow-out-enclosing-class. + ;; + ;; paren-state is the state from c-parse-state outside + ;; containing-sexp, or at indent-point if containing-sexp is + ;; nil. paren-state is not limited to the narrowed region, as + ;; opposed to c-state-cache. + (if c-state-cache + (progn + (setq containing-sexp (car paren-state) + paren-state (cdr paren-state)) + (if (consp containing-sexp) + (progn + (setq lim (cdr containing-sexp)) + (if (cdr c-state-cache) + ;; Ignore balanced paren. The next entry + ;; can't be another one. + (setq containing-sexp (car (cdr c-state-cache)) + paren-state (cdr paren-state)) + ;; If there is no surrounding open paren then + ;; put the last balanced pair back on paren-state. + (setq paren-state (cons containing-sexp paren-state) + containing-sexp nil))) + (setq lim (1+ containing-sexp)))) + (setq lim (point-min))) + + ;; If we're in a parenthesis list then ',' delimits the + ;; "statements" rather than being an operator (with the + ;; exception of the "for" clause). This difference is + ;; typically only noticeable when statements are used in macro + ;; arglists. + (when (and containing-sexp + (eq (char-after containing-sexp) ?\()) + (setq c-stmt-delim-chars c-stmt-delim-chars-with-comma)) + + ;; cache char before and after indent point, and move point to + ;; the most likely position to perform the majority of tests + (goto-char indent-point) + (c-backward-syntactic-ws lim) + (setq char-before-ip (char-before)) + (goto-char indent-point) + (skip-chars-forward " \t") + (setq char-after-ip (char-after)) + + ;; are we in a literal? + (setq literal (c-in-literal lim)) + + ;; now figure out syntactic qualities of the current line + (cond + ;; CASE 1: in a string. + ((eq literal 'string) + (c-add-syntax 'string (c-point 'bopl))) + ;; CASE 2: in a C or C++ style comment. + ((memq literal '(c c++)) + (c-add-syntax literal (car (c-literal-limits lim)))) + ;; CASE 3: in a cpp preprocessor macro continuation. + ((and (save-excursion + (when (c-beginning-of-macro) + (setq macro-start (point)))) + (/= macro-start (c-point 'boi)) + (progn + (setq tmpsymbol 'cpp-macro-cont) + (or (not c-syntactic-indentation-in-macros) + (save-excursion + (goto-char macro-start) + ;; If at the beginning of the body of a #define + ;; directive then analyze as cpp-define-intro + ;; only. Go on with the syntactic analysis + ;; otherwise. in-macro-expr is set if we're in a + ;; cpp expression, i.e. before the #define body + ;; or anywhere in a non-#define directive. + (if (c-forward-to-cpp-define-body) + (let ((indent-boi (c-point 'boi indent-point))) + (setq in-macro-expr (> (point) indent-boi) + tmpsymbol 'cpp-define-intro) + (= (point) indent-boi)) + (setq in-macro-expr t) + nil))))) + (c-add-syntax tmpsymbol macro-start) + (setq macro-start nil)) + ;; CASE 11: an else clause? + ((looking-at "else\\>[^_]") + (c-beginning-of-statement-1 containing-sexp) + (c-add-stmt-syntax 'else-clause t containing-sexp paren-state)) + ;; CASE 12: while closure of a do/while construct? + ((and (looking-at "while\\>[^_]") + (save-excursion + (prog1 (eq (c-beginning-of-statement-1 containing-sexp) + 'beginning) + (setq placeholder (point))))) + (goto-char placeholder) + (c-add-stmt-syntax 'do-while-closure t containing-sexp paren-state)) + ;; CASE 13: A catch or finally clause? This case is simpler + ;; than if-else and do-while, because a block is required + ;; after every try, catch and finally. + ((save-excursion + (and (cond ((c-major-mode-is 'c++-mode) + (looking-at "catch\\>[^_]")) + ((c-major-mode-is 'java-mode) + (looking-at "\\(catch\\|finally\\)\\>[^_]"))) + (and (c-safe (c-backward-syntactic-ws) + (c-backward-sexp) + t) + (eq (char-after) ?{) + (c-safe (c-backward-syntactic-ws) + (c-backward-sexp) + t) + (if (eq (char-after) ?\() + (c-safe (c-backward-sexp) t) + t)) + (looking-at "\\(try\\|catch\\)\\>[^_]") + (setq placeholder (point)))) + (goto-char placeholder) + (c-add-stmt-syntax 'catch-clause t containing-sexp paren-state)) + ;; CASE 18: A substatement we can recognize by keyword. + ((save-excursion + (and c-opt-block-stmt-key + (not (eq char-before-ip ?\;)) + (not (memq char-after-ip '(?\) ?\] ?,))) + (or (not (eq char-before-ip ?})) + (c-looking-at-inexpr-block-backward c-state-cache)) + (> (point) + (progn + ;; Ought to cache the result from the + ;; c-beginning-of-statement-1 calls here. + (setq placeholder (point)) + (while (eq (setq step-type + (c-beginning-of-statement-1 lim)) + 'label)) + (if (eq step-type 'previous) + (goto-char placeholder) + (setq placeholder (point)) + (if (and (eq step-type 'same) + (not (looking-at c-opt-block-stmt-key))) + ;; Step up to the containing statement if we + ;; stayed in the same one. + (let (step) + (while (eq + (setq step + (c-beginning-of-statement-1 lim)) + 'label)) + (if (eq step 'up) + (setq placeholder (point)) + ;; There was no containing statement afterall. + (goto-char placeholder))))) + placeholder)) + (if (looking-at c-block-stmt-2-key) + ;; Require a parenthesis after these keywords. + ;; Necessary to catch e.g. synchronized in Java, + ;; which can be used both as statement and + ;; modifier. + (and (= (c-forward-token-1 1 nil) 0) + (eq (char-after) ?\()) + (looking-at c-opt-block-stmt-key)))) + (if (eq step-type 'up) + ;; CASE 18A: Simple substatement. + (progn + (goto-char placeholder) + (cond + ((eq char-after-ip ?{) + (c-add-stmt-syntax 'substatement-open nil + containing-sexp paren-state)) + ((save-excursion + (goto-char indent-point) + (back-to-indentation) + (looking-at c-label-key)) + (c-add-stmt-syntax 'substatement-label nil + containing-sexp paren-state)) + (t + (c-add-stmt-syntax 'substatement nil + containing-sexp paren-state)))) + ;; CASE 18B: Some other substatement. This is shared + ;; with case 10. + (c-guess-continued-construct indent-point + char-after-ip + placeholder + lim + paren-state))) + ;; CASE 4: In-expression statement. C.f. cases 7B, 16A and + ;; 17E. + ((and (or c-opt-inexpr-class-key + c-opt-inexpr-block-key + c-opt-lambda-key) + (setq placeholder (c-looking-at-inexpr-block + (c-safe-position containing-sexp paren-state) + containing-sexp))) + (setq tmpsymbol (assq (car placeholder) + '((inexpr-class . class-open) + (inexpr-statement . block-open)))) + (if tmpsymbol + ;; It's a statement block or an anonymous class. + (setq tmpsymbol (cdr tmpsymbol)) + ;; It's a Pike lambda. Check whether we are between the + ;; lambda keyword and the argument list or at the defun + ;; opener. + (setq tmpsymbol (if (eq char-after-ip ?{) + 'inline-open + 'lambda-intro-cont))) + (goto-char (cdr placeholder)) + (back-to-indentation) + (c-add-stmt-syntax tmpsymbol t + (c-most-enclosing-brace c-state-cache (point)) + (c-whack-state-after (point) paren-state)) + (unless (eq (point) (cdr placeholder)) + (c-add-syntax (car placeholder)))) + ;; CASE 5: Line is at top level. + ((null containing-sexp) + (cond + ;; CASE 5A: we are looking at a defun, brace list, class, + ;; or inline-inclass method opening brace + ((setq special-brace-list + (or (and c-special-brace-lists + (c-looking-at-special-brace-list)) + (eq char-after-ip ?{))) + (cond + ;; CASE 5A.1: extern language or namespace construct + ((save-excursion + (goto-char indent-point) + (skip-chars-forward " \t") + (and (c-safe (progn (c-backward-sexp 2) t)) + (looking-at c-other-decl-block-key) + (setq keyword (match-string 1) + placeholder (point)) + (or (and (string-equal keyword "namespace") + (setq tmpsymbol 'namespace-open)) + (and (string-equal keyword "extern") + (progn + (c-forward-sexp 1) + (c-forward-syntactic-ws) + (eq (char-after) ?\")) + (setq tmpsymbol 'extern-lang-open))) + )) + (goto-char placeholder) + (c-add-syntax tmpsymbol (c-point 'boi))) + ;; CASE 5A.2: we are looking at a class opening brace + ((save-excursion + (goto-char indent-point) + (skip-chars-forward " \t{") + (let ((decl (c-search-uplist-for-classkey (c-parse-state)))) + (and decl + (setq placeholder (aref decl 0))) + )) + (c-add-syntax 'class-open placeholder)) + ;; CASE 5A.3: brace list open + ((save-excursion + (c-beginning-of-decl-1 lim) + (if (looking-at "typedef\\>[^_]") + (progn (c-forward-sexp 1) + (c-forward-syntactic-ws indent-point))) + (setq placeholder (c-point 'boi)) + (or (consp special-brace-list) + (and (or (save-excursion + (goto-char indent-point) + (setq tmpsymbol nil) + (while (and (> (point) placeholder) + (= (c-backward-token-1 1 t) 0) + (/= (char-after) ?=)) + (if (and (not tmpsymbol) + (looking-at "new\\>[^_]")) + (setq tmpsymbol 'topmost-intro-cont))) + (eq (char-after) ?=)) + (looking-at "enum\\>[^_]")) + (save-excursion + (while (and (< (point) indent-point) + (= (c-forward-token-1 1 t) 0) + (not (memq (char-after) '(?\; ?\())))) + (not (memq (char-after) '(?\; ?\())) + )))) + (if (and (c-major-mode-is 'java-mode) + (eq tmpsymbol 'topmost-intro-cont)) + ;; We're in Java and have found that the open brace + ;; belongs to a "new Foo[]" initialization list, + ;; which means the brace list is part of an + ;; expression and not a top level definition. We + ;; therefore treat it as any topmost continuation + ;; even though the semantically correct symbol still + ;; is brace-list-open, on the same grounds as in + ;; case 10B.2. + (progn + (c-beginning-of-statement-1 lim) + (c-add-syntax 'topmost-intro-cont (c-point 'boi))) + (c-add-syntax 'brace-list-open placeholder))) + ;; CASE 5A.4: inline defun open + ((and inclass-p (not inenclosing-p)) + (c-add-syntax 'inline-open) + (c-add-class-syntax 'inclass inclass-p paren-state)) + ;; CASE 5A.5: ordinary defun open + (t + (goto-char placeholder) + (if (or inclass-p macro-start) + (c-add-syntax 'defun-open (c-point 'boi)) + ;; Bogus to use bol here, but it's the legacy. + (c-add-syntax 'defun-open (c-point 'bol))) + ))) + ;; CASE 5B: first K&R arg decl or member init + ((c-just-after-func-arglist-p nil lim) + (cond + ;; CASE 5B.1: a member init + ((or (eq char-before-ip ?:) + (eq char-after-ip ?:)) + ;; this line should be indented relative to the beginning + ;; of indentation for the topmost-intro line that contains + ;; the prototype's open paren + ;; TBD: is the following redundant? + (if (eq char-before-ip ?:) + (forward-char -1)) + (c-backward-syntactic-ws lim) + ;; TBD: is the preceding redundant? + (if (eq (char-before) ?:) + (progn (forward-char -1) + (c-backward-syntactic-ws lim))) + (if (eq (char-before) ?\)) + (c-backward-sexp 1)) + (setq placeholder (point)) + (save-excursion + (and (c-safe (c-backward-sexp 1) t) + (looking-at "throw[^_]") + (c-safe (c-backward-sexp 1) t) + (setq placeholder (point)))) + (goto-char placeholder) + (c-add-syntax 'member-init-intro (c-point 'boi)) + ;; we don't need to add any class offset since this + ;; should be relative to the ctor's indentation + ) + ;; CASE 5B.2: K&R arg decl intro + (c-recognize-knr-p + (c-beginning-of-statement-1 lim) + (c-add-syntax 'knr-argdecl-intro (c-point 'boi)) + (if inclass-p + (c-add-class-syntax 'inclass inclass-p paren-state))) + ;; CASE 5B.3: Inside a member init list. + ((c-beginning-of-member-init-list lim) + (c-forward-syntactic-ws) + (c-add-syntax 'member-init-cont (point))) + ;; CASE 5B.4: Nether region after a C++ or Java func + ;; decl, which could include a `throws' declaration. + (t + (c-beginning-of-statement-1 lim) + (c-add-syntax 'func-decl-cont (c-point 'boi)) + ))) + ;; CASE 5C: inheritance line. could be first inheritance + ;; line, or continuation of a multiple inheritance + ((or (and (c-major-mode-is 'c++-mode) + (progn + (when (eq char-after-ip ?,) + (skip-chars-forward " \t") + (forward-char)) + (looking-at c-opt-decl-spec-key))) + (and (or (eq char-before-ip ?:) + ;; watch out for scope operator + (save-excursion + (and (eq char-after-ip ?:) + (c-safe (progn (forward-char 1) t)) + (not (eq (char-after) ?:)) + ))) + (save-excursion + (c-backward-syntactic-ws lim) + (if (eq char-before-ip ?:) + (progn + (forward-char -1) + (c-backward-syntactic-ws lim))) + (back-to-indentation) + (looking-at c-class-key))) + ;; for Java + (and (c-major-mode-is 'java-mode) + (let ((fence (save-excursion + (c-beginning-of-statement-1 lim) + (point))) + cont done) + (save-excursion + (while (not done) + (cond ((looking-at c-opt-decl-spec-key) + (setq injava-inher (cons cont (point)) + done t)) + ((or (not (c-safe (c-forward-sexp -1) t)) + (<= (point) fence)) + (setq done t)) + ) + (setq cont t))) + injava-inher) + (not (c-crosses-statement-barrier-p (cdr injava-inher) + (point))) + )) + (cond + ;; CASE 5C.1: non-hanging colon on an inher intro + ((eq char-after-ip ?:) + (c-beginning-of-statement-1 lim) + (c-add-syntax 'inher-intro (c-point 'boi)) + ;; don't add inclass symbol since relative point already + ;; contains any class offset + ) + ;; CASE 5C.2: hanging colon on an inher intro + ((eq char-before-ip ?:) + (c-beginning-of-statement-1 lim) + (c-add-syntax 'inher-intro (c-point 'boi)) + (if inclass-p + (c-add-class-syntax 'inclass inclass-p paren-state))) + ;; KDE Hack Start: + ((and inclass-p + c-access-key + (looking-at c-access-key)) + (c-add-syntax 'access-label (c-point 'bonl)) + (setq placeholder (c-add-class-syntax 'inclass inclass-p + paren-state))) + ;;(nconc syntax (list (cons 'access-label placeholder)))) + ;; KDE Hack End. + ;; CASE 5C.3: in a Java implements/extends + (injava-inher + (let ((where (cdr injava-inher)) + (cont (car injava-inher))) + (goto-char where) + (cond ((looking-at "throws\\>[^_]") + (c-add-syntax 'func-decl-cont + (progn (c-beginning-of-statement-1 lim) + (c-point 'boi)))) + (cont (c-add-syntax 'inher-cont where)) + (t (c-add-syntax 'inher-intro + (progn (goto-char (cdr injava-inher)) + (c-beginning-of-statement-1 lim) + (point)))) + ))) + ;; CASE 5C.4: a continued inheritance line + (t + (c-beginning-of-inheritance-list lim) + (c-add-syntax 'inher-cont (point)) + ;; don't add inclass symbol since relative point already + ;; contains any class offset + ))) + ;; CASE 5D: this could be a top-level initialization, a + ;; member init list continuation, or a template argument + ;; list continuation. + ((c-with-syntax-table (if (c-major-mode-is 'c++-mode) + c++-template-syntax-table + (syntax-table)) + (save-excursion + ;; Note: We use the fact that lim is always after any + ;; preceding brace sexp. + (while (and (= (c-backward-token-1 1 t lim) 0) + (not (looking-at "[;<,=]")))) + (or (memq (char-after) '(?, ?=)) + (and (c-major-mode-is 'c++-mode) + (= (c-backward-token-1 1 nil lim) 0) + (eq (char-after) ?<))))) + (goto-char indent-point) + (c-beginning-of-member-init-list lim) + (cond + ;; CASE 5D.1: hanging member init colon, but watch out + ;; for bogus matches on access specifiers inside classes. + ((and (save-excursion + (setq placeholder (point)) + (c-backward-token-1 1 t lim) + (and (eq (char-after) ?:) + (not (eq (char-before) ?:)))) + (save-excursion + (goto-char placeholder) + (back-to-indentation) + (or + (/= (car (save-excursion + (parse-partial-sexp (point) placeholder))) + 0) + (and + (if c-opt-access-key + (not (looking-at c-opt-access-key)) t) + (not (looking-at c-class-key)) + (if c-opt-bitfield-key + (not (looking-at c-opt-bitfield-key)) t)) + ))) + (goto-char placeholder) + (c-forward-syntactic-ws) + (c-add-syntax 'member-init-cont (point)) + ;; we do not need to add class offset since relative + ;; point is the member init above us + ) + ;; CASE 5D.2: non-hanging member init colon + ((progn + (c-forward-syntactic-ws indent-point) + (eq (char-after) ?:)) + (skip-chars-forward " \t:") + (c-add-syntax 'member-init-cont (point))) + ;; CASE 5D.3: perhaps a template list continuation? + ((and (c-major-mode-is 'c++-mode) + (save-excursion + (save-restriction + (c-with-syntax-table c++-template-syntax-table + (goto-char indent-point) + (setq placeholder (c-up-list-backward (point))) + (and placeholder + (eq (char-after placeholder) ?<)))))) + ;; we can probably indent it just like an arglist-cont + (goto-char placeholder) + (c-beginning-of-statement-1 lim t) + (c-add-syntax 'template-args-cont (c-point 'boi))) + ;; CASE 5D.4: perhaps a multiple inheritance line? + ((and (c-major-mode-is 'c++-mode) + (save-excursion + (c-beginning-of-statement-1 lim) + (setq placeholder (point)) + (if (looking-at "static\\>[^_]") + (c-forward-token-1 1 nil indent-point)) + (and (looking-at c-class-key) + (= (c-forward-token-1 2 nil indent-point) 0) + (if (eq (char-after) ?<) + (c-with-syntax-table c++-template-syntax-table + (= (c-forward-token-1 1 t indent-point) 0)) + t) + (eq (char-after) ?:)))) + (goto-char placeholder) + (c-add-syntax 'inher-cont (c-point 'boi))) + ;; CASE 5D.5: Continuation of the "expression part" of a + ;; top level construct. + (t + (while (and (eq (car (c-beginning-of-decl-1 containing-sexp)) + 'same) + (save-excursion + (c-backward-syntactic-ws) + (eq (char-before) ?})))) + (c-add-stmt-syntax + (if (eq char-before-ip ?,) + ;; A preceding comma at the top level means that a + ;; new variable declaration starts here. Use + ;; topmost-intro-cont for it, for consistency with + ;; the first variable declaration. C.f. case 5N. + 'topmost-intro-cont + 'statement-cont) + nil containing-sexp paren-state)) + )) + ;; CASE 5E: we are looking at a access specifier + ((and inclass-p + c-opt-access-key + (looking-at c-opt-access-key)) + (setq placeholder (c-add-class-syntax 'inclass inclass-p + paren-state)) + ;; Append access-label with the same anchor point as inclass gets. + (nconc syntax (list (cons 'access-label placeholder)))) + ;; CASE 5F: extern-lang-close or namespace-close? + ((and inenclosing-p + (eq char-after-ip ?})) + (setq tmpsymbol (if (eq inenclosing-p 'extern) + 'extern-lang-close + 'namespace-close)) + (c-add-syntax tmpsymbol (aref inclass-p 0))) + ;; CASE 5G: we are looking at the brace which closes the + ;; enclosing nested class decl + ((and inclass-p + (eq char-after-ip ?}) + (save-excursion + (save-restriction + (widen) + (forward-char 1) + (and (c-safe (progn (c-backward-sexp 1) t)) + (= (point) (aref inclass-p 1)) + )))) + (c-add-class-syntax 'class-close inclass-p paren-state)) + ;; CASE 5H: we could be looking at subsequent knr-argdecls + ((and c-recognize-knr-p + (not (eq char-before-ip ?})) + (save-excursion + (setq placeholder (cdr (c-beginning-of-decl-1 lim))) + (and placeholder + ;; Do an extra check to avoid tripping up on + ;; statements that occur in invalid contexts + ;; (e.g. in macro bodies where we don't really + ;; know the context of what we're looking at). + (not (and c-opt-block-stmt-key + (looking-at c-opt-block-stmt-key))))) + (< placeholder indent-point)) + (goto-char placeholder) + (c-add-syntax 'knr-argdecl (point))) + ;; CASE 5I: ObjC method definition. + ((and c-opt-method-key + (looking-at c-opt-method-key)) + (c-beginning-of-statement-1 lim) + (c-add-syntax 'objc-method-intro (c-point 'boi))) + ;; CASE 5N: At a variable declaration that follows a class + ;; definition or some other block declaration that doesn't + ;; end at the closing '}'. C.f. case 5D.5. + ((progn + (c-backward-syntactic-ws lim) + (and (eq (char-before) ?}) + (save-excursion + (let ((start (point))) + (if paren-state + ;; Speed up the backward search a bit. + (goto-char (car (car paren-state)))) + (c-beginning-of-decl-1 containing-sexp) + (setq placeholder (point)) + (if (= start (point)) + ;; The '}' is unbalanced. + nil + (c-end-of-decl-1) + (> (point) indent-point)))))) + (goto-char placeholder) + (c-add-stmt-syntax 'topmost-intro-cont nil + containing-sexp paren-state)) + ;; CASE 5J: we are at the topmost level, make + ;; sure we skip back past any access specifiers + ((progn + (while (and inclass-p + c-opt-access-key + (not (bobp)) + (save-excursion + (c-safe (progn (c-backward-sexp 1) t)) + (and (looking-at "slots:") + (c-backward-sexp 1)) + (looking-at c-opt-access-key))) + (c-backward-sexp 1) + (c-backward-syntactic-ws lim)) + (or (bobp) + (memq (char-before) '(?\; ?})) + (and (c-major-mode-is 'objc-mode) + (progn + (c-beginning-of-statement-1 lim) + (eq (char-after) ?@))))) + ;; real beginning-of-line could be narrowed out due to + ;; enclosure in a class block + (save-restriction + (widen) + (c-add-syntax 'topmost-intro (c-point 'bol)) + ;; Using bol instead of boi above is highly bogus, and + ;; it makes our lives hard to remain compatible. :P + (if inclass-p + (progn + (goto-char (aref inclass-p 1)) + (or (= (point) (c-point 'boi)) + (goto-char (aref inclass-p 0))) + (cond + ((eq inenclosing-p 'extern) + (c-add-syntax 'inextern-lang (c-point 'boi))) + ((eq inenclosing-p 'namespace) + (c-add-syntax 'innamespace (c-point 'boi))) + (t (c-add-class-syntax 'inclass inclass-p paren-state))) + )) + (when (and c-syntactic-indentation-in-macros + macro-start + (/= macro-start (c-point 'boi indent-point))) + (c-add-syntax 'cpp-define-intro) + (setq macro-start nil)) + )) + ;; CASE 5K: we are at an ObjC method definition + ;; continuation line. + ((and c-opt-method-key + (progn + (c-beginning-of-statement-1 lim) + (beginning-of-line) + (looking-at c-opt-method-key))) + (c-add-syntax 'objc-method-args-cont (point))) + ;; CASE 5L: we are at the first argument of a template + ;; arglist that begins on the previous line. + ((eq (char-before) ?<) + (c-beginning-of-statement-1 (c-safe-position (point) paren-state)) + (c-add-syntax 'template-args-cont (c-point 'boi))) + ;; CASE 5M: we are at a topmost continuation line + ;; KDE Hack 2 + ;; NOTE: is there a way to detect these sooner ? + (t + (c-beginning-of-statement-1 (c-safe-position (point) paren-state)) + (if (re-search-forward c-access-key (point-at-eol) t) + (progn + (c-add-syntax 'topmost-intro (c-point 'bol)) + (c-add-class-syntax 'inclass inclass-p paren-state) + ) + (progn + (c-add-syntax 'topmost-intro-cont (c-point 'boi)) + )) + ) + )) + ;; (CASE 6 has been removed.) + ;; CASE 7: line is an expression, not a statement. Most + ;; likely we are either in a function prototype or a function + ;; call argument list + ((not (or (and c-special-brace-lists + (save-excursion + (goto-char containing-sexp) + (c-looking-at-special-brace-list))) + (eq (char-after containing-sexp) ?{))) + (cond + ;; CASE 7A: we are looking at the arglist closing paren + ((memq char-after-ip '(?\) ?\])) + (goto-char containing-sexp) + (setq placeholder (c-point 'boi)) + (when (and (c-safe (backward-up-list 1) t) + (> (point) placeholder)) + (forward-char) + (skip-chars-forward " \t") + (setq placeholder (point))) + (c-add-syntax 'arglist-close placeholder)) + ;; CASE 7B: Looking at the opening brace of an + ;; in-expression block or brace list. C.f. cases 4, 16A + ;; and 17E. + ((and (eq char-after-ip ?{) + (progn + (setq placeholder (c-inside-bracelist-p (point) + c-state-cache)) + (if placeholder + (setq tmpsymbol '(brace-list-open . inexpr-class)) + (setq tmpsymbol '(block-open . inexpr-statement) + placeholder + (cdr-safe (c-looking-at-inexpr-block + (c-safe-position containing-sexp + paren-state) + containing-sexp))) + ;; placeholder is nil if it's a block directly in + ;; a function arglist. That makes us skip out of + ;; this case. + ))) + (goto-char placeholder) + (back-to-indentation) + (c-add-stmt-syntax (car tmpsymbol) t + (c-most-enclosing-brace paren-state (point)) + (c-whack-state-after (point) paren-state)) + (if (/= (point) placeholder) + (c-add-syntax (cdr tmpsymbol)))) + ;; CASE 7C: we are looking at the first argument in an empty + ;; argument list. Use arglist-close if we're actually + ;; looking at a close paren or bracket. + ((memq char-before-ip '(?\( ?\[)) + (goto-char containing-sexp) + (setq placeholder (c-point 'boi)) + (when (and (c-safe (backward-up-list 1) t) + (> (point) placeholder)) + (forward-char) + (skip-chars-forward " \t") + (setq placeholder (point))) + (c-add-syntax 'arglist-intro placeholder)) + ;; CASE 7D: we are inside a conditional test clause. treat + ;; these things as statements + ((progn + (goto-char containing-sexp) + (and (c-safe (progn (c-forward-sexp -1) t)) + (looking-at "\\<for\\>[^_]"))) + (goto-char (1+ containing-sexp)) + (c-forward-syntactic-ws indent-point) + (if (eq char-before-ip ?\;) + (c-add-syntax 'statement (point)) + (c-add-syntax 'statement-cont (point)) + )) + ;; CASE 7E: maybe a continued ObjC method call. This is the + ;; case when we are inside a [] bracketed exp, and what + ;; precede the opening bracket is not an identifier. + ((and c-opt-method-key + (eq (char-after containing-sexp) ?\[) + (progn + (goto-char (1- containing-sexp)) + (c-backward-syntactic-ws (c-point 'bod)) + (if (not (looking-at c-symbol-key)) + (c-add-syntax 'objc-method-call-cont containing-sexp)) + ))) + ;; CASE 7F: we are looking at an arglist continuation line, + ;; but the preceding argument is on the same line as the + ;; opening paren. This case includes multi-line + ;; mathematical paren groupings, but we could be on a + ;; for-list continuation line + ((progn + (goto-char (1+ containing-sexp)) + (skip-chars-forward " \t") + (and (not (eolp)) + (not (looking-at "\\\\$")))) + (goto-char containing-sexp) + (setq placeholder (c-point 'boi)) + (when (and (c-safe (backward-up-list 1) t) + (> (point) placeholder)) + (forward-char) + (skip-chars-forward " \t") + (setq placeholder (point))) + (c-add-syntax 'arglist-cont-nonempty placeholder)) + ;; CASE 7G: we are looking at just a normal arglist + ;; continuation line + (t (c-forward-syntactic-ws indent-point) + (c-add-syntax 'arglist-cont (c-point 'boi))) + )) + ;; CASE 8: func-local multi-inheritance line + ((and (c-major-mode-is 'c++-mode) + (save-excursion + (goto-char indent-point) + (skip-chars-forward " \t") + (looking-at c-opt-decl-spec-key))) + (goto-char indent-point) + (skip-chars-forward " \t") + (cond + ;; CASE 8A: non-hanging colon on an inher intro + ((eq char-after-ip ?:) + (c-backward-syntactic-ws lim) + (c-add-syntax 'inher-intro (c-point 'boi))) + ;; CASE 8B: hanging colon on an inher intro + ((eq char-before-ip ?:) + (c-add-syntax 'inher-intro (c-point 'boi))) + ;; CASE 8C: a continued inheritance line + (t + (c-beginning-of-inheritance-list lim) + (c-add-syntax 'inher-cont (point)) + ))) + ;; CASE 9: we are inside a brace-list + ((setq special-brace-list + (or (and c-special-brace-lists + (save-excursion + (goto-char containing-sexp) + (c-looking-at-special-brace-list))) + (c-inside-bracelist-p containing-sexp paren-state))) + (cond + ;; CASE 9A: In the middle of a special brace list opener. + ((and (consp special-brace-list) + (save-excursion + (goto-char containing-sexp) + (eq (char-after) ?\()) + (eq char-after-ip (car (cdr special-brace-list)))) + (goto-char (car (car special-brace-list))) + (skip-chars-backward " \t") + (if (and (bolp) + (assoc 'statement-cont + (setq placeholder (c-guess-basic-syntax)))) + (setq syntax placeholder) + (c-beginning-of-statement-1 + (c-safe-position (1- containing-sexp) paren-state)) + (c-forward-token-1 0) + (if (looking-at "typedef\\>[^_]") (c-forward-token-1 1)) + (c-add-syntax 'brace-list-open (c-point 'boi)))) + ;; CASE 9B: brace-list-close brace + ((if (consp special-brace-list) + ;; Check special brace list closer. + (progn + (goto-char (car (car special-brace-list))) + (save-excursion + (goto-char indent-point) + (back-to-indentation) + (or + ;; We were between the special close char and the `)'. + (and (eq (char-after) ?\)) + (eq (1+ (point)) (cdr (car special-brace-list)))) + ;; We were before the special close char. + (and (eq (char-after) (cdr (cdr special-brace-list))) + (= (c-forward-token-1) 0) + (eq (1+ (point)) (cdr (car special-brace-list))))))) + ;; Normal brace list check. + (and (eq char-after-ip ?}) + (c-safe (progn (goto-char (c-up-list-backward (point))) + t)) + (= (point) containing-sexp))) + (if (eq (point) (c-point 'boi)) + (c-add-syntax 'brace-list-close (point)) + (setq lim (c-most-enclosing-brace c-state-cache (point))) + (c-beginning-of-statement-1 lim) + (c-add-stmt-syntax 'brace-list-close t lim + (c-whack-state-after (point) paren-state) + t))) + (t + ;; Prepare for the rest of the cases below by going to the + ;; token following the opening brace + (if (consp special-brace-list) + (progn + (goto-char (car (car special-brace-list))) + (c-forward-token-1 1 nil indent-point)) + (goto-char containing-sexp)) + (forward-char) + (let ((start (point))) + (c-forward-syntactic-ws indent-point) + (goto-char (max start (c-point 'bol)))) + (c-skip-ws-forward indent-point) + (cond + ;; CASE 9C: we're looking at the first line in a brace-list + ((= (point) indent-point) + (if (consp special-brace-list) + (goto-char (car (car special-brace-list))) + (goto-char containing-sexp)) + (if (eq (point) (c-point 'boi)) + (c-add-syntax 'brace-list-intro (point)) + (setq lim (c-most-enclosing-brace c-state-cache (point))) + (c-beginning-of-statement-1 lim) + (c-add-stmt-syntax 'brace-list-intro t lim + (c-whack-state-after (point) paren-state) + t))) + ;; CASE 9D: this is just a later brace-list-entry or + ;; brace-entry-open + (t (if (or (eq char-after-ip ?{) + (and c-special-brace-lists + (save-excursion + (goto-char indent-point) + (c-forward-syntactic-ws (c-point 'eol)) + (c-looking-at-special-brace-list (point))))) + (c-add-syntax 'brace-entry-open (point)) + (c-add-syntax 'brace-list-entry (point)) + )) + )))) + ;; CASE 10: A continued statement or top level construct. + ((and (not (memq char-before-ip '(?\; ?:))) + (or (not (eq char-before-ip ?})) + (c-looking-at-inexpr-block-backward c-state-cache)) + (> (point) + (save-excursion + (c-beginning-of-statement-1 containing-sexp) + (setq placeholder (point)))) + (/= placeholder containing-sexp)) + ;; This is shared with case 18. + (c-guess-continued-construct indent-point + char-after-ip + placeholder + containing-sexp + paren-state)) + ;; CASE 14: A case or default label + ((looking-at c-label-kwds-regexp) + (goto-char containing-sexp) + (setq lim (c-most-enclosing-brace c-state-cache containing-sexp)) + (c-backward-to-block-anchor lim) + (c-add-stmt-syntax 'case-label t lim paren-state)) + ;; CASE 15: any other label + ((looking-at c-label-key) + (goto-char containing-sexp) + (setq lim (c-most-enclosing-brace c-state-cache containing-sexp)) + (save-excursion + (setq tmpsymbol + (if (and (eq (c-beginning-of-statement-1 lim) 'up) + (looking-at "switch\\>[^_]")) + ;; If the surrounding statement is a switch then + ;; let's analyze all labels as switch labels, so + ;; that they get lined up consistently. + 'case-label + 'label))) + (c-backward-to-block-anchor lim) + (c-add-stmt-syntax tmpsymbol t lim paren-state)) + ;; CASE 16: block close brace, possibly closing the defun or + ;; the class + ((eq char-after-ip ?}) + ;; From here on we have the next containing sexp in lim. + (setq lim (c-most-enclosing-brace paren-state)) + (goto-char containing-sexp) + (cond + ;; CASE 16E: Closing a statement block? This catches + ;; cases where it's preceded by a statement keyword, + ;; which works even when used in an "invalid" context, + ;; e.g. a macro argument. + ((c-after-conditional) + (c-backward-to-block-anchor lim) + (c-add-stmt-syntax 'block-close t lim paren-state)) + ;; CASE 16A: closing a lambda defun or an in-expression + ;; block? C.f. cases 4, 7B and 17E. + ((setq placeholder (c-looking-at-inexpr-block + (c-safe-position containing-sexp paren-state) + nil)) + (setq tmpsymbol (if (eq (car placeholder) 'inlambda) + 'inline-close + 'block-close)) + (goto-char containing-sexp) + (back-to-indentation) + (if (= containing-sexp (point)) + (c-add-syntax tmpsymbol (point)) + (goto-char (cdr placeholder)) + (back-to-indentation) + (c-add-stmt-syntax tmpsymbol t + (c-most-enclosing-brace paren-state (point)) + (c-whack-state-after (point) paren-state)) + (if (/= (point) (cdr placeholder)) + (c-add-syntax (car placeholder))))) + ;; CASE 16B: does this close an inline or a function in + ;; an extern block or namespace? + ((setq placeholder (c-search-uplist-for-classkey paren-state)) + (c-backward-to-decl-anchor lim) + (back-to-indentation) + (if (save-excursion + (goto-char (aref placeholder 0)) + (looking-at c-other-decl-block-key)) + (c-add-syntax 'defun-close (point)) + (c-add-syntax 'inline-close (point)))) + ;; CASE 16F: Can be a defun-close of a function declared + ;; in a statement block, e.g. in Pike or when using gcc + ;; extensions. Might also trigger it with some macros + ;; followed by blocks, and this gives sane indentation + ;; then too. Let it through to be handled below. + ;; C.f. cases B.3 and 17G. + ((and (not inenclosing-p) + lim + (save-excursion + (and (not (c-looking-at-bos)) + (eq (c-beginning-of-statement-1 lim nil nil t) 'same) + (setq placeholder (point))))) + (back-to-indentation) + (if (/= (point) containing-sexp) + (goto-char placeholder)) + (c-add-stmt-syntax 'defun-close t lim paren-state)) + ;; CASE 16C: if there an enclosing brace that hasn't + ;; been narrowed out by a class, then this is a + ;; block-close. C.f. case 17H. + ((and (not inenclosing-p) lim) + ;; If the block is preceded by a case/switch label on + ;; the same line, we anchor at the first preceding label + ;; at boi. The default handling in c-add-stmt-syntax is + ;; really fixes it better, but we do like this to keep + ;; the indentation compatible with version 5.28 and + ;; earlier. + (while (and (/= (setq placeholder (point)) (c-point 'boi)) + (eq (c-beginning-of-statement-1 lim) 'label))) + (goto-char placeholder) + (if (looking-at c-label-kwds-regexp) + (c-add-syntax 'block-close (point)) + (goto-char containing-sexp) + ;; c-backward-to-block-anchor not necessary here; those + ;; situations are handled in case 16E above. + (c-add-stmt-syntax 'block-close t lim paren-state))) + ;; CASE 16D: find out whether we're closing a top-level + ;; class or a defun + (t + (save-restriction + (narrow-to-region (point-min) indent-point) + (let ((decl (c-search-uplist-for-classkey (c-parse-state)))) + (if decl + (c-add-class-syntax 'class-close decl paren-state) + (goto-char containing-sexp) + (c-backward-to-decl-anchor lim) + (back-to-indentation) + (c-add-syntax 'defun-close (point))))) + ))) + ;; CASE 17: Statement or defun catchall. + (t + (goto-char indent-point) + ;; Back up statements until we find one that starts at boi. + (while (let* ((prev-point (point)) + (last-step-type (c-beginning-of-statement-1 + containing-sexp))) + (if (= (point) prev-point) + (progn + (setq step-type (or step-type last-step-type)) + nil) + (setq step-type last-step-type) + (/= (point) (c-point 'boi))))) + (cond + ;; CASE 17B: continued statement + ((and (eq step-type 'same) + (/= (point) indent-point)) + (c-add-stmt-syntax 'statement-cont nil + containing-sexp paren-state)) + ;; CASE 17A: After a case/default label? + ((progn + (while (and (eq step-type 'label) + (not (looking-at c-label-kwds-regexp))) + (setq step-type + (c-beginning-of-statement-1 containing-sexp))) + (eq step-type 'label)) + (c-add-stmt-syntax (if (eq char-after-ip ?{) + 'statement-case-open + 'statement-case-intro) + t containing-sexp paren-state)) + ;; CASE 17D: any old statement + ((progn + (while (eq step-type 'label) + (setq step-type + (c-beginning-of-statement-1 containing-sexp))) + (eq step-type 'previous)) + (c-add-stmt-syntax 'statement t containing-sexp paren-state) + (if (eq char-after-ip ?{) + (c-add-syntax 'block-open))) + ;; CASE 17I: Inside a substatement block. + ((progn + ;; The following tests are all based on containing-sexp. + (goto-char containing-sexp) + ;; From here on we have the next containing sexp in lim. + (setq lim (c-most-enclosing-brace paren-state containing-sexp)) + (c-after-conditional)) + (c-backward-to-block-anchor lim) + (c-add-stmt-syntax 'statement-block-intro t lim paren-state) + (if (eq char-after-ip ?{) + (c-add-syntax 'block-open))) + ;; CASE 17E: first statement in an in-expression block. + ;; C.f. cases 4, 7B and 16A. + ((setq placeholder (c-looking-at-inexpr-block + (c-safe-position containing-sexp paren-state) + nil)) + (setq tmpsymbol (if (eq (car placeholder) 'inlambda) + 'defun-block-intro + 'statement-block-intro)) + (back-to-indentation) + (if (= containing-sexp (point)) + (c-add-syntax tmpsymbol (point)) + (goto-char (cdr placeholder)) + (back-to-indentation) + (c-add-stmt-syntax tmpsymbol t + (c-most-enclosing-brace c-state-cache (point)) + (c-whack-state-after (point) paren-state)) + (if (/= (point) (cdr placeholder)) + (c-add-syntax (car placeholder)))) + (if (eq char-after-ip ?{) + (c-add-syntax 'block-open))) + ;; CASE 17F: first statement in an inline, or first + ;; statement in a top-level defun. we can tell this is it + ;; if there are no enclosing braces that haven't been + ;; narrowed out by a class (i.e. don't use bod here). + ;; However, we first check for statements that we can + ;; recognize by keywords. That increases the robustness in + ;; cases where statements are used on the top level, + ;; e.g. in macro definitions. + ((save-excursion + (save-restriction + (widen) + (c-narrow-out-enclosing-class paren-state containing-sexp) + (not (c-most-enclosing-brace paren-state)))) + (c-backward-to-decl-anchor lim) + (back-to-indentation) + (c-add-syntax 'defun-block-intro (point))) + ;; CASE 17G: First statement in a function declared inside + ;; a normal block. This can occur in Pike and with + ;; e.g. the gcc extensions. Might also trigger it with + ;; some macros followed by blocks, and this gives sane + ;; indentation then too. C.f. cases B.3 and 16F. + ((save-excursion + (and (not (c-looking-at-bos)) + (eq (c-beginning-of-statement-1 lim nil nil t) 'same) + (setq placeholder (point)))) + (back-to-indentation) + (if (/= (point) containing-sexp) + (goto-char placeholder)) + (c-add-stmt-syntax 'defun-block-intro t lim paren-state)) + ;; CASE 17H: First statement in a block. C.f. case 16C. + (t + ;; If the block is preceded by a case/switch label on the + ;; same line, we anchor at the first preceding label at + ;; boi. The default handling in c-add-stmt-syntax is + ;; really fixes it better, but we do like this to keep the + ;; indentation compatible with version 5.28 and earlier. + (while (and (/= (setq placeholder (point)) (c-point 'boi)) + (eq (c-beginning-of-statement-1 lim) 'label))) + (goto-char placeholder) + (if (looking-at c-label-kwds-regexp) + (c-add-syntax 'statement-block-intro (point)) + (goto-char containing-sexp) + ;; c-backward-to-block-anchor not necessary here; those + ;; situations are handled in case 17I above. + (c-add-stmt-syntax 'statement-block-intro t lim paren-state)) + (if (eq char-after-ip ?{) + (c-add-syntax 'block-open))) + )) + ) + ;; now we need to look at any modifiers + (goto-char indent-point) + (skip-chars-forward " \t") + ;; are we looking at a comment only line? + (when (and (looking-at c-comment-start-regexp) + (/= (c-forward-token-1 0 nil (c-point 'eol)) 0)) + (c-add-syntax 'comment-intro)) + ;; we might want to give additional offset to friends (in C++). + (when (and c-opt-friend-key + (looking-at c-opt-friend-key)) + (c-add-syntax 'friend)) + ;; Start of or a continuation of a preprocessor directive? + (if (and macro-start + (eq macro-start (c-point 'boi)) + (not (and (c-major-mode-is 'pike-mode) + (eq (char-after (1+ macro-start)) ?\")))) + (c-add-syntax 'cpp-macro) + (when (and c-syntactic-indentation-in-macros macro-start) + (if in-macro-expr + (when (or (< syntactic-relpos macro-start) + (not (or (assq 'arglist-intro syntax) + (assq 'arglist-cont syntax) + (assq 'arglist-cont-nonempty syntax) + (assq 'arglist-close syntax)))) + ;; If inside a cpp expression, i.e. anywhere in a + ;; cpp directive except a #define body, we only let + ;; through the syntactic analysis that is internal + ;; in the expression. That means the arglist + ;; elements, if they are anchored inside the cpp + ;; expression. + (setq syntax `((cpp-macro-cont . ,macro-start)))) + (when (and (eq macro-start syntactic-relpos) + (not (assq 'cpp-define-intro syntax)) + (save-excursion + (goto-char macro-start) + (or (not (c-forward-to-cpp-define-body)) + (<= (point) (c-point 'boi indent-point))))) + ;; Inside a #define body and the syntactic analysis is + ;; anchored on the start of the #define. In this case + ;; we add cpp-define-intro to get the extra + ;; indentation of the #define body. + (c-add-syntax 'cpp-define-intro))))) + ;; return the syntax + syntax))))) + ((defun c-guess-basic-syntax () + (save-excursion + (save-restriction + (beginning-of-line) + (let* ((indent-point (point)) + (case-fold-search nil) + (fullstate (c-parse-state)) + (state fullstate) + literal containing-sexp char-before-ip char-after-ip lim + syntax placeholder c-in-literal-cache inswitch-p + tmpsymbol keyword injava-inher special-brace-list + ;; narrow out any enclosing class or extern "C" block + (inclass-p (c-narrow-out-enclosing-class state indent-point)) + inenclosing-p) + ;; check for meta top-level enclosing constructs, possible + ;; extern language definitions, possibly (in C++) namespace + ;; definitions. + (save-excursion + (save-restriction + (widen) + (if (and inclass-p + (progn + (goto-char (aref inclass-p 0)) + (looking-at (concat c-extra-toplevel-key "[^_]")))) + (let ((enclosing (match-string 1))) + (cond + ((string-equal enclosing "extern") + (setq inenclosing-p 'extern)) + ((string-equal enclosing "namespace") + (setq inenclosing-p 'namespace)) + ))))) + ;; get the buffer position of the most nested opening brace, + ;; if there is one, and it hasn't been narrowed out + (save-excursion + (goto-char indent-point) + (skip-chars-forward " \t}") + (skip-chars-backward " \t") + (while (and state + (not containing-sexp)) + (setq containing-sexp (car state) + state (cdr state)) + (if (consp containing-sexp) + ;; if cdr == point, then containing sexp is the brace + ;; that opens the sexp we close + (if (= (cdr containing-sexp) (point)) + (setq containing-sexp (car containing-sexp)) + ;; otherwise, ignore this element + (setq containing-sexp nil)) + ;; ignore the bufpos if its been narrowed out by the + ;; containing class or does not contain the indent point + (if (or (<= containing-sexp (point-min)) + (>= containing-sexp indent-point)) + (setq containing-sexp nil))))) + ;; (imenu "agulbra-c++-tab") + ;; set the limit on the farthest back we need to search + (setq lim (or containing-sexp + (if (consp (car fullstate)) + (cdr (car fullstate)) + nil) + (point-min))) + + ;; cache char before and after indent point, and move point to + ;; the most likely position to perform the majority of tests + (goto-char indent-point) + (skip-chars-forward " \t") + (setq char-after-ip (char-after)) + (c-backward-syntactic-ws lim) + (setq char-before-ip (char-before)) + (goto-char indent-point) + (skip-chars-forward " \t") + + ;; are we in a literal? + (setq literal (c-in-literal lim)) + + ;; now figure out syntactic qualities of the current line + (cond + ;; CASE 1: in a string. + ((memq literal '(string)) + (c-add-syntax 'string (c-point 'bopl))) + ;; CASE 2: in a C or C++ style comment. + ((memq literal '(c c++)) + (c-add-syntax literal (car (c-literal-limits lim)))) + ;; CASE 3: in a cpp preprocessor macro continuation. + ((and (eq literal 'pound) + (/= (save-excursion + (c-beginning-of-macro lim) + (setq placeholder (point))) + (c-point 'boi))) + (c-add-syntax 'cpp-macro-cont placeholder)) + ;; CASE 4: In-expression statement. + ((and (or c-inexpr-class-key c-inexpr-block-key c-lambda-key) + (setq placeholder (c-looking-at-inexpr-block))) + (setq tmpsymbol (assq (car placeholder) + '((inexpr-class . class-open) + (inexpr-statement . block-open)))) + (if tmpsymbol + ;; It's a statement block or an anonymous class. + (setq tmpsymbol (cdr tmpsymbol)) + ;; It's a Pike lambda. Check whether we are between the + ;; lambda keyword and the argument list or at the defun + ;; opener. + (setq tmpsymbol (if (eq char-after-ip ?{) + 'inline-open + 'lambda-intro-cont))) + (goto-char (cdr placeholder)) + (back-to-indentation) + (c-add-syntax tmpsymbol (point)) + (unless (eq (point) (cdr placeholder)) + (c-add-syntax (car placeholder)))) + ;; CASE 5: Line is at top level. + ((null containing-sexp) + (cond + ;; CASE 5A: we are looking at a defun, brace list, class, + ;; or inline-inclass method opening brace + ((setq special-brace-list + (or (and c-special-brace-lists + (c-looking-at-special-brace-list)) + (eq char-after-ip ?{))) + (cond + ;; CASE 5A.1: extern language or namespace construct + ((save-excursion + (goto-char indent-point) + (skip-chars-forward " \t") + (and (c-safe (progn (c-backward-sexp 2) t)) + (looking-at (concat c-extra-toplevel-key "[^_]")) + (setq keyword (match-string 1) + placeholder (point)) + (or (and (string-equal keyword "namespace") + (setq tmpsymbol 'namespace-open)) + (and (string-equal keyword "extern") + (progn + (c-forward-sexp 1) + (c-forward-syntactic-ws) + (eq (char-after) ?\")) + (setq tmpsymbol 'extern-lang-open))) + )) + (goto-char placeholder) + (c-add-syntax tmpsymbol (c-point 'boi))) + ;; CASE 5A.2: we are looking at a class opening brace + ((save-excursion + (goto-char indent-point) + (skip-chars-forward " \t{") + ;; TBD: watch out! there could be a bogus + ;; c-state-cache in place when we get here. we have + ;; to go through much chicanery to ignore the cache. + ;; But of course, there may not be! BLECH! BOGUS! + (let ((decl + (let ((c-state-cache nil)) + (c-search-uplist-for-classkey (c-parse-state)) + ))) + (and decl + (setq placeholder (aref decl 0))) + )) + (c-add-syntax 'class-open placeholder)) + ;; CASE 5A.3: brace list open + ((save-excursion + (c-beginning-of-statement-1 lim) + ;; c-b-o-s could have left us at point-min + (and (bobp) + (c-forward-syntactic-ws indent-point)) + (if (looking-at "typedef[^_]") + (progn (c-forward-sexp 1) + (c-forward-syntactic-ws indent-point))) + (setq placeholder (c-point 'boi)) + (or (consp special-brace-list) + (and (or (save-excursion + (goto-char indent-point) + (setq tmpsymbol nil) + (while (and (> (point) placeholder) + (= (c-backward-token-1 1 t) 0) + (/= (char-after) ?=)) + (if (and (not tmpsymbol) + (looking-at "new\\>[^_]")) + (setq tmpsymbol 'topmost-intro-cont))) + (eq (char-after) ?=)) + (looking-at "enum[ \t\n]+")) + (save-excursion + (while (and (< (point) indent-point) + (= (c-forward-token-1 1 t) 0) + (not (memq (char-after) '(?\; ?\())))) + (not (memq (char-after) '(?\; ?\())) + )))) + (if (and (c-major-mode-is 'java-mode) + (eq tmpsymbol 'topmost-intro-cont)) + ;; We're in Java and have found that the open brace + ;; belongs to a "new Foo[]" initialization list, + ;; which means the brace list is part of an + ;; expression and not a top level definition. We + ;; therefore treat it as any topmost continuation + ;; even though the semantically correct symbol still + ;; is brace-list-open, on the same grounds as in + ;; case 10B.2. + (progn + (c-beginning-of-statement-1 lim) + (c-forward-syntactic-ws) + (c-add-syntax 'topmost-intro-cont (c-point 'boi))) + (c-add-syntax 'brace-list-open placeholder))) + ;; CASE 5A.4: inline defun open + ((and inclass-p (not inenclosing-p)) + (c-add-syntax 'inline-open) + (c-add-class-syntax 'inclass inclass-p)) + ;; CASE 5A.5: ordinary defun open + (t + (goto-char placeholder) + (if inclass-p + (c-add-syntax 'defun-open (c-point 'boi)) + (c-add-syntax 'defun-open (c-point 'bol))) + ))) + ;; CASE 5B: first K&R arg decl or member init + ((c-just-after-func-arglist-p) + (cond + ;; CASE 5B.1: a member init + ((or (eq char-before-ip ?:) + (eq char-after-ip ?:)) + ;; this line should be indented relative to the beginning + ;; of indentation for the topmost-intro line that contains + ;; the prototype's open paren + ;; TBD: is the following redundant? + (if (eq char-before-ip ?:) + (forward-char -1)) + (c-backward-syntactic-ws lim) + ;; TBD: is the preceding redundant? + (if (eq (char-before) ?:) + (progn (forward-char -1) + (c-backward-syntactic-ws lim))) + (if (eq (char-before) ?\)) + (c-backward-sexp 1)) + (setq placeholder (point)) + (save-excursion + (and (c-safe (c-backward-sexp 1) t) + (looking-at "throw[^_]") + (c-safe (c-backward-sexp 1) t) + (setq placeholder (point)))) + (goto-char placeholder) + (c-add-syntax 'member-init-intro (c-point 'boi)) + ;; we don't need to add any class offset since this + ;; should be relative to the ctor's indentation + ) + ;; CASE 5B.2: K&R arg decl intro + (c-recognize-knr-p + (c-add-syntax 'knr-argdecl-intro (c-point 'boi)) + (if inclass-p (c-add-class-syntax 'inclass inclass-p))) + ;; CASE 5B.3: Inside a member init list. + ((c-beginning-of-member-init-list lim) + (c-forward-syntactic-ws) + (c-add-syntax 'member-init-cont (point))) + ;; CASE 5B.4: Nether region after a C++ or Java func + ;; decl, which could include a `throws' declaration. + (t + (c-beginning-of-statement-1 lim) + (c-add-syntax 'func-decl-cont (c-point 'boi)) + ))) + ;; CASE 5C: inheritance line. could be first inheritance + ;; line, or continuation of a multiple inheritance + ((or (and c-baseclass-key + (progn + (when (eq char-after-ip ?,) + (skip-chars-forward " \t") + (forward-char)) + (looking-at c-baseclass-key))) + (and (or (eq char-before-ip ?:) + ;; watch out for scope operator + (save-excursion + (and (eq char-after-ip ?:) + (c-safe (progn (forward-char 1) t)) + (not (eq (char-after) ?:)) + ))) + (save-excursion + (c-backward-syntactic-ws lim) + (if (eq char-before-ip ?:) + (progn + (forward-char -1) + (c-backward-syntactic-ws lim))) + (back-to-indentation) + (looking-at c-class-key))) + ;; for Java + (and (c-major-mode-is 'java-mode) + (let ((fence (save-excursion + (c-beginning-of-statement-1 lim) + (point))) + cont done) + (save-excursion + (while (not done) + (cond ((looking-at c-Java-special-key) + (setq injava-inher (cons cont (point)) + done t)) + ((or (not (c-safe (c-forward-sexp -1) t)) + (<= (point) fence)) + (setq done t)) + ) + (setq cont t))) + injava-inher) + (not (c-crosses-statement-barrier-p (cdr injava-inher) + (point))) + )) + (cond + ;; CASE 5C.1: non-hanging colon on an inher intro + ((eq char-after-ip ?:) + (c-backward-syntactic-ws lim) + (c-add-syntax 'inher-intro (c-point 'boi)) + ;; don't add inclass symbol since relative point already + ;; contains any class offset + ) + ;; CASE 5C.2: hanging colon on an inher intro + ((eq char-before-ip ?:) + (c-add-syntax 'inher-intro (c-point 'boi)) + (if inclass-p (c-add-class-syntax 'inclass inclass-p))) + ;; CASE agulbrahack.1: + ((and inclass-p + c-access-key + (looking-at c-access-key)) + (c-add-syntax 'access-label (c-point 'bonl)) + (c-add-class-syntax 'inclass inclass-p) + ) + ;; CASE 5C.3: in a Java implements/extends + (injava-inher + (let ((where (cdr injava-inher)) + (cont (car injava-inher))) + (goto-char where) + (cond ((looking-at "throws[ \t\n]") + (c-add-syntax 'func-decl-cont + (progn (c-beginning-of-statement-1 lim) + (c-point 'boi)))) + (cont (c-add-syntax 'inher-cont where)) + (t (c-add-syntax 'inher-intro + (progn (goto-char (cdr injava-inher)) + (c-beginning-of-statement-1 lim) + (point)))) + ))) + ;; CASE 5C.4: a continued inheritance line + (t + (c-beginning-of-inheritance-list lim) + (c-add-syntax 'inher-cont (point)) + ;; don't add inclass symbol since relative point already + ;; contains any class offset + ))) + ;; CASE 5D: this could be a top-level compound statement, a + ;; member init list continuation, or a template argument + ;; list continuation. + ((c-with-syntax-table (if (c-major-mode-is 'c++-mode) + c++-template-syntax-table + (syntax-table)) + (save-excursion + (while (and (= (c-backward-token-1 1 t lim) 0) + (not (looking-at "[;{<,]")))) + (eq (char-after) ?,))) + (goto-char indent-point) + (c-beginning-of-member-init-list lim) + (cond + ;; CASE 5D.1: hanging member init colon, but watch out + ;; for bogus matches on access specifiers inside classes. + ((and (save-excursion + (setq plaaceholder (point)) + (c-backward-token-1 1 t lim) + (and (eq (char-after) ?:) + (not (eq (char-before) ?:)))) + (save-excursion + (goto-char placeholder) + (back-to-indentation) + (or + (/= (car (save-excursion + (parse-partial-sexp (point) placeholder))) + 0) + (and + (if c-access-key (not (looking-at c-access-key)) t) + (not (looking-at c-class-key)) + (if c-bitfield-key (not (looking-at c-bitfield-key)) t)) + ))) + (goto-char placeholder) + (c-forward-syntactic-ws) + (c-add-syntax 'member-init-cont (point)) + ;; we do not need to add class offset since relative + ;; point is the member init above us + ) + ;; CASE 5D.2: non-hanging member init colon + ((progn + (c-forward-syntactic-ws indent-point) + (eq (char-after) ?:)) + (skip-chars-forward " \t:") + (c-add-syntax 'member-init-cont (point))) + ;; CASE 5D.3: perhaps a multiple inheritance line? + ((save-excursion + (c-beginning-of-statement-1 lim) + (setq placeholder (point)) + (looking-at c-inher-key)) + (goto-char placeholder) + (c-add-syntax 'inher-cont (c-point 'boi))) + ;; CASE 5D.4: perhaps a template list continuation? + ((save-excursion + (goto-char indent-point) + (skip-chars-backward "^<" lim) + ;; not sure if this is the right test, but it should + ;; be fast and mostly accurate. + (setq placeholder (point)) + (and (eq (char-before) ?<) + (not (c-in-literal lim)))) + ;; we can probably indent it just like an arglist-cont + (goto-char placeholder) + (c-beginning-of-statement-1 lim) + (c-add-syntax 'template-args-cont (c-point 'boi))) + ;; CASE 5D.5: perhaps a top-level statement-cont + (t + (c-beginning-of-statement-1 lim) + ;; skip over any access-specifiers + (and inclass-p c-access-key + (while (looking-at c-access-key) + (forward-line 1))) + ;; skip over comments, whitespace + (c-forward-syntactic-ws indent-point) + (c-add-syntax 'statement-cont (c-point 'boi))) + )) + ;; CASE 5E: we are looking at a access specifier + ((and inclass-p + c-access-key + (looking-at c-access-key)) + (c-add-syntax 'access-label (c-point 'bonl)) + (c-add-class-syntax 'inclass inclass-p)) + ;; CASE 5F: extern-lang-close or namespace-close? + ((and inenclosing-p + (eq char-after-ip ?})) + (setq tmpsymbol (if (eq inenclosing-p 'extern) + 'extern-lang-close + 'namespace-close)) + (c-add-syntax tmpsymbol (aref inclass-p 0))) + ;; CASE 5G: we are looking at the brace which closes the + ;; enclosing nested class decl + ((and inclass-p + (eq char-after-ip ?}) + (save-excursion + (save-restriction + (widen) + (forward-char 1) + (and (c-safe (progn (c-backward-sexp 1) t)) + (= (point) (aref inclass-p 1)) + )))) + (c-add-class-syntax 'class-close inclass-p)) + ;; CASE 5H: we could be looking at subsequent knr-argdecls + ((and c-recognize-knr-p + ;; here we essentially use the hack that is used in + ;; Emacs' c-mode.el to limit how far back we should + ;; look. The assumption is made that argdecls are + ;; indented at least one space and that function + ;; headers are not indented. + (let ((limit (save-excursion + (re-search-backward "^[^ \^L\t\n#]" nil 'move) + (point)))) + (save-excursion + (c-backward-syntactic-ws limit) + (setq placeholder (point)) + (while (and (memq (char-before) '(?\; ?,)) + (> (point) limit)) + (beginning-of-line) + (setq placeholder (point)) + (c-backward-syntactic-ws limit)) + (and (eq (char-before) ?\)) + (or (not c-method-key) + (progn + (c-forward-sexp -1) + (forward-char -1) + (c-backward-syntactic-ws) + (not (or (memq (char-before) '(?- ?+)) + ;; or a class category + (progn + (c-forward-sexp -2) + (looking-at c-class-key)) + ))))) + )) + (save-excursion + (c-beginning-of-statement-1) + (not (looking-at "typedef[ \t\n]+")))) + (goto-char placeholder) + (c-add-syntax 'knr-argdecl (c-point 'boi))) + ;; CASE 5I: ObjC method definition. + ((and c-method-key + (looking-at c-method-key)) + (c-add-syntax 'objc-method-intro (c-point 'boi))) + ;; CASE 5J: we are at the topmost level, make sure we skip + ;; back past any access specifiers + ((progn + (c-backward-syntactic-ws lim) + (while (and inclass-p + c-access-key + (not (bobp)) + (save-excursion + (c-safe (progn (c-backward-sexp 1) t)) + ;; agulbrahack 2 + (and (looking-at "slots:") + (c-backward-sexp 1)) + (looking-at c-access-key))) + (c-backward-sexp 1) + (c-backward-syntactic-ws lim)) + (or (bobp) + (memq (char-before) '(?\; ?\})))) + ;; real beginning-of-line could be narrowed out due to + ;; enclosure in a class block + (save-restriction + (widen) + (c-add-syntax 'topmost-intro (c-point 'bol)) + (if inclass-p + (progn + (goto-char (aref inclass-p 1)) + (or (= (point) (c-point 'boi)) + (goto-char (aref inclass-p 0))) + (cond + ((eq inenclosing-p 'extern) + (c-add-syntax 'inextern-lang (c-point 'boi))) + ((eq inenclosing-p 'namespace) + (c-add-syntax 'innamespace (c-point 'boi))) + (t (c-add-class-syntax 'inclass inclass-p))) + )) + )) + ;; CASE 5K: we are at an ObjC or Java method definition + ;; continuation line. + ((and c-method-key + (progn + (c-beginning-of-statement-1 lim) + (beginning-of-line) + (looking-at c-method-key))) + (c-add-syntax 'objc-method-args-cont (point))) + ;; CASE 5L: we are at the first argument of a template + ;; arglist that begins on the previous line. + ((eq (char-before) ?<) + (c-beginning-of-statement-1 lim) + (c-forward-syntactic-ws) + (c-add-syntax 'template-args-cont (c-point 'boi))) + ;; CASE 5M: we are at a topmost continuation line + (t + (c-beginning-of-statement-1 lim) + (c-forward-syntactic-ws) + (c-add-syntax 'topmost-intro-cont (c-point 'boi))) + )) ; end CASE 5 + ;; (CASE 6 has been removed.) + ;; CASE 7: line is an expression, not a statement. Most + ;; likely we are either in a function prototype or a function + ;; call argument list + ((not (or (and c-special-brace-lists + (save-excursion + (goto-char containing-sexp) + (c-looking-at-special-brace-list))) + (eq (char-after containing-sexp) ?{))) + (c-backward-syntactic-ws containing-sexp) + (cond + ;; CASE 7A: we are looking at the arglist closing paren + ((and (or (c-major-mode-is 'pike-mode) + ;; Don't check this in Pike since it allows a + ;; comma after the last arg. + (not (eq char-before-ip ?,))) + (memq char-after-ip '(?\) ?\]))) + (goto-char containing-sexp) + (setq placeholder (c-point 'boi)) + (when (and (c-safe (backward-up-list 1) t) + (> (point) placeholder)) + (forward-char) + (skip-chars-forward " \t") + (setq placeholder (point))) + (c-add-syntax 'arglist-close placeholder)) + ;; CASE 7B: Looking at the opening brace of an + ;; in-expression block or brace list. + ((eq char-after-ip ?{) + (goto-char indent-point) + (setq placeholder (c-point 'boi)) + (goto-char containing-sexp) + (if (c-inside-bracelist-p placeholder + (cons containing-sexp state)) + (progn + (c-add-syntax 'brace-list-open (c-point 'boi)) + (c-add-syntax 'inexpr-class)) + (c-add-syntax 'block-open (c-point 'boi)) + (c-add-syntax 'inexpr-statement))) + ;; CASE 7C: we are looking at the first argument in an empty + ;; argument list. Use arglist-close if we're actually + ;; looking at a close paren or bracket. + ((memq char-before-ip '(?\( ?\[)) + (goto-char containing-sexp) + (setq placeholder (c-point 'boi)) + (when (and (c-safe (backward-up-list 1) t) + (> (point) placeholder)) + (forward-char) + (skip-chars-forward " \t") + (setq placeholder (point))) + (c-add-syntax 'arglist-intro placeholder)) + ;; CASE 7D: we are inside a conditional test clause. treat + ;; these things as statements + ((save-excursion + (goto-char containing-sexp) + (and (c-safe (progn (c-forward-sexp -1) t)) + (looking-at "\\<for\\>[^_]"))) + (goto-char (1+ containing-sexp)) + (c-forward-syntactic-ws indent-point) + (c-beginning-of-statement-1 containing-sexp) + (if (eq char-before-ip ?\;) + (c-add-syntax 'statement (point)) + (c-add-syntax 'statement-cont (point)) + )) + ;; CASE 7E: maybe a continued method call. This is the case + ;; when we are inside a [] bracketed exp, and what precede + ;; the opening bracket is not an identifier. + ((and c-method-key + (eq (char-after containing-sexp) ?\[) + (save-excursion + (goto-char (1- containing-sexp)) + (c-backward-syntactic-ws (c-point 'bod)) + (if (not (looking-at c-symbol-key)) + (c-add-syntax 'objc-method-call-cont containing-sexp)) + ))) + ;; CASE 7F: we are looking at an arglist continuation line, + ;; but the preceding argument is on the same line as the + ;; opening paren. This case includes multi-line + ;; mathematical paren groupings, but we could be on a + ;; for-list continuation line + ((save-excursion + (goto-char (1+ containing-sexp)) + (skip-chars-forward " \t") + (not (eolp))) + (goto-char containing-sexp) + (setq placeholder (c-point 'boi)) + (when (and (c-safe (backward-up-list 1) t) + (> (point) placeholder)) + (forward-char) + (skip-chars-forward " \t") + (setq placeholder (point))) + (c-add-syntax 'arglist-cont-nonempty placeholder)) + ;; CASE 7G: we are looking at just a normal arglist + ;; continuation line + (t (c-beginning-of-statement-1 containing-sexp) + (forward-char 1) + (c-forward-syntactic-ws indent-point) + (c-add-syntax 'arglist-cont (c-point 'boi))) + )) + ;; CASE 8: func-local multi-inheritance line + ((and c-baseclass-key + (save-excursion + (goto-char indent-point) + (skip-chars-forward " \t") + (looking-at c-baseclass-key))) + (goto-char indent-point) + (skip-chars-forward " \t") + (cond + ;; CASE 8A: non-hanging colon on an inher intro + ((eq char-after-ip ?:) + (c-backward-syntactic-ws lim) + (c-add-syntax 'inher-intro (c-point 'boi))) + ;; CASE 8B: hanging colon on an inher intro + ((eq char-before-ip ?:) + (c-add-syntax 'inher-intro (c-point 'boi))) + ;; CASE 8C: a continued inheritance line + (t + (c-beginning-of-inheritance-list lim) + (c-add-syntax 'inher-cont (point)) + ))) + ;; CASE 9: we are inside a brace-list + ((setq special-brace-list + (or (and c-special-brace-lists + (save-excursion + (goto-char containing-sexp) + (c-looking-at-special-brace-list))) + (c-inside-bracelist-p containing-sexp state))) + (cond + ;; CASE 9A: In the middle of a special brace list opener. + ((and (consp special-brace-list) + (save-excursion + (goto-char containing-sexp) + (eq (char-after) ?\()) + (eq char-after-ip (car (cdr special-brace-list)))) + (goto-char (car (car special-brace-list))) + (skip-chars-backward " \t") + (if (and (bolp) + (assoc 'statement-cont + (setq placeholder (c-guess-basic-syntax)))) + (setq syntax placeholder) + (c-beginning-of-statement-1 lim) + (c-forward-token-1 0) + (if (looking-at "typedef\\>") (c-forward-token-1 1)) + (c-add-syntax 'brace-list-open (c-point 'boi)))) + ;; CASE 9B: brace-list-close brace + ((if (consp special-brace-list) + ;; Check special brace list closer. + (progn + (goto-char (car (car special-brace-list))) + (save-excursion + (goto-char indent-point) + (back-to-indentation) + (or + ;; We were between the special close char and the `)'. + (and (eq (char-after) ?\)) + (eq (1+ (point)) (cdr (car special-brace-list)))) + ;; We were before the special close char. + (and (eq (char-after) (cdr (cdr special-brace-list))) + (= (c-forward-token-1) 0) + (eq (1+ (point)) (cdr (car special-brace-list))))))) + ;; Normal brace list check. + (and (eq char-after-ip ?}) + (c-safe (progn (forward-char 1) + (c-backward-sexp 1) + t)) + (= (point) containing-sexp))) + (c-add-syntax 'brace-list-close (c-point 'boi))) + (t + ;; Prepare for the rest of the cases below by going to the + ;; token following the opening brace + (if (consp special-brace-list) + (progn + (goto-char (car (car special-brace-list))) + (c-forward-token-1 1 nil indent-point)) + (goto-char containing-sexp)) + (forward-char) + (let ((start (point))) + (c-forward-syntactic-ws indent-point) + (goto-char (max start (c-point 'bol)))) + (skip-chars-forward " \t\n\r" indent-point) + (cond + ;; CASE 9C: we're looking at the first line in a brace-list + ((= (point) indent-point) + (goto-char containing-sexp) + (c-add-syntax 'brace-list-intro (c-point 'boi)) + ) ; end CASE 9C + ;; CASE 9D: this is just a later brace-list-entry or + ;; brace-entry-open + (t (if (or (eq char-after-ip ?{) + (and c-special-brace-lists + (save-excursion + (goto-char indent-point) + (c-forward-syntactic-ws (c-point 'eol)) + (c-looking-at-special-brace-list (point))))) + (c-add-syntax 'brace-entry-open (point)) + (c-add-syntax 'brace-list-entry (point)) + )) ; end CASE 9D + )))) ; end CASE 9 + ;; CASE 10: A continued statement + ((and (not (memq char-before-ip '(?\; ?:))) + (or (not (eq char-before-ip ?})) + (c-looking-at-inexpr-block-backward containing-sexp)) + (> (point) + (save-excursion + (c-beginning-of-statement-1 containing-sexp) + (c-forward-syntactic-ws) + (setq placeholder (point)))) + (/= placeholder containing-sexp)) + (goto-char indent-point) + (skip-chars-forward " \t") + (let ((after-cond-placeholder + (save-excursion + (goto-char placeholder) + (if (and c-conditional-key (looking-at c-conditional-key)) + (progn + (c-safe (c-skip-conditional)) + (c-forward-syntactic-ws) + (if (eq (char-after) ?\;) + (progn + (forward-char 1) + (c-forward-syntactic-ws))) + (point)) + nil)))) + (cond + ;; CASE 10A: substatement + ((and after-cond-placeholder + (>= after-cond-placeholder indent-point)) + (goto-char placeholder) + (if (eq char-after-ip ?{) + (c-add-syntax 'substatement-open (c-point 'boi)) + (c-add-syntax 'substatement (c-point 'boi)))) + ;; CASE 10B: open braces for class or brace-lists + ((setq special-brace-list + (or (and c-special-brace-lists + (c-looking-at-special-brace-list)) + (eq char-after-ip ?{))) + (cond + ;; CASE 10B.1: class-open + ((save-excursion + (goto-char indent-point) + (skip-chars-forward " \t{") + (let ((decl (c-search-uplist-for-classkey (c-parse-state)))) + (and decl + (setq placeholder (aref decl 0))) + )) + (c-add-syntax 'class-open placeholder)) + ;; CASE 10B.2: brace-list-open + ((or (consp special-brace-list) + (save-excursion + (goto-char placeholder) + (looking-at "\\<enum\\>")) + (save-excursion + (goto-char indent-point) + (while (and (> (point) placeholder) + (= (c-backward-token-1 1 t) 0) + (/= (char-after) ?=))) + (eq (char-after) ?=))) + ;; The most semantically accurate symbol here is + ;; brace-list-open, but we report it simply as a + ;; statement-cont. The reason is that one normally + ;; adjusts brace-list-open for brace lists as + ;; top-level constructs, and brace lists inside + ;; statements is a completely different context. + (goto-char indent-point) + (c-beginning-of-closest-statement) + (c-add-syntax 'statement-cont (c-point 'boi))) + ;; CASE 10B.3: The body of a function declared inside a + ;; normal block. This can only occur in Pike. + ((and (c-major-mode-is 'pike-mode) + (progn + (goto-char indent-point) + (not (c-looking-at-bos)))) + (c-beginning-of-closest-statement) + (c-add-syntax 'defun-open (c-point 'boi))) + ;; CASE 10B.4: catch-all for unknown construct. + (t + ;; Can and should I add an extensibility hook here? + ;; Something like c-recognize-hook so support for + ;; unknown constructs could be added. It's probably a + ;; losing proposition, so I dunno. + (goto-char placeholder) + (c-add-syntax 'statement-cont (c-point 'boi)) + (c-add-syntax 'block-open)) + )) + ;; CASE 10C: iostream insertion or extraction operator + ((looking-at "<<\\|>>") + (goto-char placeholder) + (and after-cond-placeholder + (goto-char after-cond-placeholder)) + (while (and (re-search-forward "<<\\|>>" indent-point 'move) + (c-in-literal placeholder))) + ;; if we ended up at indent-point, then the first + ;; streamop is on a separate line. Indent the line like + ;; a statement-cont instead + (if (/= (point) indent-point) + (c-add-syntax 'stream-op (c-point 'boi)) + (c-backward-syntactic-ws lim) + (c-add-syntax 'statement-cont (c-point 'boi)))) + ;; CASE 10D: continued statement. find the accurate + ;; beginning of statement or substatement + (t + (c-beginning-of-statement-1 after-cond-placeholder) + ;; KLUDGE ALERT! c-beginning-of-statement-1 can leave + ;; us before the lim we're passing in. It should be + ;; fixed, but I'm worried about side-effects at this + ;; late date. Fix for v5. + (goto-char (or (and after-cond-placeholder + (max after-cond-placeholder (point))) + (point))) + (c-add-syntax 'statement-cont (point))) + ))) + ;; CASE 11: an else clause? + ((looking-at "\\<else\\>[^_]") + (c-backward-to-start-of-if containing-sexp) + (c-add-syntax 'else-clause (c-point 'boi))) + ;; CASE 12: Statement. But what kind? Lets see if its a + ;; while closure of a do/while construct + ((progn + (goto-char indent-point) + (skip-chars-forward " \t") + (and (looking-at "while\\b[^_]") + (save-excursion + (c-backward-to-start-of-do containing-sexp) + (setq placeholder (point)) + (looking-at "do\\b[^_]")) + )) + (goto-char placeholder) + (c-add-syntax 'do-while-closure (c-point 'boi))) + ;; CASE 13: A catch or finally clause? This case is simpler + ;; than if-else and do-while, because a block is required + ;; after every try, catch and finally. + ((save-excursion + (and (cond ((c-major-mode-is 'c++-mode) + (looking-at "\\<catch\\>[^_]")) + ((c-major-mode-is 'java-mode) + (looking-at "\\<\\(catch\\|finally\\)\\>[^_]"))) + (c-safe (c-backward-sexp) t) + (eq (char-after) ?{) + (c-safe (c-backward-sexp) t) + (if (eq (char-after) ?\() + (c-safe (c-backward-sexp) t) + t) + (looking-at "\\<\\(try\\|catch\\)\\>[^_]") + (setq placeholder (c-point 'boi)))) + (c-add-syntax 'catch-clause placeholder)) + ;; CASE 14: A case or default label + ((looking-at c-switch-label-key) + (goto-char containing-sexp) + ;; check for hanging braces + (if (/= (point) (c-point 'boi)) + (c-forward-sexp -1)) + (c-add-syntax 'case-label (c-point 'boi))) + ;; CASE 15: any other label + ((looking-at c-label-key) + (goto-char containing-sexp) + ;; check for hanging braces + (if (/= (point) (c-point 'boi)) + (c-forward-sexp -1)) + (c-add-syntax 'label (c-point 'boi))) + ;; CASE 16: block close brace, possibly closing the defun or + ;; the class + ((eq char-after-ip ?}) + (let* ((lim (c-safe-position containing-sexp fullstate)) + (relpos (save-excursion + (goto-char containing-sexp) + (if (/= (point) (c-point 'boi)) + (c-beginning-of-statement-1 lim)) + (c-point 'boi)))) + (cond + ;; CASE 16A: closing a lambda defun or an in-expression + ;; block? + ((save-excursion + (goto-char containing-sexp) + (setq placeholder (c-looking-at-inexpr-block))) + (setq tmpsymbol (if (eq (car placeholder) 'inlambda) + 'inline-close + 'block-close)) + (goto-char containing-sexp) + (back-to-indentation) + (if (= containing-sexp (point)) + (c-add-syntax tmpsymbol (point)) + (goto-char (cdr placeholder)) + (back-to-indentation) + (c-add-syntax tmpsymbol (point)) + (if (/= (point) (cdr placeholder)) + (c-add-syntax (car placeholder))))) + ;; CASE 16B: does this close an inline or a function in + ;; an extern block or namespace? + ((progn + (goto-char containing-sexp) + (setq placeholder (c-search-uplist-for-classkey state))) + (goto-char (aref placeholder 0)) + (if (looking-at (concat c-extra-toplevel-key "[^_]")) + (c-add-syntax 'defun-close relpos) + (c-add-syntax 'inline-close relpos))) + ;; CASE 16C: if there an enclosing brace that hasn't + ;; been narrowed out by a class, then this is a + ;; block-close + ((and (not inenclosing-p) + (c-most-enclosing-brace state) + (or (not (c-major-mode-is 'pike-mode)) + ;; In Pike it can be a defun-close of a + ;; function declared in a statement block. Let + ;; it through to be handled below. + (or (c-looking-at-bos) + (progn + (c-beginning-of-statement-1) + (looking-at c-conditional-key))))) + (c-add-syntax 'block-close relpos)) + ;; CASE 16D: find out whether we're closing a top-level + ;; class or a defun + (t + (save-restriction + (narrow-to-region (point-min) indent-point) + (let ((decl (c-search-uplist-for-classkey (c-parse-state)))) + (if decl + (c-add-class-syntax 'class-close decl) + (c-add-syntax 'defun-close relpos))))) + ))) + ;; CASE 17: statement catchall + (t + ;; we know its a statement, but we need to find out if it is + ;; the first statement in a block + (goto-char containing-sexp) + (forward-char 1) + (c-forward-syntactic-ws indent-point) + ;; now skip forward past any case/default clauses we might find. + (while (or (c-skip-case-statement-forward fullstate indent-point) + (and (looking-at c-switch-label-key) + (not inswitch-p))) + (setq inswitch-p t)) + ;; we want to ignore non-case labels when skipping forward + (while (and (looking-at c-label-key) + (goto-char (match-end 0))) + (c-forward-syntactic-ws indent-point)) + (cond + ;; CASE 17A: we are inside a case/default clause inside a + ;; switch statement. find out if we are at the statement + ;; just after the case/default label. + ((and inswitch-p + (progn + (goto-char indent-point) + (c-beginning-of-statement-1 containing-sexp) + (setq placeholder (point)) + (beginning-of-line) + (when (re-search-forward c-switch-label-key + (max placeholder (c-point 'eol)) t) + (setq placeholder (match-beginning 0))))) + (goto-char indent-point) + (skip-chars-forward " \t") + (if (eq (char-after) ?{) + (c-add-syntax 'statement-case-open placeholder) + (c-add-syntax 'statement-case-intro placeholder))) + ;; CASE 17B: continued statement + ((eq char-before-ip ?,) + (goto-char indent-point) + (c-beginning-of-closest-statement) + (c-add-syntax 'statement-cont (c-point 'boi))) + ;; CASE 17C: a question/colon construct? But make sure + ;; what came before was not a label, and what comes after + ;; is not a globally scoped function call! + ((or (and (memq char-before-ip '(?: ??)) + (save-excursion + (goto-char indent-point) + (c-backward-syntactic-ws lim) + (back-to-indentation) + (not (looking-at c-label-key)))) + (and (memq char-after-ip '(?: ??)) + (save-excursion + (goto-char indent-point) + (skip-chars-forward " \t") + ;; watch out for scope operator + (not (looking-at "::"))))) + (goto-char indent-point) + (c-beginning-of-closest-statement) + (c-add-syntax 'statement-cont (c-point 'boi))) + ;; CASE 17D: any old statement + ((< (point) indent-point) + (let ((safepos (c-most-enclosing-brace fullstate)) + relpos done) + (goto-char indent-point) + (c-beginning-of-statement-1 safepos) + ;; It is possible we're on the brace that opens a nested + ;; function. + (if (and (eq (char-after) ?{) + (save-excursion + (c-backward-syntactic-ws safepos) + (not (eq (char-before) ?\;)))) + (c-beginning-of-statement-1 safepos)) + (if (and inswitch-p + (looking-at c-switch-label-key)) + (progn + (goto-char (match-end 0)) + (c-forward-syntactic-ws))) + (setq relpos (c-point 'boi)) + (while (and (not done) + (<= safepos (point)) + (/= relpos (point))) + (c-beginning-of-statement-1 safepos) + (if (= relpos (c-point 'boi)) + (setq done t)) + (setq relpos (c-point 'boi))) + (c-add-syntax 'statement relpos) + (if (eq char-after-ip ?{) + (c-add-syntax 'block-open)))) + ;; CASE 17E: first statement in an in-expression block + ((setq placeholder + (save-excursion + (goto-char containing-sexp) + (c-looking-at-inexpr-block))) + (goto-char containing-sexp) + (back-to-indentation) + (let ((block-intro (if (eq (car placeholder) 'inlambda) + 'defun-block-intro + 'statement-block-intro))) + (if (= containing-sexp (point)) + (c-add-syntax block-intro (point)) + (goto-char (cdr placeholder)) + (back-to-indentation) + (c-add-syntax block-intro (point)) + (if (/= (point) (cdr placeholder)) + (c-add-syntax (car placeholder))))) + (if (eq char-after-ip ?{) + (c-add-syntax 'block-open))) + ;; CASE 17F: first statement in an inline, or first + ;; statement in a top-level defun. we can tell this is it + ;; if there are no enclosing braces that haven't been + ;; narrowed out by a class (i.e. don't use bod here!) + ((save-excursion + (save-restriction + (widen) + (goto-char containing-sexp) + (c-narrow-out-enclosing-class state containing-sexp) + (not (c-most-enclosing-brace state)))) + (goto-char containing-sexp) + ;; if not at boi, then defun-opening braces are hung on + ;; right side, so we need a different relpos + (if (/= (point) (c-point 'boi)) + (progn + (c-backward-syntactic-ws) + (c-safe (c-forward-sexp (if (eq (char-before) ?\)) + -1 -2))) + ;; looking at a Java throws clause following a + ;; method's parameter list + (c-beginning-of-statement-1) + )) + (c-add-syntax 'defun-block-intro (c-point 'boi))) + ;; CASE 17G: First statement in a function declared inside + ;; a normal block. This can only occur in Pike. + ((and (c-major-mode-is 'pike-mode) + (progn + (goto-char containing-sexp) + (and (not (c-looking-at-bos)) + (progn + (c-beginning-of-statement-1) + (not (looking-at c-conditional-key)))))) + (c-add-syntax 'defun-block-intro (c-point 'boi))) + ;; CASE 17H: first statement in a block + (t (goto-char containing-sexp) + (if (/= (point) (c-point 'boi)) + (c-beginning-of-statement-1 + (if (= (point) lim) + (c-safe-position (point) state) lim))) + (c-add-syntax 'statement-block-intro (c-point 'boi)) + (if (eq char-after-ip ?{) + (c-add-syntax 'block-open))) + )) + ) + ;; now we need to look at any modifiers + (goto-char indent-point) + (skip-chars-forward " \t") + (cond + ;; are we looking at a comment only line? + ((and (looking-at c-comment-start-regexp) + (/= (c-forward-token-1 0 nil (c-point 'eol)) 0)) + (c-add-syntax 'comment-intro)) + ;; we might want to give additional offset to friends (in C++). + ((and (c-major-mode-is 'c++-mode) + (looking-at c-C++-friend-key)) + (c-add-syntax 'friend)) + ;; Start of a preprocessor directive? + ((and (eq literal 'pound) + (= (save-excursion + (c-beginning-of-macro lim) + (setq placeholder (point))) + (c-point 'boi)) + (not (and (c-major-mode-is 'pike-mode) + (eq (char-after (1+ placeholder)) ?\")))) + (c-add-syntax 'cpp-macro))) + ;; return the syntax + syntax)))))) + +(add-hook 'find-file-hooks 'agulbra-c++-clean-out-spaces) +(add-hook 'write-file-hooks 'agulbra-c++-clean-out-spaces) + +(add-hook 'c++-mode-hook 'kde-c++-mode-hook) +(add-hook 'c-mode-hook 'kde-c-mode-hook) +; always end a file with a newline +(setq-default require-final-newline t) +; 'next-line won't be adding newlines +(setq-default next-line-add-newlines nil) +(setq compilation-error-regexp-systems-list '(gnu of comma 4bsd) + compilation-ask-about-save nil) + +(provide 'kde-emacs-core) diff --git a/scripts/kde-emacs/kde-emacs-doc.el b/scripts/kde-emacs/kde-emacs-doc.el new file mode 100644 index 00000000..5fca1361 --- /dev/null +++ b/scripts/kde-emacs/kde-emacs-doc.el @@ -0,0 +1,322 @@ +;; kde-emacs-doc.el +;; +;; Copyright (C) 2002 Zack Rusin <zack@kde.org> +;; +;; This library is free software; you can redistribute it and/or +;; modify it under the terms of the GNU Lesser General Public +;; License as published by the Free Software Foundation; either +;; version 2.1 of the License, or (at your option) any later version. +;; +;; This library is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +;; Lesser General Public License for more details. +;; +;; You should have received a copy of the GNU Lesser General Public +;; License along with this library; if not, write to the Free Software +;; Foundation, Inc., 51 Franklin Steet, Fifth Floor, Boston, MA +;; 02110-1301 USA +;; +;; +;;; Documentation : +;; Interactive functions: +;; kde-license-insert - inserts the chosen license header in the current +;; buffer, +;; kde-doc-function-insert - insert documentation skeleton for the function +;; at the current location +;; kde-doc-multiline-insert - inserts blank mutliline comment skeleton +;; kde-doc-oneliner-insert - inserts blank one line comment skeleton +;; +;;; TODO : +;; - add interactive functions to insert file, class, brief, +;; and group comments, +;; - change the way commenting works after license insertion, +;; - add syntax higlighting for doxygen/kdoc keywords +;; - add more license headers + + +(require 'kde-emacs-core) +(require 'kde-emacs-semantic) + +;*---------------------------------------------------------------------*/ +;* Licenses ... */ +;*---------------------------------------------------------------------*/ + +(defvar LGPL "This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 51 Franklin Steet, Fifth Floor, Boston, MA +02110-1301 USA" + "GNU LGPL license header.") + +(defvar GPL "This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Steet, Fifth Floor, Boston, MA +02110-1301, USA." + "GNU GPL license header.") + +(defvar FDL "Permission is granted to copy, distribute and/or modify this document +under the terms of the GNU Free Documentation License, Version 1.1 +or any later version published by the Free Software Foundation; +with the Invariant Sections being LIST THEIR TITLES, with the +Front-Cover Texts being LIST, and with the Back-Cover Texts being LIST. +A copy of the license is included in the section entitled \"GNU +Free Documentation License\"." + "GNU FDL license header.") + +(defvar BSD "Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." + "BSD license header.") + + +;;---------------- +;; Variables | +;;---------------- + +(defconst kde-doc-styles + '( + (javadoc . + ((start . "/**") + (end . "*/") + (separator . "\n*") + (oneliner . "///") + (element . "/**< */") + (param . "@param %s") + (return . "@return") + (seealso . "@see") + (class . "") + (brief . "@brief") + (file . "@file %s") + )) + (qt . + ((start . "/*!") + (end . "*/") + (separator . "\n") + (oneliner . "//!") + (element . "/*!< */") + (param . "\\param %s") + (return . "\\return") + (seealso . "\\sa") + (class . "\\class") + (brief . "\\brief") + (file . "\\file %s") + )) + ) + "Documentation styles used by KDE.") + +(defcustom kde-doc-style 'javadoc + "Current documentation style. This variable is buffer local." + :group 'kde-devel + :version "0.1" + :type (if (boundp 'kde-doc-styles) + `(choice ,@(mapcar (lambda (s) `(const ,(car s))) kde-doc-styles)) + 'symbol)) +(make-variable-buffer-local 'kde-doc-style) + +(defcustom kde-license-comment-style 'box + "Style to be used for `kde-license-insert'. +See `comment-styles' for a list of available styles." + :group 'kde-devel + :version "0.1" + :type (if (boundp 'comment-styles) + `(choice ,@(mapcar (lambda (s) `(const ,(car s))) comment-styles)) + 'symbol)) + +;*---------------------------------------------------------------------*/ +;* Functions ... */ +;*---------------------------------------------------------------------*/ + +(defun kde-license-header () + (let ((ret (file-name-nondirectory (buffer-file-name)))) + (setq ret (concat ret " \n\n")) + (setq ret (concat ret "Copyright (C) " (format-time-string "%Y ") + kde-full-name " <"kde-email">\n\n")) + )) + +(defun kde-license-insert (license) + "Inserts the chosen license header at the top of the current +buffer." + (interactive (list (completing-read + "Which license do you want to use? " + '(("GNU GPL" 1) ("GNU LGPL" 2) ("GNU FDL" 3) ("BSD" 4)) + nil t nil))) + (save-excursion + (let ((start (point-min)) + (end) + ) + (setq comment-style kde-license-comment-style) + (goto-char start) + (if license + (progn + (cond ((string= license "GNU GPL") + (insert (kde-license-header)) + (insert GPL) + ) + ((string= license "GNU LGPL") + (insert (kde-license-header)) + (insert LGPL) + ) + ((string= license "GNU FDL") + (insert (kde-license-header)) + (insert FDL) + ) + ((string= license "BSD") + (insert (kde-license-header)) + (insert BSD) + ) + ) + (insert "\n") + (setq end (point)) + (comment-region start end) + ) + ) + ) + )) + +(defmacro kde-doc-type-string (arg) + "Maps doc element from kde-doc-style to string." + `(cdr (assoc ,arg (assoc kde-doc-style kde-doc-styles))) + ) + +(defun kde-doc-param-string (ARG) + "Substitues %s in the param string with ARG." + (let ((par (kde-doc-type-string 'param))) + (if (string-match "\%s" par) + (replace-match ARG t t par) + par)) + ) + +(defun kde-function-documentation (function) + (let ((ret "") (rettype (semantic-token-type function))) + (setq ret (kde-doc-type-string 'start)) + (setq ret (concat ret (kde-doc-type-string 'separator))) + (dolist (elt (semantic-token-function-args function) ret) + (setq ret (concat ret (kde-doc-type-string 'separator) " " + (kde-doc-param-string (semantic-token-name elt)))) + ) + (if (not (or + (kde-is-constructor function) + (semantic-token-function-destructor function))) + (progn + (if (listp rettype) + (setq rettype (car rettype))) + (if (not (string= rettype "void")) + (setq ret (concat ret (kde-doc-type-string 'separator) " " (kde-doc-type-string 'return))) + ) + ) + ) + (setq ret (concat ret "\n" (kde-doc-type-string 'end) )) + )) + +(defun kde-doc-function-insert () + "Inserts skeleton function documentation for a function +at the current location." + (interactive) + (save-excursion + (let* ((pt (point)) + (token (kde-function-at-point pt)) + (ret "") + (start) (end) + ) + (if (not token) + (error "There's no function at %d." pt) + (progn + (setq ret (kde-function-documentation token)) + (goto-char (semantic-token-start token)) + (previous-line) + (goto-char (point-at-eol)) + (setq start (point)) + (insert "\n " ret) + (setq end (semantic-token-end token)) + (indent-region start end nil) + ) + ) + ))) + +(defun kde-doc-oneliner-insert () + "Insert oneliner comment at the current point. If the line is not empty newline is inserted." + (interactive) + (let ((thisblank)(pt)) + (save-excursion + (beginning-of-line) + (setq pt (point)) + (setq thisblank (looking-at "[ \t]*$")) + (if (not thisblank) + (progn + (newline) + (goto-char pt) + )) + (insert (kde-doc-type-string 'oneliner)) + (setq pt (point-at-eol)) + (end-of-line) + ) + (goto-char pt) + )) + +(defun kde-doc-multiline-insert () + "Inserts blank multiline comment at point. If the current line isn't blank +the functions inserts a newline." + (interactive) + (let ((thisblank)(start) (end)) + (save-excursion + (beginning-of-line) + (setq start (point)) + (setq thisblank (looking-at "[ \t]*$")) + (if (not thisblank) + (progn + (newline) + (goto-char start) + )) + ;; The blank to fix sometimes occuring + ;; weird behavior in indent-region + (insert " " + (kde-doc-type-string 'start) + (kde-doc-type-string 'separator) "\n" + (kde-doc-type-string 'end) + ) + (setq end (point)) + (indent-region start end nil) + ) + (goto-char start) + (end-of-line) + )) + + +(provide 'kde-emacs-doc) diff --git a/scripts/kde-emacs/kde-emacs-general.el b/scripts/kde-emacs/kde-emacs-general.el new file mode 100644 index 00000000..be34047c --- /dev/null +++ b/scripts/kde-emacs/kde-emacs-general.el @@ -0,0 +1,179 @@ +;; kde-emacs-general.el +;; +;; Copyright (C) 2002 KDE Development Team <www.kde.org> +;; +;; This library is free software; you can redistribute it and/or +;; modify it under the terms of the GNU Lesser General Public +;; License as published by the Free Software Foundation; either +;; version 2.1 of the License, or (at your option) any later version. +;; +;; This library is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +;; Lesser General Public License for more details. +;; +;; You should have received a copy of the GNU Lesser General Public +;; License along with this library; if not, write to the Free Software +;; Foundation, Inc., 51 Franklin Steet, Fifth Floor, Boston, MA +;; 02110-1301 USA + +;;; Commentary: +;; + +;;; Code: + +(require 'kde-emacs-vars) + +;*---------------------------------------------------------------------*/ +;* Functions ... */ +;*---------------------------------------------------------------------*/ + +;; Helper for kde-file-get-cpp-h +(defun kde-find-file (filename basedir) + "Looks for \"filename\" under \"basedir\"" + (if basedir + (let ((path (concat basedir "/" filename))) + (if (file-readable-p path) + path)) + ) +) + +(defun kde-file-get-cpp-h () + "Function returns a corresponding source or header file. The returned +variable is a list of the form (FILENAME IS_READABLE) e.g. when being in +test.h file and having test.cpp file readable in the same directory it will +return (\"test.cpp\" t)." + (interactive) + (let* ((name (buffer-file-name)) + (nname (file-name-sans-extension name)) + (ext (file-name-extension name)) + (path nil) + (ret nil) + (listit nil)) + (cond + ((member ext kde-header-files) + (setq listit kde-source-files) + (while (and listit (not ret)) ; loop over the list but stop once ret is set + (setq path (concat nname "." (car listit))) + (if (file-readable-p path) + (setq ret (cons path t)) + ) + (if (not ret) + (if (string-match "_p$" nname) + (progn + (setq path (concat (substring nname 0 (string-match "_p$" nname)) "." (car listit))) + (if (file-readable-p path) + (setq ret (cons path t)) + ))) + ) + (if (not ret) + (progn ; look in kde-source-directory + (setq path (kde-find-file (file-name-nondirectory path) kde-source-directory)) + (if (and + path + (file-readable-p path)) + (setq ret (cons path t)) + )) + ) + (setq listit (cdr listit)) ; ++listit + ) + ; not found, will create one + (if (not ret) + (setq ret (cons (concat nname "." kde-prefered-source-extension) nil )) + )) + + ((member ext kde-source-files) + (setq listit kde-header-files) + (while (and listit (not ret)) ; loop over the list but stop once ret is set + (setq path (concat nname "." (car listit))) + ; look in current dir + (if (file-readable-p path) + (setq ret (cons path t))) + (if (not ret) ;check for header_p.h files + (progn (setq path (concat nname "_p." (car listit))) + (if (file-readable-p path) + (setq ret (cons path t))))) + (if (not (file-readable-p path)) + (progn ; look in kde-include-directory + (setq path (kde-find-file (file-name-nondirectory path) kde-include-directory)) + (if (and + path + (file-readable-p path)) + (setq ret (cons path t)) + )) + ) + (setq listit (cdr listit)) ; ++listit + ) + ; not found, will create one + (if (not ret) + (setq ret (cons (concat nname "." (car kde-header-files)) nil )) + )) + ) + ret + )) + +(defun kde-switch-cpp-h () + "Switches between the source and the header file +(both directions)." + (interactive) + (let ((file (kde-file-get-cpp-h))) + (if (car file) + (find-file (car file)) + (error "Corresponding source file doesn't exist.") + ) + )) + +(defun kde-delete-backward-ws () + "Function deletes all preceding whitespace characters." + (interactive) + (let ((start (point)) + end) + (save-excursion + (setq end (re-search-backward "[^ \t]" (point-at-bol) t)) + (if (not end) + (setq end (point-at-bol)) + (setq end (1+ end)))) + (delete-backward-char (- start end)))) + +(defun kde-skip-blank-lines () + "Skips backwards past blank lines, stopping +at a first non-blank line" + (let* ((start (point-at-bol)) + (end (point-at-eol)) + (mstring (buffer-substring start end)) + (ret 0)) + (while (or + (string-match "^[ \t\r\n]+$" mstring) + (and (string= mstring "") + (= ret 0))) + (setq ret (forward-line -1)) ; if ret != 0, we stop, since we're at the first line... + (setq start (point-at-bol) + end (point-at-eol)) + (setq mstring (buffer-substring start end)) + ) + )) + +(defun kde-comments-begin () + "Skip back from current point past any preceding C-based comments at the beginning of lines. +Presumes no \"/*\" strings are nested within multi-line comments." + (let ((opoint)) + (while (progn (setq opoint (point)) + ;; To previous line + (if (zerop (forward-line -1)) + (cond + ;; If begins with "//" or ends with "*/", then is a + ;; comment. + ((looking-at "[ \t]*\\(//\\|$\\)")) + ((looking-at ".*\\*/[ \t]*$") + (progn (end-of-line) + ;; Avoid //*** single line comments here. + (if (re-search-backward "\\(^\\|[^/]\\)/\\*" nil t) + (progn (beginning-of-line) + (looking-at "[ \t]*/\\*"))))) + (t nil))))) + (goto-char opoint) + ;; Skip past whitespace + (skip-chars-forward " \t\n\r\f") + (beginning-of-line))) + +(provide 'kde-emacs-general) diff --git a/scripts/kde-emacs/kde-emacs-semantic.el b/scripts/kde-emacs/kde-emacs-semantic.el new file mode 100644 index 00000000..1753520b --- /dev/null +++ b/scripts/kde-emacs/kde-emacs-semantic.el @@ -0,0 +1,456 @@ +;; kde-emacs-semantic.el +;; +;; Copyright (C) 2002 Zack Rusin <zack@kde.org> +;; +;; This library is free software; you can redistribute it and/or +;; modify it under the terms of the GNU Lesser General Public +;; License as published by the Free Software Foundation; either +;; version 2.1 of the License, or (at your option) any later version. +;; +;; This library is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +;; Lesser General Public License for more details. +;; +;; You should have received a copy of the GNU Lesser General Public +;; License along with this library; if not, write to the Free Software +;; Foundation, Inc., 51 Franklin Steet, Fifth Floor, Boston, MA +;; 02110-1301 USA + +;;; Commentary: +;; Package provides four interactive functions: +;; - kde-function-doc-insert - creates a skeleton doxygen +;; documentation for function at point. +;; Customize it with kde-func-doc variables. +;; +;; - kde-function-expanded-at-point - returns t if function at point +;; has already been expanded. +;; +;; - kde-function-expand-at-point - expand (creates a stub) for function +;; at point (as long as function is a prototype +;; and haven't been expanded). +;; +;; - kde-create-skeletons - creates stubs for all methods in the current +;; header file. +;; +;; Package is very flexible, look at defcustom variables for things +;; you can customize. + +;;; Problems: +;; Most problems relate to C++ syntax which isn't handled correctly +;; by the Semantic package. For now templates aren't supported, I +;; have a temporary solution for other problems (e.g. const functions, +;; QT/KDE specific access specifiers) + +;;; Code: +(require 'kde-emacs-vars) +(require 'kde-emacs-general) + +;*---------------------------------------------------------------------*/ +;* User configuration ... */ +;*---------------------------------------------------------------------*/ +;;Not yet, not yet +;(defcustom kde-summary-function 'semantic-uml-prototype-nonterminal +; "*Function to use when showing info about the token" +; :group 'kde-devel +; :type semantic-token->text-custom-list +; ) + +(defcustom kde-generate-docs-with-stubs nil + "*Should function documentation be generated with the stubs." + :group 'kde-devel + :type 'boolean) + +(defcustom kde-expand-arg-start "( " + "*A string which specifies how the function arguments format should start. +e.g. \"( \" would start function arguments list like : \"func( int arg\". +and \" (\" will format the begining of the function argument list as +follows : \"func (int arg\"." + :group 'kde-devel + :version "0.1" + :type 'string) + +(defcustom kde-expand-arg-end " )" + "*Just like kde-expand-arg-start but specifies how the list should end." + :group 'kde-devel + :version "0.1" + :type 'string) + +(defcustom kde-expand-arg-break ", " + "*Specifies how the arguments should be separated." + :group 'kde-devel + :version "0.1" + :type 'string) + + +;*---------------------------------------------------------------------*/ +;* Functions ... */ +;*---------------------------------------------------------------------*/ +;; FIXME : semantic doesn't handle QT access specifiers +;(setq-default global-semantic-show-unmatched-syntax-mode nil) +;(setq-default global-semantic-show-dirty-mode nil) + +(defun kde-format-func-arg (arg) + "Formats one argument (from token to string)." + (let ((ret "")) + (if (semantic-token-variable-extra-spec arg 'const) + (setq ret "const ")) + (setq ret (concat ret (car (semantic-token-type arg)))) + (if (semantic-token-variable-extra-spec arg 'pointer) + (dotimes (idx (semantic-token-variable-extra-spec arg 'pointer)) + (setq ret (concat ret "*")) + ) + ) + (if (semantic-token-variable-extra-spec arg 'reference) + (setq ret (concat ret "&")) + ) + (setq ret (concat ret " " (semantic-token-name arg))) + ret + )) + +(defun kde-format-args (token) + "Formats all arguments from token to string. +Token has to be the function variable list e.g. +from semantic-token-function-args" + (let ((res kde-expand-arg-start) (idx 1)) + (dolist (elt token res) + (setq res (concat res (kde-format-func-arg elt))) + (when (< idx (length token)) + (setq res (concat res kde-expand-arg-break))) + (setq idx (1+ idx)) + ) + (setq res (concat res kde-expand-arg-end)) + ;; if it's something like "( )" replace it with "()" + (when (string= res (concat kde-expand-arg-start kde-expand-arg-end)) + (setq res (replace-regexp-in-string "([ \t]+)" "()" res))) + res + )) + +(defun kde-function-in-tokens (FUNC TOKENS) + "Search for function in tokens. FUNC has to be a function +token and TOKENS have to be a list of functions from buffer." + (let ((ret)(elt)) + (while (and TOKENS (not ret)) + (setq elt (car TOKENS)) + (setq TOKENS (cdr TOKENS)) + (if (and (string= (semantic-token-name FUNC) + (semantic-token-name elt)) + (equal (semantic-token-type FUNC) + (semantic-token-type elt)) + ;; FIXME (semantic) : Functions in some classes don't have the + ;; 'parent property set !!! + ;;(string= (semantic-token-function-parent FUNC1) + ;; (semantic-token-function-parent FUNC2)) + (string= (kde-format-args (semantic-token-function-args FUNC)) + (kde-format-args (semantic-token-function-args elt)))) + (setq ret t)) + ) + ret + )) + +(defmacro kde-label-signals (pt) + "Returns none-nil if the current access label == \"signals\"" + `(save-excursion + (goto-char ,pt) + (if (looking-at ":") + (re-search-backward "signals" (point-at-bol) t) + ) + )) + +(defun kde-label-namespace (pt) + "Return the namespace to which the variable/function at point PT belongs to." + (save-excursion + (goto-char pt) + (if (looking-at "::") + (let ((start) (end)) + (re-search-backward "\\b\\w+" (point-at-bol) t) + (setq start (match-beginning 0)) + (setq end (match-end 0)) + (buffer-substring-no-properties start end) + ) + ) + )) + +(defmacro kde-label-slots (pt) + "Return none-nil if at PT there's slots access specifier." + `(save-excursion + (goto-char ,pt) + (if (looking-at ":") + ;; export this regex to a kde-emacs-vars defvar + (re-search-backward "\\(public\\|protected\\|private\\)[ \t]+slots" (point-at-bol) t)) + )) + +(defmacro kde-is-constructor (function) + "Returns t if the FUNCTION is a constructor." + `(semantic-token-function-extra-spec ,function 'constructor) + ) + +(defun kde-function-const (function) + "Returns t if the FUNCTION has been declared as const, e.g. +if given a token representing \"int getInt() const\" this functions +would return t" + (save-excursion + (let ((start (semantic-token-start function)) + (end (semantic-token-end function))) + (goto-char end) + (if (re-search-backward "const\b*;" start t) + t + nil) + ) + )) + +(defun kde-is-prototype (function) + "Returns t if the FUNCTION is only a prototype." + (cond + ((semantic-token-function-extra-spec function 'prototype) + t) + (t + (kde-function-const function)) + )) + + + +(defun kde-function-at-point (pt) + "Return function at pt as a token." + (save-excursion + (let ((token) + (what (semantic-find-nonterminal-by-position pt (current-buffer))) + (ctx)) + (goto-char pt) + (if (eq (semantic-token-token what) 'function) + what + (semantic-find-nonterminal-by-position pt (semantic-token-type-parts what))) + ) + )) + +(defun kde-function-construct (token pclass) + "Constructs a function string from the TOKEN, with the parent class PCLASS." + (let ((fname (semantic-token-name token))) + (if (semantic-token-function-destructor token) + (setq fname (concat "~" fname)) + ) + (if pclass + (setq fname (concat pclass "::" fname)) + ) + (if (and + (not (kde-is-constructor token)) + (not (semantic-token-function-destructor token))) + (progn + (cond + ((stringp (semantic-token-type token)) + (setq fname (concat (semantic-token-type token) "\n" fname)) + ) + (t + (setq fname (concat (car (semantic-token-type token)) "\n" fname))) + ) + (if (semantic-token-function-extra-spec token 'const) + (setq fname (concat "const " fname)) + ) + ) + ) + (setq fname (concat fname (kde-format-args (semantic-token-function-args token)))) + (if (kde-function-const token) + (setq fname (concat fname " const" )) + ) + (setq fname (concat fname "\n{" "\n}")) + fname + ) + ) + +(defun kde-class-expand (class-token) + "Returns stubs for member functions as a string. +class-token has to be a token representing either a class or a struct." + (let ((ret "") + (name (semantic-token-name class-token)) + (parents (semantic-token-type-parent class-token)) + (parts (semantic-token-type-parts class-token)) + (cur-token) + (cur-token-name) + (asignal) + (aslot) + (namespace) + ) + (dolist (elt parts ret) + (setq cur-token (semantic-token-token elt)) + (setq cur-token-name (semantic-token-name elt)) + (cond + ((and + (eq cur-token 'type) + (stringp cur-token-name)) + (cond + ((string= cur-token-name "class") + (kde-class-expand elt) + ) + ((string= cur-token-name "enum") + ;;skip enums + ) + ((string= cur-token-name "struct") + (kde-class-expand elt) + ) + ) + ) + ((and + (eq cur-token 'function) + (stringp cur-token-name)) + ;;FUNCTION - generate a skeleton for it + (if (and (kde-is-prototype elt) + (not asignal)) + (setq ret (concat ret (kde-function-construct elt name) "\n\n")) + ) + ;(insert (kde-function-documentation elt) "\n") + ) + ((and + (eq cur-token 'label) + (stringp cur-token-name)) + (setq aslot nil + asignal nil) + ;;LABEL - unsets both signals and slots + ) + ((and + (eq cur-token 'variable) + cur-token-name) + ;;VARIABLE - doesn't handle static variables correctly right now + ) + ((not (stringp cur-token-name)) + (cond + ((kde-label-signals (car (semantic-token-extent elt))) + ;;SIGNALS - next prototypes belong to signals and we don't want to + ;; expand those + (setq asignal t + aslot nil) + ) + ((kde-label-namespace (car (semantic-token-extent elt))) + ;;NAMESPACE - semantic doesn't handle things like Qt::ButtonState correctly + ;; so we do ;) + (setq namespace (kde-label-namespace (car (semantic-token-extent elt)))) + ) + ((kde-label-slots (car (semantic-token-extent elt))) + ;;SLOTS - for now just unset signals + (setq aslot t + asignal nil) + ) + (t + (insert "something else at " (number-to-string (car (semantic-token-extent elt))) "\n")) + )) + (t + (insert "Unknown type :: " (prin1-to-string elt) " >>" (prin1-to-string cur-token) "\n")) + ) + ) + ret + ) + ) + +(defun kde-expand-tokens (tokens) + "Expands smenatic tokens to strings." + (let ((ret "")) + (dolist (elt tokens ret) + (cond + ((eq (semantic-token-token elt) 'type) + (setq ret (concat ret (kde-class-expand elt))) + ) + ((eq (semantic-token-token elt) 'function) + (if (kde-is-prototype elt) + (setq ret (concat ret (kde-function-construct elt nil) "\n\n")) + ) + ) + ((eq (semantic-token-token elt) 'variable) + ;; skip + ;;(kde-extract-variable elt) + ) + ((eq (semantic-token-token elt) 'include) + ;;ignore includes for now + ) + (t (insert "Unknown type : " (prin1-to-string (semantic-token-type elt)) "\n")) + ) + ) + ) + ) + + +(defun kde-tokens-in-file (FILENAME) + "Returns all tokens from a file with the FILENAME." + (let ((exists (file-readable-p FILENAME)) + (buf (current-buffer)) + (tokens)) + (if exists + (progn + (find-file FILENAME) + (setq tokens (semantic-bovinate-toplevel t)) + (switch-to-buffer buf) + tokens) + nil) + )) + +(defun kde-function-in-file (FUNC FILENAME) + "Returns non-nil if FUNC is in a file named FILENAME" + (let ((tokens (kde-tokens-in-file FILENAME))) + (if tokens + (kde-function-in-tokens FUNC tokens) + nil + ) + )) + +(defun kde-function-is-expanded (FUNC) + "Returns t if the function FUNC has been expanded." + (let ((file (kde-file-get-cpp-h))) + (if (cdr file) + (if (kde-function-in-file FUNC (car file)) + t + nil + ) + nil) + )) + +(defun kde-function-expanded-at-point (PT) + "Returns non-nil if the function at point PT has already been expanded." + (interactive "d") + (let ((func (kde-function-at-point PT))) + (kde-function-is-expanded func) + ) + ) + +(defun kde-create-skeletons () + "Creates functions stubs in the source file, for all functions +in the current header file." + (interactive) + (let* ((all-tokens (semantic-bovinate-toplevel t)) + (filename (buffer-name)) + (cppfile (car (kde-file-get-cpp-h))) + (funcs (kde-expand-tokens all-tokens))) + (find-file cppfile) + (save-excursion + (insert "#include \"" filename "\"\n\n") + (insert funcs) + ) + ) + ) + +(defun kde-function-expand-at-point (PT) + "Expand function at point PT." + (interactive "d") + (let ((object (semantic-find-nonterminal-by-position PT (current-buffer))) + (func (kde-function-at-point PT)) + (file) + (buf) + (parent)) + (if (and object (equal (semantic-token-type object) "class")) + (setq parent (semantic-token-name object))) + (if (and (not (kde-function-expanded-at-point PT)) + (kde-is-prototype func)) + (progn + (setq func (kde-function-construct func parent)) + (setq file (car (kde-file-get-cpp-h))) + (setq buf (current-buffer)) + (find-file file) + (save-excursion + (goto-char (point-max)) + (insert "\n" func "\n") + ) + (switch-to-buffer buf) + ) + (error "Function already expanded or defined!") + ) + ) + ) + +(provide 'kde-emacs-semantic) diff --git a/scripts/kde-emacs/kde-emacs-tips.texi b/scripts/kde-emacs/kde-emacs-tips.texi new file mode 100644 index 00000000..ee7c0f19 --- /dev/null +++ b/scripts/kde-emacs/kde-emacs-tips.texi @@ -0,0 +1,257 @@ +\input texinfo @c -*-texinfo-*- + +@finalout + +@c %**start of header +@setfilename kde-emacs-tips +@settitle KDE Emacs usefull programming tips +@footnotestyle end +@c @setchapternewpage odd !! we don't want blank pages +@c %**end of header + +@dircategory Emacs +@direntry +* KDE Emacs: (kde-emacs). Emacs mode for editing KDE/QT C++/C code. +@end direntry + +@ifnottex +Copyright @copyright{} 2002 Zack Rusin and KDE Development Team + +Permission is granted to copy, distribute and/or modify this document +under the terms of the GNU Free Documentation License, Version 1.1 or +any later version published by the Free Software Foundation; with the +Invariant Sections being ``The GNU Manifesto'', ``Distribution'' and +``GNU GENERAL PUBLIC LICENSE'', with the Front-Cover texts being ``A GNU +Manual'', and with the Back-Cover Texts as in (a) below. A copy of the +license is included in the section entitled ``GNU Free Documentation +License'' in the Emacs manual. + +(a) The FSF's Back-Cover Text is: ``You have freedom to copy and modify +this GNU Manual, like GNU software. Copies published by the Free +Software Foundation raise funds for GNU development.'' + +This document is part of a collection distributed under the GNU Free +Documentation License. If you want to distribute this document +separately from the collection, you can do so by adding a copy of the +license to the document, as described in section 6 of the license. +@end ifnottex + +@titlepage +@sp 10 + +@center @titlefont{KDE Emacs Package} +@sp 2 +@center @subtitlefont{KDE Emacs package documentation and programming tips.} +@sp 2 +@author Zack Rusin + +@page +@vskip 0pt plus 1filll +Copyright @copyright{} 2002 Zack Rusin & KDE Development Team +@sp 1 +Permission is granted to copy, distribute and/or modify this document +under the terms of the GNU Free Documentation License, Version 1.1 or +any later version published by the Free Software Foundation; with the +Invariant Sections being ``The GNU Manifesto'', ``Distribution'' and +``GNU GENERAL PUBLIC LICENSE'', with the Front-Cover texts being ``A GNU +Manual'', and with the Back-Cover Texts as in (a) below. A copy of the +license is included in the section entitled ``GNU Free Documentation +License'' in the Emacs manual. + +(a) The FSF's Back-Cover Text is: ``You have freedom to copy and modify +this GNU Manual, like GNU software. Copies published by the Free +Software Foundation raise funds for GNU development.'' + +This document is part of a collection distributed under the GNU Free +Documentation License. If you want to distribute this document +separately from the collection, you can do so by adding a copy of the +license to the document, as described in section 6 of the license. +@end titlepage + +@node Top, Introduction, (dir), (dir) +@comment node-name, next, previous, up + +@macro kdeemacs +KDE Emacs +@end macro + +@ifinfo +@top @kdeemacs{} + +@kdeemacs{} is an Emacs package with tons of useful features +which ease KDE development process. +KDE Emacs usefull programming tips. + +@end ifinfo + +@menu +* Introduction:: +* Getting Connected:: +* Generating stubs:: +* Tips:: +@end menu + +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +@node Introduction, Getting Connected, Top, Top +@comment node-name, next, previous, up +@chapter Introduction +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +@node Getting Connected, Generating stubs, Introduction, Top +@comment node-name, next, previous, up +@chapter Getting Connected +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +@menu +* Sect. 2.1:: Installation +* Sect. 2.2:: Files +* Sect. 2.3:: Keybindings +@end menu + +@node Sect. 2.1, Sect. 2.2, Chapter 2, Chapter 2 +@section @code{Installation} +@comment node-name, next, previous, up + +@node Sect. 2.2, Sect. 2.3, Sect. 2.1, Chapter 2 +@section @code{Files} +@comment node-name, next, previous, up + +@node Sect. 2.3, , Sect 2.2, Chapter 2 +@section @code{Keybindings} +@comment node-name, next, previous, up + +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +@node Generating stubs , Tips, Getting Connected, Top +@comment node-name, next, previous, up +@chapter Generating stubs +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +@node Tips, Top, Generating stubs, Top +@comment node-name, next, previous, up +@chapter Tips +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +@sp 1 +@strong{Q.} @emph{How do I hide #ifdef's in source files without +actually changing them?} + +@strong{A.} Use @code{hide-ifdef-mode} which supports hiding of ifdef +blocks without actually changing the file. In this mode @kbd{C-c @@ +C-d} hides ifdef block and @kbd{C-c @@ C-s} shows it again. + +@sp 1 +@strong{Q.} @emph{How do I get more informations about the keybindings +of the currently active modes?} + +@strong{A.} Type @kbd{M-x describe-mode}. + +@sp 1 +@strong{Q.} @emph{How do I get automatic syntax higlighting of my +custom types?} + +@strong{A.} Use a package named @file{ctypes.el} which does exactly +that. + +@sp 1 +@strong{Q.} @emph{Is it possible to highlight dangerous syntax, just +like Borland JBuilder does it?} + +@strong{A.} Yes, use the @file{cwarn.el} package. + +@sp 1 +@strong{Q.} @emph{How do I easily customize Emacs faces/colors?} + +@strong{A.} Use the @file{color-theme.el} package. + +@sp 1 +@strong{Q.} @emph{How do I set the taskbar Emacs identification string?} + +@strong{A.} To your @file{.emacs} add a line like: +@example +(setq frame-title-format "%b (%m)") +@end example +which will display ``filename (mode)'' type of string in the +taskbar. Type @kbd{C-h v frame-title-format} to get more info. + +@sp 1 +@strong{Q.} @emph{Can I make Emacs jump to the matching parenthesis +with @kbd{%} just like vi?} + +@strong{A.} Yes, just add to your @file{.emacs} something like: +@example +;; Make the % key jump to the matching {}[]() if on another, like VI +(global-set-key "%" 'match-paren) + +(defun match-paren (arg) + "Go to the matching parenthesis if on parenthesis otherwise insert %." + (interactive "p") + (cond ((looking-at "\\s\(") (forward-list 1) (backward-char 1)) + ((looking-at "\\s\)") (forward-char 1) (backward-list 1)) + (t (self-insert-command (or arg 1))))) +@end example + +@sp 1 +@strong{Q.} @emph{Can I have words like FIXME, TODO, HACK or NOTE +higlighted in documentation strings?} + +@strong{A.} Yes, either use @file{code-keywords.el} package or wait +till I'll add it to @kdeemacs{}. + +@sp 1 +@strong{Q.} @emph{I really, really hate identifiersNamedLikeThis. I'd +like to change them to identifiers_named_like_this but the +maintainer of the application/library that I'm hacking on doesn't +agree with me. What can I do? } + +@strong{A.} Use the @file{glasses.el} package which changes +identifiersNamedLikeThis to identifiers_named_like_this in the +buffers you're editing and switches them back to their original form +once you save those buffers. + +@sp 1 +@strong{Q.} @emph{Is it possible to get function completion or +signature display in Emacs? Will it ever be done?} + +@strong{A.} Yes and yes. I've been planning on doing this for quite a +while and hopefully will have this finished pretty soon (no dates +though :) ) The first thing that should be done is writing a few +fixes for the Semantic package (@file{c.bnf} to be more exact), +because Semantic doesn't handle templates, member function declared +as const or KDE access specifiers, once this is done all that will be +left is using semanticdb package which efficiently stores and retrieves +large amounts of tokens and then displaying tokens belonging to types at +point which match current context. + +@sp 1 +@strong{Q.} @emph{Is there a package that would highlight changes that +I made to a certain file?} + +@strong{A.} I wouldn't be writing this if there wouldn't - try +@kbd{M-x highlight-changes-mode}. + +@sp 1 +@strong{Q.} @emph{How to get a diff between the stuff I have in my +local buffer and the file on disk?} + +@strong{A.} Use ibuffer package. After @kbd{M-x ibuffer} typing +@kbd{=} over a file will display a diff between the buffer and the +file on the disk. + +@sp 1 +@strong{Q.} @emph{I want to temporarily highlight certain variable in +a file, how to do it?} + +@strong{A.} Type @kbd{M-x hi-lock-mode}, now @kbd{C-x w h +@emph{regexp} @key{RET} @emph{face} @key{RET}} highlights regexp with +face in the current file and @kbd{C-x w r @emph{regexp} @key{RET}} +unhighlights it. + +@node Concept Index, , Variables Index, Top +@c node-name, next, previous, up +@unnumbered Concept Index + +@printindex cp + +@contents +@bye diff --git a/scripts/kde-emacs/kde-emacs-utils.el b/scripts/kde-emacs/kde-emacs-utils.el new file mode 100644 index 00000000..c6904539 --- /dev/null +++ b/scripts/kde-emacs/kde-emacs-utils.el @@ -0,0 +1,894 @@ +;; kde-emacs-utils.el +;; +;; Copyright (C) 2002-2005 KDE Development Team <www.kde.org> +;; +;; This library is free software; you can redistribute it and/or +;; modify it under the terms of the GNU Lesser General Public +;; License as published by the Free Software Foundation; either +;; version 2.1 of the License, or (at your option) any later version. +;; +;; This library is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +;; Lesser General Public License for more details. +;; +;; You should have received a copy of the GNU Lesser General Public +;; License along with this library; if not, write to the Free Software +;; Foundation, Inc., 51 Franklin Steet, Fifth Floor, Boston, MA +;; 02110-1301 USA + + +(require 'kde-emacs-vars) +(require 'kde-emacs-general) +(require 'kde-emacs-compat) + +(if (eq kde-emacs-type 'xemacs) + (progn + (require 'func-menu) + (add-hook 'find-file-hooks 'fume-add-menubar-entry)) + (require 'imenu)) + +(defmacro c-safe-scan-lists (from count depth) + "Like `scan-lists' but returns nil instead of signalling errors. +This function does not do any hidden buffer changes." + (if (featurep 'xemacs) + `(scan-lists ,from ,count ,depth nil t) + `(c-safe (scan-lists ,from ,count ,depth)))) + +;; returns non-nil if the given file has a using declaration +;; with the passed namespace +(defun kde-file-has-using (namespace) + (let (found) + (save-excursion + (beginning-of-buffer) + (setq found (re-search-forward "^using" nil 1)) + (if found + (setq found (search-forward namespace (line-end-position) 1)) + ) + ) + found) + ) + +;; returns non-nill if the given file has a "namespace SomeNM" declaration +;; where SomeNM is passed via the namespace argument +(defun kde-file-is-in-namespace (namespace) + (let (found) + (save-excursion + (beginning-of-buffer) + (setq found (re-search-forward "^namespace" nil 1)) + (if found + (setq found (search-forward namespace (line-end-position) 1)) + ) + ) + found) + ) + +; Helper function for parsing our current position in a C++ header file +; returns (namespace (class function)) where (a b) is a cons. +(defun method-under-point () + (let ((class nil) + (namespace "") ; will contain A::B:: + (function nil)) + (save-excursion + (backward-char) ; in case we're after the ';' + (search-forward ";" nil t) ; look for the ';' + (backward-char) + (save-excursion + ; Go up a level, skipping entire classes etc. + ; This is a modified version of (backward-up-list) which doesn't + ; throw an error when not found. + (let ((pos (c-safe-scan-lists (point) -1 1))) + ; +1 added here so that the regexp in the while matches the { too. + (goto-char (if pos (+ pos 1) (point-min)))) + (while (re-search-backward "^[ ]*\\(class\\|namespace\\|struct\\)[ \t][^};]*{" nil t) + (save-excursion + (forward-word 1) + (when (looking-at "[ \t]*[A-Z_]*_EXPORT[A-Z_]*[ \t]") + (forward-word 1) + (re-search-forward "[ \t]" nil t)) + (while (looking-at "[ \t]") + (forward-char 1)) + (setq start (point)) + ; Parse class name ("Foo" or "Foo::Bar::Blah"). + ; Beware of "Foo:" + (while (or (looking-at "[A-Za-z0-9_]") (looking-at "::")) + (while (looking-at "[A-Za-z0-9_]") + (forward-char 1)) + (while (looking-at "::") + (forward-char 2)) + ) + (cond + (class ; class found already, so the rest goes into the namespace + (setq namespace (concat (buffer-substring start (point)) "::" namespace))) + (t ; class==nil + (setq class (buffer-substring start (point))))) + ) + ; Go up one level again + (let ((pos (c-safe-scan-lists (point) -1 1))) + (goto-char (if pos (+ pos 1) (point-min)))) + )) + + ; Back to where we were, parse function name + (let ((end (point))) ; remember where the function decl ends + (search-backward ")" nil t) ; look back for the end of the argument list + (forward-char) + (backward-sexp) ; brings us back to the '(' + (backward-word 1) + (when (looking-at "throw[ \t]") ; exception specification, look for () again + (search-backward ")" nil t) + (forward-char) + (backward-sexp)) + ; now that we moved back enough, go to beginning of line. + ; (we assume that the return type, function name, and '(' are on the same line) + (re-search-backward "^[ \t]*") + (while (looking-at "[ \t]") + (forward-char 1)) + (setq function (buffer-substring (point) end)) + ) + ) ; end of global save-excursion + (cons namespace (cons class function)) ; the returned value + ) + ) + +; get rid of virtual, static, multiple spaces, default values. +(defun canonical-function-sig (function) + (and (string-match "[ \t]*\\<virtual\\>[ \t]*" function) + (setq function (replace-match " " t t function))) + (and (string-match "^\\(virtual\\>\\)?[ \t]*" function) + (setq function (replace-match "" t t function))) + (and (string-match "^\\(explicit\\>\\)?[ \t]*" function) + (setq function (replace-match "" t t function))) + (and (string-match "^\\(static\\>\\)?[ \t]*" function) + (setq function (replace-match "" t t function))) + (while (string-match " +" function) ; simplifyWhiteSpace + (setq function (replace-match " " t t function))) + (while (string-match "\t+" function) + (setq function (replace-match " " t t function))) + (while (string-match "^ " function) ; remove leading whitespace + (setq function (replace-match "" t t function))) + (let ((startargs (string-match "(" function))) + (while (string-match " ?=[^,)]+" function startargs) ; remove default values + (setq function (replace-match " " t t function)))) + (while (string-match " +," function) ; remove space before commas + (setq function (replace-match "," t t function))) + function ; the return value +) + +; Helper method which turns the function as seen in the header +; into the signature for its implementation +; Returns the fully-qualified signature of the function implementation +(defun kde-function-impl-sig (namespace class _function) + (let ( + (function (canonical-function-sig _function)) + (insertion-string nil)) + (and (stringp class) + (cond + ((string-match (concat "^ *" class "[ \\t]*(") function) ; constructor + (setq insertion-string + (replace-match + (concat namespace class "::" class "(") + t t function) + )) + ((string-match (concat "^ *~" class "[ \\t]*(") function) ; destructor + (setq insertion-string + (replace-match + (concat namespace class "::~" class "(") + t t function) + )) + )) ; end of "class required" + (if (not (stringp insertion-string)) ; no ctor nor dtor + (if (or (string-match " *\\([a-zA-Z0-9_]+\\)[ \\t]*(" function) ; normal method + (string-match " *\\(operator[^ \\t]+\\)[ \\t]*(" function)) ; operator + (setq insertion-string + (replace-match + (if class + (concat " " namespace class "::" "\\1(") ; c++ method + (concat " " "\\1(")) ; c function + t nil function) + ) + ; else + (error (concat "Can't parse declaration ``" + function "'' in class ``" class + "'', aborting")))) + insertion-string ; the return value + ) + ) + +;; Switch between the declaration of a class member in .cc/.cpp/.C, and its definition in the .h file +;; Written by David and Reggie after much hair tearing +;; Found since, might be worth looking at: http://www.hendawi.com/emacs/sourcepair.el +(defun switch-to-function-def () + (interactive) + (let ((n (buffer-file-name)) + (namespace "") + (class "") + (function "") + found + ) + (if (or (string-match "\\.cc$" n) + (string-match "\\.cpp$" n) + (string-match "\\.C$" n)) + ; TODO replace fume-function-before-point, needed for emacs, + ; and for better namespace support. + ;(progn + ; (let ((pos (kde-scan-lists (point) -1 1 nil t))) ; Go up a level + ; (goto-char (if pos (+ pos 1) (point-min)))) + (let ((a (fume-function-before-point))) + (and (string-match "^\\(.*\\)::\\(.*\\)$" a) + (progn + (setq class (match-string 1 a)) + (setq function (match-string 2 a)) + (kde-switch-cpp-h) + (goto-char 0) + ; Look for beginning of class ("\\s-+" means whitespace including newlines) + (re-search-forward + (concat "\\(class\\|struct\\|namespace\\)\\s-+" + "\\([A-Z_]+_EXPORT[A-Z_]*\\)?\\s-+" ; allow for optional EXPORT macro + class "\\b" ; the classname - with word separator + "[^;]+{" ; the optional inheritance and the '{' + ) nil t) + ;; TODO keep looking, until we find a match that's not inside a comment + (re-search-forward (concat "\\b" (kde-function-regexp-quote function) "[ \t]*(") nil t))))) + (if (string-match "\\.h$" n) + (progn + (let ((mup (method-under-point)) + (sig "") + (pos 0)) + (setq namespace (car mup)) + (setq class (car (cdr mup))) + (setq function (cdr (cdr mup))) + (kde-switch-cpp-h) + + ;; First search with namespace prefixed + (goto-char 0) + (setq sig (kde-remove-newline (kde-function-impl-sig namespace class function))) + (if (string-match "(.*" sig) ; remove args + (setq sig (replace-match "" nil t sig))) + (setq found (re-search-forward (concat "^[^()]*" (kde-function-regexp-quote sig) "[ \t]*(") nil t) ) + + (if (not found) + (progn + ; Now search without name space prefix + + (goto-char 0) + (setq sig (kde-remove-newline (kde-function-impl-sig "" class function))) + + (if (string-match "(.*" sig) ; remove args + (setq sig (replace-match "" nil t sig))) + (re-search-forward (concat "^[^()]*" (kde-function-regexp-quote sig) "[ \t]*(") nil t) ) ) + ))))) + +(defun kde-remove-newline (str) + (replace-in-string str "\n" " ")) +; quote for use as regexp, but replace spaces with "any whitespace" +(defun kde-function-regexp-quote (str) + (replace-in-string (regexp-quote str) "[ \n\t]" "[ \n\t]")) + +; Initial implementation by Arnt Gulbransen +; Current maintainer: David Faure +(defun agulbra-make-member () + "make a skeleton member function in the .cpp or .cc file" + (interactive) + (let* ( + (mup (method-under-point)) + (namespace (car mup)) ; will contain A::B:: + (class (car (cdr mup))) + (function (cdr (cdr mup))) + (file (buffer-file-name)) + (insertion-string (kde-function-impl-sig namespace class function)) + (msubstr nil) + (start nil) + (newcppfile nil) + ) + (setq insertion-string + (concat insertion-string "\n{\n" + (replace-in-string kde-make-member-default-impl "FUNCTION" + ; the function name and args, without newlines + (replace-in-string insertion-string "\n" " " t) + t) + "}\n")) + ; move to next method, to be ready for next call + (backward-char) ; in case we're after the ';' + (re-search-forward ";" nil t) ; end of this method decl + (let ((moveToNext t)) + (while moveToNext + (re-search-forward ";" nil t) ; end of next method decl + (save-excursion + (forward-char -2) ; -1 goes to ';' itself, so go before that + (while (looking-at "[ \t0=]") + (forward-char -1)) + (forward-char 1) + ; move to next method again if we're at a pure virtual method + (setq moveToNext (looking-at "[ \t]*=[ \t]*0;")) + ) + ) + ) + + (setq newcppfile (not (cdr (kde-file-get-cpp-h)))) + (if (string-match "\\.h$" file) + (kde-switch-cpp-h) + ) + (goto-char (point-max)) + (kde-comments-begin) + (kde-skip-blank-lines) + (setq msubstr (buffer-substring (point-at-bol) (point-at-eol))) + (if (string-match "^#include.*moc.*" msubstr) + (progn + (forward-line -1) + (end-of-line) + (insert "\n"))) + (if (string-match "}" msubstr) + (progn + (end-of-line) + (insert "\n") + (forward-line 1) + )) + (when newcppfile + (insert "\n")) + (insert insertion-string) + (forward-char -3) + (c-indent-defun) + (save-excursion + (and (string-match ".*/" file) + (setq file (replace-match "" t nil file))) + (and (string-match "\\.h$" file) + (functionp 'kdab-insert-include-file) + (kdab-insert-include-file file 't nil))) + (when (featurep 'fume-rescan-buffer) + (fume-rescan-buffer)) + )) + +(defun add-file-to-buildsystem () + "Add the current (C++) file to either Makefile.am or a .pro file, whichever exists." + ; Author: David + (interactive) + (if (file-readable-p "Makefile.am") + (add-file-to-makefile-am) + ; else: find a .pro file and add it there + (let* ((files (directory-files "." nil ".pro$" nil t)) + (projfile (car files))) + (if projfile + (add-file-to-project projfile "^SOURCES[ \t]*") ; could be SOURCES= or SOURCES+= + ; else: error + (error "No build system file found") + ))) + ) + +; internal helper for add-file-to-* +(defun add-file-to-project (makefile searchString) + (let ((file (buffer-name))) + (if (not (file-readable-p makefile)) + (error (concat makefile " not found!")) + ) + (find-file makefile) + (goto-char (point-min)) + (if (re-search-forward searchString nil t) + (progn + (end-of-line) + ; check if line ends with '\' [had to read make-mode.el to find this one!] + (while (= (char-before) ?\\) + (end-of-line 2)) ; moves to end of next line + (insert " ") + (insert file) + ) + (error (concat searchString " not found")) + )) + ) + +(defun add-file-to-makefile-am () + "Add the current file to the first _SOURCES line in the Makefile.am" + ; Author: David + (interactive) + (add-file-to-project "Makefile.am" "_SOURCES") + ) + + +; Inserts a kdDebug statement showing the name of the current method. +; You need to create the empty line first. +(defun insert-kdDebug () + (interactive) + (insert "kdDebug() << ") + ;; no unnecessary fume-* functions which aren't available on GNU/Emacs + (insert "k_funcinfo") + (insert " << endl;") + ) + +; finds a string to be used in the header-protection function ( see below ) +(defun kde-header-protection-definable-string () + (let* ((definablestring "") + (f (buffer-file-name)) + (parts (nreverse (split-string f "/"))) + (i) + (first-iter t) + (iters (min (length parts) kde-header-protection-parts-to-show))) + (dotimes (i iters) + (let ((part (pop parts))) + (setq definablestring + (concat + (upcase (replace-in-string part "[\\.-]" "_")) + (if (not first-iter) "_" "") + definablestring + ) + ) + (setq first-iter nil) + ) + ) + definablestring + ) + ) + +; Creates the ifndef/define/endif statements necessary for a header file +(defun header-protection () + (interactive) + (let ((s (kde-header-protection-definable-string))) + (save-excursion + (goto-char (point-min)) + (insert "#ifndef " s "\n#define " s "\n\n") + (goto-char (point-max)) + (insert "\n#endif\n") + ) + ) + ) + +; Makes '(' insert '(' or ' ( ' where appropiate +(defun insert-parens (arg) (interactive "*P") + (if (not (c-in-literal)) + (let ((n nil) (except nil)) + (save-excursion + (setq n (or (progn (forward-char -2) (looking-at "if")) + (progn (forward-char -1) (looking-at "for")) + (progn (forward-char -1) (looking-at "case")) + (progn (forward-char -1) (looking-at "while")) + ) + ) + (setq except (or (progn (forward-char -2) (looking-at "kdDebug")) + (looking-at "kdError") + (progn (forward-char -2) (looking-at "kdWarning")) + ) + ) + ) + (cond + (n (progn + (insert " ") + (self-insert-command (prefix-numeric-value arg)) + (insert kde-emacs-after-parent-string) + )) + (t ;else + (self-insert-command (prefix-numeric-value arg)) + (cond ((not except) (insert kde-emacs-after-parent-string))) + ))) + (self-insert-command (prefix-numeric-value arg))) + ) + +(defun insert-parens2 (arg) (interactive "*P") + (if (not (c-in-literal)) + (let ((remv nil) (nospac nil)) + (forward-char -2) + (setq remv (looking-at "( ")) ; () -> we'll have to remove that space + (forward-char 1) + (setq nospac ; no space to be added + (or (looking-at " ") + (looking-at "(") + (save-excursion ; check for kdDebug(123 + (while (looking-at "[0-9]") + (forward-char -1)) + (forward-char -7) + (or (looking-at "kdDebug(") + (looking-at "kdError(") + (progn (forward-char -2) (looking-at "kdWarning(")) + ) + ) + ) + ) + (forward-char 1) + (cond + (remv (progn + (delete-backward-char 1) + (self-insert-command (prefix-numeric-value arg)))) ; the () case + (nospac (self-insert-command (prefix-numeric-value arg))) ; no space to be added + (t ;else + (if abbrev-mode ; XEmacs + (expand-abbrev)) + (insert kde-emacs-after-parent-string) + (self-insert-command (prefix-numeric-value arg)) + ))) ; normal case, prepend a space + ;;(blink-matching-open) ; show the matching parens + (self-insert-command (prefix-numeric-value arg))) + ) + +; Makes ',' insert ', ' +(defun insert-comma (arg) + (interactive "*P") + (let* ((ch (char-after)) + (spacep (not (or (eq ch ? ) + (c-in-literal) + arg)))) + (self-insert-command (prefix-numeric-value arg)) + (if spacep + (insert " ")))) + +(defun insert-semicolon (arg) + (interactive "*P") + (self-insert-command (prefix-numeric-value arg)) + (newline-and-indent)) + +(defun insert-curly-brace (arg) (interactive "*P") + (if (not (c-in-literal)) + (let ((n nil) (o nil) + (spacep nil) (c nil) + (oneliner nil)) + (save-excursion + (save-excursion + (if (re-search-forward "[a-zA-Z]" (point-at-eol) t) + (setq oneliner t))) + (forward-char -1) ; These three lines are for the situation where + (if (not (looking-at " ")) ; the user already have inserted a space after + (forward-char 1) ; the closing parenthesis + (setq spacep t)) + (forward-char -2) + (setq o (looking-at "()")) + (forward-char 1) + (setq n (looking-at ")")) + (if (and + (not oneliner) + (not (eq + (count-lines (point-min) (point)) + (count-lines (point-min) (point-max))))) + (progn + (next-line 1) + (beginning-of-line) + (if (re-search-forward "[a-zA-Z]" (point-at-eol) t) + (setq c (eq (car (car (c-guess-basic-syntax))) 'substatement))) + ) + ) + ) + (cond + (n (progn + (if (not spacep) (insert " ")) + (self-insert-command (prefix-numeric-value arg)) + (if (not c) (newline-and-indent)) + (if oneliner (end-of-line)) + (save-excursion + (if c + (progn + (next-line 1) + (end-of-line) + )) + (newline-and-indent) + (insert "}")(c-indent-line)) + (c-indent-line) + )) + (o (progn + (newline) + (self-insert-command (prefix-numeric-value arg)) + (newline-and-indent))) + (t (progn ;else + (self-insert-command (prefix-numeric-value arg)) + (save-excursion + (beginning-of-line) + (c-indent-command)))) + )) + (self-insert-command (prefix-numeric-value arg)) + ) +) + +;; have PelDel mode work +(put 'insert-parens 'pending-delete t) +(put 'insert-parens2 'pending-delete t) +(put 'insert-comma 'pending-delete t) +(put 'insert-curly-brace 'pending-delete t) +(put 'newline-and-indent 'pending-delete t) + +; A wheel mouse that doesn't beep, unlike mwheel-install +(defun scroll-me-up () (interactive) (scroll-up 4)) +(defun scroll-me-down () (interactive) (scroll-down 4)) +(defun scroll-me-up-a-bit () (interactive) (scroll-up 1)) +(defun scroll-me-down-a-bit () (interactive) (scroll-down 1)) + +; Compilation +(defun makeclean () + "Executes a \"make clean\" in the current directory" + (interactive) + (compile (concat kde-emacs-make " clean")) + ) + +(defun make () + "Executes a \"make\" in the current directory" + (interactive) + (compile (concat kde-emacs-make " -k")) + ) + +(defun makeinstall () + "Executes a \"make install\" in the current directory" + (interactive) + (compile (concat kde-emacs-make " -k install")) + ) + +(defun makeinstallexec () + "Executes a \"make install-exec\" in the current directory" + (interactive) + (compile (concat kde-emacs-make " -k install-exec")) + ) + +(defun makethisfile () + "Try to compile the currently opened file" + (interactive) + (let ((f (file-name-nondirectory (buffer-file-name))) + (objext nil)) + + (if (file-readable-p "Makefile.am") + (setq objext "\.lo") + (setq objext "\.o")) + (if (string-match "\.cpp$" f) (setq f (replace-match objext t t f))) + (if (string-match "\.cc$" f) (setq f (replace-match objext t t f))) + (compile (concat kde-emacs-make " " f))) + ) + +;; pc-like textmarking +(when kde-use-pc-select + (progn + (load "pc-select") + (if (eq kde-emacs-type 'xemacs) + (funcall 'pc-select-mode) + (funcall 'pc-selection-mode)))) + + +; Move in other window +(defun scroll-other-up () (interactive) (scroll-other-window-down 1)) ; hehe :) +(defun scroll-other-down () (interactive) (scroll-other-window 1)) + +(defun match-paren (arg) + "Go to the matching parenthesis if on parenthesis otherwise insert %." + (interactive "p") + (cond ((looking-at "\\s\(") (forward-list 1) (backward-char 1)) + ((looking-at "\\s\)") (forward-char 1) (backward-list 1)) + (t (self-insert-command (or arg 1))))) + +(defun kde-start-c++-header () + "Start a new C++ header by inserting include guards ( see \ + header-protection function ), inserting a license statement \ + and putting (point) at the correct position" + (interactive) + (header-protection) + (insert "\n") + (beginning-of-buffer) + (kde-license-insert "GNU GPL") + (next-line 1) + (kill-line) + (end-of-buffer) + (next-line -3) + (insert "\n") +) + +(defun kde-year-range-parse-years-string (string) + "parses something like \"2000, 2008-2010\" into a list of the form \ + ((2008 . 2010)(2000 . 2000))" + (let ((pos -1) + (oldpos) + (l (length string)) + (currange "") + (startyear) + (endyear) + (ret) + ) + (while (< pos l) + (setq oldpos (+ pos 1)) + (setq pos (string-match "[,]" string (+ pos 1))) + (unless pos (setq pos l)) + (setq currange (substring string oldpos pos)) + (string-match "[0-9]+" currange) + (setq startyear (string-to-int (match-string 0 currange))) + (setq endyear + (if (string-match "-" currange) + (string-to-int (substring currange (match-end 0))) + startyear)) + (setq ret (cons (cons startyear endyear) ret)) + ) + ret + ) + ) + +(defun kde-year-range-contains-year (ranges year) + "checks whether year is in ranges.. ( ranges is a list as \ + kde-year-range-parse-years-string returns.. " + (let ((ret)) + (dolist (range ranges ret) + (when (and (>= year (car range)) (<= year (cdr range))) + (setq ret t)) + ))) + +(defun kde-year-range-to-string (ranges) + "converts ranges to a string.." + (let ((ret "")) + (dolist (range ranges) + (setq ret + (concat + (int-to-string (car range)) + (if (/= (cdr range) (car range)) + (concat "-" (int-to-string (cdr range))) + "") + ", " + ret) + ) + ) + ; remove extraneous ", " + (setq ret (substring ret 0 (- (length ret) 2))) + ) + ) + +; merges adjacent year ranges into one.. +(defun kde-year-range-cleanup (range) + (let ((origrange range)) + (while (and range (cdr range)) + (let ((years (car range)) (nyears (cadr range))) + (when (>= (+ (cdr nyears) 1) (car nyears)) + (setcar range (cons (car nyears) (cdr years))) + (setcdr range (cddr range))) + ) + (setq range (cdr range)) + ) + origrange + ) + ) + +; adds year to range.. +(defun kde-year-range-add-year (range year) + (while range + (let ((years (car range))) + (cond + ((and (>= year (car years)) (<= year (cdr years)) + ; year is already in the range.. + (setq range nil))) + ((= year (+ (cdr years) 1)) + (setcdr years year) + (setq range nil)) + ((= year (- (car years) 1)) + (setcar years year) + (setq range nil)) + ) + ) + (setq range (cdr range)) + ) + (kde-year-range-cleanup range) + ) + +(defun kde-add-copyright () (interactive) + "Tries to add your kde-full-name and kde-email to the Copyright \ + statements at the top of a file... It tries to figure out \ + if it's already there, and if so, updates the line to include the \ + current year.. ( well, replaces it by a new one, anyway :) )" + (let ((wascomment "")) + (save-excursion + (beginning-of-buffer) + (if (re-search-forward (concat "Copyright ([Cc]) \\([0-9 ,-]*\\) " (regexp-quote kde-full-name)) nil t) + (progn + (beginning-of-line) + (let ((years (kde-year-range-cleanup (kde-year-range-parse-years-string (match-string 1)))) + (new-copyright-string "Copyright (C) ") + (this-year (string-to-int (format-time-string "%Y")))) + (when (not (kde-year-range-contains-year years this-year)) + (kde-year-range-add-year years this-year)) + (setq new-copyright-string + (concat new-copyright-string (kde-year-range-to-string years))) + ; finish new-copyright-string + (setq new-copyright-string + (concat new-copyright-string " " kde-full-name " <" kde-email ">")) + (beginning-of-line) + (re-search-forward "Copyright ([Cc])") + (beginning-of-line) + (setq wascomment + (buffer-substring (point) + (match-beginning 0) + )) + (kill-line nil) + (insert new-copyright-string) + ) + ) + (beginning-of-buffer) + (let ((first-copyright-str (re-search-forward "Copyright ([Cc])" nil t))) + (if first-copyright-str + (progn + (goto-char first-copyright-str) + (beginning-of-line) + (setq wascomment (buffer-substring (point) (match-beginning 0))) + (forward-line 1) + ) + (goto-line 2)) + ) + (beginning-of-line) + (insert "Copyright (C) " (format-time-string "%Y") " " + kde-full-name " <" kde-email ">\n") + (forward-line -1) + ) + (end-of-line) + (let ((end (point))) + (beginning-of-line) + (insert wascomment) + ) + ) + ) + ) + +(defun kde-emacs-file-style-update () + "Updates the style header of this file" + (interactive) + (if (or (eq major-mode 'c++-mode) + (eq major-mode 'c-mode)) + (let ((startpoint) (endpoint) + (firstline) (strings) + (str) (m) (m2) (var) (value) + (final)) + (save-excursion + (beginning-of-buffer) + (setq startpoint (point)) + (setq endpoint (point-at-eol))) + (setq firstline (buffer-substring startpoint endpoint)) + (if (string-match "-\*-\\([A-Za-z0-9\-\+\:\; ]+\\)-\*-" firstline) + (delete-region startpoint endpoint)) + (setq final (concat "-*- " + "Mode: " mode-name "; " + "c-basic-offset: " (prin1-to-string c-basic-offset) "; " + "indent-tabs-mode: " (prin1-to-string indent-tabs-mode) "; " + "tab-width: " (prin1-to-string tab-width) "; " + "-*-")) + (save-excursion + (beginning-of-buffer) + (insert final) + (comment-region (point-at-bol) (point-at-eol)) + (newline))))) + +; Helper for qt-open-header, for Qt 4. Opens a file if it says #include "../foo/bar.h", +; close it and open that file instead; recursively until finding a real file. +(defun qt-follow-includes (file) + (let ((line "") + (begin nil) + (buffer nil)) + (find-file file) + (goto-char 0) + (if (looking-at "#include \"") + (progn + (forward-char 10) + (setq begin (point)) + (re-search-forward "\"" nil t) + (backward-char 1) + (setq file (buffer-substring begin (point))) + (setq buffer (current-buffer)) + (qt-follow-includes file) + (kill-buffer buffer) + ) + ; else: this is the right file, skip the comments and go to the class + (progn + (re-search-forward "^class" nil t) + (beginning-of-line)) + ))) + +(defun qt-open-header () + "Open the Qt header file for the class under point" + (interactive) + (let* ((qtinc (concat (getenv "QTDIR") "/include/")) + (class (thing-at-point 'word)) + (f nil) + (file nil) + (files nil) + ) + (save-excursion + ; The Qt3 case: the includes are directly in $QTDIR/include/, lowercased + (setq f (concat qtinc (downcase class) ".h" )) + (if (file-readable-p f) + (setq file f) + ; For some Qt3/e classes: add _qws + (setq f (concat qtinc (downcase class) "_qws.h" )) + (if (file-readable-p f) + (setq file f) + ; The Qt4 case: the includes are in $QTDIR/include/QSomething/, in original case + (setq files (directory-files qtinc t nil "dirsonly")) + (dolist (f files nil) + (if (file-readable-p (concat f "/" class) ) + (setq file (concat f "/" class)))) + )) + (and file + (qt-follow-includes file)) + ) + )) + +(provide 'kde-emacs-utils) diff --git a/scripts/kde-emacs/kde-emacs-vars.el b/scripts/kde-emacs/kde-emacs-vars.el new file mode 100644 index 00000000..216e64f5 --- /dev/null +++ b/scripts/kde-emacs/kde-emacs-vars.el @@ -0,0 +1,147 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; kde-emacs-vars.el ;; +;; ;; +;; Copyright (C) 2002 Zack Rusin <zack@kde.org> ;; +;; ;; +;; This program is free software; you can redistribute it and/or ;; +;; modify it under the terms of the GNU General Public License ;; +;; as published by the Free Software Foundation; either version 2 ;; +;; of the License, or (at your option) any later version. ;; +;; ;; +;; This program is distributed in the hope that it will be useful, ;; +;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;; +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;; +;; GNU General Public License for more details. ;; +;; ;; +;; You should have received a copy of the GNU General Public License ;; +;; along with this program; if not, write to the Free Software ;; +;; Foundation, Inc., 51 Franklin Steet, Fifth Floor, Boston, MA ;; +;; 02110-1301, USA. ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(defconst kde-emacs-version "0.2" + "KDE Emacs package version number.") +(defun kde-emacs-version () + "Returns the version of KDE Emacs package." + (interactive) + (message "KDE Emacs version : %s" kde-emacs-version)) + + +(defvar kde-emacs-type + (eval-when-compile + (if (string-match "XEmacs" (emacs-version)) + 'xemacs + 'emacs)) + "The type of Emacs we are running on.") + +;*---------------------------------------------------------------------*/ +;* Constants ... */ +;*---------------------------------------------------------------------*/ + +(defconst kde-access-labels + "\\<\\(signals\\|k_dcop\\|\\(public\\|protected\\|private\\)\\([ ]+slots\\)?\\)\\>:" + "KDE specific access labels regexp.") + +(defconst kde-source-files '("cpp" "cc" "cxx" "CC" "C" "c") + "List of source-file extensions.") + +(defconst kde-header-files '("h" "H" "hh" "hxx" "hpp") + "List of header-file extensions.") + +;*---------------------------------------------------------------------*/ +;* Group ... */ +;*---------------------------------------------------------------------*/ +(defgroup kde-devel nil + "Development utilities." + :tag "KDE devel" + :prefix "kdedevel-" + :group 'programming) + +(defcustom kde-full-name (or user-full-name + (getenv "USER") + "Your Name") + "*Name used by kde-emacs." + :group 'kde-devel + :version "0.1" + :type 'string) + +(defcustom kde-email (or user-mail-address + (concat (getenv "LOGNAME") "@" (getenv "HOSTNAME")) + "Your Email") + "*Email address used by kde-emacs." + :group 'kde-devel + :version "0.1" + :type 'string) + +(defcustom kde-cvs-root (concat (getenv "HOME") "/cvs/kde") + "*Root Directory of KDE CVS Respiratory" + :group 'kde-devel + :type 'string) + +(defcustom magic-keys-mode 't + "Set this variable to true to have some special keybindings. E.g. bind '(' to a function which inserts '( ' when appropriate..." + :group 'kde-devel + :type 'boolean) + +(defcustom kde-emacs-make "make" + "Specifies the make command which KDE Emacs will use" + :group 'kde-devel + :type 'string) + +;;Make styles a list of the format (radio (const kde-c++) (const kde-c) style) +;;and assign it to type. +(defcustom kde-c++-style "kde-c++" + "Set this variable to the CC Mode style you would like loaded when you open a C++ KDE source code file..." + :group 'kde-devel + :type 'string) + +(defcustom kde-c-style "kde-c" + "Set this variable to the CC Mode style you would like loaded when you open a C KDE source code file..." + :group 'kde-devel + :type 'string) + +(defcustom kde-use-pc-select 't + "Set this to nil if you really hate PC Select Mode..." + :group 'kde-devel + :type 'boolean) + +(defcustom kde-emacs-newline-semicolon nil + "Set this to true to have typing \";\" automatically insert +a newline." + :group 'kde-devel + :type 'boolean) + +(defcustom kde-header-protection-parts-to-show 1 + "Set this variable to the number of parts from the file name you want to be used for the defined word in the +header-protection function.. E.g. setting this to 3 makes header-protection define KIG_MISC_NEWTYPE_H for a +file named /home/domi/src/kdenonbeta/kig/misc/newtype.h" + :group 'kde-devel + :type 'integer) + +(defcustom kde-emacs-after-parent-string " " + "Set this to whatever you want to have inserted after the first parenthesis. Works only if +magic-keys-mode is set to true. " + :group 'kde-devel + :type 'string) + +(defcustom kde-include-directory nil + "Set this to the directory holding the includes for the current module/project/whatever." + :group 'kde-devel + :type 'string) + +(defcustom kde-source-directory nil + "Set this to the directory holding the sources for the current module/project/whatever." + :group 'kde-devel + :type 'string) + +(defcustom kde-make-member-default-impl " \n" + "Default implementation added by agulbra-make-member. FUNCTION gets replaced by the full signature of the function/method." + :group 'kde-devel + :type 'string) + +; a grep in the part of kde-source I have gives: +; 5579 files uses .cpp, 1402 uses .cc, 10 uses .cxx, and 1 uses .C +(defconst kde-prefered-source-extension "cpp" + "Source extension which kde-* functions should use for creating new files.") + +(provide 'kde-emacs-vars) diff --git a/scripts/kde-emacs/kde-emacs.el b/scripts/kde-emacs/kde-emacs.el new file mode 100644 index 00000000..b2865c53 --- /dev/null +++ b/scripts/kde-emacs/kde-emacs.el @@ -0,0 +1,66 @@ +;; kde-emacs.el +;; Time-stamp: <2002-06-26 00:49:48 zack> +;; +;; Copyright (C) 2002 Zack Rusin <zackrat@att.net> +;; +;; This library is free software; you can redistribute it and/or +;; modify it under the terms of the GNU Lesser General Public +;; License as published by the Free Software Foundation; either +;; version 2.1 of the License, or (at your option) any later version. +;; +;; This library is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +;; Lesser General Public License for more details. +;; +;; You should have received a copy of the GNU Lesser General Public +;; License along with this library; if not, write to the Free Software +;; Foundation, Inc., 51 Franklin Steet, Fifth Floor, Boston, MA +;; 02110-1301 USA + +;;; Installation: +;; +;; Put the following lines in your ".emacs": +;; (add-to-list 'load-path "~/path-to-kde-emacs") +;; (require 'kde-emacs) +;; +;; I also strongly recommend to add the following two lines to +;; .emacs file: +;; (setq kde-full-name "Your Name") +;; (setq kde-email "Your Email") +;; +;; You may want to byte-compile the package to speed it up +;; a bit. To do it in the *scratch* buffer type in the following +;; line: +;; (byte-recompile-directory "~/kde-emacs" t) +;; place the cursor after the closing paren and hit "Ctrl-x Ctrl-e", +;; that's it. +;; +;; All keybindings are in kde-emacs-bindings.el, look at/customize +;; this file before byte-compiling the package! +;; If you want to see things you can customize type: +;; M-x customize-group +;; and type in "kde-devel" group. +;; +;; TODO: +;; - in (if kde-emacs-type... change direct function calls +;; to funcall's +;; + +(require 'cc-mode) ;; needed by kde-emacs-core's test on c-version + +(require 'kde-emacs-compat) +(require 'kde-emacs-core) +(require 'kde-emacs-general) +(require 'klaralv) +(require 'kde-emacs-utils) +(require 'dirvars) + +;; load this only if semantic package is present +(when (featurep 'semantic) + (require 'kde-emacs-semantic) + (require 'kde-emacs-doc)) + +(require 'kde-emacs-bindings) + +(provide 'kde-emacs) diff --git a/scripts/kde-emacs/klaralv.el b/scripts/kde-emacs/klaralv.el new file mode 100644 index 00000000..df29ff78 --- /dev/null +++ b/scripts/kde-emacs/klaralv.el @@ -0,0 +1,422 @@ +;; ------------------------------ COPYRIGHT NOTICE ------------------------------ +;; klaralv.el version 1.3 +;; Copyright Klaralvdalens Datakonsult AB. +;; +;; This program is free software; you can redistribute it and/or modify it +;; under the terms of the GNU General Public License as published by the Free +;; Software Foundation; either version 2 of the License, or (at your option) +;; any later version. +;; +;; This program is distributed in the hope that it will be useful, but +;; WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +;; for more details. +;; +;; You should have received a copy of the GNU General Public License along +;; with GNU Emacs. If you did not, write to the Free Software Foundation, +;; Inc., 675 Mass Ave., Cambridge, MA 02139, USA. + + +;; ------------------------------ INSTALLATION ------------------------------ +;; To use this file, add the current directory to your load path. +;; you do this by inserting something like the following to your .emacs: +;; (setq load-path (cons "/home/blackie/Emacs/" load-path)) +;; +;; Next insert the following line into your .emacs +;; (require 'klaralv) +;; (global-set-key [(f5)] 'kdab-insert-header) +;; (global-set-key [(shift f5)] 'kdab-insert-forward-decl) +;; (setq kdab-qt-documentation "file://usr/local/qt/html/doc/XXX.html") +;; (global-set-key [(control f5)] 'kdab-lookup-qt-documentation) +;; +;; If you use QTopia, and do not want include files to be prefixed with qpe/, +;; as in qpe/qpeapplication, then insert the following code in your setup +;; (setq kdab-prefix-qpe nil) + +;; ------------------------------ CONFIGURATION ------------------------------ +(defvar kdab-qt-documentation + "http://doc.trolltech.com/3.0/XXX.html" + "URL for Qt documentation. XXX must be in the string. + Example: file://packages/kde-src/qt-copy/doc/html/XXX.html") + +(defvar kdab-qpe-documentation + "file://opt/qtopia/doc/XXX.html" + "URL for QTopia documentatin. XXX must be in the string. + Example: file:/opt/qtopia/doc/XXX.html") + + +(defvar kdab-prefix-qpe 't + "set this to nil if you do not want QPE header files prefixed with qpe/") + +;; special case for include files +;; Please notify blackie@klaralvdalens-datakonsult.se with any modification to this variable! +(defvar kdab-special-includes + '( + (qlayout.h QHBoxLayout QVBoxLayout QGridLayout QBoxLayout) + (qlistview.h QListViewItem QCheckListItem QListViewItemIterator) + (qiconview.h QIconViewItem QIconDragItem QIconDrag) + (qdragobject.h QTextDrag QStoredDrag QUriDag QColorDrag QImageDrag QDragManager) + (qmime.h QMimeSource QMimeSourceFactory QWindowsMime) + (qptrlist.h QPtrListIterator) + (qevent.h QTimerEvent QMouseEvent QWheelEvent QTabletEvent QKeyEvent + QFocusEvent QPaintEvent QMoveEvent QResizeEvent QCloseEvent + QShowEvent QHideEvent QContextMenuEvent QIMEvent QDropEvent + QDragMoveEvent QDragEnterEvent QDragResponseEvent QDragLeaveEvent + QChildEvent QCustomEvent) + (qdatetime.h QTime QDateTime QDate) + (qdatetimeedit.h QTimeEdit QDateTimeEditBase QDateEdit QDateTimeEdit) + (qcstring.h QByteArray) + (qobjectlist.h QObjectListIt QObjectListIterator) + (qwidgetlist.h QWidgetListIt) + (qtabbar.h QTab) + (qpalette.h QColorGroup) + (qaction.h QActionGroup) + (qvalidator.h QIntValidator QDoubleValidator QRegExpValidator) + (qlistbox.h QListBoxItem QListBoxText QListBoxPixmap) + (qstring.h QChar QCharRef QConstString) + (qcanvas.h QCanvasSprite QCanvasPolygonalItem QCanvasRectangle + QCanvasPolygon QCanvasEllipse QCanvasText QCanvasLine + QCanvasChunk QCanvas QCanvasItem QCanvasView QCanvasPixmap) + (qgl.h QGLFormat QGL QGLContext QGLWidget QGLColormap) + (qtable.h QTableSelection QTableItem QComboTableItem QCheckTableItem) + (qsqlfield.h QSqlField QSqlFieldInfo) + (qsqlrecord.h QSqlRecord QSqlRecordInfo) + + ; Qt/Embedded + (qcopchannel_qws.h QCopChannel) + (qdirectpainter_qws.h QDirectPainter) + (qfontfactorybdf_qws.h QFontFactoryBDF) + (qfontfactoryttf_qws.h QFontFactoryFT) + (qfontmanager_qws.h QGlyphMetrics QGlyph QRenderedFont QDiskFont QFontManager QFontFactory) + (qgfx_qws.h QScreenCursor QPoolEntry QScreen QGfx) + (qgfxlinuxfb_qws.h QLinuxFbScreen) + (qgfxmatroxdefs_qws.h QQnxFbGfx QQnxScreen) + (qgfxraster_qws.h QGfxRasterBase QGfxRaster) + (qgfxvnc_qws.h QRfbRect QRfbPixelFormat QRfbServerInit QRfbSetEncodings + QRfbFrameBufferUpdateRequest QRfbKeyEvent QRfbPointerEvent QRfbClientCutText QVNCServer) + (qkeyboard_qws.h QWSKeyboardHandler) + (qlock_qws.h QLock QLockHolder) + (qmemorymanager_qws.h QMemoryManagerPixmap QMemoryManager) + (qsoundqss_qws.h QWSSoundServer QWSSoundClient QWSSoundServerClient QWSSoundServerSocket) + (qwindowsystem_qws.h QWSInternalWindowInfo QWSScreenSaver QWSWindow QWSSoundServer + QWSServer QWSServer KeyboardFilter QWSClient) + (qwsbeosdecoration_qws.h QWSBeOSDecoration) + (qwscursor_qws.h QWSCursor) + (qwsdecoration_qws.h QWSDecoration) + (qwsdefaultdecoration_qws.h QWSDefaultDecoration) + (qwsdisplay_qws.h QWSWindowInfo QWSDisplay) + (qwshydrodecoration_qws.h QWSHydroDecoration) + (qwskde2decoration_qws.h QWSKDE2Decoration) + (qwskdedecoration_qws.h QWSKDEDecoration) + (qwsmanager_qws.h QWSManager QWSButton) + (qwsmouse_qws.h QWSPointerCalibrationData QWSMouseHandler QCalibratedMouseHandler + QAutoMouseHandlerPrivate QWSMouseHandlerPrivate QVrTPanelHandlerPrivate + QTPanelHandlerPrivate QYopyTPanelHandlerPrivate QCustomTPanelHandlerPrivate + QVFbMouseHandlerPrivate) + (qwsproperty_qws.h QWSPropertyManager) + (qwsregionmanager_qws.h QWSRegionManager) + (qwssocket_qws.h QWSSocket QWSServerSocket) + (qwswindowsdecoration_qws.h QWSWindowsDecoration) + (qstatusbar.h statusBar()) + + ; KDE + (kdebug.h kdDebug kdWarning kdError kdFatal kdBacktrace) + (kconfig.h KConfigGroup) + (kiconloader.h BarIcon SmallIcon DesktopIcon KIcon) + (kicondialog.h KIconCanvas KIconButton) + (knuminput.h KDoubleNumInput KIntNumInput) + + ; KDGear - http://www.klaralvdalens-datakonsult.se + (KDCheckableGroupBox.h KDCheckableGroupBox) + (KDCheckableHGroupBox.h KDCheckableHGroupBox) + (KDCheckableVGroupBox.h KDCheckableVGroupBox) + (KDCloseableWidget.h KDCloseableWidget) + (KDConfigDialog.h KDConfigDialog) + (KDConfigWidget.h KDConfigWidget) + (KDDateWidget.h KDDateWidget KDDateTimeWidget) + (KDDirMonitor.h KDDirMonitor) + (KDGridWidget.h KDGridWidget) + (KDListBoxPair.h KDListBoxPair) + (KDMinimizeSplitter.h KDMinimizeSplitter) + (KDSearchableListBox.h KDSearchableListBox) + (KDSemiSizingControl.h KDSemiSizingControl) + (KDShowHideTableControl.h KDShowHideTableControl) + (KDSimpleSizingControl.h KDSimpleSizingControl) + (KDSizingControl.h KDSizingControl) + (KDStream.h KDStream) + (KDTimeWidget.h KDTimeWidget) + + ; KDChart - http://www.klaralvdalens-datakonsult.se + (KDChart.h KDChart) + (KDChartAxisParams.h KDChartAxisParams) + (KDChartBaseSeries.h KDChartBaseSeries) + (KDChartCustomBox.h KDChartCustomBox) + (KDChartData.h KDChartData) + (KDChartEnums.h KDChartEnums) + (KDChartListTable.h KDChartListTableData KDChartListTablePrivate) + (KDChartNotEnoughSpaceException.h KDChartNotEnoughSpaceException) + (KDChartPainter.h KDChartPainter) + (KDChartParams.h KDChartFrameSettings KDChartParams ModeAndChart) + (KDChartPlaneSeries.h KDChartPlaneSeries) + (KDChartPropertySet.h KDChartPropertySet) + (KDChartSeriesCollection.h KDChartSeriesCollection) + (KDChartTable.h KDChartTableData) + (KDChartTableBase.h KDChartTableDataBase) + (KDChartTextPiece.h KDChartTextPiece) + (KDChartUnknownTypeException.h KDChartUnknownTypeException) + (KDChartVectorSeries.h KDChartVectorSeries) + (KDChartVectorTable.h KDChartVectorTableData KDChartVectorTablePrivate) + (KDChartWidget.h KDChartWidget) + (KDFrame.h KDFrame KDFrameCorner) + (KDFrameProfileSection.h KDFrameProfileSection) + + + ; Useful fake entries + (qapplication.h qApp) + (kapplication.h kapp) + (klocale.h i18n I18N_NOOP) + (kstandarddirs.h locate locateLocal) + (stdlib.h getenv) + (unistd.h unlink sleep usleep) + (iostream cout cerr) + (ctype.h isalnum isalpha isascii isblank iscntrl isdigit isgraph islower isprint ispunct isspace isupper isxdigit) + (qeventloop.h eventloop) + + ) + "List of special include files which do not follow the normal scheme") + +(defvar kdab-qpe-includes + '( + (alarmserver.h AlarmServer) + (applnk.h AppLnk DocLnk AppLnkSet DocLnkSet) + (calendar.h Calendar) + (categories.h CategoryGroup CategoryGroup Categories CheckedListView) + (categorymenu.h CategoryMenu) + (categoryselect.h CategoryCombo CategorySelect CategoryEdit CategoryWidget) + (config.h Config) + (contact.h Contact) + (database.h QWSDatabase DatabaseDefaultView Database DatabaseView DatabaseDefaultView) + (datebookdb.h DateBookDB) + (datebookmonth.h DateBookMonthHeader DayItemMonth DateBookMonthTable DateBookMonth DateButton) + (event.h Event EffectiveEvent EffectiveEventSizeSorter EffectiveEventTimeSorter) + (filemanager.h FileManager) + (fileselector.h FileSelectorItem FileSelector) + (finddialog.h FindDialog) + (fontdatabase.h FontDatabase) + (fontmanager.h FontManager) + (global.h Global) + (imageedit.h ImageEdit) + (inputmethodinterface.h InputMethodInterface) + (ir.h Ir) + (lightstyle.h LightStyle) + (lnkproperties.h LnkProperties) + (mediaplayerplugininterface.h MediaPlayerDecoder) + (menubutton.h MenuButton) + (mimetype.h MimeType) + (network.h Network) + (palmtoprecord.h Record) + (palmtopuidgen.h UidGen) + (password.h Password) + (power.h PowerStatus PowerStatusManager ) + (process.h Process) + (qcopenvelope_qws.h QCopEnvelope) + (qdawg.h QDawg) + (qlibrary.h QLibrary) + (qpeapplication.h QPEApplication) + (qpedecoration_qws.h QPEDecoration QPEManager) + (qpedialog.h QPEDialogListener) + (qpemenubar.h QPEMenuToolFocusManager QPEMenuBar) + (qpemessagebox.h QPEMessageBox) + (qpestyle.h QPEStyle : public QWindowsStyle) + (qpetoolbar.h QPEToolBar) + (record.h Record) + (resource.h Resource) + (sound.h Sound) + (storage.h StorageInfo FileSystem) + (task.h Task) + (timeconversion.h TimeConversion) + (timestring.h DateFormat TimeString) + (tzselect.h TZCombo TimeZoneSelector) + )) + +;; ------------------------------ SOURCE CODE ------------------------------ + +;; Merge in qpe classes +(defun kdab-get-special-include-list () + (let (elm header classes (list kdab-qpe-includes) filename (result kdab-special-includes)) + (while list + (setq elm (car list)) + (setq list (cdr list)) + (setq filename (concat (if kdab-prefix-qpe "qpe/" "") (symbol-name (car elm)))) + (setq result (cons (cons (intern filename) (cdr elm)) result))) + result)) + +;; Lookup class `cls' in kdab-special-includes and return the associate include file name +(defun kdab-map-special (cls) + (let ((list (kdab-get-special-include-list)) + (found nil)) + (while (and list (not found)) + (let* ( (elm (car list)) + (include-file (car elm)) + (classes (cdr elm))) + ( while (and classes (not found)) + (if (string= (downcase cls) (downcase (symbol-name (car classes)))) + (setq found include-file) + (setq classes (cdr classes))))) + (setq list (cdr list))) + (if found + (symbol-name found) + nil) ; return value + )) + + + +;-------------------------------------------------------------------------------- +; Insert include file for Qt program. +; Place point anywhere on a Qt class, and invoke this function. A result of +; this is that an include line is added (if it does not already exists) for +; the given class. +;-------------------------------------------------------------------------------- +(defun kdab-insert-header ( prefix ) + "Insert include file for class at point" + (interactive "P") + (save-excursion + (let* ((word-at-point (if prefix + (read-from-minibuffer "Class: ") + (current-word)))) + (kdab-insert-header-non-interactive word-at-point)))) + +;-------------------------------------------------------------------------------- +; insert include file for `word-with-case' non-interactively. +; for an interactive version see kdab-insert-header +;-------------------------------------------------------------------------------- +(defun kdab-insert-header-non-interactive (word-with-case) + (save-excursion + (let* ((word (downcase word-with-case)) + (special-header (cond + ((kdab-map-special word) (kdab-map-special word)) + ((string-match "^qdom" word) "qdom.h") + ((string-match "^qxml" word) "qxml.h") + (t (concat word ".h")))) + header is-local) + + + ;; decide on the header file. + (if (file-exists-p (concat word-with-case ".h")) + (progn ; file exists in given case in pwd. + (setq header (concat word-with-case ".h")) + (setq is-local 't)) + (if (file-exists-p (concat word ".h")) ; file exists in lowercase in pwd + (progn + (setq header (concat word ".h")) + (setq is-local 't)) + (progn ; header in <..> path + (setq header special-header) + (setq is-local nil)))) + + (kdab-insert-include-file header is-local t)))) + +;-------------------------------------------------------------------------------- +; Insert header file for header. If is-local insert it with "" +; otherwise insert it with <> +;-------------------------------------------------------------------------------- +(defun kdab-insert-include-file (header is-local show-message) + (let ((include-file (if is-local + (concat "#include \"" header "\"") + (concat "#include <" header ">")))) + + (beginning-of-buffer) + (if (re-search-forward (concat "^ *// *\\(#include *[<\"][ \t]*" header "[ \t]*[>\"]\\)") nil t) + (progn + (replace-match "\\1") + (when show-message + (message (concat "commented in #include for " header)))) + + (if (not (re-search-forward (concat "#include *[\"<][ \t]*" header "[ \t]*[\">]") nil t)) + (progn + ; No include existed + (goto-char (point-max)) ; Using end-of-buffer makes point move, despite save-excursion + (if (not (re-search-backward "^#include *[\"<][^\">]+\.h *[\">]" nil t)) + (beginning-of-buffer) + (progn (end-of-line) (forward-char 1))) + + ;; Now insert the header + (insert (concat include-file "\n")) + (when show-message + (message (concat "inserted " include-file)))) + (when show-message + (message (concat "header file \"" header "\" is already included"))))))) + + + +;---------------------------------------------------------------------------- +; Insert a forward declaration for a Qt class. +; Place point anywhere on a Qt class, and invoke this function. A +; result of this is that a forward declaration line is added (if it does +; not already exist) for the given class. +;---------------------------------------------------------------------------- +(defun kdab-insert-forward-decl ( prefix ) + (interactive "P") + (save-excursion + (let* ((word (if prefix (read-from-minibuffer "Class: ") + (current-word)))) + (beginning-of-buffer) + (if (re-search-forward (concat "^ *// *\\(class *" word ";\\)") nil t) + (progn + (replace-match "\\1") + (message (concat "commented in forward declaration for " word))) + + (if (not (re-search-forward (concat "class *" word ";") nil t)) + (progn + ; No forward decl existed + ; Look for other forward declarations and insert this one before them + ; (this avoids finding class Private; inside a class, or other stuff in the middle of the file) + (if (re-search-forward "^[ \t]*class .*;" nil t) + (progn + ; Exit namespace foo { class bar; } if necessary + ; This is a modified version of (backward-up-list) which doesn't + ; throw an error when not found. + (goto-char (or (scan-lists (point) -1 1 nil t) (point))) ; ### do multiple times if necessary + (re-search-backward "^[ \t]*namespace " nil t) ; in case of namespace foo\n{ + (beginning-of-line)) + ; No forward declarations found, lets search for include lines. + ; For those we start from the end, because we want to leave file.h first. + (progn (goto-char (point-max)) + (if (re-search-backward "#include" nil t) + (progn (end-of-line) (forward-char 1)) + (beginning-of-buffer)))) + + (progn + (insert "class " word ";\n") + (message (concat "inserted class " word ";")))) + (message (concat "forward decl for \"" word "\" already exists"))))))) + + +(defun is-qpe-class (class) + (let ((list kdab-qpe-includes) classes (found nil)) + (while (and (not found) list) + (setq classes (cdr (car list))) + (while classes + (if (string= (downcase (symbol-name (car classes))) (downcase class)) + (setq found 't)) + (setq classes (cdr classes))) + (setq list (cdr list))) + found)) + +;-------------------------------------------------------------------------------- +; Start konqueror with documentation for the class under point. +; set `kdab-qt-documentation' and `kdab-qpe-documentation' +; to specify the replacement for the documentation +;-------------------------------------------------------------------------------- +(defun kdab-lookup-qt-documentation () + (interactive "") + (save-excursion + (let* ((word (downcase (current-word))) + (doc (if (is-qpe-class word) kdab-qpe-documentation kdab-qt-documentation)) + (url (if (not (string-match "XXX" doc)) + (error "didn't find three X's in kdab-qt-documentation or kdab-qpe-documentation") + (replace-match word t t doc)))) + (start-process "qt documentation" nil "kfmclient" "openURL" url) + (message (concat "Loading " url))))) + +(provide 'klaralv) |