See also: AbbrevMode.
Dynamic Abbreviations are one of the coolest functions in Emacs.
A dynamic abbreviation (dabbrev) is almost like a normal abbreviation that you define, with the following differences:
What it does is to look at the “word” to the left of point and try to expand that word by looking for text in the current buffer, and if not found there, in all open buffers (e.g. /usr/share/dict/words) ;-) --Andre
Did I say that this is extremely cool? :)
Let’s say you define
somewhere in the code. Somewhere further down in the code you want to write the variable name again. Instead of doing this, just type a few letters, for example “this”, and then activate the dabbrev-expand command.
If the expansion is not what you wanted, you can cycle through all possible expansions by repeatedly executing the command again.
This works on all kinds of text in all buffers.
This is bound to M-/ by default. Since that is rather hard to type on some keyboards, try this:
(global-set-key (kbd "C-<tab>") 'dabbrev-expand) (define-key minibuffer-local-map (kbd "C-<tab>") 'dabbrev-expand)
You need the second statement because in the MiniBuffer, `
C-<tab>’ has a separate binding which overrides the global one.
I’ve been writing C# code with Emacs and it has a lot of StudlyCaps style variable names. I use dabbrev-expand (and sometimes also hippie-expand) a lot to ‘tab-complete’ my words. When given two variable names, ‘ThisWord’ and ‘thisWord’, ‘Th’ + dabbrev-expand yields correctly ‘ThisName’, but ‘th’ + dabbrev-expand produces ‘thisname’, instead of ‘thisName’. Is there a way to correct this? – DuncanMak
If there is more than one expansion for the same prefix, using dabbrev-expand repeatedly will cause it to search for other possible expansions. For example, if you have a buffer that looks like this:
and you type “this” then execute dabbrev-expand, “this” will be expanded as “thisOtherLongVariableName”. If you immediately execute dabbrev-expand again, the expansion will be replaced with “thisLongVariable”.
Once you have successfully used dabbrev-expand to expand a word, hitting <space> then immediately using dabbrev-expand again will continue to expand from the point that the expansion was found. For example. If previously in the buffer, you had made the function call:
Then at some point later in the buffer you type: “this” then use dabbrev-expand to expand “this” to “thisLongVariableName”, if you then type <space> and then use dabbrev-expand again, it will expand “thisLongVariableName” to “thisLongVariableName.someFunction”. Continuing this, if you type <space> again then dabbrev-expand again, it will add “(someArgument” and the following word to the expansion.
In Vim, C-p/C-n expands current words according by parsing #include lines recursively. This could be done like the following:
(require 'cl) (defvar cdsb-include-re "^\\s-*#\\s-*\\(?:include\\|import\\)\\s-*\\([\"<]\\)\\([^\">]+\\)[\">]\\s-*$") (defun cdsb-extract-includes-in-buffer (buffer) (with-current-buffer buffer (save-excursion (goto-char (point-min)) (loop while (re-search-forward cdsb-include-re nil t) collect (cons (match-string-no-properties 2) (not (string-equal (match-string-no-properties 1) "\""))))))) (defun cdsb-acc-buffers (buffer non-system-files buffer-list) (loop with new-buffer-list = nil for (name . system-include-p) in (cdsb-extract-includes-in-buffer buffer) do (let* ((file (if system-include-p (ffap-c-mode name) (let ((name-re (concat "/" (regexp-quote name) "$"))) (loop for file in non-system-files if (string-match name-re file) return file)))) (buf (and file (find-file-noselect file t)))) ;; (message "check %s => %s" name file) (and buf (not (position buf buffer-list)) (setq buffer-list (cdsb-acc-buffers buf non-system-files (cons buf buffer-list))))) finally return buffer-list)) (defun c-dabbrev--select-buffers () (if (memq major-mode '(c-mode c++-mode objc-mode)) (save-excursion (require 'ffap) (let ((top (project-top-directory)) (cur (current-buffer))) (nreverse (cdr (nreverse (cdsb-acc-buffers cur (and top (project-source-files top)) (list cur))))))) (dabbrev--select-buffers))) (add-hook 'c-mode-common-hook (lambda () (set (make-variable-buffer-local 'dabbrev-select-buffers-function) 'c-dabbrev--select-buffers)))
‘dabbrev-completion’: apropos (regexp) Completion, cycling of completion candidates…