Emacs Ctrl modifiers don't work in console - emacs

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.

Related

How can i remap a non-ascii keyboard character in evil-mode?

I would like to remap the key "é" on my keyboard to ctrl-w in emacs evil-mode (doom emacs)
I tried with
(define-key evil-operator-state-map "é" "\C-w")
;; and
(global-set-key "é" "\C-w")
But none of these worked.
Is what I'm trying to do possible ?
How can I do it ?
Try this:
(define-key key-translation-map (kbd "é") (kbd "C-w"))
Use (kbd KEY-SEQUENCE), where KEY-SEQUENCE is what Emacs tells you the key sequence is.
Use key-translation-map to translate keys. See the Elisp manual, node Translation Keymaps.

Key map for ex command in emacs evil-mode

In emacs evil-mode, how do I bind a key sequence so that it pre-populates the evil-mode ex command line and positions the cursor? In vim, I can do this:
nnoremap g/r :%s//g<left><left>
In emacs, I tried this (and several variations):
(define-key evil-normal-state-map "g/" nil)
(define-key evil-normal-state-map (kbd "g/r")
(lambda () (interactive) (kbd ":%s/")))
It has no effect, and I don't see any messages after trying the keymap.
It looks like emacs used to have a useful function evil-ex-read-command that sent input to the evil-mode command line:
https://github.com/magnars/.emacs.d/blob/master/site-lisp/evil/evil-ex.el#L554
But that function doesn't seem to be available anymore.
If you mean to bind the key combination
Press and release g
Press and release /
Press and release r
your string in kdb should be "g / r".
Emacs is not based on keystrokes as vim is, but keystrokes are just a means to execute functions. So pressing k in normal mode does not execute the function k (as in vim), but self-insert-char. That means that you do not bind the combination g / r to equal some other keystrokes, but rather to call an arbitrary function. And evil defines an evil-ex function, that does exactly what you want (Actually it's the exact function, that is called, when you press : in normal mode).
Untested but it should work
(define-key evil-normal-state-map (kbd "g / r") (lambda () (evil-ex "%s/")))

Emacs input-decode-map for terminal

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.

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

Binding M-<up> / M-<down> in Emacs 23.1.1

I'm trying to put in a feature that I miss from Eclipse, where Alt+[Up/Down] transposes the lines up or down, but can not for the life of me figure out how to assign to these keys properly. I am using it in -nw mode (so just in a shell window), and typically run in a screen session.
Using a global key binding, I can get it to work with letter combinations, like (kbd "M-m"), but every combination I have tried for the arrow keys just gives me a message that doesn't make sense, I always get:
"ESC <up> is undefined"
What I have tried:
(global-set-key (kbd "M-<up>") 'transpose-line-up)
(global-set-key (kbd "<escape>-<up>") 'transpose-line-up)
(global-set-key [M-up] 'transpose-line-up)
(global-set-key [\e \M-O A] 'transpose-line-up)
And C-h c just returns:
ESC <up> (translated from ESC M-O A) is undefined
None of these work, either using ESC or Alt.
Any idea how I can make this work? I would prefer to have these as Alt+[Up/Down] just because that is what I am used to.
Edit
From the comments:
C-q Up prints ^[OA.
C-q M-Up prints ^[ and moves the cursor up a line.
C-h k (Alt+Up) prints ESC <up> (translated from ESC M-O A) is undefined.
Thanks for the suggestions, but they all turned out the same.
Emacs has a complex mechanism to handle the vicissitudes of function key and modifier encodings on various terminal types. It doesn't work out of the box in all cases. The following settings should work on your terminal:
(define-key input-decode-map "\e\eOA" [(meta up)])
(define-key input-decode-map "\e\eOB" [(meta down)])
(global-set-key [(meta up)] 'transpose-line-up)
(global-set-key [(meta down)] 'transpose-line-down)
You should be able to use (kbd "<M-up>") and (kbd "<M-down>") in place of [(meta up)] and [(meta down)], as long as you've done the step of telling Emacs (via input-decode-map) about the escape sequences that your terminal uses to encode these key combinations.
I always use C-h k (key) (i.e. describe-key) to find out how Emacs refers to (key), and then use (kbd) with that same string to utilise it.
In this case, describe-key returns <M-up>, so I would use (global-set-key (kbd "<M-up>") 'transpose-line-up) (exactly as J.F. Sebastian has done).
Edit:
Running emacs -nw (but not through screen), describe-key reports ESC <up> (translated from ESC M-[ A), and (kbd "ESC <up>") is successful for binding it.
Running screen emacs -nw, describe-key reports ESC <up> (translated from ESC M-O A), which seems to match what you see, and the binding for (kbd "ESC <up>") still works for me.
(n.b. Tested under Cygwin with screen 4.00.03, and Emacs 23.2.1.)
(global-set-key [M-up] 'beginning-of-buffer)
(global-set-key [M-down] 'end-of-buffer)
In my OSX, I have this definition to perform Alt-up/down to jump to top/bottom of buffer.
ugly workaround:
I've typed C-q <M-up> it produced ^[[1;3A on the terminal inside screen inside emacs.
(global-set-key (kbd "<M-up>") 'transpose-line-up)
(global-set-key (kbd "^[[1;3A") 'transpose-line-up)
I've got Lisp error: (void-function transpose-line-up) so the key bindings work.
Note: C-q runs the command quoted-insert.
The following lines work for me on macOS 10.11.6 and GNU Emacs 25.2.1:
(global-set-key (kbd "ESC <down>") 'end-of-buffer)
(global-set-key (kbd "ESC <up>") 'beginning-of-buffer)
Assuming you have the functions transpose-line-up and transpose-line-down already defined (as it seems to be from the example code in your original question):
(global-set-key [(meta up)] 'transpose-line-up)
(global-set-key [(meta down)] 'transpose-line-down)
works on OSX Terminal:
(global-set-key (kbd "ESC <up>") 'transpose-line-up)
(global-set-key (kbd "ESC <down>") 'transpose-line-down)