Closed dylankb closed 4 years ago
Thank you very much for the report! 3031007 is a version 22 days ago. Could you try the latest version (by ble-update
) to see if it works? Actually this was reported by another user in #38. After that issue, I have changed the detailed behavior of ble.sh
so that fzf
works.
The shortcut for fuzzy tab completion does not work as expected.
For the command cd
, actually ble.sh
uses its own completer. You can turn off this ble.sh completer by the following setting so that the user setting (i.e., fzf
completer) is used:
blehook/eval-after-load complete 'unset -f ble/cmdinfo/complete:cd'
For the other commands, ble.sh
uses the user-provided settings so fzf
should be effective. However, fzf
completer does not work as expected. There are several design problems.
**
to the first filename before fzf
is calledble.sh
implements its own completion system that enhances the original completion mechanism of Bash, i.e. it modifies the behavior of completion. Before calling a user-provided completer, ble.sh
tries to translate the content of the command line to a plainer form so that a naive user-provided completer can work for complicated cases. For the simplest example, when you have a command line like echo A; echo B "${C%/}/★
where ★ represents the cursor position and the value of the variable C
is X
, ble.sh
constructs a virtual command line echo B X/
and passes it to the user-provided completer. In this way, even if the user-provided completer does not recognize incomplete quoting and the parameter expansions, it can generate appropriate completions.
ble.sh also tries to expand pathname patterns containing *
, ?
, etc. before passing it to the user-provided completer. Specifically it replaces pathname patterns with the first filepath generated by the pathname expansions. If you have **
in your command line, the command line that fzf
receives is something like cd somefile
where somefile
is the first file in the current directory. As a result, fzf
will never see the trigger string **
, and therefore fzf
selection will never be triggered.
fzf
Another problem is that ble.sh uses the same completion setting for auto-complete. If you setup up fzf
for completion, it will be used by auto-complete as well as by TAB completions. The result is that when you are typing a command line like cd some**
, fzf
will pop up even without pressing TAB. But maybe this is not a problem if you want to invoke fzf
instantly after typing **
(without TAB).
Also there are other design problems, but they are easy to work around.
I need to consider how to design the combination of these two different enhancement by ble.sh and by fzf. Of course I can still write a code to detect fzf
and behaves differently when fzf
is used, but I do not want to adopt such an ad hoc way.
**
(2)There were too many mismatches between fzf and ble.sh, so it is hard to combine them by modifying only ble.sh. The behavior of fzf
functions should also be modified. I finally decided to dynamically patch fzf
functions. I created a couple of utilities for dynamical patching of shell functions fbe531a, and also added a few options to the ble.sh completion system 58e1be4.
Could you please (1) update ble.sh by ble-update
and then (2) write the following settings instead of "[ -f ~/.fzf.bash ] && source ~/.fzf.bash
"?
# bashrc
if [ -f ~/.fzf.bash ]; then
source ~/.fzf.bash
# clear blesh completer for cd
blehook/eval-after-load complete 'unset -f ble/cmdinfo/complete:cd'
# patch fzf functions
ble/function#advice around __fzf_generic_path_completion _fzf_complete.advice
ble/function#advice around _fzf_complete _fzf_complete.advice
ble/function#advice around _fzf_complete_kill _fzf_complete.advice
function _fzf_complete.advice {
[[ :$comp_type: == *:auto:* ]] && { compopt -o default; return; }
compopt -o noquote
COMP_WORDS=("${comp_words[@]}") COMP_CWORD=$comp_cword
COMP_LINE=$comp_line COMP_POINT=$comp_point
ble/function#push printf '[[ $1 == "\e[5n" ]] || builtin printf "$@"'
ble/function#advice/do < /dev/tty &> /dev/tty
ble/function#pop printf
ble/textarea#invalidate
}
fi
Oh, great! This seems to work very well, even the fzf completer ** for cd
works once the additional bashrc settings are added.
ble.sh also tries to expand pathname patterns containing *, ?, etc. before passing it to the user-provided completer. Specifically it replaces pathname patterns with the first filepath generated by the pathname expansions.
That's neat - I didn't realize that about ble.sh before. If ble.sh was able to provide the possible expand pathname patterns containing * to the autcomplete menu it would probably reduce a fair amount of what I use fzf for in terms of file navigation.
Anyways, thanks for the very quick response!
One thing I did notice when I ran ble-upgrade
was I got this message.
sed: RE error: illegal byte sequence.
It seems I get this message now anytime I try to use the ble-bind
function. For example, just copying this example from the readme into ~/.blerc
causes this error to appear.
ble-bind -c 'M-c' 'my-command'
I have no existing ble-bind
functions in my .blerc file, but I was considering adding some fzf key bindings for easier git navigation.
https://junegunn.kr/2016/07/fzf-git/
https://gist.github.com/junegunn/8b572b8d4b5eddd8b85e5f4d40f17236
sed: RE error: illegal byte sequence.
Thank you. I hope this commit 0cc9160 fixes the problem.
Great, that did solve the issue.
Final question. I have a bash version of a key binding that I want to convert to ble-bind
but I'm having a bit of trouble. The bash version is bind '"\C-g\C-f": "$(gf)\e\C-e\er"
which allows for appending a branch selection to the current line (equivalent of git checkout $(gf)
without having to write the $(gf)
bit - see Gist above). My ble-bind version is below. I referenced this line to check for the ble version of shell-expand-line
ble-bind -c 'C-g C-b' '$(gb) M-C-e'
If I run gb
in the terminal I can succesfully print the branch selection to standard output. However if I try and use the ble-bind
as above I get:
-bash: $BRANCH No such file or directory
It's as if there was a return entered based on what was in standard out. Is this something I'm doing wrong?
Great, that did solve the issue.
OK! Thank you for checking!
Final question.
The ble.sh native way is to define a widget and register it through ble-bind -f
:
function ble/widget/fzf-git {
ble/widget/insert-string "$($1)"
ble/textarea#invalidate
}
ble-bind -f 'C-g C-f' 'fzf-git gf'
ble-bind -f 'C-g C-b' 'fzf-git gb'
ble-bind -f 'C-g C-t' 'fzf-git gt'
ble-bind -f 'C-g C-h' 'fzf-git gh'
ble-bind -f 'C-g C-r' 'fzf-git gr'
Here ble/widget/insert-string "$($1)"
inserts the result of the command substitution "$($1)"
where $1
contains an argument specified in ble-bind
such as gf
, gb
, etc. The line ble/textarea#invalidate
notifies ble.sh that the textarea contents has been lost (overwritten by fzf) to induce the later redraw.
But if you don't know how to define it, actually you can still use the readline style settings (though it is not as flexible as the native style settings). ble.sh internally tries to translate the readline style settings for ble-bind
:
# Actually you could just copy and paste
# (Note: \eX is equilvalent to \M-X)
bind '"\er": redraw-current-line'
bind '"\C-g\C-f": "$(gf)\e\C-e\er"'
bind '"\C-g\C-b": "$(gb)\e\C-e\er"'
bind '"\C-g\C-t": "$(gt)\e\C-e\er"'
bind '"\C-g\C-h": "$(gh)\e\C-e\er"'
bind '"\C-g\C-r": "$(gr)\e\C-e\er"'
# Or you can use existing binding C-M-l for redraw-line:
bind '"\C-g\C-f": "$(gf)\M-\C-e\M-\C-l"'
bind '"\C-g\C-b": "$(gb)\M-\C-e\M-\C-l"'
bind '"\C-g\C-t": "$(gt)\M-\C-e\M-\C-l"'
bind '"\C-g\C-h": "$(gh)\M-\C-e\M-\C-l"'
bind '"\C-g\C-r": "$(gr)\M-\C-e\M-\C-l"'
ble-bind -c 'C-g C-b' '$(gb) M-C-e'
A shell command can be specified for the option for -c
; i.e., $(gb) M-C-e
above will be treated as a single command. That is the reason it doesn't work. Instead you can use the option -s
to specify a (readline-style) keyseq. The working version of the above setting is as follows:
ble-bind -s 'C-g C-b' '$(gb)\M-\C-e'
Nice, a really fascinating explanation. The only thing I did differently was include the \C-M-l
portion to redraw the line like you mentioned: ble-bind -s 'C-g C-b' '$(gb)\M-\C-e\M-\C-l'
The only problem with the above is that C-g
looks like it's bound toauto_complete/cancel
and C-b
to @nomarked backward-char
. The result is cancelled auto-suggestions and white space removals before the cursor must happen before function can trigger, but I can probably work around that by thinking of a different key mappings to use.
One side note is that ble-bind -L
returns an error for me.
$ ble-bind -L
/usr/bin/sed: illegal option -- r
usage: sed script [-Ealn] [-i extension] [file ...]
sed [-Ealn] [-i extension] [-e script] ... [-f script_file] ... [file ...]
but I can probably work around that by thinking of a different key mappings to use.
Maybe you can also think about using sabbrev
. The sabbrev expansions can be invoked by hitting SP just after the registered words. For example, with the following settings, SP after echo gb
expands gb
to the word selected in fzf
.
function fzf-git.sabbrev {
COMPREPLY=$($1)
ble/textarea#invalidate
}
ble-sabbrev -m gf='fzf-git.sabbrev gf'
ble-sabbrev -m gb='fzf-git.sabbrev gb'
ble-sabbrev -m gt='fzf-git.sabbrev gt'
ble-sabbrev -m gh='fzf-git.sabbrev gh'
ble-sabbrev -m gr='fzf-git.sabbrev gr'
Another possibility would be to use lib/vim-arpeggio.sh
(it is named vim-*
but actually can be used in Emacs editing mode as well). You can bind simultaneous pressing of two letters. (Be careful that if you bind two letters to a keyboard macro that contains that two letters using the option -s
, it will cause infinite loop.)
function ble/widget/fzf-git {
ble/widget/insert-string "$($1)"
ble/textarea#invalidate
}
ble-import 'lib/vim-arpeggio.sh'
ble/lib/vim-arpeggio.sh/bind -f 'gf' 'fzf-git gf'
ble/lib/vim-arpeggio.sh/bind -f 'gb' 'fzf-git gb'
ble/lib/vim-arpeggio.sh/bind -f 'gt' 'fzf-git gt'
ble/lib/vim-arpeggio.sh/bind -f 'gh' 'fzf-git gh'
ble/lib/vim-arpeggio.sh/bind -f 'gr' 'fzf-git gr'
One side note is that ble-bind -L returns an error for me.
Thank you! This is another bug related to sed
compatibility in different systems. Fixed 2184739
Cool, looks like that fixed the issue.
Those were interesting options I didn't know about - thanks!
ble version:
0.4.0-devel2+3031007
Bash version:
5.0.11(1)-release
I've noticed two issues if I have both
fzf
and bleh.sh sourced. I.e[ -f ~/.fzf.bash ] && source ~/.fzf.bash
is run manually or in your bashrc.1) fzf history search does not work well.
C-r
to see and select previous commandReturn
and the line number will be returned rather than the command. For example, if you select command 515, then'!515'
will be written to standard out.2) The shortcut for fuzzy tab completion does not work as expected.
cd **
returnsDo you think it's possible to resolve these types of issues? Thanks in advance!