Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

24.1.50 + lexical-binding + server.el + server-visit-hook = problem

61 views
Skip to first unread message

Jim Diamond

unread,
Jun 4, 2012, 2:48:04 PM6/4/12
to
While using 23.4 (and some other older versions) I added a hook to
server-visit-hook. My hook function uses the variable "dir", which is
meaningful at the point where server-visit-hook is called.

However, in 24.1.50, the new and improved server.el has
lexical-binding: t
at the top of the file, which (apparently) means that dir is not
available to my hook.

Can some emacs guru (or wizard or ...) enlighten me as to what is the
"proper" way of dealing with this problem?

Thanks.

Jim

Kevin Rodgers

unread,
Jun 5, 2012, 12:11:51 AM6/5/12
to help-gn...@gnu.org
How and where is the binding of dir established?

--
Kevin Rodgers
Denver, Colorado, USA


Jim Diamond

unread,
Jun 5, 2012, 7:21:47 AM6/5/12
to
With a (let) in server-process-filter (lines 1035 and 889 of the
server.el I downloaded the other day).

Jim

Stefan Monnier

unread,
Jun 5, 2012, 9:17:07 PM6/5/12
to
> While using 23.4 (and some other older versions) I added a hook to
> server-visit-hook. My hook function uses the variable "dir", which is
> meaningful at the point where server-visit-hook is called.

What does your hook do and how does it use this `dir'?


Stefan

Jim Diamond

unread,
Jun 6, 2012, 4:01:48 PM6/6/12
to
At the risk of boring you with an overly long story...

For a long, long time I have been using a package called saveconf.el.
(I have modified it over the years, but the first two lines are
as follows:
;;; Save Emacs buffer and window configuration between editing sessions.
;;; Copyright (C) 1987, 1988 Kyle E. Jones
)

This package, originally designed for use NOT in server/daemon mode,
saves the information about what files you were working on when you
exited emacs. Unlike (my possibly incorrect) understanding of
desktop.el, it saves this information on a per-directory basis, so
that if you were editing /a/b/c/xyz.c in directory D last week and now
cd into that directory, a script I wrote will start up emacsclient
with the appropriate file (/a/b/c/xyz.c) at the appropriate line.
(Or, if I start a new instance of emacs, the information will be read
automagically and the file I was previously editing will reappear at
the correct line.)

To clarify, in directory D a file is saved which has /a/b/c/xyz.c and
the line number of (point) when I finished editing the file.

I modified (possibly in a bad way) saveconf.el for the server/client
scenario by adding a function to server-visit-hook. This function
saves the file's directory in a buffer-local variable when the file is
initially visited. This information is used when I finish editing the
buffer, so that it knows in which directory to store my information
file.

Here is my code which I believe is relevant to your question:

(require 'server)
(defvar emacsclient-dir-for-this-buffer nil
"Name of the directory emacsclient was called from for this buffer.")
(make-variable-buffer-local 'emacsclient-dir-for-this-buffer)
(defun saveconf-server-save-emacsclient-dir ()
"Save the directory from which emacsclient was called.
This is called from a place in server.el (server-visit-files)
where the variable 'dir' is equal to the directory emacsclient
was called from."
(setq emacsclient-dir-for-this-buffer dir)
)
(add-hook 'server-visit-hook 'saveconf-server-save-emacsclient-dir)


Does that answer your question?
And, if so, do you have a suggestion on the right way to get this
information I want?

Thanks.
Jim

Kevin Rodgers

unread,
Jun 6, 2012, 11:42:52 PM6/6/12
to help-gn...@gnu.org
Ideally, server.el would define a global dynamically-scoped variable
`server-default-directory' that users could reliably reference to get
the value of the -dir DIRNAME emacsclient option (instead of defining
the internal lexically scoped `dir').

But until then, I think you could fake it by calling emacsclient from
a shell with -eval "(setq server-default-directory \"$PWD\")"

Jim Diamond

unread,
Jun 9, 2012, 10:33:19 AM6/9/12
to
On 2012-06-07 at 00:42 ADT, Kevin Rodgers <kevin.d...@gmail.com> wrote:
> On 6/6/12 2:01 PM, Jim Diamond wrote:

>> (require 'server)
>> (defvar emacsclient-dir-for-this-buffer nil
>> "Name of the directory emacsclient was called from for this buffer.")
>> (make-variable-buffer-local 'emacsclient-dir-for-this-buffer)
>> (defun saveconf-server-save-emacsclient-dir ()
>> "Save the directory from which emacsclient was called.
>> This is called from a place in server.el (server-visit-files)
>> where the variable 'dir' is equal to the directory emacsclient
>> was called from."
>> (setq emacsclient-dir-for-this-buffer dir)
>> )
>> (add-hook 'server-visit-hook 'saveconf-server-save-emacsclient-dir)

>> And, if so, do you have a suggestion on the right way to get this
>> information I want?

> Ideally, server.el would define a global dynamically-scoped variable
> `server-default-directory' that users could reliably reference to get
> the value of the -dir DIRNAME emacsclient option (instead of defining
> the internal lexically scoped `dir').
That sounds good to me.

> But until then,
Do you think that is likely to happen?

> I think you could fake it by calling emacsclient from a shell with
> -eval "(setq server-default-directory \"$PWD\")"
Well, after a bit of fussing around, I do have a solution that works
with that idea, thanks very much. It is unfortunate (at least in this
case) that emacsclient does not let you visit files (in the "usual"
way) if you use --eval.

Thanks for your help.

Jim

Stefan Monnier

unread,
Jun 11, 2012, 9:27:32 AM6/11/12
to
> Ideally, server.el would define a global dynamically-scoped variable
> `server-default-directory' that users could reliably reference to get
> the value of the -dir DIRNAME emacsclient option (instead of defining
> the internal lexically scoped `dir').

It's not quite ideal, tho, because you can have several active
emacsclients at the same time. A better solution is to store this `dir'
into the process's properties.

A related problem is that server-visit-hook is not quite right since
it's run once-per-file, so if you run "emacsclient FILE1 FILE2 FILE3"
it's run 3 times, and if you run "emacsclient -t" it's not run at all.
And server-switch-hook is not any better.

So we'd want a new hook.

Maybe server-visit-files-function would make sense: its default value
would be server-visit-files, and you could override it with any other
function which takes the same arguments (and can call
server-visit-files internally). Since server-visit-files receives the
`proc' as argument, it would have easy access to the process's properties
(although that would not actually be needed in this case since that
function is called with default-directory set as needed) and it also
receives the list of files to visit, which might also come in handy.

> a shell with -eval "(setq server-default-directory \"$PWD\")"

You don't need to rely on $PWD, you can use

-eval "(setq server-default-directory default-directory)"

but indeed, it's not very convenient.


Stefan

Jim Diamond

unread,
Jun 11, 2012, 10:33:49 AM6/11/12
to
On 2012-06-11 at 10:27 ADT, Stefan Monnier <mon...@iro.umontreal.ca> wrote:
(>> comments are from Kevin Rodger)
>> Ideally, server.el would define a global dynamically-scoped variable
>> `server-default-directory' that users could reliably reference to get
>> the value of the -dir DIRNAME emacsclient option (instead of defining
>> the internal lexically scoped `dir').
> It's not quite ideal, tho, because you can have several active
> emacsclients at the same time.
True, but if you capture the value of the variable into a "safe place"
when the hook is called, that's not an issue.

On the other hand, why not have this variable be buffer-local, which
would solve the problem of having multiple concurrent emacsclients?


> A better solution is to store this `dir' into the process's
> properties.

> A related problem is that server-visit-hook is not quite right since
> it's run once-per-file, so if you run "emacsclient FILE1 FILE2 FILE3"
> it's run 3 times, and if you run "emacsclient -t" it's not run at all.
> And server-switch-hook is not any better.
Running the hook 3 times for "emacsclient f1 f2 f3" is not a problem
for me, but your point is good.

> So we'd want a new hook.

> Maybe server-visit-files-function would make sense: its default value
> would be server-visit-files, and you could override it with any other
> function which takes the same arguments (and can call
> server-visit-files internally). Since server-visit-files receives the
> `proc' as argument, it would have easy access to the process's properties
> (although that would not actually be needed in this case since that
> function is called with default-directory set as needed) and it also
> receives the list of files to visit, which might also come in handy.

Thanks for your thoughts. Given the lack of discussion in this
thread, I get the idea I'm the only person doing anything like this.

Jim

Stefan Monnier

unread,
Jun 13, 2012, 11:13:53 AM6/13/12
to
>>> Ideally, server.el would define a global dynamically-scoped variable
>>> `server-default-directory' that users could reliably reference to get
>>> the value of the -dir DIRNAME emacsclient option (instead of defining
>>> the internal lexically scoped `dir').
>> It's not quite ideal, tho, because you can have several active
>> emacsclients at the same time.
> True, but if you capture the value of the variable into a "safe place"
> when the hook is called, that's not an issue.

If that safe place is shared by emacsclients, then it won't always work
(tho it may be sufficient for your particular use case).

> On the other hand, why not have this variable be buffer-local, which
> would solve the problem of having multiple concurrent emacsclients?

No, making this buffer-local just pushes the problem to "local to
*which* buffer". E.g. all emacsclient connections share the same
internal buffer.

>> A better solution is to store this `dir' into the process's
>> properties.

Because that's the only real "safe place".

> Thanks for your thoughts. Given the lack of discussion in this
> thread, I get the idea I'm the only person doing anything like this.

Maybe, but I'd still accept a patch that makes it easier,


Stefan

Jim Diamond

unread,
Jun 24, 2012, 4:34:58 PM6/24/12
to
On 2012-06-13 at 12:13 ADT, Stefan Monnier <mon...@iro.umontreal.ca> wrote:
>>>> Ideally, server.el would define a global dynamically-scoped variable
>>>> `server-default-directory' that users could reliably reference to get
>>>> the value of the -dir DIRNAME emacsclient option (instead of defining
>>>> the internal lexically scoped `dir').
>>> It's not quite ideal, tho, because you can have several active
>>> emacsclients at the same time.
>> True, but if you capture the value of the variable into a "safe place"
>> when the hook is called, that's not an issue.
>
> If that safe place is shared by emacsclients, then it won't always work
> (tho it may be sufficient for your particular use case).
>
>> On the other hand, why not have this variable be buffer-local, which
>> would solve the problem of having multiple concurrent emacsclients?
>
> No, making this buffer-local just pushes the problem to "local to
> *which* buffer". E.g. all emacsclient connections share the same
> internal buffer.
>
>>> A better solution is to store this `dir' into the process's
>>> properties.
>
> Because that's the only real "safe place".
I'll take your word for that. Putting the directory in a buffer-local
variable worked for me, but putting it in the process avoids the need
for the hook, which is nice.

>> Thanks for your thoughts. Given the lack of discussion in this
>> thread, I get the idea I'm the only person doing anything like this.
> Maybe, but I'd still accept a patch that makes it easier,

When you say "I'd accept a patch", does that mean you are willing to
put such a thing in, assuming the patch is OK?
If so, how about this diff against the server.el from 24.1:

diff server.el.orig server.el
1131c1131,1133
< (setq dir (command-line-normalize-file-name dir)))
---
> (setq dir (command-line-normalize-file-name dir))
> (process-put proc 'emacsclient-cwd dir)
> )

In my tests, that does what I want. I'm not in love with the name
"emacsclient-cwd", so if there is something which is seen as a better
name, that's find with me.

What do you think?

Jim

Stefan Monnier

unread,
Jun 25, 2012, 7:03:11 PM6/25/12
to
>>> Thanks for your thoughts. Given the lack of discussion in this
>>> thread, I get the idea I'm the only person doing anything like this.
>> Maybe, but I'd still accept a patch that makes it easier,
> When you say "I'd accept a patch", does that mean you are willing to
> put such a thing in, assuming the patch is OK?

Yes.

> If so, how about this diff against the server.el from 24.1:
> diff server.el.orig server.el
> 1131c1131,1133
> < (setq dir (command-line-normalize-file-name dir)))
> ---
> > (setq dir (command-line-normalize-file-name dir))
> > (process-put proc 'emacsclient-cwd dir)
> > )

"diff -u" is a better choice for output format, but thanks.
The patch looks good, I installed it in Emacs's trunk.

> In my tests, that does what I want. I'm not in love with the name
> "emacsclient-cwd", so if there is something which is seen as a better
> name, that's find with me.

I've changed it to `server-client-directory' (the "server-" part is
just a kind of "module name prefix").


Stefan

Jim Diamond

unread,
Jun 26, 2012, 12:15:59 PM6/26/12
to
On 2012-06-25 at 20:03 ADT, Stefan Monnier <mon...@iro.umontreal.ca> wrote:
>>>> Thanks for your thoughts. Given the lack of discussion in this
>>>> thread, I get the idea I'm the only person doing anything like this.
>>> Maybe, but I'd still accept a patch that makes it easier,
>> When you say "I'd accept a patch", does that mean you are willing to
>> put such a thing in, assuming the patch is OK?
> Yes.
Great.

>> If so, how about this diff against the server.el from 24.1:
>> diff server.el.orig server.el
>> 1131c1131,1133
>> < (setq dir (command-line-normalize-file-name dir)))
>> ---
>> > (setq dir (command-line-normalize-file-name dir))
>> > (process-put proc 'emacsclient-cwd dir)
>> > )
>
> "diff -u" is a better choice for output format, but thanks.
I figured I should use another incantation of diff, but given the lack
of extensiveness, I figured that might do.

> The patch looks good, I installed it in Emacs's trunk.
Thanks very much.

>> In my tests, that does what I want. I'm not in love with the name
>> "emacsclient-cwd", so if there is something which is seen as a better
>> name, that's find with me.
> I've changed it to `server-client-directory' (the "server-" part is
> just a kind of "module name prefix").
Sounds fine.

Thanks for your help with this.

Jim
0 new messages