I repeatedly had the problem of fzf erroring with:
(wrong-type-argument stringp nil)
and not working again until I restarted Emacs. Turning on tracebacks
with M-x toggle-debug-on-error showed that the error, confusingly, was
in a call that did not even have a nil argument:
The start-process C code, however, uses another value in addition to
its explicit arguments: the current buffer’s default-directory. I
added some debug statements and verified that once the current directory
of the *fzf* buffer first becomes nil, fzf never recovers. In other
words, the sequence of calls:
(fzf/start "~/project") ;; works fine
(fzf/start nil) ;; dies with wrong-type-argument, as expected
(fzf/start "~/project") ;; also dies with wrong-type-argument!
does not only raise wrong-type-argument in the second call as one
would expect, but in the third and all subsequent calls, because the
*fzf* buffer somehow remembers the nil working directory for the
rest of its lifetime.
The solution is to replace the fzf/start local variable:
(let ((default-directory directory))
with the more emphatic action of reaching inside of the *fzf* buffer
itself and setting its default-directory variable:
With this improvement, fzf recovers perfectly from a nil argument on
its very next call if a directory is provided instead.
How did I wind up ever calling fzf with a nil argument to begin with?
The answer is that I have a key bound to a function:
(defun fzf-repository ()
"Run the fzf file selection tool in the current repository."
(interactive)
(fzf-directory (vc-git-root default-directory)))
that usually passes fzf a directory, but when I accidentally invoke it
outside a repository, passes nil instead. I am going to fix my macro
so that it detects nil and prints a reasonable error message instead
of passing nil on to fzf. But, as a second layer of defense, I would
love to see this pull request land too, to protect fzf from all other
situations where users might send it nil by accident.
Note that most of this pull request simply un-indents everything
inside the (let).
I repeatedly had the problem of fzf erroring with:
and not working again until I restarted Emacs. Turning on tracebacks with
M-x toggle-debug-on-error
showed that the error, confusingly, was in a call that did not even have anil
argument:The
start-process
C code, however, uses another value in addition to its explicit arguments: the current buffer’sdefault-directory
. I added some debug statements and verified that once the current directory of the*fzf*
buffer first becomesnil
, fzf never recovers. In other words, the sequence of calls:does not only raise
wrong-type-argument
in the second call as one would expect, but in the third and all subsequent calls, because the*fzf*
buffer somehow remembers thenil
working directory for the rest of its lifetime.The solution is to replace the
fzf/start
local variable:with the more emphatic action of reaching inside of the
*fzf*
buffer itself and setting itsdefault-directory
variable:With this improvement, fzf recovers perfectly from a
nil
argument on its very next call if a directory is provided instead.How did I wind up ever calling fzf with a
nil
argument to begin with? The answer is that I have a key bound to a function:that usually passes fzf a directory, but when I accidentally invoke it outside a repository, passes
nil
instead. I am going to fix my macro so that it detectsnil
and prints a reasonable error message instead of passingnil
on to fzf. But, as a second layer of defense, I would love to see this pull request land too, to protectfzf
from all other situations where users might send itnil
by accident.Note that most of this pull request simply un-indents everything inside the
(let)
.