This page is about some ways to complete text in a buffer (other than the minibuffer).
tabkey2.el (available from nXhtml repository at Launchpad) is a little library that tries to generalize the ideas from Smart Tab. However, it works a bit differently. In most major modes, the first Tab press will indent and following Tab presses will complete. Since there are many ways to complete you can also choose which function you want to use (major mode specific completion, dynamic abbreviation completion etc). By default you do that by pressing F8 (this key binding will probably be changed).
If you are using tabkey2 with yasnippets, and see this behavior:
‘Tab’
, and enter the tab completion state. The popup (after 2 seconds) shows that YASnippet is the active function even though `(yas/expandable-at-point)’ returns ‘false’
(checked by eval-expression). Pressing ‘Tab’
second time gives the message‘Tab’
more times has no effect.you should download the latest version from the link above.
There was a bug report here (saying there were problems using Yasnippet or pabbrev with tabkey2-mode), but I get no answer when trying to get more details and I can’t reproduce the problem. If someone has problem with tabkey2-mode please download the latest version and file a bug report here: https://bugs.launchpad.net/nxhtml
However there indeed are problems with MuMaMo (part of nXhtml) and YASnippet so I have just filed a bug report for YASnippets about this: http://code.google.com/p/yasnippet/issues/detail?id=143 – LennartBorgman
Here’s what I use every day:
It feels very natural (to me at least), <tab>
always do what I mean.
‘indent-region’
if mark is active (so, to reindent the whole file, you would do C-x h <tab>
).C-u
, always smart indent without completing.Note the use of “\\_>
” instead of “\\>
”: this allows to tab-expand symbols, according to the major mode. Like “(goto-
…”, or “BOOST_
…” (useful when coding in Lisp or C).
Note: to enable tab completion in the `eval-expression` minibuffer, I just bind the tab key to `hippie-expand` in the `read-expression-map`.
(define-key read-expression-map [(tab)] 'hippie-expand)
Note: and since I like to undo the expansion before the end of an expansion cycle, I like to define unexpand as well:
(defun hippie-unexpand () (interactive) (hippie-expand 0)) (define-key read-expression-map [(shift tab)] 'hippie-unexpand)
I hope you like it, cheers!
Update: DanielHackney has created a nice minor mode out of it and submited it to ELPA (see his git repository).
Then, JohnAnderson forked his code and added SebastianB’s great mode-specific behavior.
Please use their version of smart-tab, I’m using John’s fork of Daniel’s code myself.
Cheers!
I love this function and have created a git repository for it. This doesn’t seem to be a function that is in too much danger of growing large and unwieldy, but there were enough other suggestions by people that a repository might be nice.
(minibuffer-complete)
with (unless (minibuffer-complete) (dabbrev-expand nil))
.(defun smart-tab () "This smart tab is minibuffer compliant: it acts as usual in the minibuffer. Else, if mark is active, indents region. Else if point is at the end of a symbol, expands it. Else indents the current line." (interactive) (if (minibufferp) (unless (minibuffer-complete) (dabbrev-expand nil)) (if mark-active (indent-region (region-beginning) (region-end)) (if (looking-at "\\_>") (dabbrev-expand nil) (indent-for-tab-command)))))
hippie-expand
with dabbrev-expand
. hippie-expand
, while very powerful, is for “advanced” users and needs to be set up to work satisfactorily. dabbrev-expand
is Emacs’ standard completion and works out of the box.)dabbrev-expand
(or hippie-expand
) in the minibuffer regardless of whether minibuffer-complete
is successful, one should make a key binding for it. The standard binding is the somewhat cumbersome M-/
. I suggest binding it to Shift-Tab: (global-set-key '[S-tab] 'dabbrev-expand)
.(if (and (minibufferp) (not (string-match "^Eval:" (minibuffer-prompt)))) (minibuffer-complete) ...
(defun smart-tab () "This smart tab is minibuffer compliant: it acts as usual in the minibuffer. Else, if mark is active, indents region. Else if point is at the end of a symbol, expands it. Else indents the current line." (interactive) (if (string-match "Minibuf" (buffer-name)) (unless (minibuffer-complete) (dabbrev-expand nil)) (if mark-active (indent-region (region-beginning) (region-end)) (if (looking-at "\\>") (dabbrev-expand nil) (indent-for-tab-command)))))
(defvar smart-tab-completion-functions '((emacs-lisp-mode lisp-complete-symbol) (lisp-mode slime-complete-symbol) (python-mode py-complete) (text-mode dabbrev-completion)) "List of major modes in which to use a mode specific completion function.") (defun get-completion-function() "Get a completion function according to current major mode." (let ((completion-function (second (assq major-mode smart-tab-completion-functions)))) (if (null completion-function) 'dabbrev-completion completion-function))) (defun smart-tab (prefix) "Needs `transient-mark-mode' to be on. This smart tab is minibuffer compliant: it acts as usual in the minibuffer. In all other buffers: if PREFIX is \\[universal-argument], calls `smart-indent'. Else if point is at the end of a symbol, expands it. Else calls `smart-indent'." (interactive "P") (if (minibufferp) (minibuffer-complete) (if (smart-tab-must-expand prefix) (let ((dabbrev-case-fold-search t) (dabbrev-case-replace nil)) (funcall (get-completion-function)))) (smart-indent)))
Seems to be working well enough for my purposes. I hope I didn’t screw anything up, if anybody has some style advice, I’d be glad to hear it, I haven’t got too much experience with elisp so far.
I wanted the mode-specific functionality of Sebastian’s code, so I forked the github project and added it in – http://github.com/genehack/smart-tab/tree/master
When using ido-mode, you do not wan’t to use minibuffer-complete but ido-complete instead. Ido is active when ido-cur-item is bound. I’m using the original smart-tab.el, but as far as I can see, this is needed for John Anderson’s edition too. Inserting this after the cond seems to do the trick
((boundp ‘ido-cur-item) (ido-complete))
This works for me better than SuperTab. In Python, multiple presses to tab will re-indent at different levels and I like this functionality. This function fixes it. Likely it could be merged into SuperTab but I don’t have the desire yet.
(defun fancy-tab (arg) (interactive "P") (setq this-command last-command) (if (or (eq this-command 'hippie-expand) (looking-at "\\_>")) (progn (setq this-command 'hippie-expand) (hippie-expand arg)) (setq this-command 'indent-for-tab-command) (indent-for-tab-command arg))) (define-key read-expression-map [(tab)] 'hippie-expand) (global-set-key (kbd "TAB") 'fancy-tab)
(defun indent-or-complete () "Complete if point is at end of a word, otherwise indent line." (interactive) (if (looking-at "\\>") (dabbrev-expand nil) (indent-for-tab-command) ))
(add-hook 'c-mode-common-hook (function (lambda () (local-set-key (kbd "<tab>") 'indent-or-complete) )))
(add-hook 'find-file-hooks (function (lambda () (local-set-key (kbd "<tab>") 'indent-or-complete))))
(defun indent-or-complete () "Complete if point is at end of line, and indent line." (interactive) (if (looking-at "$") (hippie-expand nil)) (indent-for-tab-command))
(defun indent-or-complete () "Complete if point is at end of line, and indent line." (interactive) (if (and (looking-at "$") (not (looking-back "^\\s-*"))) (hippie-expand nil)) (indent-for-tab-command) )
(defun indent-or-complete () "Complete if point is at end of a word, otherwise indent line." (interactive) (if snippet (snippet-next-field) (if (looking-at "\\>") (dabbrev-expand nil) (indent-for-tab-command))))
indent-or-rotate-or-complete
. – mina86See Also: