Overload a Keybinding in Emacs - emacs

I've looked through a number of other questions and el files looking for something i could modify to suit my needs but I'm having trouble so I came to the experts.
Is there anyway to have a key behave differently depending on where in the line the cursor is?
To be more specific I'd like to map the tab key to go to the end of the line if I'm in the middle of the line but work as a tab normally would if my cursor is positioned at the beginning of the line.
So far I have braces and quotes auto-pairing and re-positioning the cursor within them for C++/Java etc. I'd like to use the tab key to end-of-line if for example a function doesn't have any arguments.

Behaving differently depending on where point is in the line is the easy bit (see (if (looking-back "^") ...) in the code). "[Working] as a tab normally would" is the harder bit, as that's contextual.
Here's one approach, but I was thinking afterwards that a more robust method would be to define a minor mode with its own binding for TAB and let that function look up the fallback binding dynamically. I wasn't sure how to do that last bit, but there's a solution right here:
Emacs key binding fallback
(defvar my-major-mode-tab-function-alist nil)
(defmacro make-my-tab-function ()
"Return a major mode-specific function suitable for binding to TAB.
Performs the original TAB behaviour when point is at the beginning of
a line, and moves point to the end of the line otherwise."
;; If we have already defined a custom function for this mode,
;; return that (otherwise that would be our fall-back function).
(or (cdr (assq major-mode my-major-mode-tab-function-alist))
;; Otherwise find the current binding for this mode, and
;; specify it as the fall-back for our custom function.
(let ((original-tab-function (key-binding (kbd "TAB") t)))
`(let ((new-tab-function
(lambda ()
(interactive)
(if (looking-back "^") ;; point is at bol
(,original-tab-function)
(move-end-of-line nil)))))
(add-to-list 'my-major-mode-tab-function-alist
(cons ',major-mode new-tab-function))
new-tab-function))))
(add-hook
'java-mode-hook
(lambda () (local-set-key (kbd "TAB") (make-my-tab-function)))
t) ;; Append, so that we run after the other hooks.

This page of Emacs Wiki lists several packages (smarttab, etc.) which make TAB do different things depending on the context. You can probably modify one of them to do what you want.

Related

How can I jump to a definition without being queried in Emacs?

I have a problem when using Etags in Emacs. Everytime I tap \M+. to jump to a difinition point, a query is always popping up, like:
Find tag (default function_name):
And I have to tap 'Enter' to make sure of it.
But in most cases, I find I can choose the default one. So is there any method with which I can surpress this message?
I found the reason is because:
(defun find-tag (tagname &optional next-p regexp-p)
(interactive (find-tag-interactive "Find tag: "))
...
)
Why do I have to choose a tag? Why can not the default one just be the word under the point? Can I just remove this line? (interactive), or is there a good solution?
Going shortly through a couple of defuns in the etags sources via Emacs's awesome C-h f, one can find that the default tag to search is determined via a function named find-tag-default.
This means you could just define the following function:
(defun find-tag-under-point ()
(interactive)
(find-tag (find-tag-default)))
Then you can bind this to whatever key you want via define-key or global-set-key or local-set-key.
(The interactive form is always necessary if you want a function to be a "command" which can be called with M-x or bound to a key.)
You can write your own functionality over the find-tag (or any interactive function likewise)
(defun find-tag-under-point (&optional arg)
(interactive "P")
(cond ((eq arg 9)
(let ((current-prefix-arg nil))
(call-interactively 'find-tag)))
(arg
(call-interactively 'find-tag))
(t
(find-tag (find-tag-default)))))
(global-set-key (kbd "M-.") 'find-tag-under-point)
Then hotkey C-9M-. calls find-tag (old function) as usual, but the behaviour of find-tag-under-point (new-function) by default is what you want.

Predicate-based dynamic key binding with default fallback [duplicate]

I'm trying to write a custom tab completion implementation which tries a bunch of different completions depending on where the point is. However, if none of the conditions for completions are met I would like tab to do what ever the current mode originally intended it to do.
Something like this:
(defun my-custom-tab-completion ()
(interactive)
(cond
(some-condition
(do-something))
(some-other-condition
(do-something-else))
(t
(do-whatever-tab-is-supposed-to-do-in-the-current-mode))) ;; How do I do this?
Currently I'm checking for specific modes and doing the right thing for that mode, but I really would like a solution that just does the right thing without me having to explicitly add a condition for that specific mode.
Any ideas of how to do this?
Thanks! /Erik
BTW, here is another solution:
(define-key <map> <key>
`(menu-item "" <my-cmd> :filter ,(lambda (cmd) (if <my-predicate> cmd))))
Here is a macro I wrote based on Emacs key binding fallback to define a keybinding conditionally. It adds the keybinding to the specified minor mode but if the condition is not true, the previously assigned action is executed:
(defmacro define-key-with-fallback (keymap key def condition &optional mode)
"Define key with fallback. Binds KEY to definition DEF in keymap KEYMAP,
the binding is active when the CONDITION is true. Otherwise turns MODE off
and re-enables previous definition for KEY. If MODE is nil, tries to recover
it by stripping off \"-map\" from KEYMAP name."
`(define-key ,keymap ,key
(lambda () (interactive)
(if ,condition ,def
(let* ((,(if mode mode
(let* ((keymap-str (symbol-name keymap))
(mode-name-end (- (string-width keymap-str) 4)))
(if (string= "-map" (substring keymap-str mode-name-end))
(intern (substring keymap-str 0 mode-name-end))
(error "Could not deduce mode name from keymap name (\"-map\" missing?)"))))
nil)
(original-func (key-binding ,key)))
(call-interactively original-func))))))
Then I can do things like the following to use the special binding for TAB only when I am on a header in outline-minor-mode. Otherwise my default action (I have both indent and yasnippets) is executed:
(define-key-with-fallback outline-minor-mode-map (kbd "TAB")
(outline-cycle 1) (outline-on-heading-p))
You could use functions such as key-binding (or its more specific variants global-key-binding, minor-mode-key-binding and local-key-binding) to probe active keymaps for bindings.
For example:
(call-interactively (key-binding (kbd "TAB")))
;; in an emacs-lisp-mode buffer:
;; --> indent-for-tab-command
;;
;; in a c++-mode buffer with yas/minor-mode:
;; --> yas/expand
One way to avoid infinite loops if your command is bound to TAB could be to put your binding in a minor mode, and temporarily disable its keymap while looking for the TAB binding:
(define-minor-mode my-complete-mode
"Smart completion"
:keymap (let ((map (make-sparse-keymap)))
(define-key map (kbd "TAB") 'my-complete)
map))
(defun my-complete ()
(interactive)
(if (my-condition)
(message "my-complete")
(let ((my-complete-mode nil))
(call-interactively (key-binding (kbd "TAB"))))))
It's possible that you could achieve this without any special workarounds at all. In most modes TAB just does indentation by default, but if you set the global variable tab-always-indent to 'complete it will try to do completion first, and indent if no completion is possible. This usually works really well, although if TAB is bound to another command in one of your major modes you might be out of luck.
If that works in the modes you need, you'll just need to add your custom completion function to the front of the list completion-at-point-functions in all applicable buffers (maybe using a mode hook). The completion-at-point command calls each function listed in completion-at-point-functions until one of them returns non-nil, so all you need to do to have your custom completion function "fall through" to the existing behavior is return nil from it.
This isn't a 100% answer to the question, but if the major modes you're working with are written according to the normal guidelines it might be the cleanest way.
define-key can accept quoted string or interactive lambdas like in this example.
;Static
(define-key evil-normal-state-mapr "m" 'evil-motion-state)
;Conditional
(define-key evil-normal-state-map "m"
(lambda () (interactive) (message "%s" major-mode)))
Lambda's can be replaced with named functions like my-tab-completion and used more effectively.
From define-key's docstring (Emacs 25)
DEF is anything that can be a key's definition:
nil (means key is undefined in this keymap),
a command (a Lisp function suitable for interactive calling),
a string (treated as a keyboard macro),
a keymap (to define a prefix key),
a symbol (when the key is looked up, the symbol will stand for its
function definition, which should at that time be one of the above,
or another symbol whose function definition is used, etc.),
a cons (STRING . DEFN), meaning that DEFN is the definition
(DEFN should be a valid definition in its own right),
or a cons (MAP . CHAR), meaning use definition of CHAR in keymap MAP,
or an extended menu item definition.
(See info node `(elisp)Extended Menu Items'.)

Elisp: Conditionally change keybinding

I'm trying to write a custom tab completion implementation which tries a bunch of different completions depending on where the point is. However, if none of the conditions for completions are met I would like tab to do what ever the current mode originally intended it to do.
Something like this:
(defun my-custom-tab-completion ()
(interactive)
(cond
(some-condition
(do-something))
(some-other-condition
(do-something-else))
(t
(do-whatever-tab-is-supposed-to-do-in-the-current-mode))) ;; How do I do this?
Currently I'm checking for specific modes and doing the right thing for that mode, but I really would like a solution that just does the right thing without me having to explicitly add a condition for that specific mode.
Any ideas of how to do this?
Thanks! /Erik
BTW, here is another solution:
(define-key <map> <key>
`(menu-item "" <my-cmd> :filter ,(lambda (cmd) (if <my-predicate> cmd))))
Here is a macro I wrote based on Emacs key binding fallback to define a keybinding conditionally. It adds the keybinding to the specified minor mode but if the condition is not true, the previously assigned action is executed:
(defmacro define-key-with-fallback (keymap key def condition &optional mode)
"Define key with fallback. Binds KEY to definition DEF in keymap KEYMAP,
the binding is active when the CONDITION is true. Otherwise turns MODE off
and re-enables previous definition for KEY. If MODE is nil, tries to recover
it by stripping off \"-map\" from KEYMAP name."
`(define-key ,keymap ,key
(lambda () (interactive)
(if ,condition ,def
(let* ((,(if mode mode
(let* ((keymap-str (symbol-name keymap))
(mode-name-end (- (string-width keymap-str) 4)))
(if (string= "-map" (substring keymap-str mode-name-end))
(intern (substring keymap-str 0 mode-name-end))
(error "Could not deduce mode name from keymap name (\"-map\" missing?)"))))
nil)
(original-func (key-binding ,key)))
(call-interactively original-func))))))
Then I can do things like the following to use the special binding for TAB only when I am on a header in outline-minor-mode. Otherwise my default action (I have both indent and yasnippets) is executed:
(define-key-with-fallback outline-minor-mode-map (kbd "TAB")
(outline-cycle 1) (outline-on-heading-p))
You could use functions such as key-binding (or its more specific variants global-key-binding, minor-mode-key-binding and local-key-binding) to probe active keymaps for bindings.
For example:
(call-interactively (key-binding (kbd "TAB")))
;; in an emacs-lisp-mode buffer:
;; --> indent-for-tab-command
;;
;; in a c++-mode buffer with yas/minor-mode:
;; --> yas/expand
One way to avoid infinite loops if your command is bound to TAB could be to put your binding in a minor mode, and temporarily disable its keymap while looking for the TAB binding:
(define-minor-mode my-complete-mode
"Smart completion"
:keymap (let ((map (make-sparse-keymap)))
(define-key map (kbd "TAB") 'my-complete)
map))
(defun my-complete ()
(interactive)
(if (my-condition)
(message "my-complete")
(let ((my-complete-mode nil))
(call-interactively (key-binding (kbd "TAB"))))))
It's possible that you could achieve this without any special workarounds at all. In most modes TAB just does indentation by default, but if you set the global variable tab-always-indent to 'complete it will try to do completion first, and indent if no completion is possible. This usually works really well, although if TAB is bound to another command in one of your major modes you might be out of luck.
If that works in the modes you need, you'll just need to add your custom completion function to the front of the list completion-at-point-functions in all applicable buffers (maybe using a mode hook). The completion-at-point command calls each function listed in completion-at-point-functions until one of them returns non-nil, so all you need to do to have your custom completion function "fall through" to the existing behavior is return nil from it.
This isn't a 100% answer to the question, but if the major modes you're working with are written according to the normal guidelines it might be the cleanest way.
define-key can accept quoted string or interactive lambdas like in this example.
;Static
(define-key evil-normal-state-mapr "m" 'evil-motion-state)
;Conditional
(define-key evil-normal-state-map "m"
(lambda () (interactive) (message "%s" major-mode)))
Lambda's can be replaced with named functions like my-tab-completion and used more effectively.
From define-key's docstring (Emacs 25)
DEF is anything that can be a key's definition:
nil (means key is undefined in this keymap),
a command (a Lisp function suitable for interactive calling),
a string (treated as a keyboard macro),
a keymap (to define a prefix key),
a symbol (when the key is looked up, the symbol will stand for its
function definition, which should at that time be one of the above,
or another symbol whose function definition is used, etc.),
a cons (STRING . DEFN), meaning that DEFN is the definition
(DEFN should be a valid definition in its own right),
or a cons (MAP . CHAR), meaning use definition of CHAR in keymap MAP,
or an extended menu item definition.
(See info node `(elisp)Extended Menu Items'.)

How to safely override tab key just for indentation in emacs

I'm a new user to emacs, and I don't particularly like the way emacs modes handle indentation, especially when mixing modes (say ASP and perl). I have written the following functions to indent things the way a "classic" editor would:
(defun classic-indent (width)
"Tab the current line or block the 'classic' way"
(save-excursion
(if (not (use-region-p)) (select-current-line))
(indent-rigidly (mark) (point) width)))
(defun indent-forward ()
"tab two space forward"
(interactive)
(classic-indent 2))
(defun indent-back ()
"tab two spaces back"
(interactive)
(classic-indent -2))
(defun select-current-line ()
"Select the current line"
(interactive)
(end-of-line) ; move to end of line
(set-mark (line-beginning-position)))
The idea here being to bind indent-back to <backtab> and indent-forward to <tab>. The functions work great when calling them with M-x, and the <backtab> binding works fine, but if I try to bind <tab> directly, it interfere's with all sorts of cool things like auto-completion. I tried setting indent-line-function with:
(setq indent-line-function 'indent-forward)
and setting my major modes indentation function with:
(setq cperl-indent-command 'indent-forward)
but neither has any effect. I'm not sure if I'm setting them wrong or if this is even the right approach.
to sum up, How can I override indentation with the tab key without clobbering other 'tab' behavior like auto-completion?
Emacs wiki has a whole category page about indentation and TAB: http://www.emacswiki.org/emacs/CategoryIndentation. See that for other wiki pages about libraries or snippets that give you various kinds of TAB DWIM ("smart" TAB) behavior. Here are a couple:
http://www.emacswiki.org/emacs/TabCompletion
http://www.emacswiki.org/emacs/IndentOrInsertTab
It's likely the major-mode default is overriding your setting when you load a buffer. Do something like this ensure your indent-line-function is used buffer-local and it will work.
(add-hook 'elixir-mode-hook
(lambda ()
(electric-indent-mode -1)
(setq indent-line-function 'indent-forward)))
ref: https://www.emacswiki.org/emacs/BufferLocalVariable

Emacs: highlighting TODO *only* in comments

This question is related to another one, Emacs :TODO indicator at left side. I recently came across a minor mode I like a lot called FixmeMode. It supports auto highlighting of TODO marks, and navigating between them. However, I think it makes more sense to recognize the "TODO" strings only in comments, rather than polluting the whole file. Is it possible?
Check out the library fic-mode.el, it has been verified in C++ and Emacs-Lisp.
It was written specifically to answer this question.
The installation is like any standard package:
(require 'fic-mode)
(add-hook 'c++-mode-hook 'turn-on-fic-mode)
Though Wei Hu did ask for an easy way to add it to multiple modes, so here goes:
(defun add-something-to-mode-hooks (mode-list something)
"helper function to add a callback to multiple hooks"
(dolist (mode mode-list)
(add-hook (intern (concat (symbol-name mode) "-mode-hook")) something)))
(add-something-to-mode-hooks '(c++ tcl emacs-lisp) 'turn-on-fic-mode)
It's possible but quite a bit trickier. Fixme mode uses font-lock to do its highlighting, so it works on an as-you-type basis to highlight the keywords. Font-lock hooks in at a very low level, basically running after every change is made to the buffer's contents. It is highly optimized, though, which allows it to appear instantaneous on modern computers.
The TODO indicator in the left fringe is static. Execute the function and all current TODO's are highlighted; change the buffer (adding or removing TODO's) does not change the fringe indicator; that's only changed when the function runs again.
Your approach would have to get into syntax tables, determining first when you're in a comment and then looking for the keywords. The tricky part comes in doing this interactively (i.e. as you type). You should be able to hook into the font-lock constructs to do this, but the function you provide to search for the comment syntax table and then for the keywords better be very efficient, as it will be run each and every time a buffer changes (though it will only run on the changed region, I think). You would want to stuff all of this in font-lock-syntactic-keywords rather than font-lock-keywords because the syntactic-keyword pass happens before the syntactic pass (which happens before the keyword pass), and you need to set TODO inside comments before comments themselves are set.
Sorry it's not a full working-code answer.....
Maybe this will help: there's a fn c-in-literal in
cc-mode, and a similar csharp-in-literal in csharp mode. The
return value is c if in a C-style comment, c++ if in a C++
style comment. You could add that to the code at
Emacs :TODO indicator at left side
to get what you want.
(defun annotate-todo ()
"put fringe marker on TODO: lines in the curent buffer"
(interactive)
(let (lit)
(save-excursion
(goto-char (point-min))
(while (re-search-forward "TODO:" nil t)
(progn
(setq lit (c-in-literal)) ;; or csharp-in-literal
(if (or (eq lit 'c) (eq lit 'c++))
(let ((overlay (make-overlay (- (point) 5) (point))))
(overlay-put overlay 'before-string
(propertize "A"
'display
'(left-fringe ;; right
horizontal-bar
better-fringes-important-bitmap))))))))))
https://github.com/tarsius/hl-todo seems to do exactly what you want. I just tried it and love it.