How to bind multiple keys in gnu screen, specifically using arrow keys - linux

First off, I'm using Opensuse 13.2 64-bit and also Arch_Linux 64-bit
Can't get the bind to work for either of them (well, the binds that I want), but I'm mostly focused on the Arch_Linux. Also, using openbox wm, xfce4-terminal. ( in opensuse using konsole and gnome 3) and my $TERM is set to xterm-256color in my ~/.bashrc and is switched to screen-256color when using screen in opensuse, but strangely is not changed in Arch.
I want to bind C-a down: to focus down, C-a up: to focus up, C-a left: to focus left etc.. Lets just focus on focus down for the moment.
I've tried everything in my ~/.screenrc file
bind "\E[B" focus down
bind "\EOB" focus down
bind "^[[B" focus down
bind "^[OB" focus down
bind "\033[B" focus down
bind "\033OB" focus down
bind "\033\133\102" focus down
bind j focus down # works fine
Nothing catches the down arrow key. I CAN use the following
bind -k kd focus down
however, I also want to bind multiple keys using the arrows and AFAIK the -k option only allows binding 1 key (or shift + left/right) . Actually I'm lucky I can even use the -k option since it is not documented.
Now I've checked my kd (termcap) and kcud1 (terminfo) using infocmp
infocmp -1 | grep kcud1
kcud1=\EOB,
infocmp -1C | grep kd
:kd=\EOB:\
and BTW these symbols can be looked up here for termcap and here for terminfo and its termcap equivelancies (actually I guess you can just use: man terminfo)
when I use Ctrl-v and press down arrow I get
^[[B
showkey -a
^[[B 27 0033 0x1b
91 0133 0x5b
66 0102 0x42
Anyone know how to go about this. I want to know why I can't use bind without the -k termcap_name and/or how to use combo of keys(such as ctrl/alt) and termcap names. Thanks for all and any info.
I've tried setting termcapinfo also with no luck. don't think I'm using it right.
termcapinfo * kd=\EOB
bind "\EOB" focus down
termcapinfo * kd=\E[B
bind "\E[B" focus down
etc...

It appears that GNU screen doesn't permit binding sequences of multiple keys.
Quoting the man page:
bind [-c class] key [command [args]]
Bind a command to a key.
...
The key argument is either a single
character, a two-character sequence of the form "^x" (meaning
"C-x"), a backslash followed by an octal number (specifying
the ASCII code of the character), or a backslash followed by a
second character, such as "\^" or "\". The argument can also
be quoted, if you like.
...

As said in this answer, try:
bindkey "^A^[OB" focus down
The vim trick is really helpful to get the code for the combinations you want (for example, if you wanted the combo Ctrla Ctrldown instead of Ctrla down, this would be ^[[1;5B instead of ^[OB).
Credit should go to koyae for the original answer.

Related

Terminal: send a do-nothing escape sequence or control character

I need my terminal to send an unused control character or escape sequence, one that has no effect at all layers: ignored by shells (bash, ...), ignored by line-editors (readline, ...), and ignored by all applications (vim, less, mutt, ...). I'll then bind this key within tmux, with a user defined key escape sequence if necessary. What control character or escape sequence do I use? More information below:
I want the Control-Shift-c key chord in tmux bound to an action which will copy the tmux selection into the X clipboard selection buffer. That and continue to have Control-Shift-c copy the terminal selection into the X clipboard selection buffer when tmux is not running. Terminal emulators generate the same output for both Control-Shift-key and Control-key inputs, see [1][2]. The first step is to change this:
# Enable fixterms (I think) sequences for all keys:
xterm -xrm "XTerm.vt100.modifyOtherKeys: 2" -xrm "XTerm.vt100.formatOtherKeys: 1"
This instructs xterm to construct an escape sequence for all keys modified by Control, Alt, or Meta. As far as I can tell nothing supports these escape sequence, whether they're formatted using the original xterm sequences or via the new fixterms [3] specifications. Even tmux supports only a subset of these sequences [4], rather than a full-blown CSI-sequence parser [5].
The simplest workaround is to have only Control-Shift-c send a fixterms sequence, as per [6]. Since this sequence isn't supported by tmux, it'll have to be manually defined via the user-keys option. It will also have to be bound in the root key table of tmux rather than one of the copy-mode tables; otherwise if tmux isn't in copy-mode the binding will be ignored and passed through tmux to one of the terminal applications.
# Configure only Control-Shift-c to send a fixterms sequence:
xterm -xrm "XTerm*vt100.translations: #override \n\
Ctrl Shift <Key>c: string(0x1b) string ([67;6u)"
# Recognize (but don't handle) the Control-Shift-c fixterms sequence:
tmux set-option -s user-keys[0] "\e[67;6u"
# Copy the selection to the clipboard buffer only when in copy-mode. If
# there is no selection, nothing will be copied:
tmux bind-key -T root User0 if-shell -Ft= "#{pane_in_mode}"
"send-keys -X copy-pipe 'xsel -i -b'"
All other applications, which don't support fixterms sequences, will receive input junk. Even worse, unknown escape sequences are likely to be misinterpreted and trigger application-specific commands. Initially I considered using tcgetpgrp(3)[7] to get the name of the command currently running within the terminal, much like #{pane_current_command} in tmux[8].
xterm <-> bash <-> command
The terminal binding for Control-Shift-c would first copy the terminal's selection to the clipboard buffer, as usual; then call my external program[9]. If the terminal command isn't currently tmux, nothing happens; otherwise the external command writes the fixterms Control-Shift-c sequence to the terminal's pts. When tmux receives that sequence it will overwrite the clipboard buffer with its own selection.
xterm -xrm "XTerm*vt100.translations: #override \n\
Ctrl Shift <Key>c: copy-selection(PRIMARY) \n\
exec-formatted("~/send_fixterms_sequence_if_tmux.py")
This fails to handle nested terminal emulators, as when running tmux over ssh - which is very common.
xterm <-> bash <-> ssh <-> bash <-> tmux <-> bash <-> command
That's my dilemma and I'm currently considering several alternatives:
Have the terminal send a control character rather than an escape sequence. Control characters are always supported. I'd like there to exist a do-nothing character and was hopeful for Control-# (NUL or ASCII 0), but that character is echoed by the shell and has a significant effect in insert mode in vim. If no such character exists, see #3. Perhaps I could appropriate an uncommon control character, but it would also have to be configured to do nothing, across all layers: xterm, bash, readline, vim, etc.
Have the terminal send an unused or do-nothing escape sequence rather than the Control-Shift-c fixterms sequence. The sequence would need be ignored at all layers: ignored by shells (bash, ...), ignored by line-editors (readline, ...), and ignored by all applications (vim, less, mutt, ...). See #3.
Modify the terminfo entry for my terminal to ensure that at least one of the above (control code, standard escape sequence, or fixterms escape sequence) is ignored at all layers, as per [10]. Then, bind this modified sequence in tmux.
Invoke readline to do something magical. A long-shot as this is unlikely to have any effect on alternate-mode terminal applications.
The idea is to, as before, copy the terminal's selection to the clipboard buffer. Then insert <STRING> as if it had been typed. When tmux receives <STRING> it will overwrite the clipboard buffer with its own selection. Any other application will ignore it: including and especially having nothing printed to the terminal.
xterm -xrm "XTerm*vt100.translations: #override \n\
Ctrl Shift <Key>c: copy-selection(PRIMARY) string(<STRING>)
I'm also planning on extending this to gnome-terminal, so an example of writing the escape sequence or control character to the terminal's pts would be appreciated. I only use xterm as a working example - this question is definitely not xterm-specific.
https://stackoverflow.com/a/14876639
https://unix.stackexchange.com/a/116630
http://www.leonerd.org.uk/hacks/fixterms/
https://github.com/tmux/tmux/blob/master/xterm-keys.c
http://www.leonerd.org.uk/code/libtermkey/
https://stackoverflow.com/a/2179779
http://man7.org/linux/man-pages/man3/tcgetpgrp.3.html
https://github.com/tmux/tmux/blob/master/osdep-linux.c
https://invisible-island.net/xterm/manpage/xterm.html#h2-KEY-BINDINGS
Bind Ctrl+Tab and Ctrl+Shift+Tab in tmux
https://man.openbsd.org/ssh#ESCAPE_CHARACTERS
edit, new idea: SSH provides its own terminal emulator, or at least is hooked up to a pts pair[11]. Does that mean it can handle incoming escape sequences, and perhaps run an external remote command, such as one using tcgetpgrp? Or would that be an insecurity? Rather than configuring a possibly endless series of terminal applications to ignore an escape sequence, I'd prefer to configure only SSH as I would tmux.
All the available sequences will potentially look like a key of some kind to the application receiving it (for example, 0 is C-# and C-Space), there is no sequence that applications are guaranteed to ignore.
If I was you I'd just send the escape sequence for F20 or something and bind that key to do nothing in the other applications you use a lot.

Ctrl Right and Ctrl Left doesn't move from a word to another in Fish Shell

When I use my Fish Shell on Linux Mint, using the Ctrl+Left or Ctrl+Right keys isn't moving the cursor to the previous or next word. It switches between an I and an N instead:
Here is the I and then the N:
I cannot do partial completion then, so it's really boring.
How can I fix this?
Glenn Jackman's comment is correct - you are using vi-mode.
Some third-party prompts (e.g. from Oh-My-Fish or similar) enable it for some reason.
To switch back, usually executing fish_default_key_bindings once interactively should suffice once you have deleted the offending line or package (search for fish_vi_key_bindings).
Or, if you like vi-mode, you can add a binding. Create a function called fish_user_key_bindings (e.g. with funced).
The content should look like this
function fish_user_key_bindings
bind -M $mode $sequence $command
end
where "$command" here would be "backward-word". $mode would be the vi-mode you want the binding to be valid for, e.g. "insert" or "default" (what vi would call "normal" mode).
"$sequence" would be the text sequence that the terminal sends to fish whenever this key combination is pressed. Unfortunately they aren't standardized, so you need to figure out which it is on your system.
fish_key_reader is useful here - execute it, press the combination and use what it tells you. On my terminal ctrl+left sends \e\[1\;5D (and ctrl+right sends the same with C instead of D).

How do I bind C-? in bash?

I want to bind C-? to history-search-backward in bash and/or zsh. I tried the following way
bind '"^?": history-search-backward' # bash
bindkey '^?' history-search-backward # zsh
The binding works fine, but at the same time BS (backspace) stops working correctly. The reason is that BS generates the same code as C-? what one can check with C-v BS and C-v C-?. Thus the final result is that both C-? and BS are bound to history-search-backward what is obviously not what I wanted.
So the question is how can I properly bind C-? without affecting BS?
Which string is sent to the shell when pressing a key or key combination is determined by the terminal.
It seems that a lot (most?) terminal emulators by default send ^? (ASCII 0x7f, Delete) when pressing the backspace key. While the actual backspace character would be ^H (ASCII 0x08, Backspace).
If you can change the behaviour of your terminal emulator to send ^H you should be able to maintain the function of the backspace key while still being able to bind ^? to something else.
Terminal emulators the provide a GUI for configuration (gnome-terminal, roxterm, konsole, ...) should have an option for that.
Others (xterm, urxvt, ...) may have appropriate X resources that may be set in ~/.Xdefaults (or - depending on your distribution - ~/.Xresources).
For xterm you need to set:
XTerm.backarrowKeyIsErase: False
For urxvt set
URxvt.backspacekey: ^H
please note that this is the actual ^H (ASCII 0x08) character and not a two character string consisting of ^ and H.
To load these settings either call xrdb -merge ~/.Xdefaults or close and restart your X session. (The settings will only be enabled for new terminals)

How do I insert a tab character in Iterm?

Simply put, I know you can do ctrl+v+tab to insert a physically real tab character in a bash statement. But how do I do the same for iTerm?
The answer was to hit control+v, then tab afterwards, not all together! Hope this helps someone.
It's not iTerm, but your shell that affects how you''re able to insert a tab.
First, make sure you're in BASH shell: Type the following command:
$ echo $RANDOM $BASH_VERSINFO
23714 3
The first is a random number, and the second should be the BASH Version number. If you get a blank line or just a random number, you're not in the BASH shell, and that's probably one of your issues.
Another thing is to execute this command:
$ set -o
allexport off
braceexpand on
emacs on
errexit off
errtrace off
[...]
privileged off
verbose off
vi off
trace off
The two lines of interest is the emacs and the vi lines. One of those should be on. If they're both off, you can't do the Ctrl-V-Tab to insert a tab character.
When the vi mode is on, it should be Ctrl-V-Tab like you said. With emacs mode on, it is either Ctrl-V-tab, or possibly Ctrl-Q-tab.
However, this isn't an iTerm thing, this is your shell that's doing it.
If by a "physically real tab character" you mean sending the tab hex code (0x09) to the shell, then you can do this in iTerm by pressing Ctrl + Tab (⌃ ⇥).
This is the default setting, although you can change it (as well as add other hex code values to send) in iTerm > Preferences > Profiles > Keys.
I'm not certain why you're comparing a "bash statement" with iTerm. You write bash scripts in iTerm. Which means, assuming you're writing your scripts in iTerm, you're already doing what you want.
I'll assume you mean scripting in vi vs command line. The way I get literal characters on the command line is by using vi editing mode. Do set -o vi. Then you can use ctrl+v followed by tab in the manner that you're used to.
IMO, using vi editing mode comes with a slew of other pluses like searching your history, faster navigation, etc. So you could just add it to your .bashrc if you wanted and use it all the time.
One should also try Ctl + V Ctl + I. It is working in konsole where Ctl+V+Tab deosn't work.

Mapping numeric keypad keys in vim

I'm unable to get this mapping to work in vim inside an xterm terminal.
:map <k0> :echo 'Hello'<CR>
I can get the same mapping to work fine in gvim. If I issue the above command in vim on a terminal, it accepts it, and it shows up correctly when I type :map. But in normal mode, if I press the 0 keypad key, a "0" shows up on the status line, and then disappears with the next keypress.
I'm using the vim that came with Fedora 14 if that matters, and a plain xterm. The keypad keys work fine in insert mode, both with numlock on and off.
What am I missing?
Try to add this line to your ~/.Xdefaults:
xterm*appkeypadDefault: false
and relaunch xterm.
The "Application Keypad Mode" is likely the reason of your troubles.
But I don't think you should do what you are doing. In --NORMAL-- mode, numeric input is used to indicate "count" like in 4dd. Mapping numbers to other commands is going to get you into troubles fast.
You should add a xterm tag to your question.
There's some ambiguity in the question, which may indicate the actual problem. vim accepts that binding for k0 supposing that it is a function key.
Most keyboards that you'll see number function-keys starting at 1, and a few terminal descriptions equate function-key 1 to k0, a few equate it k0 to function-key 10. It's also possible that someone assumes that is part of the numeric keypad, but unlikely (since the keypad uses different character sequences than the function keys).
That's assuming you used a terminal description that knows about the function keys. The vt100 terminal description doesn't do that, since vt100's had no function keys (other than PF1 through PF4 which are or aren't depending who you talk to). But if you had TERM=vt100, then some of the numeric keypad could be recognized on the basis of the terminal description (see for instance the lengthy comment above the vt100+fnkeys description).
It's not in TERM=xterm, however.
What you're overlooking is that vim (helpfully perhaps) amends the terminal description using its built-in termcaps. It recognizes PF1, etc. using table entries like this:
{K_XF1, IF_EB("\033O*P", ESC_STR "O*P")},
{K_XF2, IF_EB("\033O*Q", ESC_STR "O*Q")},
{K_XF3, IF_EB("\033O*R", ESC_STR "O*R")},
{K_XF4, IF_EB("\033O*S", ESC_STR "O*S")},
But there are no entries for the numbered keys; there's no "\033O*p" for the 0 key.
If vim has (in the terminal description) the k0, and you haven't mapped it to anything, vim will treat it as a literal 0. The same happens with k1, etc., in effect treating the function-keys and numeric keypad as the same thing.
For what it's worth, GNU screen does the same thing, but also for the numbered keys. If I run vim inside screen, vim will see only the 0's. A literal 0 in vim doesn't do much in command-mode.

Resources