Dir-local variables and Helm sources

40 views
Skip to first unread message

Tianxiang Xiong

unread,
Mar 19, 2018, 2:55:03 AM3/19/18
to emacs-helm
It seems that closures, Helm sources, and dir-local variables are a problematic combination.

In a project directory w/ a `.dir-locals.el` containing:

((nil (foo . "foo")))


And a test file `test.el`, if I call:

(helm :sources (helm-build-sync-source "test"
                 
:candidates (list foo)))


in `test.el` I get a Helm buffer w/ candidate "foo".

If I call

(helm :sources (helm-build-sync-source "test"
                 
:candidates (lambda () (list foo))))


I get an error:

Debugger entered--Lisp error: (void-variable foo)
  (list foo)

What's the right way to solve this? Currently, the sources are held in `defvar`s, but we need the candidate list to be dynamically computed, thus the closure.

Thierry Volpiatto

unread,
Mar 19, 2018, 4:24:39 AM3/19/18
to emacs...@googlegroups.com

Tianxiang Xiong <tianxia...@gmail.com> writes:

> It seems that closures, Helm sources, and dir-local variables are a problematic combination.
>
> In a project directory w/ a `.dir-locals.el` containing:
>
> ((nil (foo . "foo")))
>
> And a test file `test.el`, if I call:
>
> (helm :sources (helm-build-sync-source "test"
> :candidates (list foo)))
>
> in `test.el` I get a Helm buffer w/ candidate "foo".
>
> If I call
>
> (helm :sources (helm-build-sync-source "test"
> :candidates (lambda () (list foo))))
>
> I get an error:
>
> Debugger entered--Lisp error: (void-variable foo)
> (list foo)
>
> What's the right way to solve this?

Probably using a quoted lambda works:

`(lambda () (list ,foo))

--
Thierry

Thierry Volpiatto

unread,
Mar 19, 2018, 10:32:16 AM3/19/18
to emacs...@googlegroups.com
Or specifying from where the variable is local:

(helm :sources (helm-build-sync-source "test"
:candidates (lambda () (list (with-helm-current-buffer foo)))))

--
Thierry

Message has been deleted

Thierry Volpiatto

unread,
Mar 20, 2018, 7:45:35 AM3/20/18
to emacs...@googlegroups.com

'Tianxiang Xiong' via emacs-helm <emacs...@googlegroups.com> writes:

> The syntax-quote solution doesn't work b/c sometimes the variables are not used directly, but by functions calling functions. The second seems to work,
> thanks.
>
> Just so I understand fully, can you explain in some detail what's
> going on here? I thinkthe problem is that the Helm source is built
> using a buffer which, unless explicitly specified w/
> `with-helm-current-buffer`, is not in the project, and therefore
> doesn't get the dir-local variable values? Is there a reason that the
> current buffer is not used by default?

Well helm is computing candidates from its buffer (helm-buffer) so if
the function in charge of computing candidates use a local variable
from another buffer, you have to specify the computation happens in this
buffer by making this buffer current (use with-current-buffer).

If you build the source in your local buffer, you can use a quoted
lambda to hard code the value of local variable in your function.

It is why I provided the two options in previous posts.

--
Thierry

Thierry Volpiatto

unread,
Mar 20, 2018, 8:04:11 AM3/20/18
to emacs...@googlegroups.com

Here example from scratch buffer:

(setq-local foo "foo")

(helm :sources (helm-build-sync-source "test"
:candidates
(lambda ()
(with-helm-current-buffer
(list foo))))
:buffer "*helm test*")

=> "foo"

(helm :sources (helm-build-sync-source "test"
:init (lambda ()
(helm-set-local-variable 'foo "bar"))
:candidates
(lambda ()
(list foo)))
:buffer "*helm test*")

=> "bar"

(helm :sources (helm-build-sync-source "test"
:candidates
`(lambda () (list ,foo)))
:buffer "*helm test*")

=> "foo"

--
Thierry

Reply all
Reply to author
Forward
0 new messages