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.
Related
I encountered a problem with my terminal where when I paste text, it is prefixed by 00~ and suffixed with 01~.
For example, I will highlight text and push Command-C. I then push Command-V into the terminal and I see those weird characters pop up at the beginning and end of the text.
For example, I can highlight text and paste it into the terminal. I then see 00~text01~.
The text can be from anywhere, even from the Terminal itself. I do not have any copy/paste plugins installed, this is just the normal Copy/Paste. I am using the default Mac Terminal without any modifications.
I did some searching online, apparently the Paste wraps the text in special characters so that certain applications will see that this is pasted text and will handle it properly. However, the terminal is not handling this correctly, and is therefore not removing the weird characters. Apparently this paste mode is called the "Bracketed Paste Mode" http://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h2-Bracketed-Paste-Mode
I found another question that gave a solution on how to solve this issue on a linux machine, but after trying that solution I still have that same problem.
Can someone tell me how I can disable bracketed paste mode for the terminal? Or tell me the right way to get rid of these annoying characters?
What happens when text is pasted
Text has made it into the "system" (e.g. X, MacOS/Aqua) copy buffer from somewhere, maybe from the same terminal. The text is not altered here.
The text is pasted into the terminal; that is, "system" sees to that the terminal (e.g. xterm) receives the unaltered character sequence from the copy buffer. The terminal is aware that this is a paste, not keyboard input.
The terminal sends the char sequence in the buffer to the program running in the foreground (a shell, an editor, whatever). To the program the received data is indistinguishable from user input through the keyboard.
Discussion
This transparency (or opaqueness? whatever) is often a good thing much like the Unix paradigm of transparent pipe plumbing in general. But sometimes programs could deal with the data better if they knew it is pasted. For example an editor like vim could switch off auto indent — after all, the code is likely indented already!
Bracketed paste
Enter bracketed paste. For principal reasons the paradigm of transparent data piping cannot be altered; but the data can be decorated with sequences which would ordinarily not appear in terminal input to mark its start and end. If the terminal is so configured — for the xterm the configuration would be to send ESC [ ? 2 0 0 4 h — the pasted data is bracketed with escape sequences: ESC [ 2 0 0 ~ <buffer contents> ESC [ 2 0 1 ~.
The foreground program receives this "decorated" data, and it's up to to the program to handle it. A naive program treats all of it as user input, which is what you see.
A good discussion of bracketed paste can be found in this article.
Remedies
There are two issues in your case: The terminal ends up unexpectedly in bracketed paste mode; and the receiving program — presumably the shell — does not handle it.
One solution is user83536's: Identify the program which leaves the terminal in that state and call it through a wrapper which simply switches bracketed paste mode off again after the program has ended.
The program probably tried to switch bracketed paste mode off but failed. One reason can be that it sends the wrong escape sequence. Try setting the TERMINAL environment variable to the value best describing your terminal.
Try to switch off bracketed paste in the offending application. In vim one would say set t_BE=. That prevents vim from putting the terminal in bracketed paste mode and when it is set in a session, sends the "end bracketed paste mode" to the terminal.
Embrace bracketed paste. It seems to be a good idea. For the bash and other programs using readline one would put set enable-bracketed-paste on. For vim one could follow the suggestions here.
This may not apply directly to your problem, but I found this symptom to probably, in my case, be caused by my editor-of-choice 'mcedit' (Midnight Commander)
To alleviate the bug problem, I added the following function to my .bashrc file:
### vvv 'function mcedit' is a fix-up for the ~0/~1 paste problem
function mcedit() { command mcedit $# ; printf '\e[?2004l' ; }
Then 'source .bashrc'
Now every time I execute 'mcedit', it automatically adds the 'printf "\e[?2004l"' when I close out to reset the "Bracketed Paste Mode"
Works for me, YMMV.
To disable bracketed paste mode in your terminal, run the following command:
printf '\e[?2004l'
To disable bracketed paste globally, on Linux, add this line to ~/.inputrc :
set enable-bracketed-paste 0
To disable only in the current running Xterm (v 372) (running bash shell version 5.1.16 (probably earlier too, but I don't know)):
% bind 'set enable-bracketed-paste 0'
With either of the above two methods, you can re-enable bracketed paste (in the current Xterm) in the obvious way, namely:
% bind 'set enable-bracketed-paste 1'
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.
i have Vim with plugin vim-go and neocomplete, when o move the cursor from left to right in insert mode this happens
Note: this only happens with go code and vim-go required binaries (such as gocode, godef, goimports, etc..)
someone have same problem?
i am running Ubuntu 14.04.2 LTS 64bits with Kernel 3.13.0-48 Vim 7.4.52 with lua support
thanks in advance
It looks as if you are using gnome-terminal or konsole.
When you use cursor-keys to move around in insert-mode, the keys send escape sequences. In particular, if you happen to press the shift- or control-keys, those can send different escape sequences (with numbers), possibly with semicolons to separate the numbers. There are some limitations on vim's handling strings of that sort, and in some cases (see this discussion) it will get confused and stop interpreting the string, leaving junk on the screen.
The root of the problem is that in vi, the program (mis)uses the escape character for two different reasons:
a special "command" character sent by the user to the editor
the first character in the strings sent by most special keys to an application (including an editor).
The latter requires the program (vim) to wait "a while" to determine which case to use. If you are using a slow machine (or a slow connection) and your keyboard-repeat is fast, that defeats vim's attempt to distinguish the two cases. Likewise, your plugins send many characters to the screen for each keystroke, making vim slower.
It is aggravated by modified keys (using shift- or control-modifiers) since xterm and other terminals encode that information as a number. gnome-terminal and konsole use an older variant of xterm's (see xterm FAQ How can I use shift- or control-modifiers?) which is more easily mistaken by vim as not being an escape sequence.
If it is only a matter of timing, then moving your cursor more slowly would avoid the problem (agreeing that is only a workaround). You can gauge the amount of output done by vim by running it in script to capture the output into a typescript file. I do that to analyze bugs, by sending the data back to the terminal more slowly. Some of those typescript files are surprisingly large, for the little apparent work done.
I changed from neocomplete to YouCompleteMe, the random characters is not showing anymore.
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)
What I want to develop:
Terminal which can use at least 2 fonts in the same time. One font I will use for shell input lines, another font for command output. For example:
user#host$ ls /home
user user1 user2 user3
Why:
More readable terminal/shell
How: Here I have problem. Probably shell needs to generate some new escape sequences. And terminal need to load different fonts and handle those sequences. Where to start? How to define new escaping sequence, where are standards?
Future: Maybe somebody want to join me in this project?
The standard for control sequences is pretty much the Xterm Control Sequences document ctlseqs.ms in the XTerm source code. (You can turn it into a PDF with the command groff -ms -Tps ctlseqs.ms | ps2pdf - ctlseqs.pdf, though the -ms option seems to be broken on Ubuntu 12.04).
XTerm already supports control sequences to change the font, but for the entire terminal at once. Open xterm and type into your shell—
echo -e "\033[?35h\033]50;#+1^G\033\\" # aka CSI ? 35 h OSC 50 ; #+1 BEL ST
the font for the entire terminal should change. This control sequence actually supports the names of True-Type fonts as well; see page 21.
If you'd like to change an existing terminal to support changing the font inline, you're
welcome to choose pretty much any control sequences not already allocated in ctrlseqs.ms and use them. However, it's a good idea to choose new control sequences similar to the control sequences for functionality that already exists.
Your next step is to get the source code for an existing terminal and start digging. What terminal do you use right now? The source code for Konsole or gnome-terminal is probably going to be easier to work with than that for XTerm.
There is a standard sequence for swapping fonts.
SGR 11
Also known as
CSI 11m
ESC [ 11m
Similarly
SGR 10
will switch back to the default font.
However, as has been commented, almost no terminal actually supports this. You'd likely be better off using some other rendering attribute, such as bold/underline/italics. Though note also not many terminals support italics.
For reference
SGR 1 = bold
SGR 4 = underline
SGR 3 = italics
If you are happy with just different font attributes (and not different fonts) you can even implement something similar without writing your own terminal emulator if you use zsh. You can just set up your shell to emit the right escape sequences to set the correct terminal attribute (italics, bold, color, ...) before and after the prompt and before command execution.
Let's assume you use Xterm and want your prompt to be bold, the typed command line to be italics and the command output to be normal.
Then the setup looks like this:
# bold is \e[1m and italics is \e[3m , \e[0m resets the attributes
PS1=$'\e[1m'$PS1$'\e[0;3m' # I assume you have set PS1 already
function reset-terminal-attributes { printf '\e[0m'; }
autoload add-zsh-hook
add-zsh-hook preexec reset-terminal-attributes