Emacs input-decode-map for terminal - emacs

I have asked a question about Ctrl-arrow keybinding in Emacs in terminal:
Emacs Ctrl modifiers don't work in console
And was told, that Linux terminal emulator doesn't process this combination. I managed to create a file for loadkeys command, that processes these keys:
control keycode 105 = F100
string F100 = "\033[[left"
control keycode 106 = F101
string F101 = "\033[[right"
Then loaded it from root:
#loadkeys ./funcskeys
After that every time I click Ctrl-right or Ctrl-left in console, I get 'right' or 'left' printed. Now I need to process this in Emacs. As far as I understand from this question:
Binding M-<up> / M-<down> in Emacs 23.1.1
it must be done, using input-decode-map function. But I couldn't make it work. Plz, help.

Change your "funcskeys" file slightly to produce the following escape sequences:
control keycode 105 = F100
string F100 = "\033[1;5D"
control keycode 106 = F101
string F101 = "\033[1;5C"
Then add the following lines to your .emacs file:
(define-key input-decode-map "\e[1;5C" [(control right)])
(define-key input-decode-map "\e[1;5D" [(control left)])
After running loadkeys and restarting Emacs, CTRL+left and CTRL+right should work. You can verify this by typing:
C-h k C-right
and
C-h k C-left
To actually bind these keystrokes to a command, such as forward-word, you might have to add the following lines to your .emacs file as well:
(global-set-key [(control right)] 'forward-word)
(global-set-key [(control left)] 'backward-word)
Note that this whole approach specifically only makes the key combinations CTRL+left and CTRL+right work. It does not for instance make ALT+left / ALT+right work, or any other key combinations involving the CTRL character.

Related

Emacs/elisp: global-set-key bindings not taking effect for Meta-<down> or -<up>?

I am trying to bind M-<up> and M-<down> to scroll-down-line and scroll-up-line respectively as indicated here: https://stackoverflow.com/a/16229080/562139.
This is what I have in my .emacs:
;; Key bindings
(global-set-key (kbd "M-g") 'goto-line)
;; Scroll line by line
(global-set-key (kbd "M-<down>") 'scroll-up-line)
(global-set-key (kbd "M-<up>") 'scroll-down-line)
Problem:
The scroll key bindings are not taking effect, while the one for goto-line does.
When I run M-x scroll-down-line however, emacs prompts me and says
"you can run the command with <M-down>"
Note:
When I run global-set-key (kbd "M-<down>") 'scroll-up-line) or (global-set-key (kbd "M-<up>") 'scroll-down-line) directly in the mini-buffer, the bindings take effect! However, I seem to have noticed through the corner of my eye when I do the latter, that pressing M-<up> actually sends something like ESC ESC-<up>.
I'm foxed. What gives?
Note: I am running emacs 24.3 in a terminal (via iTerm on OSX with Option key mapped to ESC+) over SSH to a RHEL5 virtual machine.)
Update
I followed the suggestion in this answer and found that pressing M-<up> results in something completely different:
ESC <up> (translated from ESC M-[ A) runs the command
scroll-down-line, which is an interactive compiled Lisp function.
It is bound to <M-up>, ESC <up>.
(scroll-down-line &optional ARG)
I'm going to try binding that key sequence to the function and check the result.
Try starting Emacs without your init file: emacs -Q, and see if you can reproduce the problem.
I do not see the problem, with Emacs 24.3 in terminal mode.
What you saw briefly was probably ESC <up>, which is equivalent to M-<up>.
Did you perhaps mean to type "When I run M-x scroll-up-line (instead of down)?
I suspect that you are in some mode that gives a local binding or a minor-mode binding to these keys, which overrides the global binding. To test that, try in a buffer that is in fundamental mode. If that is the case, then to override that overriding you will need to also bind the keys in that mode's keymap.
If you cannot repro the problem starting from emacs -Q then bisect your init file (~/.emacs) recursively until you find the culprit code.
Seems key got lost in translation.
Planted a forward-paragraph at openSuse that way:
(global-set-key [(meta down)] 'forward-paragraph)

Bind command to C-RET in Emacs

Say I have some interactive function in Emacs my-function, how can I bind it to Ctrl + RET?
I have tried with:
(global-set-key (kbd "C-RET") 'my-function)
and
(global-set-key (kbd "C-return") 'my-function)
but none of them seem to work. is this at all possible?
Always remember that kbd very conveniently accepts the exact same syntax that Emacs gives you when you ask it about a key sequence, so you never ever have to guess.
C-hkC-RET tells me:
<C-return>
therefore I would use (kbd "<C-return>")
OTOH, when running Emacs in my terminal, C-hkC-RET tells me:
C-j
because C-RET isn't a valid control character in a terminal, and therefore Emacs isn't receiving the same input that it gets in GUI mode (so I wouldn't be able to use that binding in my terminal).
This should work:
(global-set-key [(control return)] 'my-function)
It works for me, but may not in a terminal as per #phils's answer.

Emacs Ctrl modifiers don't work in console

I have 2 hotkeys for dired, that work in GUI mode in Emacs:
(add-hook 'dired-mode-hook
(lambda ()
(define-key dired-mode-map (kbd "C-<up>")
(lambda () (interactive) (find-alternate-file "..")))))
(add-hook 'dired-mode-hook
(lambda ()
(define-key dired-mode-map (kbd "C-<right>") 'diredp-find-file-reuse-dir-buffer)))
But when I click CTRL+→ or CTRL+↑ in console the cursor just moves as if the arrow was pressed.
When I try CTRL+H K and then CTRL+→, it gives me the right key docs as if CTRL wasn't pressed at all.
How to fix this strange behaviour in console?
I am using Linux Slackware 14, Emacs 24.2.1.
Here is the algorithm, how to make modifier keys work in Emacs in terminal.
1.Create a file funcskeys with content:
control keycode 105 = F100
string F100 = "\033[1;5D"
control keycode 106 = F101
string F101 = "\033[1;5C"
control keycode 103 = F102
string F102 = "\033[1;5E"
altgr keycode 105 = F103
string F103 = "\033[1;5F"
At the end must be an empty line!
2.Under root load the file:
#loadkeys funcskeys
3.Put this into the beginning of .emacs:
(unless (display-graphic-p)
(progn
(define-key input-decode-map "\e[1;5C" [(control right)])
(define-key input-decode-map "\e[1;5D" [(control left)])
(define-key input-decode-map "\e[1;5E" [(control up)])
(define-key input-decode-map "\e[1;5F" [(meta left)])))
End of algorythm
After this hotkeys will work:
(global-set-key (kbd "C-<right>") 'forward-word)
(global-set-key (kbd "C-<left>") 'backward-word)
Your terminal likely doesn't produce different escape sequences for CTRL-right‬ versus just right.
You can easily verify this by typing CTRL-v CTRL-right‬ and CTRL-v right‬. Here, CTRL-v tells the terminal to print the escape sequence for the key that follows. If these two produce the same sequences then your terminal sends the exact same information to Emacs whether you press CTRL or not.
For instance, if I type these shortcuts in a Gnome terminal, I get:
^[[C for CTRL-v right‬
^[[1;5C for CTRL-v CTRL-right‬
When I do the same on one of the Linux consoles, I get:
^[[C for CTRL-v right‬
^[[C for CTRL-v CTRL-right‬
As you can see, in the latter case it's exactly the same result for both key sequences, hence there's no way Emacs can distinguish the two.
The only way to fix this is to convince your terminal to send a different sequence when you hold down the CTRL key - see this question for more information.
An easier work-around would be to simply use different key bindings in Emacs.
Look out for loadkeys. At least in Debian/Ubuntu it's in the package kbd. With it, you can modify your keyboard layout and probably also some more "exotic" key combinations.

Why emacs confuse PageDown (<next>) key with M-[?

I found big distinction in standard emacs-nox and emacs-gtk.
I know that emacs console version (emacs-nox) has problem with some keys (eg Shift-Tab - ), but not with PageDown.
When I have empty .emacs file, and try to recognize command name run by PageDown key (by C-h c), emacs-nox emacs-gtk works normally - pushing PageDown makes scroll-up, and C-h c PageDown print scroll-up in minibuffer.
The problem arise when i try to bind "M-[" key.
In .emacs i has only one statement:
(global-set-key (kbd "M-[") 'hippie-expand)
emacs-nox does not recognize command name run by key - it does'nt print in minibuffer anything when C-h c PageDown, insted wriets to buffer "~6".
When I try
C-h k PageDown
I get: M-[ runs the command hippie-expand
emacs-gtk works normally - pushing PageDown makes scroll-up, and C-h c PageDown print scroll-up in minibuffer.
So I guess emacs nox treats PageDown as M-[ and add something extra.
Any idea how to fix this in emacs-nox?
I use emacs v23.2
EDIT:
I tested other case: In .emacs I have only:
(global-set-key (kbd "") 'hippie-expand)
and both C-h c PageDown and C-h k PageDown works properly (prints hippie-expand), and when in buffer I push PageDown also works good.
The problem has to do with the escape sequence the terminal sends to Emacs. You can check the escape sequence by typing C-v in a terminal window, followed by the key combination. So, for instance, if you type
C-v M-[
you should see something like this in the terminal window:
^[[
If you type
C-v PageDown
you should see
^[[6~
And that explains the problem: the key sequence generated by M-[ is a prefix of the key sequence generated by PageDown. Thus when you bind that prefix to a function (e.g., by globally setting M-[ to 'hippie-expand), you get the following effect when hitting PageDown:
The first two characters (^[[) of PageDown's escape sequence are interpreted as the prefix and thus 'hippie-expand is called. Then the remaining two characters are interpreters like ordinary key strokes, and are thus inserted into the buffer. That's why you see "6~" when you press PageDown.
I think the only way to change this is to convince the terminal to send different sequences for those keys. But the more painless way is just to use a different shortcut than M-[. (I would suggest M-/.)
This has to do with the terminal emulation and how Emacs-nox interprets the escape sequences sent to it by the terminal whenever you hit a key.
It thus depends on your terminal, but you could try to put the following lines in your .emacs file:
(unless window-system
(define-key input-decode-map "" [next])
(define-key input-decode-map "" [prior]))
Then move the cursor between the first two "" characters and type C-q PageDown, then move it between the "" in the row underneath and type C-q PageUp. The result should look like this:
(unless window-system
(define-key input-decode-map "^[[6~" [next])
(define-key input-decode-map "^[[5~" [prior]))
but note that the ^[ is only a single character (escape) - that's why you cannot simply copy & paste it from this answer.
Do the keys work after restarting emacs-nox?

emacs -- keybind questions

I have successfully used Ctrl+Shift+Up ' Ctrl+Shift+down '
Ctrl+Shift+left' Ctrl+Shift+Right to different commands. But when I
tried to use Ctrl+s to the command save-buffer and Ctrl+Shift+s, which
is equivalent to Ctrl+S, to another command, it has some problem.
save-buffer works fine, but when I type Ctrl+Shift+s, it excute
the command save-buffer. I used Ctrl+q to find the control sequences of
Ctrl+s and Ctrl+Shift+S, I get the same result, which is ^S.
I expect that I will get ^s for Ctrl+s, but it doesn't.
Anyone knows the reason?
Another queston is: I use Ctrl+c for the command killing-ring-save. In this
case, all commands (which are of large number) begin with Ctrl+c don't work now.
Is there a way to replace the prefix Ctrl+c by another customized prefix?
I may pose my question in the wrong direction. I use ctrl+c as
killing-ring-save. It works fine in emacs (no mode). But if I open a .c file (C-mode), then
when I type Ctrl+c, it waits me to type another key. I think in this case,
ctrl+c is regarded as a prefix. In this case, I need the following modifications:
Using a custom defined prefix, say Ctrl+a, as Ctrl+c ; Remove the
prefix Ctrl+c ; Using Ctrl+c as killing-ring-save.
I add the following to my ~/.emacs :
(global-set-key (kbd "C-a") mode-specific-map)
(global-set-key (kbd "C-c") 'kill-ring-save)
(global-set-key (kbd "C-f") 'isearch-forward)
(global-set-key (kbd "C-v") 'yank)
(global-set-key (kbd "C-s") 'save-buffer)
(defun my-c-initialization-hook ()
(define-key c-mode-base-map (kbd "C-a") mode-specific-map)
(define-key c-mode-base-map (kbd "C-c") 'kill-ring-save))
(add-hook 'c-initialization-hook 'my-c-initialization-hook)
But this doesn't work. Ctrl+c is still regarded as a prefix, so I can't use it
as kill-ring-save. Furthermore, if I type Ctrl+a Ctrl+c, it said it's not
defined. (I thought it will have the same result as I type Ctrl+c Ctrl+c)
The C-c binding is tricky, CUA mode solves it well, by only making it do kill-ring-save when you have a region marked.
First, Control-S is an ASCII control character -- ^s and ^S are the same character.
Keys are something different from characters, however, and if you are using Emacs with a window manager then you can distinguish the keys C-s and C-S-s. The latter is Control-Shift-s.
The problem you are hitting is that if you do not explicitly bind the shifted version of a letter key, then the shifted letter key uses the binding of the unshifted key. This is a "feature".
So you need to bind both C-s and C-S-s.
(global-set-key (kbd "C-s") 'save-buffer)
(global-set-key (kbd "C-S-s") 'another-command)
If you're running emacs in a terminal, then the reason for the shift-ctl-c issue could be the terminal driver. In that case, give the command stty stop undef, then run emacs again, and see if it affects the problem. Also, see if you get same problem with shift-ctl-other letters