Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Is it possible to trigger fzf completion with a key on blesh ? #20

Closed
3ximus opened this issue Aug 17, 2024 · 6 comments
Closed

Is it possible to trigger fzf completion with a key on blesh ? #20

3ximus opened this issue Aug 17, 2024 · 6 comments

Comments

@3ximus
Copy link

3ximus commented Aug 17, 2024

Hello there!
I currently have fzf completion and bindings working perfectly with blesh, but I was wondering if I could do sort of an hybrid of both, basically instead of using the ** to trigger fzf completion would it be possible to use a custom binding to trigger this kind of completion ?

I've seen this issue junegunn/fzf#1804 where he says to create a custom function for each command which I could do, but I'm wondering if there's a way to just use the existing completion.bash from them.

Thanks in advance

@akinomyoga
Copy link
Owner

akinomyoga commented Aug 18, 2024

to trigger this kind of completion ?

I'm not sure if I understand the request correctly, but doesn't the approach of the example provided in junegunn/fzf#1804 (comment) work?

The completion by ** is implemented as merely parts of shell functions here and here, but there is basically no way to execute only a part of the specified shell function. Then, one needs to anyway extract the relevant part to a new shell function and call it from the keybinding. That seems essentially equivalent to the solution provided in junegunn/fzf#1804 (comment).

I'm not sure if the fzf completion really needs to be called through the programmable completion, but if one needs to force it without implementing a new function or modifying completiion.bash, one may do it in a brute force way by replacing all the completion settings temporarily:

function ble/widget/fzf-complete {
  local completion_save FZF_COMPLETION_TRIGGER=
  ble/util/assign completion_save 'complete -p' # save the current completion settings
  complete -r
  complete -F _fzf_path_completion -D # e.g. if you want to trigger the ** completion for the path completions
  ble/widget/complete; local ext=$?
  complete -r
  builtin eval -- "$completion_save" # restore the original completion settings
  return "$ext"
}
ble-bind -f 'C-x C-i' fzf-complete

@3ximus
Copy link
Author

3ximus commented Aug 18, 2024

To be honest the only advantage I'm looking for is merely aesthetic since the solution proposed by junegunn hides current prompt and replaces it with the fzf program, however the ** completion places the fzf program underneath the line and still displays the current prompt so I would just prefer that solution.

Your snipped works perfectly. From my understanding it temporarily disables the default completion method and replaces it with the fzf one and then restores the previous completions methods. Is there any drawbacks to this approach ? It seems like it still fallsback to default completion for some commands unless they are the ones defined on completion.bash of fzf, but I dont't understand why since the completions should have been cleared...

Either way I guess this should allow me to write a wrapper to achieve what I need!
Thanks once again :)

@3ximus 3ximus closed this as completed Aug 18, 2024
@akinomyoga
Copy link
Owner

since the solution proposed by junegunn hides current prompt and replaces it with the fzf program,

Ah, OK. You are right. That is the behavior of Bash for bind -x bindings. Bash hides the last line of the prompt and the command line before calling the shell command registered to bind -x and restores it after the shell command is completed. For the compatibility with Bash, ble.sh also behaves in the same way. ble.sh behaved in a different way in the past, but there was a request to make the behavior of bind -x consistent with Bash.

Is there any drawbacks to this approach?

I worried about the case where the execution of the widget is canceled in the middle and the completion settings are left in the temporary state, but I think it won't happen practically because as far as I remember, I haven't experienced any cancellation of the widget execution in the middle for about nine years since I started to use ble.sh as a daily driver.

It seems like it still fallsback to default completion for some commands unless they are the ones defined on completion.bash of fzf, but I dont't understand why since the completions should have been cleared...

Ah, OK. I forgot that there is another path for ble.sh to find the completion settings. Even if no completion settings are set (in particular complete -p -D is not set), if a shell function _comp_load or _completion_loader exists, ble.sh tries to dynamically load a completion setting using the function. To eliminate also this path, one needs to mask the shell function _comp_load.

In addition, it would probably be better to mask also the completion settings that the fzf completion internally saves.

Here's an updated version:

function ble/widget/fzf-complete {
  # Mask completion settings cached by fzf
  local -a fzf_orig_completions
  fzf_orig_completions=("${!_fzf_orig_completion_@}")
  local "${fzf_orig_completions[@]/%/=}"

  # Replace the programmable-completion setting
  local completion_save
  ble/util/assign completion_save 'complete -p'
  complete -r
  complete -F _fzf_path_completion -D

  # Disable completion auto-loader
  ble/function#push _comp_load 'return 1'

  # Trigger fzf-completion without '**'
  local FZF_COMPLETION_TRIGGER=

  ble/widget/complete; local ext=$?

  # restore the settings
  ble/function#pop _comp_load
  complete -r
  builtin eval -- "$completion_save"
  return "$ext"
}

@akinomyoga
Copy link
Owner

akinomyoga commented Aug 22, 2024

In the latest push, I added the above ble/widget/fzf-complete (with some changes) in ble-import integration/fzf-completion, so after updating ble.sh by running ble-update, you can now just bind it using ble-bind -f KEYSPECS fzf-complete.

@3ximus
Copy link
Author

3ximus commented Aug 26, 2024

That's awesome! Much appreciated! I'll start using it this way
Thanks once again for your work, ble.sh is simply amazing!

@akinomyoga
Copy link
Owner

Thank you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants