How to create a key binding that inserts text in the Fish shell - fish

I would like to save typing in the Fish shell by binding a key to a text. When I press the key, the text should be inserted into the shell. The effect should be the same as typing that text.
One of the problems is that the text should not be executed, just inserted. The closest I came is this experiment where the text "whoami" is inserted when I press Alt+G:
bind \eg "echo -n whoami"
However, when I press enter the command is not executed, so the effect is not the same as typing the text directly in the shell.

You want to modify the commandline, which incidentally is possible with the commandline builtin.
bind \eg "commandline -i whoami"

Related

Function bound to a key in Fish shell requires me to press enter, how to avoid that?

I have the following fish shell function
# gohome.fish
function gohome
cd ~
end
When I bind it with bind \eg gohome and press Alt+G I still have to press enter to invoke it. Is it possible to execute gohome immediately upon pressing Alt+G?
When I bind it with bind \eg gohome and press Alt+G I still have to press enter to invoke it.
You don't. The function is executed as soon as you press the key.
What happens is that your prompt isn't repainted to update the current directory, and pressing enter triggers that.
Do commandline -f repaint either in
bind \eg 'gohome; commandline -f repaint'
or in the function.

Tab-complete herbstclient with fish shell?

I'd like to be able to simply type herb and then press tab and have fish-shell tab-complete it to herbstclient. I've tried looking it up, but every result I can find has to do with overiding fish's autocomplete with tab rather than ctrl + f.
Do I need to create a fish script for this? If so, what should it look like and where should I put it?
Assuming that is a command you want an abbreviation: abbr herb herbstclient. Although you don't use [tab] to complete an abbreviation; you have to press [space] or [enter]. Note that the expansion can consist of multiple tokens. For example, this is one of my most often used abbreviations: abbr -a -g -- gcm 'git checkout master'. Also, abbreviations only get expanded in the command position; i.e., start of line or after a pipe, |, or semicolon. If you want that expansion elsewhere in a command line there are ways to achieve that but it's a bit more complicated.

How to insert new lines when editing some script with fish's built-in editor?

When inputing multiline script in fish shell, e.g. I have input these script
$ for file in *.txt
echo $file
end
and my caret is after the word end. Now I want to insert a line before it, make it like:
$ for file in *.txt
echo $file
echo "hello" // I want to insert this line
end
But I found if I move my caret up and after echo $file, and press enter(or cmd/option/ctrl+enter), it just run the entire script without inserting a new line. I have to copy them to another editor and copy back after editing.
Is there any way to do it?
Update:
I just uploaded a screen recording https://asciinema.org/a/i7pOWhpdXUu0RLVOAMjVJTXbn. In the recording, I moved my caret up to after echo and pressed option + enter, but it executed the script instead of inserting a new line
fish binds escape + newline to unconditionally insert a newline. On a Mac, you would typically press option + return. However Mac terminal emulators do not send an escape-newline by default. With iTerm2 you can request that option acts as escape, under Preferences->Profiles->Keys:
Now the binding will be active and option-return will unconditionally insert a newline.
(You could instead add a key mapping for just this case if you prefer.)
You can confirm what the terminal receives from the emulator with fish_key_reader which is installed alongside fish.
In the default bindings, Alt-Enter will always insert a new line:
> bind|fgrep \\n
bind \e\n commandline\ -i\ \\n
bind \e\r commandline\ -i\ \\n
...
Depending on your system configuration, the Enter/Return key may send either a newline character (\n) or a carriage-return character (\r), so that's why there's two entries.

set commandline shortcut in tcsh for moving cursor by word

from How to move the cursor by word in command line of tcsh I know how to move cursor by word in tcsh, but they not easy to use, so can I set a shortcut on command line for example, when I use Ctrl+leftarrow, it actually works as Esc f?
To see a list of pre-defined key-bindings, visit:
http://www.csc.fi/english/pages/data-services/linux_basics/tcsh
To see a list of all commands which can be used to configure key-bindings, visit:
http://www.rohidekar.com/sridharsarnobat/mediawiki/index.php?title=TCSH_Key_bindings
Example: (Write this in your ~/.tcshrc)
bindkey '^[^[[C' forward-word
bindkey '^[^[[D' backward-word
This will bind the alt-right with forward-word and alt-left with backword-word.
To map to a different keyset, just run cat and hit enter. Hit the key-combination (in the above example, right-arrow and left-arrow), record the strings that are echoed back, and use these as the key combinations to bind.

Matlab-like command history retrieval in unix command line

In Matlab, there is a very nice feature that I like. Suppose I typed the command very-long-command and then a few several commands afterwards. Then later if I need the long command again, I just type very and press the up arrow key, my long command appears. It finds the last command that starts with very. I couldn't do the same in unix command line, when I try to do it, it disregards whatever I typed, and goes back to the last commands in chronological order. Is there a way to do it?
In bash this functionality is provided by the commands history-search-forward and history-search-backward, which by default are not bound to any keys (see here). If you run
bind '"\e[A":history-search-backward'
bind '"\e[B":history-search-forward'
it will make up-arrow and down-arrow search backward and forward through the history for the string of characters between the start of the current line and the point. See also this related Stack Overflow question.
In bash, hitting ctrl-r will let you do a history search:
$ echo 'something very long'
something very long
$ # blah
$ # many commands later...
(reverse-i-search)`ec': echo 'something very long'
In the above snippet, I hit ctrl-r on the next line after # many commands later..., and then typed ec which brought me back to the echo command. At that point hitting Enter will execute the command.
You can do the same thing by using "!". For example:
$ echo "Hello"
Hello
$ !echo
echo "Hello"
Hello
However, it is generally a bad idea to do this sort of thing (what if the last command did something destructive?). If you expect you will reuse something, then I suggest you create a shell script and save it away somewhere (whenever I plan to reuse something, I create a script in ~/.local/bin).