bling / fzf.el

A front-end for fzf
GNU General Public License v3.0
360 stars 50 forks source link

fzf-with-entries no longer selects entries with slashes #91

Closed vnckppl closed 1 year ago

vnckppl commented 1 year ago

When I run fzf-with-entries since commit https://github.com/bling/fzf.el/commit/29c715bd611e0f050604940377d73cbeb2f093d3 it no longer copies the items that contain slashes:

This works:

(progn
  (setq mylist '("abc" "def" "ghi"))
  (fzf-with-entries mylist
                    (lambda (x) (setq selected-entry x)))
  (message selected-entry)
  )

This does not:

(progn
  (setq mylist '("/abc" "/def" "/ghi"))
  (fzf-with-entries mylist
                    (lambda (x) (setq selected-entry x)))
  (message selected-entry)
  )
pierre-rouleau commented 1 year ago

@vnckppl neither work for me. Is mylist declared as a defvar before your execute the form?

Is the message output displayed before FZF exits or after when it works for you?

I must admit I don't understand the purpose of that function. How do normally it?

vnckppl commented 1 year ago

@pierre-rouleau Thanks for looking into this.

I have not declared mylist up front. I ran both snippets in a clean instance of emacs (emacs -Q) and then just opened fzf.el and did M-x eval-buffer.

After that, when I run the first snippet, the *Messages* bufffer shows:

FZF returned text: [

  ghi                                                                                                       
  def                                                                                                       
> abc                                                                                                       
  3/3                                                                                                       
>                                                                                                           
abc

Process fzf finished
]
FZF exited with code 0

When I run the second snippet (with the slashes in the list items), the *Messages* buffer only shows:

FZF exited with code 0
pierre-rouleau commented 1 year ago

@vnckppl Thanks. It's probably because I forgot to let-bind the fzf--target-validator to the fzf--pass-through function inside fzf-with-entries. Try this:

(defun fzf-with-entries (entries action &optional directory)
  "Run `fzf` with the list ENTRIES as input.                                                                                                                                                                              

ACTION is a function that takes a single argument, which is the                                                                                                                                                           
selected result from `fzf`.                                                                                                                                                                                               
If DIRECTORY is specified, fzf is run from that directory."
  (let ((fzf--target-validator  (function fzf--pass-through)))
    (if entries
        (fzf-with-command
         (concat "echo \""
                 (mapconcat (lambda (x) x) entries "\n") "\"")
         action directory)
      (user-error "No input entries specified"))))

... I mean try that with the latest code....

pierre-rouleau commented 1 year ago

However I still don't get how your snippet is supposed to work. All work needs to be done inside the action function, not after fzf-with-entries, no? Look at fzf-switch-buffer which uses fzf-with-entries.

vnckppl commented 1 year ago

Yes, you are right. Also, it may not be related to slashes (sorry for the confusion). If you download and evaluate the fzf.el from the commit /prior/ to the one I referenced, the following snippet will print your selection to the *Messages* buffer:

(progn
  (defvar selected-entry "")
  (defvar mylist "")
  (setq mylist '("abc" "def" "ghi"))
  (fzf-with-entries mylist
                    (lambda (x) (progn
                                  (setq selected-entry x)
                                  (print selected-entry)))))

When I use the fzf.el from the commit that I reference in the inital post, any more recent one, or if I use the fzf-with-entries code that you posted above, nothing is printed in the *Messages* buffer. Do you get this as well?

pierre-rouleau commented 1 year ago

OK, I think I know what's going on. The file validator gets used as the variable is bound by default. I'll submit an update.

As far as your snippet is concerned the simplest way would be do do this:

(progn
  (fzf-with-entries '("/abc" "/def" "/ghi")
                    (lambda (x)
                      (message "And the selection is.... %S" x))))

If I use the above and make sure that pass through validator is used, then the value selected is shown, just as the fzf-switch-buffer works, since it sets the validator to the pass through one.

What I'll do is to add an optional argument to fzf-with-entries to allow overriding the pass-though validator with something else if this is needed.

pierre-rouleau commented 1 year ago

OK, I have a solution I will push soon. I have only changed the code of fzf-with-entries where I added an extra optional validator argument:


(defun fzf-with-entries (entries action &optional directory validator)
  "Run `fzf` with the list ENTRIES as input.                                                                                                                                                                                                                                                                                                 

ACTION is a function that takes a single argument, which is the                                                                                                                                                                                                                                                                              
selected result from `fzf`.                                                                                                                                                                                                                                                                                                                  
If DIRECTORY is specified, fzf is run from that directory.                                                                                                                                                                                                                                                                                   
If VALIDATOR is specified it must be a function with the same signature as                                                                                                                                                                                                                                                                   
`fzf--validate-filename' and it will be used as a item validator. If VALIDATOR                                                                                                                                                                                                                                                               
is nil, the default, then the `fzf--pass-through' validator is used (doing                                                                                                                                                                                                                                                                   
no validation."
  (let ((fzf--target-validator (or validator
                                   (function fzf--pass-through))))
    (if entries
        (fzf-with-command
         (concat "echo \""
                 (mapconcat (lambda (x) x) entries "\n") "\"")
         action directory)
      (user-error "No input entries specified"))))

And then the following code works with any selection:

(progn
  (fzf-with-entries '("/abc"
                      "/def"
                      "/ghi"
                      "."
                      "123"
                      "another"
                      " yet another"
                      " - "
                      " αβχδ")
                    (lambda (x)
                      (message "And the selection is.... %S" x))))

It's a good thing you caught this one!! Thanks!

pierre-rouleau commented 1 year ago

@vnckppl Let me know if the above works for you.

pierre-rouleau commented 1 year ago

@vnckppl The latest pull request (or my fork) has the code that should fix the issue. Let me know if this is all OK.

Thanks!

vnckppl commented 1 year ago

@pierre-rouleau Thanks Pierre, I replaced the fzf.el file in my elpa/fzf folder with yours and it indeed fixed the problem. I hope your pull request is implemented soon.

pierre-rouleau commented 1 year ago

@vnckppl The PR was merged in. If all is OK, could you close this issue?