I am writing a *nix shell, I want support the key-combination of Ctrl-Enter. And the library I use is GNU readline.
I have spent several hours on it, but can't find the way.
I can bind Enter successfully, like:
========= ~/.inputrc ===============
"\C-M": "sdf"
====================================
When I press Enter, I got "sdf" echoed, just as expected.
I can also bind Esc,Enter successfully(note, here is key serial, not combination), like:
========= ~/.inputrc ===============
"\e\C-M": "sdf"
====================================
When I pressed Esc and then pressed Enter, "sdf" was echoed as expected.
However, the following line can not produce a valid Ctrl-Enter combination:
========= ~/.inputrc ===============
"\C\C-M": "sdf"
====================================
And, "\C-\C-M" doesn't work too.
Here are two related questions:
how to bind the 'Enter key'
How to bind Ctrl-Enter in fish?
Can any one help me ?
You don't mention which terminal emulator you use - which matters, because in the end, it is the terminal that decides what your program reads from it when you press CTRL+ENTER
A way to make this work is (assuming you use xterm):
Make xterm send e.g. CTRL+k when you press CTRL+ENTER, by adding a line in your .Xdefaults:
XTerm.vt100.translations: #override Ctrl<Key>Return: string("\013")
Bind this to whatever you want in .inputrc:
"\C-k": "sdf"
Not very elegant, as this will only work in xterm. But, as far as i can see, the only way to get what you want.
Related
Often when I run a command that writes to stdout, and that command fails, I have to scroll up (using uncomfortable key-bindings) looking for the place where I pressed Enter, to see what the first error was (out of hundreds others, across many screens of text). This is both annoying and time-consuming. I wish there was a feature which allowed me to pin my current terminal to the place where I am now, then start the command, see only the first lines of the output (as many as fits below my cursor) and let the rest of the output be written but not displayed. In other words I would like a feature to allow me automatically scroll up to the place where I gave the command, to see the first lines of the output (where usually the origin of the failure is displayed).
I searched for it but I didn't find it. Do you know if such feature exists? Or have an idea how to implement it with some tricks or workarounds?
If you have a unique shell prompt you could bind a key to jump between shell prompts, for example something like this will make C-b S jump to the previous shell prompt then S subsequent ones:
bind S copy-mode \; send -X search-backward 'nicholas#myhost:'
bind -Tcopy-mode S send -X search-backward 'nicholas#myhost:'
Or similarly you could search for error strings if they have a recognisable prefix. If you install the tmux 3.1 release candidate, you can search for regular expressions.
Alternatively, you could use capture-pane to load the entire history into an editor with key bindings you prefer, for example:
$ tmux capturep -S- -E- -p|vim -
Or pipe to grep or whatever. Note you will need to use a temporary file for this to work with emacs.
Or try to get into the habit of teeing commands with lots of output to a file to start with.
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).
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'
CYGWIN_NT-6.3 x86_64
I open and use a terminal (mintty) and every so often an
8~
or simply
~
will appear on the commandline.
Why does this happen and how do I prevent this from happening.
Found the cause.
I run a utility to keep my windows machine from going to sleep. In the background it creates an event for key-up for F15.
This has been transparent until using cywin.
If the utility that is causing this input is Caffeine sending a F15 key up event, you can prevent it from happening in two ways:
Prevent F15 from being interpreted on the mintty side: Add the following line to your mintty config file (e.g. ~/.minttyrc). It tells mintty to ignore F15 by itself or with the Ctrl modifier, which does the trick for me (by itself, it produces ~, and with Ctrl, ;5~):
KeyFunctions=F15:void;C+F15:void
Prevent Caffeine from sending F15 by running it with the -useshift option.
I guess the first way is preferrable, because it keeps all the benefits of using the F15 key up event.
Bash uses readline, and readline can delete the word to the right of the cursor with "kill-word".
The problem is in recognizing the keypress of control-delete. When I press them in bash, "5~" is output on the screen. I could just bind for this, but it would mean that one day I need to type "5~", and it deletes a word to the right instead! So I'd much rather discover the correct control sequence.
I have googled, and quite a few resources discuss the "delete" key, but none that I've found discuss "control-delete" key. I've experimented with many variations, but nothing works.
The worst is the hours I've spent on this tedious, mindless grind, when it really should be a non-problem.
EDIT: It's through X, so maybe there's a solution with xev and xmodmap
On my machine, pressing Ctrl-V, Ctrl-Delete outputs this:
^[[3;5~
The ^[ escape character can be replaced with \e, so you can then use bind like this for bash (in your ~/.bashrc for example):
bind '"\e[3;5~":kill-word'
Or, you can add the following to your ~/.inputrc so Ctrl-Delete does kill-word in any program that uses readline:
"\e[3;5~": kill-word
This will bind only the Ctrl-Delete key, you don't have to worry about what will happen if you need to type 5~.
What you see is not the whole truth. It's probably <ESC>5~ or something like that. Try Ctrl-V Ctrl-Delete. The Ctrl-V means "do not interpret the next thing".
So binding <ESC>5~ that should be pretty safe.
Alt+D deletes one word to the right of the cursor
Ctrl+W deletes one word to the left of the cursor
(both are based on Emacs, I believe)
If you type ^Q^V (that's Control-Q followed by Control-V, releasing the Control key between them is fine), and then press Control-Delete, do you get the output you mentioned? I just tried it, and at least using Putty I don't get a response at all. Perhaps the behvior is different on an actual Linux console, though.
For other keys, readline prints a longer sequence, often including a special "command sequence introduction" character, which is hard to type by mistake. Try it, and see if you get a longer sequence with the ^Q^V command (which is, btw, called quoted-insert).
For example, if I press ^Q^V and then Delete (without control held down), readline prints ^[[3~. This tells me I can bind stuff to the Delete key by saying \e[[3~. It seems highely likely that the CSI character is present for you, but you're not seeing it since you're not asking readline to quote the input properly.
Ctrl-W deletes words.
Ctrl-u deletes lines.
They're based on Emacs (M-w and M-u).