What's the right name for CTL-]? - emacs

From my .emacs:
(defun flip-window () "Flip this window" (interactive)
(switch-to-buffer (other-buffer)))
;; later
(global-set-key [(control ?])] 'flip-window)
It works great, but I have two questions:
is there a built-in function to flip to most recently visited buffer?
While the above works at emacs startup, it causes problems when I'm trying to update settings, there's a parse error caused by the ?]. So is there a better way to express the control-] keystroke?

Answer to the question 2.
You may try the kbd function while setting the key binding.
Like so:
(global-set-key (kbd "C-]") 'flip-window)
And to the question 1: I guess there is no built in function for that. Emacs redux teaches us to implement it like:
(defun er-switch-to-previous-buffer ()
"Switch to previously open buffer. Repeated invocations toggle between the two most recently open buffers."
(interactive)
(switch-to-buffer (other-buffer (current-buffer) 1)))
This is part of Emacs Prelude distro. See https://emacsredux.com/blog/2013/04/28/switch-to-previous-buffer/

As a side note, you can get a description of any key combination in emacs using using the C-h k key combination, which runs the describe-key function. You'll have to read the textual form of your input from the description buffer. If you want to programmatically retrieve a string containing your key combination, you could also run the following Elisp code:
(destructuring-bind ((str . code)) (help--read-key-sequence)
(help-key-description str code))
It will prompt you for input in the minibuffer and return a string, such as e.g. "C-]".

Related

How to Zoom in /out in emacs -nw (command line only) whithout having a numeric keypad (or mouse wheel)? [duplicate]

This s-expression in my .emacs file does not produce the desired result:
(define-key global-map (kbd "C-=") 'djhaskin987-untab-to-tab-stop)
Why can't I bind a command to Ctrl+=?
EDIT for clarification:
I am using emacs23-nox on the standard build of urxvt-256colors for Debian, except that I have recompiled with --disable-iso405776 (or something to that effect) it so that Ctrl+Shift doesn't do the weird 'insert character' thing. I don't know if this affects anything. For example, C-M-i sends M-TAB, which I don't understand.
EDIT II:
I apologize for not making this clear. The function djhaskin987-untab-to-tab-stop has the line (interactive) in it. This part works.
The accepted answer in combination with the link in the first comment to it is enough to get started on a complete solution. The steps are:
make your terminal output escape codes for the key
make Emacs recognise the escape codes as a standard keypress
bind the keypress in a mode map
The first is very terminal and/or operating system dependent.
The link in the first comment shows some examples for X Window System. The key names are available in /usr/X11R6/include/X11/keysymdef.h (or try locate keysymdef.h), prefixed with XK_ (which should be removed for our purposes). I read that symbolic names are preferred over key literals.
I don't currently run X but I think it should look like this in your case:
XTerm.VT100.Translations: #override \
Ctrl ~Meta ~Shift <Key> equal: string(0x1b) string("[emacs-C-=")\n
The first string is the escape, the second is of your choosing.
In iTerm you can use Preferences->Keys and choose Send Escape Sequence as the Action. For example, I have:
Emacs Wiki lists some configuration methods for other terminals.
Now you can teach Emacs to recognize it as a C-=. First define-key into input-decode-map. I have a couple of helper functions:
(defun my/global-map-and-set-key (key command &optional prefix suffix)
"`my/map-key' KEY then `global-set-key' KEY with COMMAND.
PREFIX or SUFFIX can wrap the key when passing to `global-set-key'."
(my/map-key key)
(global-set-key (kbd (concat prefix key suffix)) command))
(defun my/map-key (key)
"Map KEY from escape sequence \"\e[emacs-KEY\."
(define-key function-key-map (concat "\e[emacs-" key) (kbd key)))
So then:
(my/global-map-and-set-key "C-=" 'some-function-to-bind-to)
Some keys (currently: ()\|;'`"#.,) will need escaping in the string, like C-\..
In a terminal, TAB is represented by the same byte sequence as C-i. And typically the terminal has no special byte-sequence for C-=, so it will just send a =. There is nothing that Emacs can do about it. But you might be able to teach your terminal emulator to send some special byte sequence of your choice (check the documentation of your terminal emulator for that), after which you can teach Emacs to recognize it as a C-= (with something like (define-key input-decode-map "...thebytes..." [?\C-=])).
The problem is that you use emacs in the terminal.
The terminal does not allow "C-=".
Try your function in the graphical emacs and it will work.
You will have to find another keybinding for the terminal.
You can map C-= using the default ascii codes: ^[[61;5u. Then you can bind it in Emacs either using:
(global-set-key (kbd "C-=") 'djhaskin987-untab-to-tab-stop))
or let use-package do it, e.g.:
(use-package expand-region
:ensure t
:bind (("C-=" . er/expand-region)))
I do want to thank Sam Brightman, for his wonderful solution. It's a very clean, albeit heavy-handed, approach that will work for any keys that cannot be sent via normal ascii codes. I've been wanting to get C-TAB working inside iterm2 for a long time. I was able to do it by deleting the builtin preferences keys for C-TAB/C-S-TAB and using his approach. With the following, I can be ssh'd into remote Linux boxes and quickly switch through lots of open buffers in projects, just like a desktop editor.
(use-package nswbuff
:defer 1
:after (projectile)
:commands (nswbuff-switch-to-previous-buffer
nswbuff-switch-to-next-buffer)
:config
(progn
(my/global-map-and-set-key "C-TAB" 'nswbuff-switch-to-previous-buffer)
(my/global-map-and-set-key "C-S-TAB" 'nswbuff-switch-to-next-buffer))
:init
(setq nswbuff-display-intermediate-buffers t
nswbuff-exclude-buffer-regexps '("^ "
"^\*.*\*"
"\*Treemacs.*\*"
"^magit.*:.+")
nswbuff-include-buffer-regexps '("^*Org Src")
nswbuff-start-with-current-centered t
nswbuff-buffer-list-function '(lambda ()
(interactive)
(if (projectile-project-p)
(nswbuff-projectile-buffer-list)
(buffer-list)))))
The function you're binding must be interactive. Try:
(define-key global-map (kbd "C-=")
(lambda () (interactive) (djhaskin987-untab-to-tab-stop)))

Control Emacs behavior when splitting windows

I would like to customize the behavior when I split windows in Emacs:
I am always splitting because I want to view a separate buffer side-by-side with the one I'm currently editing.
I use electric-buffer-list (bound to C-x C-b) to navigate buffers.
I end up doing all of the following separately:
C-x 3 to split horizontally.
C-x o to switch to the other window.
C-x C-b to invoke electric-buffer-list so I can select the buffer I want to view.
It seems like I should be able to write an Elisp function that will do all of this when I press C-x 3.
I found this post which describes the focus switching part of the behavior that I want, but I don't understand how to extend that answer to achieve all of what I'm trying to do.
Edit: After reviewing #lawlist's post and debugging my syntax, I think I want to do something like this:
(defun split-right-and-buffer-list ()
(interactive)
(split-window-horizontally)
(other-window 0)
(electric-buffer-list 0))
(global-set-key (kbd "C-x 3") 'split-right-and-buffer-list)
This does everything I want, except that the buffer list that comes up only lists the current buffer, instead of the normal list of all buffers that I get when I invoke electric-buffer-list from its key binding.
With some very small modifications the function you came up with will do what you want:
(defun split-right-and-buffer-list ()
(interactive)
(split-window-horizontally)
(other-window 1)
(electric-buffer-list nil))
(global-set-key (kbd "C-x 3") 'split-right-and-buffer-list)
Passing 1 instead of 0 as an argument to other-window causes Emacs to select the new window created as a result of calling split-window-horizontally.
Passing nil instead of 0 as an argument to electric-buffer-list causes Emacs to show all buffers, not just file-visiting ones.
The thing that can trip you up here is that this isn't mentioned in the documentation for electric-buffer-list (which doesn't include any information about the ARG it takes). But when you look at the source code of this command, you'll notice that it simply passes the value of the argument on to a function called list-buffers-noselect (and doesn't use it for anything else). The documentation of this function contains the missing piece of information mentioned above.
If you do not mind having custom commands to do what you want try the following functions
(require 'ido)
(defun my-split-window-open-buffer-right (buffer)
(interactive (list (ido-read-buffer "Please select a buffer: ")))
(select-window (split-window-right))
(switch-to-buffer buffer))
(defun my-split-window-open-buffer-below (buffer)
(interactive (list (ido-read-buffer "Please select a buffer: ")))
(select-window (split-window-below))
(switch-to-buffer buffer))
Bind them to keys of you liking. I would prefer this over redefining/advising functions I have not written.

how to emulate a specific key press in Emacs Lisp

Context: I want to make a minor mode where pressing f twice fast results in whatever the pressing of ( should do at that time. This doesn't always mean just insertion of (. For example, in buffers where paredit mode or autopair mode is enabled, pressing of ( usually results in insertion of (). In a paredit mode buffer, that sometimes results in wrapping the selected text: for example, if I select a b and press (, that should result in replacing the selection with (a b).
For detection of f being pressed twice, I just need to take the logic in the short code in http://www.emacswiki.org/emacs/electric-dot-and-dash.el
So the only missing piece is a Lisp code snippet that tells Emacs "Trigger pressing of ( now!"
The first thing that came to my mind was that the snippet should do
find the command bound to the key (
and then call call-interactively on that command.
but that breaks down if the auto pairing package (autopair or paredit or other similar package) binds ( to a command that has a logic that looks up what key was used to call the command, or if the package simply relies on post-self-insert-hook or post-command-hook instead of binding (.
update
I've looked up Key Chord documentation and it turns out what I am trying to do with answers to this question has a simpler solution:
(require 'key-chord)
(key-chord-mode 1)
(defvar my-easy-open-paren-mode-map
(let ((map (make-sparse-keymap)))
(key-chord-define map ",." (kbd "("))
map))
(define-minor-mode my-easy-open-paren-mode
"In this mode, pressing . and , together is another way of pressing the open paren.")
(defvar my-easy-semicolon-mode-map
(let ((map (make-sparse-keymap)))
(key-chord-define map ";;" (kbd "C-e ;"))
map))
(define-minor-mode my-easy-semicolon-mode
"In this mode, pressing semicolon twice fast is another way of pressing C-e and semicolon.")
(add-hook 'prog-mode-hook 'my-easy-open-paren-mode)
(add-hook 'c-mode-common-hook 'my-easy-semicolon-mode)
Triggering key press may still be useful in other contexts though.
You might appreciate the Key Chord library for binding functions to a double key-press. (I wouldn't recommend using f if you'll be writing in English, mind you; but YMMV.)
post-self-insert-hook would still run if the binding was self-insert-command. post-command-hook will run in any case, but if you're worried about it seeing an incorrect function and/or input event, you can manipulate those...
After looking up the binding, your function can set this-command to the function you're about to call-interactively, and last-command-event to the required key. e.g.:
(defun my-fake-paren ()
(interactive)
(let ((command (key-binding "(")))
(setq last-command-event ?\()
(setq this-command command)
(call-interactively command)))
I use Key Chord for this sort of thing, although the page you link appears to do the same thing. The trick is getting the call to call-interactively to work correctly. I wrapped it in a let that reset the variable last-command-event, such that call-interactively thinks it was a "(". This works for me in paredit and fundamental modes.
(require 'key-chord)
(key-chord-mode 1)
(defun my-paren-call ()
(interactive)
(let ((last-command-event ?\())
(call-interactively (key-binding "("))))
(key-chord-define-global "ff" 'my-paren-call)

Binding similar commands from different modes to the same key

I use emacs in multiple modes (ESS, Auctex, Slime, elisp, etc...) all using evil-mode key-bindings. Each of the interaction modes have similar functions for evaluating regions, lines or buffers that I have bound to shortcuts using spacebar as a prefix.
;; bind slime's eval and elisp eval to the key sequence "<SPC>e"
(evil-define-key 'normal lisp-mode-map (kbd "<SPC>e") 'slime-eval-last-expression)
(evil-define-key 'normal lisp-interaction-mode-map (kbd "<SPC>e") 'eval-last-sexp)
I would like to set a default key for a "type" of function, so that I don't need to have an entry like the above for every interaction mode I use and for every command. This would hopefully give a more readable .emacs init file and make it easier to change my key-bindings in the future.
I'm fairly sure that I could do this myself using a series of hooks, but I wonder if there is any existing or built-in support for this?
Thanks
tensorproduct
I don't know anything about Evil, so I'll give the normal Emacs solution:
(global-set-key [?\s ?e] #'my-eval-last-sexp)
(defvar my-eval-last-sexp-command #'undefined)
(defun my-eval-last-sexp ()
(interactive)
(call-interactively my-eval-last-sexp-command))
(add-hook 'emacs-lisp-mode-hook
(lambda () (set (make-local-variable 'my-eval-last-sexp-command) #'eval-last-sexp))
(add-hook 'lisp-mode-hook
(lambda () (set (make-local-variable 'my-eval-last-sexp-command) #'slime-eval-last-expression))
...
As you can see, there's only one mention of the key you want (in this case [?\s ?e]). But you don't save much on the amount of code you have to write. You might improve it by making my-eval-last-sexp a bit more complex (e.g. it could try to guess the command name from the major mode name), or by replacing the hook function with a global alist.
Hopefully, in some future Emacs, all such source-code modes that interact with some interpreter/compiler will share more of their code so that your problem will simply disappear.

How do I bind C-= in emacs?

This s-expression in my .emacs file does not produce the desired result:
(define-key global-map (kbd "C-=") 'djhaskin987-untab-to-tab-stop)
Why can't I bind a command to Ctrl+=?
EDIT for clarification:
I am using emacs23-nox on the standard build of urxvt-256colors for Debian, except that I have recompiled with --disable-iso405776 (or something to that effect) it so that Ctrl+Shift doesn't do the weird 'insert character' thing. I don't know if this affects anything. For example, C-M-i sends M-TAB, which I don't understand.
EDIT II:
I apologize for not making this clear. The function djhaskin987-untab-to-tab-stop has the line (interactive) in it. This part works.
The accepted answer in combination with the link in the first comment to it is enough to get started on a complete solution. The steps are:
make your terminal output escape codes for the key
make Emacs recognise the escape codes as a standard keypress
bind the keypress in a mode map
The first is very terminal and/or operating system dependent.
The link in the first comment shows some examples for X Window System. The key names are available in /usr/X11R6/include/X11/keysymdef.h (or try locate keysymdef.h), prefixed with XK_ (which should be removed for our purposes). I read that symbolic names are preferred over key literals.
I don't currently run X but I think it should look like this in your case:
XTerm.VT100.Translations: #override \
Ctrl ~Meta ~Shift <Key> equal: string(0x1b) string("[emacs-C-=")\n
The first string is the escape, the second is of your choosing.
In iTerm you can use Preferences->Keys and choose Send Escape Sequence as the Action. For example, I have:
Emacs Wiki lists some configuration methods for other terminals.
Now you can teach Emacs to recognize it as a C-=. First define-key into input-decode-map. I have a couple of helper functions:
(defun my/global-map-and-set-key (key command &optional prefix suffix)
"`my/map-key' KEY then `global-set-key' KEY with COMMAND.
PREFIX or SUFFIX can wrap the key when passing to `global-set-key'."
(my/map-key key)
(global-set-key (kbd (concat prefix key suffix)) command))
(defun my/map-key (key)
"Map KEY from escape sequence \"\e[emacs-KEY\."
(define-key function-key-map (concat "\e[emacs-" key) (kbd key)))
So then:
(my/global-map-and-set-key "C-=" 'some-function-to-bind-to)
Some keys (currently: ()\|;'`"#.,) will need escaping in the string, like C-\..
In a terminal, TAB is represented by the same byte sequence as C-i. And typically the terminal has no special byte-sequence for C-=, so it will just send a =. There is nothing that Emacs can do about it. But you might be able to teach your terminal emulator to send some special byte sequence of your choice (check the documentation of your terminal emulator for that), after which you can teach Emacs to recognize it as a C-= (with something like (define-key input-decode-map "...thebytes..." [?\C-=])).
The problem is that you use emacs in the terminal.
The terminal does not allow "C-=".
Try your function in the graphical emacs and it will work.
You will have to find another keybinding for the terminal.
You can map C-= using the default ascii codes: ^[[61;5u. Then you can bind it in Emacs either using:
(global-set-key (kbd "C-=") 'djhaskin987-untab-to-tab-stop))
or let use-package do it, e.g.:
(use-package expand-region
:ensure t
:bind (("C-=" . er/expand-region)))
I do want to thank Sam Brightman, for his wonderful solution. It's a very clean, albeit heavy-handed, approach that will work for any keys that cannot be sent via normal ascii codes. I've been wanting to get C-TAB working inside iterm2 for a long time. I was able to do it by deleting the builtin preferences keys for C-TAB/C-S-TAB and using his approach. With the following, I can be ssh'd into remote Linux boxes and quickly switch through lots of open buffers in projects, just like a desktop editor.
(use-package nswbuff
:defer 1
:after (projectile)
:commands (nswbuff-switch-to-previous-buffer
nswbuff-switch-to-next-buffer)
:config
(progn
(my/global-map-and-set-key "C-TAB" 'nswbuff-switch-to-previous-buffer)
(my/global-map-and-set-key "C-S-TAB" 'nswbuff-switch-to-next-buffer))
:init
(setq nswbuff-display-intermediate-buffers t
nswbuff-exclude-buffer-regexps '("^ "
"^\*.*\*"
"\*Treemacs.*\*"
"^magit.*:.+")
nswbuff-include-buffer-regexps '("^*Org Src")
nswbuff-start-with-current-centered t
nswbuff-buffer-list-function '(lambda ()
(interactive)
(if (projectile-project-p)
(nswbuff-projectile-buffer-list)
(buffer-list)))))
The function you're binding must be interactive. Try:
(define-key global-map (kbd "C-=")
(lambda () (interactive) (djhaskin987-untab-to-tab-stop)))