summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar Tom Willemsen2011-04-16 19:39:49 +0200
committerGravatar Tom Willemsen2011-04-16 19:39:49 +0200
commit0be324a314c0c5c0fdd7a35ed146bafe7d0850d7 (patch)
treee6c5ba3c3187ea960f015f3ef02108284bc104da
parent9420f67c17e28249e5c1a0a39c85833fdb1ccd8d (diff)
downloaddotfiles-0be324a314c0c5c0fdd7a35ed146bafe7d0850d7.tar.gz
dotfiles-0be324a314c0c5c0fdd7a35ed146bafe7d0850d7.zip
Added c-eldoc
-rw-r--r--emacs.d/20-c-eldoc.el3
-rw-r--r--emacs.d/elisp/c-eldoc.el304
2 files changed, 307 insertions, 0 deletions
diff --git a/emacs.d/20-c-eldoc.el b/emacs.d/20-c-eldoc.el
new file mode 100644
index 0000000..6269936
--- /dev/null
+++ b/emacs.d/20-c-eldoc.el
@@ -0,0 +1,3 @@
+(setq c-eldoc-includes "`pkg-config x11 --cflags` -I./ -I../")
+(load "c-eldoc")
+(add-hook 'c-mode-hook 'c-turn-on-eldoc-mode)
diff --git a/emacs.d/elisp/c-eldoc.el b/emacs.d/elisp/c-eldoc.el
new file mode 100644
index 0000000..732d00d
--- /dev/null
+++ b/emacs.d/elisp/c-eldoc.el
@@ -0,0 +1,304 @@
+;;; c-eldoc.el --- helpful description of the arguments to C functions
+
+;; Copyright (C) 2004 Paul Pogonyshev
+;; Copyright (C) 2004, 2005 Matt Strange
+;; Copyright (C) 2010 Nathaniel Flath
+
+;; This file is NOT a part of GNU Emacs
+
+;; 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+;; USA
+
+;;; Commentary:
+
+;; To enable: put the following in your .emacs file:
+;;
+;; (add-hook 'c-mode-hook 'c-turn-on-eldoc-mode)
+
+;; Nathaniel has submitted a caching patch to make this workable on large projects "like the emacs
+;; codebase"
+;; v0.5 01/02/2010
+
+;; Provides helpful description of the arguments to C functions.
+;; Uses child process grep and preprocessor commands for speed.
+;; v0.4 01/16/2005
+
+;; Your improvements are appreciated: I am no longer maintaining this code
+;; m_strange at mail dot utexas dot edu. Instead, direct all requests to
+;; flat0103@gmail.com
+
+;;; Code:
+
+(require 'eldoc)
+;; without this, you can't compile this file and have it work properly
+;; since the `c-save-buffer-state' macro needs to be known as such
+(require 'cc-defs)
+(require 'cl)
+
+;; make sure that the opening parenthesis in C will work
+(eldoc-add-command 'c-electric-paren)
+
+;;if cache.el isn't loaded, define the cache functions
+(unless (fboundp 'cache-make-cache)
+ (defun* cache-make-cache (init-fun test-fun cleanup-fun
+ &optional &key
+ (test #'eql)
+ (size 65)
+ (rehash-size 1.5)
+ (rehash-threshold 0.8)
+ (weakness nil))
+ "Creates a cached hash table. This is a hash table where
+elements expire at some condition, as specified by init-fun and
+test-fun. The three arguments do as follows:
+
+init-fun is a function that is called when a new item is inserted
+into the cache.
+
+test-fun is a function that is called when an item in the cache
+is looked up. It takes one argument, and will be passed the
+result of init-fun that was generated when the item was inserted
+into the cache.
+
+cleanup-fun is called when an item is removed from the hash
+table. It takes one argument, the value of the key-value pair
+being deleted.
+
+Note that values are only deleted from the cache when accessed.
+
+This will return a list of 4 elements: a has table and the 3
+arguments. All hash-table functions will work on the car of this
+list, although if accessed directly the lookups will return a pair
+(value, (init-fun)).
+
+The keyword arguments are the same as for make-hash-table and are applied
+to the created hash table."
+ (list (make-hash-table :test test
+ :size size
+ :rehash-size rehash-size
+ :rehash-threshold rehash-threshold
+ :weakness weakness) init-fun test-fun cleanup-fun))
+
+ (defun cache-gethash (key cache)
+ "Retrieve the value corresponding to key from cache."
+ (let ((keyval (gethash key (car cache) )))
+ (if keyval
+ (let ((val (car keyval))
+ (info (cdr keyval)))
+ (if (funcall (caddr cache) info)
+ (progn
+ (remhash key (car cache))
+ (funcall (cadddr cache) val)
+ nil)
+ val)))))
+
+ (defun cache-puthash (key val cache)
+ "Puts the key-val pair into cache."
+ (puthash key
+ (cons val (funcall (cadr cache)))
+ (car cache))))
+
+
+;; if you've got a non-GNU preprocessor with funny options, set these
+;; variables to fix it
+(defvar c-eldoc-cpp-macro-arguments "-dD -w -P")
+(defvar c-eldoc-cpp-normal-arguments "-w -P")
+(defvar c-eldoc-cpp-command "/lib/cpp ")
+(defvar c-eldoc-includes
+ "`pkg-config gtk+-2.0 --cflags` -I./ -I../ "
+ "List of commonly used packages/include directories - For
+ example, SDL or OpenGL. This shouldn't slow down cpp, even if
+ you've got a lot of them.")
+
+(defvar c-eldoc-reserved-words
+ (list "if" "else" "switch" "while" "for" "sizeof")
+ "List of commands that eldoc will not check.")
+
+
+(defvar c-eldoc-buffer-regenerate-time
+ 120
+ "Time to keep a preprocessed buffer around.")
+
+(defun c-eldoc-time-diff (t1 t2)
+ "Return the difference between the two times, in seconds.
+T1 and T2 are time values (as returned by `current-time' for example)."
+ ;; Pacify byte-compiler with `symbol-function'.
+ (time-to-seconds (subtract-time t1 t2)))
+
+(defun c-eldoc-time-difference (old-time)
+ "Returns whether or not old-time is less than c-eldoc-buffer-regenerate-time seconds ago."
+ (> (c-eldoc-time-diff (current-time) old-time) c-eldoc-buffer-regenerate-time))
+
+(defun c-eldoc-cleanup (preprocessed-buffer)
+ (kill-buffer preprocessed-buffer))
+
+(defvar c-eldoc-buffers
+ (cache-make-cache #'current-time #'c-eldoc-time-difference #'c-eldoc-cleanup)
+ "Cache of buffer->preprocessed file used to speed up finding arguments")
+
+(defun c-turn-on-eldoc-mode ()
+ "Enable c-eldoc-mode"
+ (interactive)
+ (set (make-local-variable 'eldoc-documentation-function)
+ 'c-eldoc-print-current-symbol-info)
+ (turn-on-eldoc-mode))
+
+;; call the preprocessor on the current file
+;;
+;; run cpp the first time to get macro declarations, the second time
+;; to get normal function declarations
+(defun c-eldoc-get-buffer (function-name)
+ "Call the preprocessor on the current file"
+;; run the first time for macros
+ (let ((output-buffer (cache-gethash (current-buffer) c-eldoc-buffers)))
+ (if output-buffer output-buffer
+ (let* ((this-name (concat "*" buffer-file-name "-preprocessed*"))
+ (preprocessor-command (concat c-eldoc-cpp-command " "
+ c-eldoc-cpp-macro-arguments " "
+ c-eldoc-includes " "
+ buffer-file-name))
+ (cur-buffer (current-buffer))
+ (output-buffer (generate-new-buffer this-name)))
+ (bury-buffer output-buffer)
+ (call-process-shell-command preprocessor-command nil output-buffer nil)
+ ;; run the second time for normal functions
+ (setq preprocessor-command (concat c-eldoc-cpp-command " "
+ c-eldoc-cpp-normal-arguments " "
+ c-eldoc-includes " "
+ buffer-file-name))
+ (call-process-shell-command preprocessor-command nil output-buffer nil)
+ (cache-puthash cur-buffer output-buffer c-eldoc-buffers)
+ output-buffer))))
+
+(defun c-eldoc-function-and-argument (&optional limit)
+ "Finds the current function and position in argument list."
+ (let* ((literal-limits (c-literal-limits))
+ (literal-type (c-literal-type literal-limits)))
+ (save-excursion
+ ;; if this is a string, move out to function domain
+ (when (eq literal-type 'string)
+ (goto-char (car literal-limits))
+ (setq literal-type nil))
+ (if literal-type
+ nil
+ (c-save-buffer-state ((argument-index 1))
+ (while (or (eq (c-forward-token-2 -1 t limit) 0)
+ (when (eq (char-before) ?\[)
+ (backward-char)
+ t))
+ (when (eq (char-after) ?,)
+ (setq argument-index (1+ argument-index))))
+ (c-backward-syntactic-ws)
+ (when (eq (char-before) ?\()
+ (backward-char)
+ (c-forward-token-2 -1)
+ (when (looking-at "[a-zA-Z_][a-zA-Z_0-9]*")
+ (cons (buffer-substring-no-properties
+ (match-beginning 0) (match-end 0))
+ argument-index))))))))
+
+(defun c-eldoc-format-arguments-string (arguments index)
+ "Formats the argument list of a function."
+ (let ((paren-pos (string-match "(" arguments))
+ (pos 0))
+ (when paren-pos
+ (setq arguments (replace-regexp-in-string "\\\\?[[:space:]\\\n]"
+ " "
+ (substring arguments paren-pos))
+ arguments (replace-regexp-in-string "\\s-+" " " arguments)
+ arguments (replace-regexp-in-string " *, *" ", " arguments)
+ arguments (replace-regexp-in-string "( +" "(" arguments)
+ arguments (replace-regexp-in-string " +)" ")" arguments))
+ ;; find the correct argument to highlight, taking `...'
+ ;; arguments into account
+ (while (and (> index 1)
+ pos
+ (not (string= (substring arguments (+ pos 2) (+ pos 6))
+ "...)")))
+ (setq pos (string-match "," arguments (1+ pos))
+ index (1- index)))
+ ;; embolden the current argument
+ (when (and pos
+ (setq pos (string-match "[^ ,()]" arguments pos)))
+ (add-text-properties pos (string-match "[,)]" arguments pos)
+ '(face bold) arguments))
+ arguments)))
+
+(defun c-eldoc-print-current-symbol-info ()
+ "Returns documentation string for the current symbol."
+ (let* ((current-function-cons (c-eldoc-function-and-argument (- (point) 1000)))
+ (current-function (car current-function-cons))
+ (current-function-regexp (concat "[ \t\n]+[*]*" current-function "[ \t\n]*("))
+ (current-macro-regexp (concat "#define[ \t\n]+[*]*" current-function "[ \t\n]*("))
+ (current-buffer (current-buffer))
+ (tag-buffer)
+ (function-name-point)
+ (arguments)
+ (type-face 'font-lock-type-face))
+ (when (and current-function
+ (not (member current-function c-eldoc-reserved-words)))
+ (when (setq tag-buffer (c-eldoc-get-buffer current-function))
+ ;; setup the buffer
+ (set-buffer tag-buffer)
+ (goto-char (point-min))
+ (prog1
+ ;; protected regexp search
+ (when (condition-case nil
+ (progn
+ (if (not (re-search-forward current-macro-regexp (point-max) t))
+ (re-search-forward current-function-regexp))
+ t)
+ (error (prog1 nil
+ (message "Function doesn't exist..."))))
+ ;; move outside arguments list
+ (search-backward "(")
+ (c-skip-ws-backward)
+ (setq function-name-point (point))
+ (forward-sexp)
+ (setq arguments (buffer-substring-no-properties
+ function-name-point (point)))
+ (goto-char function-name-point)
+ (backward-char (length current-function))
+ (c-skip-ws-backward)
+ (setq function-name-point (point))
+ (search-backward-regexp "[};/#]" (point-min) t)
+ ;; check for macros
+ (if (= (char-after) ?#)
+ (let ((is-define (looking-at "#[[:space:]]*define"))
+ (preprocessor-point (point)))
+ (while (prog2 (end-of-line)
+ (= (char-before) ?\\)
+ (forward-char)))
+ (when (and is-define (> (point) function-name-point))
+ (goto-char preprocessor-point)
+ (setq type-face 'font-lock-preprocessor-face)))
+ (forward-char)
+ (when (looking-back "//")
+ (end-of-line)))
+ (c-skip-ws-forward)
+ ;; colorize
+ (concat (propertize (buffer-substring-no-properties
+ (point)
+ function-name-point)
+ 'face type-face)
+ " "
+ (propertize current-function
+ 'face 'font-lock-function-name-face)
+ " "
+ (c-eldoc-format-arguments-string arguments
+ (cdr current-function-cons))))
+ (set-buffer current-buffer))))))
+
+(provide 'c-eldoc)
+;;; c-eldoc.el ends here