1

In my .emacs file I have bound the tab-key to a function called smart-tab.

(global-set-key [(tab)] 'smart-tab)

(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)
      (minibuffer-complete)
    (if mark-active
        (indent-region (region-beginning)
                       (region-end))
      (if (looking-at "\\_>") ;; \_> end of symbol
          (dabbrev-expand nil)
        (indent-for-tab-command)))))

I'm using the module xah-find. So I also load it in my .emacs file.

(require 'xah-find)

When I'm now using e.g. the function xah-find-text all the results are printed in a temporary buffer *xah-find output* which is in the major mode ∑xah-find.

This major mode binds the tab-key to xah-find-next-match. But in my case the tab-key is still bound to my function smart-tab instead.

I would like to overwrite the global set tab-key in this major mode, so that in the major mode ∑xah-find the tab-key is bound to xah-find-next-match instead to smart-tab.

7
  • That's what is supposed to happen: global-bindings are masked by local bindings. So any bindings provided by your active major mode (xah-find) should mask your global bindings. When you're in the buffer *xah find output*, what does C-h k <TAB> report? Also, what does C-h v major-mode report?
    – Tyler
    Aug 22, 2019 at 14:55
  • What @Tyler said. I inspected the source code. There is no obvious reason there why the normal behavior wouldn't work. But, I know that ergoemacs does some creasy things with keymaps. Do you have ergoemacs activated?
    – Tobias
    Aug 23, 2019 at 6:46
  • I'm using GNU Emacs 26.2 (build 1, x86_64-w64-mingw32) of 2019-04-13. I don't know ergoemacs, so I assume it is not activated.
    – Dirk80
    Aug 23, 2019 at 12:05
  • @Tyler : C-h k <TAB> reports that it is bound to smart-tab. C-h v major-mode reports xah-find-output-mode.
    – Dirk80
    Aug 23, 2019 at 12:08
  • C-h k <TAB> should also tell us which map smart-tab was found in, ie. (found in global-map) or (found in xah-find-file-map)?
    – Tyler
    Aug 23, 2019 at 14:03

2 Answers 2

1

Change this:

(global-set-key [(tab)] 'smart-tab)

to this:

(global-set-key (kbd "TAB") 'smart-tab)

and unless restarting Emacs, also evaluate this once:

(global-unset-key [(tab)])

What you weren't noticing (n.b. posting the C-hk output from Emacs in the different situations would have helped others to see what was happening sooner) was that Emacs was showing you two different key representations:

  • TAB
  • <tab>

You may also have seen the phrase "TAB (translated from <tab>)" in some situations.

These are two separate events, and which of them is sent to Emacs when you press TAB on your keyboard is contextual. Terminals send TAB (aka ASCII control character 9, or ^I or C-i), so if you are running Emacs in a terminal it will receive a TAB. GUIs on the other hand will differentiate the TAB key from C-i, and send a <tab> event.

By default Emacs wants to do the same thing regardless, so that it has the same behaviour in both terminal and GUI environments; and so in the absence of any specific binding for <tab> Emacs will translate the event to TAB and use the binding for that.

So you ought to use TAB (like xah-find.el does) because that representation works in both terminals and GUI frames, and will mesh better with other Emacs functionality.

As you were binding <tab> and your GUI was sending a <tab> event, that binding took precedence over the major mode binding for TAB -- because the translation to TAB happens only in the absence of an explicit binding for <tab>.

(And in a terminal your <tab> binding wouldn't have had any effect at all.)

2
  • Excellent answer!!! Solved my problem. Are there more keys than tab which are different for GUI and terminal? Where can I find a list?
    – Dirk80
    Aug 25, 2019 at 14:43
  • C-h i g (elisp)Function Keys is probably the thing to read first. You can delve into the local-function-key-map and other Translation Keymaps details from there, if you wish.
    – phils
    Aug 25, 2019 at 14:59
0

I did now the following to reproduce the problem on the following emacs:

"GNU Emacs 26.1 (build 2, x86_64-pc-linux-gnu, GTK+ Version 3.24.7) of 2019-04-11, modified by Debian"

Running emacs from shell with emacs -Q Then putting the following code into the scratch buffer:

(add-to-list 'load-path "/usr/share/emacs/site-lisp")

(require 'package)
(setq package-load-list
      '((xah-find t)))
(package-initialize)

(require 'xah-find)

(global-set-key [(tab)] 'smart-tab)

(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)
      (minibuffer-complete)
    (if mark-active
        (indent-region (region-beginning)
                       (region-end))
      (if (looking-at "\\_>") ;; \_> end of symbol
          (dabbrev-expand nil)
        (indent-for-tab-command)))))

I executed M-x eval-buffer. Then I tried the same things as in my previous post. And in the xah-find output buffer the tab key is still bound to smart-tab.

Note: The xah-find.el file is in this location on my computer: /usr/share/emacs/site-lisp

1
  • Could you provide a URL for a downloadable copy of xah-find.el ?
    – phils
    Aug 25, 2019 at 0:44

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.