Bind "up arrow" key to fzf command - keyboard-shortcuts

I want to use the fzf fuzzyfinder command history instead of the typical command history when I press the up arrow.
In my fzf shell keybindings file I'm able to edit which key brings up the fuzzy finder by editing the following snippet:
bindkey '{command such as ^R}' fzf-history-widget
How can I represent the up arrow key so that it calls this function when pressed? Do I have to disable other functionality somewhere else as well?

Binding <Up> key in zsh
Use
bindkey "${key[Up]}" fzf-history-widget
or
bindkey '^[[A' fzf-history-widget
or
bindkey "${terminfo[kcuu1]}" up-line-or-history
to bind <Up> key in zsh to fzf-history-widget function.
Binding <Up> key in bash
You can set the <Up> arrow key to show the commands from history beginning with the characters before the cursor on the command line
bind '"\e[A": history-search-backward'
fzf bindings for bash
There is an issue #1492:
[bash] Fire command directly with CTRL-X in CTRL-R
Accordingly, history-exec.bash plugin created for the purpose of history expansion using fzf
macOS Specific Binding
bindkey "${terminfo[kcuu1]}" fzf-history-widget

In bash version 4 or more, none of these works for me:
bind -m emacs-standard -x '"\C-p": __fzf_history__'
bind -m vi-command -x '"\C-p": __fzf_history__'
bind -m vi-insert -x '"\C-p": __fzf_history__'
This also doesn't work:
bind '"\C-p": __fzf_history__'
But this one does the trick for me:
bind -x '"\C-p": __fzf_history__'
By the way, you can use bind -X to see the current binding.

Related

Copy to client clipboard after mouse selection with tmux in a remote session

This is my .tmux.conf
setw -g mouse on
set-option -s set-clipboard off
bind-key -T copy-mode MouseDragEnd1Pane send-keys -X copy-pipe-and-cancel "xclip -selection clipboard -i"
Works well on a linux machine locally. Mouse selection is copied to system clipboard automatically.
However, in a remote session (iTerm + Mac), it doesn't work. Text isn't copied to the client's system clipboard. Apparently I have to use OSC 52. Here is a helper script.
You can use the script like so:
echo "whatever text" | osc52.sh
Now "whatever text" is copied to the client's system clipboard.
However I can't get the script to work with tmux mouse selection:
setw -g mouse on
set-option -s set-clipboard off
osc52="~/osc52.sh"
bind-key -T copy-mode MouseDragEnd1Pane send-keys -X copy-pipe-and-cancel "$osc52"
Any help is appreciated. Thanks!
This is not the way to use OSC 52. You can't send it from a script - all output from commands run from copy-pipe is ignored.
Instead, you need to configure tmux itself to do it. Try the following:
1) Remove the bind-key command and just leave MouseDragEnd1Pane as the default which is copy-selection.
2) Change set-clipboard off to set-clipboard on. Remember to restart tmux entirely after changing .tmux.conf.
3) Make sure TERM outside tmux is xterm or xterm-256color so that tmux adds the Ms capability from the default terminal-overrides. This should be the default in iTerm2. Make sure you are not removing it from terminal-overrides in .tmux.conf.
4) In iTerm2, I think you need to turn on this option, "Applications in terminal may access clipboard":

Use env variable to represent SSH options

These two ssh options:
ssh -o StrictHostKeyChecking=no -o NumberOfPasswordPrompts=0
I am interested in setting those using env variables, is there a way to do that?
export StrictHostKeyChecking=no
export NumberOfPasswordPrompts=0
but that's of course not quite right
The "proper" way to do this is within your ~/.ssh/config file, where you can make those global for all connections or you can restrict it by host (or a few more advanced things). I'm going to assume you can't do that but that you do still have the ability to alter your ~/.bashrc or whatever.
You can solve this by putting this in your ~/.bashrc or ~/.zshrc (or by running these lines before ssh):
SSH_ARGS=( -o StrictHostKeyChecking=no -o NumberOfPasswordPrompts=0 )
alias ssh='ssh "${SSH_ARGS[#]}"'
If you want explicit environment variables like what you're proposing in your question (e.g. $StrictHostKeyChecking) then you'll have to make a really ugly alias or function to convert them all to the final ssh call. Here's a solution that should work in bash but won't work in POSIX shell:
ssh() {
local SSH_VAR SSH_VAR_VALUE
for SSH_VAR in StrictHostKeyChecking NumberOfPasswordPrompts; do # expand this
SSH_VAR_VALUE="${!SSH_VAR}" # bash indirect expansion
if [ -n "$SSH_VAR_VALUE" ]; then
set -- -o "$SSH_VAR=$SSH_VAR_VALUE" "$#"
fi
done
command ssh "$#"
}
The above example only supports the two SSH variables named in the question. That line will likely have to get really long as it must explicitly name every option before the semicolon on the line with the # expand this comment.
This loops over every supported SSH variable and uses bash's indirect expansion to check whether it is in the environment (and not an empty value). If it is, a -o and the option name and its value are prepended to the start of the argument list ($#).
If you use zsh, you'll need zsh's parameter expansion flag P, replacing bash's ${!SSH_VAR} with zsh's ${(P)SSH_VAR}. Other shells may need to replace that whole "bash indirect expansion" line with eval "SSH_VAR_VALUE=\"\${$SSH_VAR}\"" (watch your quoting there, or that line can be dangerous).
Invoking command ssh prevents the recursion we'd get from calling ssh from within a function of the same name. command ssh ignores the function and actually runs the true ssh command.

Disable tmux resizing using shift (only) + hjkl

I added tmux binding for resizing pane like this
bind h select-pane -L
bind j select-pane -D
bind k select-pane -U
bind l select-pane -R
but ended up can't type HJKL (uppercase), since it's already resizing the panel. what I want to expect is using ctrl-a (prefix) then HJKL.
You can use tmux list-keys to verify if those keys are actually sit in prefix key table. You may need to explicitly reset the prefix key via set -g prefix C-a.

How can I bind a key to "exit copy-mode" in tmux?

I was trying to find a command for "leaving copy-mode" from this page, but it seems only the key binding prefix+q exists for this function; i.e., I can't find the associated :command-style command.
Does this mean it is impossible to bind another key to "leave copy-mode"? I'd like to bind the Esc key.
Copy mode uses its own set of commands, separate from tmux itself. Use send-keys -X to "type" commands in copy mode, as demonstrated by the default binding for exiting copy mode:
bind-key -T copy-mode q send-keys -X cancel
Note that Escape is already bound to the same command, at least in tmux 2.7.
% tmux list-keys | grep "send-keys -X cancel"
bind-key -T copy-mode C-c send-keys -X cancel
bind-key -T copy-mode Escape send-keys -X cancel
bind-key -T copy-mode q send-keys -X cancel
bind-key -T copy-mode-vi C-c send-keys -X cancel
bind-key -T copy-mode-vi q send-keys -X cancel
The page you were referring to is not a comprehensive list of tmux commands, but rather a comparison of how to accomplish some common tasks in different terminal multiplexers.

In zsh how do I bind a keyboard shortcut to run the last command?

I frequently find myself wanting to repeat a command, and while !! is useful, I'd like to bind that to ctrl-w or something like that. Is there a way to do that?
EDIT: I'm aware that the up arrow does what I want, however I would rather not have to leave the home row. Being an avid Vim user has taught me the value of staying on the home keys.
I looked at this post about adding a shortcut to access the info command and tried to extrapolate something out of it, but had no success. Zsh yelled at me about zle not being active or something.
I know this will rely on knowledge of how my shell is configured, so below I've pasted some relevant code, as well as a link to my entire .zshrc and dotfiles in general.
# oh-my-zsh plugins. zsh-aliases and drush are custom plugins.
plugins=( git z tmux web-search colored-man zsh-aliases drush)
ZSH_TMUX_AUTOSTART=true
#... $PATH, start background process (clipboard integration for tmux,
# glances system monitor), history options, editor, all truncated for brevity.
# use vim mode
bindkey -v
#show insert/normal mode in prompt
function zle-line-init zle-keymap-select {
RPS1="${${KEYMAP/vicmd/NORMAL}/(main|viins)/INSERT}"
RPS2=$RPS1
zle reset-prompt
}
zle -N zle-line-init
zle -N zle-keymap-select
# rebind ctrl-r
bindkey -M vicmd '^R' history-incremental-search-backward
bindkey -M viins '^R' history-incremental-search-backward
Full configs: https://github.com/yramagicman/dotfiles
Just the .zshrc: https://github.com/yramagicman/dotfiles/blob/master/.zshrc
custom plugins:
https://github.com/yramagicman/drush-zsh-plugin
https://github.com/yramagicman/zsh-aliases
To get the last command from the history you can use the up-history widget. This is by default bound to Ctrl+P in vicmd mode, so pressing Esc followed by Ctrl+P and then Enter (which invokes the widget accept-line) would do the trick.
If you want to bind it to a single shortcut, you have to write your own widget. You can add this to your ~/.zshrc:
# define function that retrieves and runs last command
function run-again {
# get previous history item
zle up-history
# confirm command
zle accept-line
}
# define run-again widget from function of the same name
zle -N run-again
# bind widget to Ctrl+X in viins mode
bindkey -M viins '^X' run-again
# bind widget to Ctrl+X in vicmd mode
bindkey -M vicmd '^X' run-again
For the example I chose Ctrl+X as shortcut because by default it is unbound in vicmd mode and self-inserts in in viins mode, whereas Ctrl+W is already bound to vi-backward-kill-word in viins. Of course you could overwrite the default binding if you do not use it anyway or bind the widget only in mode.
EDIT: Alternative that doesn't break Esc/ search:
accept-line() { [ -z "$BUFFER" ] && zle up-history; zle ".$WIDGET"; }
zle -N zle-line-init
Redefine default Enter command so it inserts last command if the buffer is empty. Inspired by this answer.
ORIGINAL:
I have this in my .zshrc:
last_if_empty() {
[ -z "$BUFFER" ] && zle up-history
zle accept-line
}
zle -N last_if_empty
bindkey -M viins '^M' last_if_empty
It remaps Enter to Run last command if nothing has been typed on the screen.
Unfortunately it seems to break Esc/ search (Enter key doesn't work). I use Ctrl+R so it doesn't bother me, but might be a dealbreaker.