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

List of buffers under version control?

11 views
Skip to first unread message

Rolf Ade

unread,
Jul 27, 2016, 8:03:59 PM7/27/16
to

I often edit files in emacs, that are under version control. It should
not, but it happens, that I haven#t save-buffer some buffer, while
check-in on the cmd line.

Since I already sometimes use a wrapper around my scm cmd line tool I
imagined, that my wrapper could ask the running emacs about unsaved
buffers under version control and warn me before actually checking in.

Looks, emacsclient -e is the most general interpretation of 'query the
running emacs' and emacsclient already works for me. Although I didn't
was aware of -e so far less than five Minutes and it still looks easily
done.

But from that, it started to get swampy. I'd like to get a yes / no
answer from emacs, if one (or more) of 'some buffers' is unsaved. I don't
want to provide, what 'some buffers' mean. A good heuristic for my usage
habits would be: some buffers are all files under version control.

I tinkered araound more than a half hour, but wasn't able to come up
with a few simple lines of emacs lisp that do that. How should I do?

Rusi

unread,
Jul 28, 2016, 12:05:26 AM7/28/16
to
Not an answer…
Still if you are using git, magit will deal with all (or most) of this
Of course you need to invert your workflow and do the command-line stuff
from inside emacs

Yuri Khan

unread,
Jul 28, 2016, 1:13:17 AM7/28/16
to Rolf Ade, help-gn...@gnu.org
On Thu, Jul 28, 2016 at 7:03 AM, Rolf Ade <ro...@pointsman.de> wrote:

> I often edit files in emacs, that are under version control. It should
> not, but it happens, that I haven#t save-buffer some buffer, while
> check-in on the cmd line.

Normally, when staging a commit, for each unsaved file, you will see a
lock (.#<filename>) and possibly a recovery file (#<filename>#) in the
same directory. This is your signal that not all files are saved. As
soon as you save the file, its lock and recovery file disappear.

(I am assuming that you are using Git, that you review the changes
before committing, and that your .gitignore does not specifically
exclude these patterns.)

Rolf Ade

unread,
Jul 28, 2016, 3:31:15 PM7/28/16
to

Rusi <rusto...@gmail.com> writes:
> On Thursday, July 28, 2016 at 5:33:59 AM UTC+5:30, Rolf Ade wrote:
>> I often edit files in emacs, that are under version control. It should
>> not, but it happens, that I haven#t save-buffer some buffer, while
>> check-in on the cmd line.
>>
>> Since I already sometimes use a wrapper around my scm cmd line tool I
>> imagined, that my wrapper could ask the running emacs about unsaved
>> buffers under version control and warn me before actually checking in.
>>
>> [...]
>
> Not an answer…
> Still if you are using git, magit will deal with all (or most) of this
> Of course you need to invert your workflow and do the command-line stuff
> from inside emacs

No, I'm (mostly) not using git, but fossil. There is a vc backend for
fossil controled files which provides useful things like vc-diff, but
doesn't has as mighty commit features as magit. I prefer to use the
command line to do the check-ins.

The paragraph above includes one bit of information, that I've missed to
provide, so far. Emacs knows, that the buffers (files) I'm interested in
are under version control.

Since emacs show me in the mode line of that buffers, that the file is
under version control, there must be a way with elisp to determine, if
the file shown in a buffer is under version control. How could that be
done?

Rolf Ade

unread,
Jul 28, 2016, 3:31:28 PM7/28/16
to

Yuri Khan <yuri....@gmail.com> writes:
> On Thu, Jul 28, 2016 at 7:03 AM, Rolf Ade <ro...@pointsman.de> wrote:
>
>> I often edit files in emacs, that are under version control. It should
>> not, but it happens, that I haven#t save-buffer some buffer, while
>> check-in on the cmd line.
>
> Normally, when staging a commit, for each unsaved file, you will see a
> lock (.#<filename>) and possibly a recovery file (#<filename>#) in the
> same directory. This is your signal that not all files are saved. As
> soon as you save the file, its lock and recovery file disappear.

Well, this proposes an enlargement of my work-flow. Do one step more:
run ls and look at the output, before I check-in.

Still, a simple ls would not be sufficent. Often, there are a few
modified files spread over sub-directories. A `find -name '#*'` instead
of a simple ls could help, but has other drawbacks. Most important, this
would only work if I check-in only in the root directory of the version
controled sub tree, which is I step, that is currently not needed. Yes,
a bit shell scripting within the wrapper around the scm command line
tool could find the root of the source tree and do the find there. But
even then other open and modified files out of that sub tree, that are
not under version control (temporary input or output files, for example)
would give false positives.

With emacsclient -e I'm able to ask the running emacs. Something like
this

(loop for buffer in (buffer-list)
until (if (buffer-file-name buffer)
(buffer-modified-p buffer)
nil)
finally return (if (buffer-modified-p buffer)
1
0))

is a skeleton of what I want. The missing piece is that I only want to
look at buffers under version control, not on all buffers, that are
visiting a file, as above.

In other words, I'm searching for a (buffer-is-under-version-control-p
buffer) function. How could that be done?

John Mastro

unread,
Jul 28, 2016, 3:52:33 PM7/28/16
to help-gn...@gnu.org, Rolf Ade
Rolf Ade <ro...@pointsman.de> wrote:
> Since emacs show me in the mode line of that buffers, that the file is
> under version control, there must be a way with elisp to determine, if
> the file shown in a buffer is under version control. How could that be
> done?

You could use `vc-backend', e.g. (vc-backend (buffer-file-name)).

`save-some-buffers' accepts an argument PRED; you could also use
`vc-backend' there:

(save-some-buffers
nil
(lambda () (vc-backend (buffer-file-name))))

That way you don't need to loop through the buffer-list yourself.

John

Marcin Borkowski

unread,
Jul 28, 2016, 3:56:41 PM7/28/16
to Rolf Ade, help-gn...@gnu.org

On 2016-07-28, at 21:31, Rolf Ade <ro...@pointsman.de> wrote:

> Since emacs show me in the mode line of that buffers, that the file is
> under version control, there must be a way with elisp to determine, if
> the file shown in a buffer is under version control. How could that be
> done?

How about this?

(if vc-mode
(message "%s" "Hi, I'm under version control!")
(message "%s" "Oops, please version control me!"))

Hth,

--
Marcin Borkowski
http://octd.wmi.amu.edu.pl/en/Marcin_Borkowski
Faculty of Mathematics and Computer Science
Adam Mickiewicz University

John Mastro

unread,
Jul 28, 2016, 3:58:37 PM7/28/16
to help-gn...@gnu.org, Rolf Ade
John Mastro <john.b...@gmail.com> wrote:
> You could use `vc-backend', e.g. (vc-backend (buffer-file-name)).

If the version control system in question isn't supported by VC, an
alternative would be to use `locate-dominating-file'. Something like
(using Git as an example, even though VC obviously does support it):

(save-some-buffers
nil
(lambda ()
(let ((file (buffer-file-name)))
(and file (locate-dominating-file file ".git")))))

John

Rolf Ade

unread,
Jul 28, 2016, 5:01:21 PM7/28/16
to
John Mastro <john.b...@gmail.com> writes:

> Rolf Ade <ro...@pointsman.de> wrote:
>> Since emacs show me in the mode line of that buffers, that the file is
>> under version control, there must be a way with elisp to determine, if
>> the file shown in a buffer is under version control. How could that be
>> done?
>
> You could use `vc-backend', e.g. (vc-backend (buffer-file-name)).

Thank you. That was the missing bit.

Something like this is it:

(loop for buffer in (buffer-list)
until (if (vc-backend (buffer-file-name buffer))
(buffer-modified-p buffer))
finally return (if (and (buffer-modified-p buffer)
(vc-backend (buffer-file-name buffer)))
1
0))

> `save-some-buffers' accepts an argument PRED; you could also use
> `vc-backend' there:

Yes. This doesn't apply in my case, because I'm 'quering' emacs from
within a script with the help of emacsclient -e and want just a yes / no
answer (hence the 'un-lispish' return values). I just want to know, if
this is the case (and ask for confirmation, to give me a chance to look
at the thing, instead of just saving).

John Mastro

unread,
Jul 28, 2016, 5:15:15 PM7/28/16
to help-gn...@gnu.org, Rolf Ade
Rolf Ade <ro...@pointsman.de> wrote:
> Thank you. That was the missing bit.
>
> Something like this is it:
>
> (loop for buffer in (buffer-list)
> until (if (vc-backend (buffer-file-name buffer))
> (buffer-modified-p buffer))
> finally return (if (and (buffer-modified-p buffer)
> (vc-backend (buffer-file-name buffer)))
> 1
> 0))
>

Glad it helps. You could do something like this to avoid repeating the
calls to `vc-backend' and `buffer-modified-p':

(if (loop for buffer in (buffer-list)
thereis (and (vc-backend (buffer-file-name buffer))
(buffer-modified-p buffer)))
1
0)

> Yes. This doesn't apply in my case, because I'm 'quering' emacs from
> within a script with the help of emacsclient -e and want just a yes / no
> answer (hence the 'un-lispish' return values). I just want to know, if
> this is the case (and ask for confirmation, to give me a chance to look
> at the thing, instead of just saving).

Not sure if it makes a difference for your use case, but
`save-some-buffers' does ask for confirmation before saving each buffer.

John

Drew Adams

unread,
Jul 28, 2016, 5:26:18 PM7/28/16
to John Mastro, help-gn...@gnu.org, Rolf Ade
> Glad it helps. You could do something like this to avoid repeating the
> calls to `vc-backend' and `buffer-modified-p':
>
> (if (loop for buffer in (buffer-list)
> thereis (and (vc-backend (buffer-file-name buffer))
> (buffer-modified-p buffer)))
> 1
> 0)

And are you using this just as a predicate (Boolean test)?
If so, just:

(loop for buffer in (buffer-list)
thereis (and (vc-backend (buffer-file-name buffer))
(buffer-modified-p buffer)))

or

(cl-some (lambda (b)
(and (vc-backend (buffer-file-name b))
(buffer-modified-p b)))
(buffer-list))

Rolf Ade

unread,
Jul 28, 2016, 5:52:26 PM7/28/16
to

John Mastro <john.b...@gmail.com> writes:
> Rolf Ade <ro...@pointsman.de> wrote:
>>
>> (loop for buffer in (buffer-list)
>> until (if (vc-backend (buffer-file-name buffer))
>> (buffer-modified-p buffer))
>> finally return (if (and (buffer-modified-p buffer)
>> (vc-backend (buffer-file-name buffer)))
>> 1
>> 0))
>>
>
> Glad it helps. You could do something like this to avoid repeating the
> calls to `vc-backend' and `buffer-modified-p':
>
> (if (loop for buffer in (buffer-list)
> thereis (and (vc-backend (buffer-file-name buffer))
> (buffer-modified-p buffer)))
> 1
> 0)

It's probably not so much about avoiding unnecessary calls (my version
does only 1 call of vc-backend and 1 call of buffer-modified-p more than
yours, no matter how long the buffer-list is (mine currently is 385)).

Your version is not only lesser code but also more to the point written
and better to understand. Thanks again.

(And learned about thereis. And tooked the opportunity, to refresh my
understanding of (the capabilities of) loop.)

Rolf Ade

unread,
Jul 28, 2016, 6:27:09 PM7/28/16
to

Drew Adams <drew....@oracle.com> writes:
>> Glad it helps. You could do something like this to avoid repeating the
>> calls to `vc-backend' and `buffer-modified-p':
>>
>> (if (loop for buffer in (buffer-list)
>> thereis (and (vc-backend (buffer-file-name buffer))
>> (buffer-modified-p buffer)))
>> 1
>> 0)
>
> And are you using this just as a predicate (Boolean test)?

No, or well, yes, but not in the context of other emacs lisp code. The
result value is used by some sh wrapper code around a command line tool.
So, John Mastro was exactly on track.

> If so, just:
>
> (loop for buffer in (buffer-list)
> thereis (and (vc-backend (buffer-file-name buffer))
> (buffer-modified-p buffer)))

Yes. I'm certain, John is aware.

> or
>
> (cl-some (lambda (b)
> (and (vc-backend (buffer-file-name b))
> (buffer-modified-p b)))
> (buffer-list))

Now, this is still some characters less, more compact, yes. Since I
wasn't aware of of `some' up to now ... I wonder: Is there something,
that is easily done with `some' that could not be done (at least well)
with `loop'?

Stefan Monnier

unread,
Jul 28, 2016, 9:43:04 PM7/28/16
to help-gn...@gnu.org
> finally return (if (and (buffer-modified-p buffer)
> (vc-backend (buffer-file-name buffer)))
> 1
> 0))

Why `if'? You could just do

finally return (and (buffer-modified-p buffer)
(vc-backend (buffer-file-name buffer))))


-- Stefan


0 new messages