Elisp: Example of Abbrev as Function Templates
Complete Example of Abbrev as Function Templates
Here, we'll use abbrev system to build a function template such that:
- Not expand when inside string quote or comment.
- Move cursor into the proper position after expansion.
- Do not add the trigger character, such as space.
Here's the complete code.
(defun xx-abbrev-enable-function () "Return t if not in string or comment. Else nil. This is for abbrev table property `:enable-function'. Version 2016-10-24" (let ((xsyntax-state (syntax-ppss))) (not (or (nth 3 xsyntax-state) (nth 4 xsyntax-state))))) (defun xx-expand-abbrev () "Expand the symbol before cursor, if cursor is not in string or comment. Returns the abbrev symbol if there's a expansion, else nil. Version 2016-10-24" (when (xx-abbrev-enable-function) ; abbrev property :enable-function is ignored, if you define your own expansion function (let ( xp1 xp2 xabrStr xabrSymbol ) (save-excursion (forward-symbol -1) (setq xp1 (point)) (forward-symbol 1) (setq xp2 (point))) (setq xabrStr (buffer-substring-no-properties xp1 xp2)) (setq xabrSymbol (abbrev-symbol xabrStr)) (if xabrSymbol (progn (abbrev-insert xabrSymbol xabrStr xp1 xp2 ) (xx--abbrev-position-cursor xp1) xabrSymbol) nil)))) (defun xx--abbrev-position-cursor (&optional Pos) "Move cursor back to ▮ if exist. Pos is a buffer position limit of search backward. If nil, default to point minus 100. Return point if found, else nil. Version: 2023-08-20" (let ((xfoundQ (search-backward "▮" (if Pos Pos (max (point-min) (- (point) 100))) t))) (when xfoundQ (delete-char 1)) xfoundQ )) (defun xx--abhook () "function to run after abbrev expansion Mostly used to prevent inserting the char that triggered expansion. Version 2016-10-24" (message "abbrev hook function ran" ) t) (put 'xx--abhook 'no-self-insert t) ;; if still dev, it's convenient to start fresh (setq xx-abbrev-table nil) (define-abbrev-table 'xx-abbrev-table '( ("fn" "function" xx--abhook) ("function" "function ▮name (x) { return x; }" xx--abhook) ;; hundreds more ) "Abbrev table for `xx'" ) (abbrev-table-put xx-abbrev-table :case-fixed t) (abbrev-table-put xx-abbrev-table :system t) (abbrev-table-put xx-abbrev-table :enable-function 'xx-abbrev-enable-function) (define-derived-mode xx prog-mode "xx" "A major mode for xx" :abbrev-table xx-abbrev-table (make-local-variable 'abbrev-expand-function) (if (or (and (>= emacs-major-version 24) (>= emacs-minor-version 4)) (>= emacs-major-version 25)) (progn (setq abbrev-expand-function 'xx-expand-abbrev)) (progn (add-hook 'abbrev-expand-functions 'xx-expand-abbrev nil t))) (abbrev-mode 1))
2016-11-05 thanks to John Kitchen ( https://x.com/johnkitchin ) for suggesting to remove the cursor position place holder char ▮ after expanding a abbrev.