unofficial mirror of bug-gnu-emacs@gnu.org 
 help / color / mirror / code / Atom feed
* bug#49980: 28.0.50; [PATCH] Should we have project-save-buffers?
@ 2021-08-10  9:23 Giap Tran
  2021-08-11  6:52 ` Juri Linkov
  2021-08-11 12:22 ` Dmitry Gutov
  0 siblings, 2 replies; 22+ messages in thread
From: Giap Tran @ 2021-08-10  9:23 UTC (permalink / raw)
  To: 49980

[-- Attachment #1: Type: text/plain, Size: 226 bytes --]

Hello,

After using `project-query-replace-regexp to query and replace. I see we don't have the function to save all buffers in project.
So after learning from projectile package. I have this patch, hope it is
useful. Thanks


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: project-save-buffers --]
[-- Type: text/x-diff, Size: 1031 bytes --]

diff --git a/lisp/progmodes/project.el b/lisp/progmodes/project.el
index 4620ea8f47..b257222e21 100644
--- a/lisp/progmodes/project.el
+++ b/lisp/progmodes/project.el
@@ -1395,5 +1395,22 @@ to directory DIR."
           (project-current-inhibit-prompt t))
       (call-interactively command))))
 
+(defun project-save-buffers ()
+  "Save all project buffers."
+  (interactive)
+  (let* ((project (project-current t))
+         (buffers (project--buffer-list project))
+         (modified-buffers (cl-remove-if-not (lambda (buf)
+                                               (and (buffer-file-name buf)
+                                                    (buffer-modified-p buf)))
+                                             buffers)))
+    (if (null modified-buffers)
+        (message "No buffers need saving")
+      (dolist (buf modified-buffers)
+        (with-current-buffer buf
+          (save-buffer)))
+      (message "Saved %d buffers" (length modified-buffers)))))
+
+
 (provide 'project)
 ;;; project.el ends here

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* bug#49980: 28.0.50; [PATCH] Should we have project-save-buffers?
  2021-08-10  9:23 bug#49980: 28.0.50; [PATCH] Should we have project-save-buffers? Giap Tran
@ 2021-08-11  6:52 ` Juri Linkov
  2021-08-11  7:38   ` Giap Tran
  2021-08-11 12:23   ` Dmitry Gutov
  2021-08-11 12:22 ` Dmitry Gutov
  1 sibling, 2 replies; 22+ messages in thread
From: Juri Linkov @ 2021-08-11  6:52 UTC (permalink / raw)
  To: Giap Tran; +Cc: 49980

> After using `project-query-replace-regexp to query and replace.
> I see we don't have the function to save all buffers in project.
> So after learning from projectile package. I have this patch, hope it is
> useful. Thanks

It would be nice to have a keybinding for this useful command,
as there is 'C-x s', but 'C-x p s' is bound to 'project-shell'.
Maybe then to bind it to 'C-x p S'?





^ permalink raw reply	[flat|nested] 22+ messages in thread

* bug#49980: 28.0.50; [PATCH] Should we have project-save-buffers?
  2021-08-11  6:52 ` Juri Linkov
@ 2021-08-11  7:38   ` Giap Tran
  2021-08-11 12:23   ` Dmitry Gutov
  1 sibling, 0 replies; 22+ messages in thread
From: Giap Tran @ 2021-08-11  7:38 UTC (permalink / raw)
  To: Juri Linkov; +Cc: 49980

Juri Linkov <juri@linkov.net> writes:

> Maybe then to bind it to 'C-x p S'?

I'm totally agree with you.





^ permalink raw reply	[flat|nested] 22+ messages in thread

* bug#49980: 28.0.50; [PATCH] Should we have project-save-buffers?
  2021-08-10  9:23 bug#49980: 28.0.50; [PATCH] Should we have project-save-buffers? Giap Tran
  2021-08-11  6:52 ` Juri Linkov
@ 2021-08-11 12:22 ` Dmitry Gutov
  2021-08-11 13:40   ` Giap Tran
  1 sibling, 1 reply; 22+ messages in thread
From: Dmitry Gutov @ 2021-08-11 12:22 UTC (permalink / raw)
  To: Giap Tran, 49980

Hi!

On 10.08.2021 12:23, Giap Tran wrote:
> After using `project-query-replace-regexp to query and replace. I see we don't have the function to save all buffers in project.

Is there any reason not to just use 'save-some-buffers' (C-x s)?

Do you often want to leave some buffers unsaved?





^ permalink raw reply	[flat|nested] 22+ messages in thread

* bug#49980: 28.0.50; [PATCH] Should we have project-save-buffers?
  2021-08-11  6:52 ` Juri Linkov
  2021-08-11  7:38   ` Giap Tran
@ 2021-08-11 12:23   ` Dmitry Gutov
  2021-08-12  7:55     ` Juri Linkov
  1 sibling, 1 reply; 22+ messages in thread
From: Dmitry Gutov @ 2021-08-11 12:23 UTC (permalink / raw)
  To: Juri Linkov, Giap Tran; +Cc: 49980

On 11.08.2021 09:52, Juri Linkov wrote:
> It would be nice to have a keybinding for this useful command,
> as there is 'C-x s', but 'C-x p s' is bound to 'project-shell'.
> Maybe then to bind it to 'C-x p S'?

If we do end up adding this command, we could move project-shell to 'C-x 
p E', for example, so that we don't spread shell-related commands over 
different letters.

Then project-save-buffers could be on 'C-x p s'.

But see my question in the other email.





^ permalink raw reply	[flat|nested] 22+ messages in thread

* bug#49980: 28.0.50; [PATCH] Should we have project-save-buffers?
  2021-08-11 12:22 ` Dmitry Gutov
@ 2021-08-11 13:40   ` Giap Tran
  2021-08-13  2:11     ` Dmitry Gutov
  0 siblings, 1 reply; 22+ messages in thread
From: Giap Tran @ 2021-08-11 13:40 UTC (permalink / raw)
  To: Dmitry Gutov; +Cc: 49980

Dmitry Gutov <dgutov@yandex.ru> writes:

> Is there any reason not to just use 'save-some-buffers' (C-x s)?
>
> Do you often want to leave some buffers unsaved?

Oh, so funny, I used Emacs for over 4 years and I don't know this
function. Looks like I just need this to solve my problem

> Then project-save-buffers could be on 'C-x p s'.

Is `project-save-buffers necessary anymore? If anyone opens many projects
with unsaved buffers. Maybe they need that because they don't want to
save buffers not in this project. I think we don't need
keybinding for that. We can use M-x, up to you :D


-- 
Giap Tran <txgvnn@gmail.com>
GnuPG/0xE655BF766A56995D





^ permalink raw reply	[flat|nested] 22+ messages in thread

* bug#49980: 28.0.50; [PATCH] Should we have project-save-buffers?
  2021-08-11 12:23   ` Dmitry Gutov
@ 2021-08-12  7:55     ` Juri Linkov
  2021-08-13  2:06       ` Dmitry Gutov
  0 siblings, 1 reply; 22+ messages in thread
From: Juri Linkov @ 2021-08-12  7:55 UTC (permalink / raw)
  To: Dmitry Gutov; +Cc: Giap Tran, 49980

>> It would be nice to have a keybinding for this useful command,
>> as there is 'C-x s', but 'C-x p s' is bound to 'project-shell'.
>> Maybe then to bind it to 'C-x p S'?
>
> If we do end up adding this command, we could move project-shell to 'C-x
> p E', for example, so that we don't spread shell-related commands over
> different letters.

Or to a new prefix map, e.g. 'C-x p x s' with mnemonics "eXecute Shell".

> But see my question in the other email.
> Is there any reason not to just use 'save-some-buffers' (C-x s)?

In bug#46374 we are adding a new option 'project-root'
to 'save-some-buffers-default-predicate' that will allow
'C-x s' to save only files under the same project root.





^ permalink raw reply	[flat|nested] 22+ messages in thread

* bug#49980: 28.0.50; [PATCH] Should we have project-save-buffers?
  2021-08-12  7:55     ` Juri Linkov
@ 2021-08-13  2:06       ` Dmitry Gutov
  2021-08-13  7:12         ` Juri Linkov
  2021-08-13  9:39         ` Arthur Miller
  0 siblings, 2 replies; 22+ messages in thread
From: Dmitry Gutov @ 2021-08-13  2:06 UTC (permalink / raw)
  To: Juri Linkov; +Cc: Giap Tran, 49980

On 12.08.2021 10:55, Juri Linkov wrote:
>>> It would be nice to have a keybinding for this useful command,
>>> as there is 'C-x s', but 'C-x p s' is bound to 'project-shell'.
>>> Maybe then to bind it to 'C-x p S'?
>>
>> If we do end up adding this command, we could move project-shell to 'C-x
>> p E', for example, so that we don't spread shell-related commands over
>> different letters.
> 
> Or to a new prefix map, e.g. 'C-x p x s' with mnemonics "eXecute Shell".

That would also displace project-execute-extended-command, which seems 
gratuitous. And if we were putting different commands together to save 
keymap space, 'project-compile' seems closer in purpose to 
'project-shell' than 'project-execute-extended-command'.

Anyway, 'e' as a mnemonic for 'Eshell' or 'shEll' seems good enough for me.

>> But see my question in the other email.
>> Is there any reason not to just use 'save-some-buffers' (C-x s)?
> 
> In bug#46374 we are adding a new option 'project-root'
> to 'save-some-buffers-default-predicate' that will allow
> 'C-x s' to save only files under the same project root.

That also seems to indicate that we don't need a separate command.





^ permalink raw reply	[flat|nested] 22+ messages in thread

* bug#49980: 28.0.50; [PATCH] Should we have project-save-buffers?
  2021-08-11 13:40   ` Giap Tran
@ 2021-08-13  2:11     ` Dmitry Gutov
  0 siblings, 0 replies; 22+ messages in thread
From: Dmitry Gutov @ 2021-08-13  2:11 UTC (permalink / raw)
  To: Giap Tran; +Cc: 49980

On 11.08.2021 16:40, Giap Tran wrote:
> Dmitry Gutov <dgutov@yandex.ru> writes:
> 
>> Is there any reason not to just use 'save-some-buffers' (C-x s)?
>>
>> Do you often want to leave some buffers unsaved?
> 
> Oh, so funny, I used Emacs for over 4 years and I don't know this
> function. Looks like I just need this to solve my problem

Excellent.

>> Then project-save-buffers could be on 'C-x p s'.
> 
> Is `project-save-buffers necessary anymore? If anyone opens many projects
> with unsaved buffers. Maybe they need that because they don't want to
> save buffers not in this project. I think we don't need
> keybinding for that. We can use M-x, up to you :D

I don't know if it's necessary indeed (and as Juri notes, there will be 
another approach available).

We might consider it problematic, though, that for 
'project-query-replace-regexp' to operate properly the user needs to 
save all the buffers manually (they both need to know that they need to 
do that, and how to do that). Maybe xref-query-replace-in-results should 
have an option to save all touched buffers in the end. Or maybe 
perform-replace should have one.

Hopefully we can also resolve this difficulty another way, providing an 
inline editing mechanism for Xref buffers.





^ permalink raw reply	[flat|nested] 22+ messages in thread

* bug#49980: 28.0.50; [PATCH] Should we have project-save-buffers?
  2021-08-13  2:06       ` Dmitry Gutov
@ 2021-08-13  7:12         ` Juri Linkov
  2021-08-13  9:39         ` Arthur Miller
  1 sibling, 0 replies; 22+ messages in thread
From: Juri Linkov @ 2021-08-13  7:12 UTC (permalink / raw)
  To: Dmitry Gutov; +Cc: Giap Tran, 49980

tags 49980 fixed
close 49980 28.0.50
quit

>> Or to a new prefix map, e.g. 'C-x p x s' with mnemonics "eXecute Shell".
>
> That would also displace project-execute-extended-command, which seems
> gratuitous. And if we were putting different commands together to save
> keymap space, 'project-compile' seems closer in purpose to 'project-shell'
> than 'project-execute-extended-command'.
>
> Anyway, 'e' as a mnemonic for 'Eshell' or 'shEll' seems good enough for me.

Then maybe 'C-x p e e' for 'Eshell' with a mnemonic "Execute Eshell",
and 'C-x p e s' for 'Shell' with a mnemonic "Execute Shell".

>>> Is there any reason not to just use 'save-some-buffers' (C-x s)?
>> In bug#46374 we are adding a new option 'project-root'
>> to 'save-some-buffers-default-predicate' that will allow
>> 'C-x s' to save only files under the same project root.
>
> That also seems to indicate that we don't need a separate command.

Indeed, so after pushing the patch to use the project root in bug#46374,
now closing this request too.





^ permalink raw reply	[flat|nested] 22+ messages in thread

* bug#49980: 28.0.50; [PATCH] Should we have project-save-buffers?
  2021-08-13  2:06       ` Dmitry Gutov
  2021-08-13  7:12         ` Juri Linkov
@ 2021-08-13  9:39         ` Arthur Miller
  2021-08-13 16:05           ` Juri Linkov
  2021-08-13 23:54           ` Dmitry Gutov
  1 sibling, 2 replies; 22+ messages in thread
From: Arthur Miller @ 2021-08-13  9:39 UTC (permalink / raw)
  To: Dmitry Gutov; +Cc: Giap Tran, 49980, Juri Linkov

Dmitry Gutov <dgutov@yandex.ru> writes:

> On 12.08.2021 10:55, Juri Linkov wrote:
>>>> It would be nice to have a keybinding for this useful command,
>>>> as there is 'C-x s', but 'C-x p s' is bound to 'project-shell'.
>>>> Maybe then to bind it to 'C-x p S'?
>>>
>>> If we do end up adding this command, we could move project-shell to 'C-x
>>> p E', for example, so that we don't spread shell-related commands over
>>> different letters.
>> Or to a new prefix map, e.g. 'C-x p x s' with mnemonics "eXecute Shell".
>
> That would also displace project-execute-extended-command, which seems
> gratuitous. And if we were putting different commands together to save keymap
> space, 'project-compile' seems closer in purpose to 'project-shell' than
> 'project-execute-extended-command'.
>
> Anyway, 'e' as a mnemonic for 'Eshell' or 'shEll' seems good enough for me.
>
>>> But see my question in the other email.
>>> Is there any reason not to just use 'save-some-buffers' (C-x s)?
>> In bug#46374 we are adding a new option 'project-root'
>> to 'save-some-buffers-default-predicate' that will allow
>> 'C-x s' to save only files under the same project root.
>
> That also seems to indicate that we don't need a separate command.

I am sorry I am bit late to the party, but I would like to have a
command to save all modified buffers belonging to a project directory. I
am just about to code something like this for myself and a small project
of mine, so I would be happy if you can point me into something that
exists.

I have coded a little branch switcher with helm. The purpose it so be
able to fast switch branch, say you are working on some bigger feature,
and than wish for some reason to switch to some other branch and then
comeback and continue on the previous one. The workflow is to simply
stash everything on change, and apply stash when branch is checked out
again. I have it working, minus the part to save all buffers belonging
to a project which is root directory wtih .git in my case.

I don't know if that fits into your purpose or something, nor do I think
it is hard to code, but I always prefer if I can skip duplicating code
and per-use soemthing.





^ permalink raw reply	[flat|nested] 22+ messages in thread

* bug#49980: 28.0.50; [PATCH] Should we have project-save-buffers?
  2021-08-13  9:39         ` Arthur Miller
@ 2021-08-13 16:05           ` Juri Linkov
  2021-08-13 17:22             ` Arthur Miller
  2021-08-14  2:25             ` Arthur Miller
  2021-08-13 23:54           ` Dmitry Gutov
  1 sibling, 2 replies; 22+ messages in thread
From: Juri Linkov @ 2021-08-13 16:05 UTC (permalink / raw)
  To: Arthur Miller; +Cc: Giap Tran, 49980, Dmitry Gutov

> I am sorry I am bit late to the party, but I would like to have a
> command to save all modified buffers belonging to a project directory. I
> am just about to code something like this for myself and a small project
> of mine, so I would be happy if you can point me into something that
> exists.
>
> I have coded a little branch switcher with helm. The purpose it so be
> able to fast switch branch, say you are working on some bigger feature,
> and than wish for some reason to switch to some other branch and then
> comeback and continue on the previous one. The workflow is to simply
> stash everything on change, and apply stash when branch is checked out
> again. I have it working, minus the part to save all buffers belonging
> to a project which is root directory wtih .git in my case.
>
> I don't know if that fits into your purpose or something, nor do I think
> it is hard to code, but I always prefer if I can skip duplicating code
> and per-use soemthing.

Now it's possible just to type 'C-x s' after customizing
'save-some-buffers-default-predicate' to 'save-some-buffers-root',
or after setting this value in project's .dir-locals.el.

If you want to use this new feature programmatically,
then just call:

  (save-some-buffers t 'save-some-buffers-root)





^ permalink raw reply	[flat|nested] 22+ messages in thread

* bug#49980: 28.0.50; [PATCH] Should we have project-save-buffers?
  2021-08-13 16:05           ` Juri Linkov
@ 2021-08-13 17:22             ` Arthur Miller
  2021-08-14  2:25             ` Arthur Miller
  1 sibling, 0 replies; 22+ messages in thread
From: Arthur Miller @ 2021-08-13 17:22 UTC (permalink / raw)
  To: Juri Linkov; +Cc: Giap Tran, 49980, Dmitry Gutov

Juri Linkov <juri@linkov.net> writes:

>> I am sorry I am bit late to the party, but I would like to have a
>> command to save all modified buffers belonging to a project directory. I
>> am just about to code something like this for myself and a small project
>> of mine, so I would be happy if you can point me into something that
>> exists.
>>
>> I have coded a little branch switcher with helm. The purpose it so be
>> able to fast switch branch, say you are working on some bigger feature,
>> and than wish for some reason to switch to some other branch and then
>> comeback and continue on the previous one. The workflow is to simply
>> stash everything on change, and apply stash when branch is checked out
>> again. I have it working, minus the part to save all buffers belonging
>> to a project which is root directory wtih .git in my case.
>>
>> I don't know if that fits into your purpose or something, nor do I think
>> it is hard to code, but I always prefer if I can skip duplicating code
>> and per-use soemthing.
>
> Now it's possible just to type 'C-x s' after customizing
> 'save-some-buffers-default-predicate' to 'save-some-buffers-root',
> or after setting this value in project's .dir-locals.el.
>
> If you want to use this new feature programmatically,
> then just call:

Yes, that is exactly my intention; I would like to save all modified
buffers belonging to git root and subdirectories programmatically.

>   (save-some-buffers t 'save-some-buffers-root)

Thank you, I have just pulled and rebuild. Will try it and let you know
how it works when I am done testing.

Thank you very much.





^ permalink raw reply	[flat|nested] 22+ messages in thread

* bug#49980: 28.0.50; [PATCH] Should we have project-save-buffers?
  2021-08-13  9:39         ` Arthur Miller
  2021-08-13 16:05           ` Juri Linkov
@ 2021-08-13 23:54           ` Dmitry Gutov
  2021-08-14  2:46             ` Arthur Miller
  1 sibling, 1 reply; 22+ messages in thread
From: Dmitry Gutov @ 2021-08-13 23:54 UTC (permalink / raw)
  To: Arthur Miller; +Cc: Giap Tran, 49980, Juri Linkov

On 13.08.2021 12:39, Arthur Miller wrote:
> I don't know if that fits into your purpose or something, nor do I think
> it is hard to code, but I always prefer if I can skip duplicating code
> and per-use soemthing.

Please check out Juri's solution, and if it doesn't work out, we can 
always add a dedicated command.





^ permalink raw reply	[flat|nested] 22+ messages in thread

* bug#49980: 28.0.50; [PATCH] Should we have project-save-buffers?
  2021-08-13 16:05           ` Juri Linkov
  2021-08-13 17:22             ` Arthur Miller
@ 2021-08-14  2:25             ` Arthur Miller
  2021-08-15  8:32               ` Juri Linkov
  1 sibling, 1 reply; 22+ messages in thread
From: Arthur Miller @ 2021-08-14  2:25 UTC (permalink / raw)
  To: Juri Linkov; +Cc: Giap Tran, 49980, Dmitry Gutov

Juri Linkov <juri@linkov.net> writes:

>> I am sorry I am bit late to the party, but I would like to have a
>> command to save all modified buffers belonging to a project directory. I
>> am just about to code something like this for myself and a small project
>> of mine, so I would be happy if you can point me into something that
>> exists.
>>
>> I have coded a little branch switcher with helm. The purpose it so be
>> able to fast switch branch, say you are working on some bigger feature,
>> and than wish for some reason to switch to some other branch and then
>> comeback and continue on the previous one. The workflow is to simply
>> stash everything on change, and apply stash when branch is checked out
>> again. I have it working, minus the part to save all buffers belonging
>> to a project which is root directory wtih .git in my case.
>>
>> I don't know if that fits into your purpose or something, nor do I think
>> it is hard to code, but I always prefer if I can skip duplicating code
>> and per-use soemthing.
>
> Now it's possible just to type 'C-x s' after customizing
> 'save-some-buffers-default-predicate' to 'save-some-buffers-root',
> or after setting this value in project's .dir-locals.el.
>
> If you want to use this new feature programmatically,
> then just call:
>
>   (save-some-buffers t 'save-some-buffers-root)

Hi again, this works just wonderful! :)

Actually it works so good, that I am thinking I am doing something wrong
here.

I created some files in top level and a subdirectory, with some content
and it worked just fine. Literally with just adding the above line:

(save-some-buffers t 'save-some-buffers-root)

Fragment of my use-case:

#+begin_src emacs-lisp

(defun helm-git-branch--checkout (branch)
  (helm-aif (helm-ls-git-root-dir)
      (with-helm-default-directory it
        (with-output-to-string
          (with-current-buffer standard-output
            (save-some-buffers t 'save-some-buffers-root)
            (when (helm-git-branch--dirty-p)
              (helm-git-branch--stash))
            (insert (call-process "git" nil t nil "checkout" branch))
            (helm-git-branch--unstash))))))

#+end_src

So how does it work? save-some-buffers-root auto detects a git repo
root via project-find-functions in project.el or something there? I
havent followed entire call chain. I ask, because I guess this is going
to be part of Emacs 28 but wonder if you have any plans to port it 
into older versions?

Anyway, thank you. That was what I needed, I think you saved me quite
some work.






^ permalink raw reply	[flat|nested] 22+ messages in thread

* bug#49980: 28.0.50; [PATCH] Should we have project-save-buffers?
  2021-08-13 23:54           ` Dmitry Gutov
@ 2021-08-14  2:46             ` Arthur Miller
  2021-08-16  0:37               ` Dmitry Gutov
  0 siblings, 1 reply; 22+ messages in thread
From: Arthur Miller @ 2021-08-14  2:46 UTC (permalink / raw)
  To: Dmitry Gutov; +Cc: Giap Tran, 49980, Juri Linkov

Dmitry Gutov <dgutov@yandex.ru> writes:

> On 13.08.2021 12:39, Arthur Miller wrote:
>> I don't know if that fits into your purpose or something, nor do I think
>> it is hard to code, but I always prefer if I can skip duplicating code
>> and per-use soemthing.
>
> Please check out Juri's solution, and if it doesn't work out, we can always add
> a dedicated command.

Yes I did, I just sent him an answer, it works great! So good that I am
thinking I did something wrong :).

Could you guys care to take a look at my little branch switcher? If you
have time. I could use some review and advice. It is ~200 sloc and most
of it is helm boiler code, I am really interesting about opinion on
stash/unstash strategy. I stash everything include untracked
files. However I am thinking of implementing other strategy, via commit
and undo commit.






^ permalink raw reply	[flat|nested] 22+ messages in thread

* bug#49980: 28.0.50; [PATCH] Should we have project-save-buffers?
  2021-08-14  2:25             ` Arthur Miller
@ 2021-08-15  8:32               ` Juri Linkov
  2021-08-15 10:44                 ` Arthur Miller
  0 siblings, 1 reply; 22+ messages in thread
From: Juri Linkov @ 2021-08-15  8:32 UTC (permalink / raw)
  To: Arthur Miller; +Cc: Giap Tran, 49980, Dmitry Gutov

> (save-some-buffers t 'save-some-buffers-root)
>
> So how does it work? save-some-buffers-root auto detects a git repo
> root via project-find-functions in project.el or something there? I
> havent followed entire call chain. I ask, because I guess this is going
> to be part of Emacs 28 but wonder if you have any plans to port it
> into older versions?

You can make it backward-compatible with older versions by copying
the contents of the function save-some-buffers-root literally
to your code.  This call should work in older versions:

#+begin_src emacs-lisp
  (save-some-buffers
   t
   (let ((root (or (and (project-current) (project-root (project-current)))
                   default-directory)))
     (lambda () (file-in-directory-p default-directory root))))
#+end_src

> Could you guys care to take a look at my little branch switcher? If you
> have time. I could use some review and advice. It is ~200 sloc and most
> of it is helm boiler code, I am really interesting about opinion on
> stash/unstash strategy. I stash everything include untracked
> files. However I am thinking of implementing other strategy, via commit
> and undo commit.

Thanks, this is a useful package.  It uses the right strategy
to stash and unstash changes.  This is much better than committing
and undoing commits like we recently discussed in
https://lists.gnu.org/archive/html/emacs-devel/2021-08/msg00346.html





^ permalink raw reply	[flat|nested] 22+ messages in thread

* bug#49980: 28.0.50; [PATCH] Should we have project-save-buffers?
  2021-08-15  8:32               ` Juri Linkov
@ 2021-08-15 10:44                 ` Arthur Miller
  0 siblings, 0 replies; 22+ messages in thread
From: Arthur Miller @ 2021-08-15 10:44 UTC (permalink / raw)
  To: Juri Linkov; +Cc: Giap Tran, 49980, Dmitry Gutov

[-- Attachment #1: Type: text/plain, Size: 2770 bytes --]

Juri Linkov <juri@linkov.net> writes:

>> (save-some-buffers t 'save-some-buffers-root)
>>
>> So how does it work? save-some-buffers-root auto detects a git repo
>> root via project-find-functions in project.el or something there? I
>> havent followed entire call chain. I ask, because I guess this is going
>> to be part of Emacs 28 but wonder if you have any plans to port it
>> into older versions?
>
> You can make it backward-compatible with older versions by copying
> the contents of the function save-some-buffers-root literally
> to your code.  This call should work in older versions:
Ah, that was was the magic. I was looking into those functions, but
wasn't really sure what I should snitch :). 

> to your code.  This call should work in older versions:
>
> #+begin_src emacs-lisp
>   (save-some-buffers
>    t
>    (let ((root (or (and (project-current) (project-root (project-current)))
>                    default-directory)))
>      (lambda () (file-in-directory-p default-directory root))))
> #+end_src

Thank you!

>> Could you guys care to take a look at my little branch switcher? If you
>> have time. I could use some review and advice. It is ~200 sloc and most
>> of it is helm boiler code, I am really interesting about opinion on
>> stash/unstash strategy. I stash everything include untracked
>> files. However I am thinking of implementing other strategy, via commit
>> and undo commit.
>
> Thanks, this is a useful package.  It uses the right strategy
> to stash and unstash changes.  This is much better than committing
> and undoing commits like we recently discussed in
> https://lists.gnu.org/archive/html/emacs-devel/2021-08/msg00346.html

I have to admit, I haven't followed so much the discussion, this was
just sommething I wished to had for longer time, but never come about to
implement.

I am not sure if my approach is correct. I think it can mess up things
when multiple branches get changed. If there are only two branches
invloved, a->b, b->c, there are no problems (I think). Also with
multiple branches without changes there should be no problems.

But in case of a->b, b->c, ... , c->n, I am not sure, but I believe they
would have to be checked out in correct reversed order. Otherwise I
think there is possiblity that applied stashes tramp over each others
and cause conflicts. I don't know, I haven't had time to test it that
far. I had this for a couple of weeks, and works fine for my modest
need, but I would appreciate some more input on the code.

I have attached it the source in this mail, if anyone is interested to
look at it, but there is also a github project with some more info in a
readme file at:

https://github.com/amno1/helm-git-branch

I am thankful for all input, and thanks for all your help Juri!


[-- Attachment #2: helm-git-branch.el --]
[-- Type: text/plain, Size: 8281 bytes --]

;;; helm-git-branch.el --- Switch git branch with Helm interface.  -*- lexical-binding: t; -*-

;; Copyright (C) 2021  Arthur Miller

;; Author: Arthur Miller <arthur.miller@live.com>
;; Keywords:

;; This program is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.

;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
;; GNU General Public License for more details.

;; You should have received a copy of the GNU General Public License
;; along with this program.  If not, see <https://www.gnu.org/licenses/>.

;;; Commentary:

;;

;;; Code:

(require 'helm-ls-git)

(defvar helm-source-git-local-branches nil
  "This source will built at runtime.
It can be build explicitly with function
`helm-git-build-local-branches-source'.")

(defface helm-git-branch-current-clean-face
    '((t :foreground "#2aa198"))
  "Files which contain rebase/merge conflicts."
  :group 'helm-ls-git)

(defface helm-git-branch-current-dirty-face
    '((t :foreground "#dc322f"))
  "Files which contain rebase/merge conflicts."
  :group 'helm-ls-git)

;;; Custom
\f
(defgroup helm-git-branch nil
  "Fast git branch switching with Helm."
  :group 'helm)

(defcustom helm-git-branch-changes-action 'stash
  "The default action upon changing a branch with uncommited changes.

If this option is set to 'stash the changes will be automatically stashed.

If this option is set to 'commit the changes will automatically commited."
  :type 'symbol
  :group 'helm)

(defgroup helm-git-branch nil
  "Fast git branch switching with Helm."
  :group 'helm)

(defcustom helm-git-branch-stash-prefix "helm-git-branch--"
  "The prefix to prepend to stash names when autostashing a branch."
  :type 'string
  :group 'helm)

(defcustom helm-git-branch-auto-save-on-change t
  ""
  :type 'boolean
  :group 'helm)

(defcustom helm-git-branch-auto-stash-unstaged t
  ""
  :type 'boolean
  :group 'helm)

(defcustom helm-git-branch-fuzzy-match nil
  "Enable fuzzy matching in `helm-git-*-branch'."
  :group 'helm-branch-git
  :set (lambda (var val)
         (set var val)
         (setq helm-source-git-local-branches nil))
  :type 'boolean)

\f
(defmacro replace-all (from to &optional buffer)
  `(with-current-buffer (or ,buffer (current-buffer))
     (goto-char (point-min))
     (while (search-forward ,from nil t)
       (replace-match ,to))))

(defun git-make-cmd (git-args &rest cmd-args)
  (let ((cmd
         (seq-concatenate
          'list
          '(call-process "git" nil t nil) (split-string git-args) cmd-args)))
    `(lambda () ,cmd)))

(defun git-call (git-args)
  (funcall (git-make-cmd git-args)))

(defmacro with-helm-git (git-cmd &rest body)
  `(nbutlast
     (split-string
      (helm-aif (helm-ls-git-root-dir)
          (with-helm-default-directory it
            (with-output-to-string
              (with-current-buffer standard-output
                (insert (format "%s" (git-call ,git-cmd)))
                ,@body
                (buffer-string))))) "\n" t "[\s\t]*")))

(defvar helm-git-branch-map
  (let ((map (make-sparse-keymap)))
    (set-keymap-parent map helm-generic-files-map)
    map))

(defvar helm-git-branch-buffer-map
  (let ((map (make-sparse-keymap)))
    (set-keymap-parent map helm-buffer-map)
    map))

\f
;;; Sources
(defun helm-git--local-branches ()
  (with-helm-git "branch"))

(defun helm-git-branch-local-transformer (candidates _source)
  (cl-loop with root = (helm-ls-git-root-dir)
        for i in candidates
        collect
        (cond ((string-match "^\\(*\\)\\(.*\\)" i) ; current branch
               (if (helm-git-branch--dirty-p)
                   (cons (propertize i 'face 'helm-git-branch-current-dirty-face)
                         (expand-file-name (match-string 2 i) root))
                 (cons (propertize i 'face 'helm-git-branch-current-clean-face)
                       (expand-file-name (match-string 2 i) root))))
              (t i))))

(defun helm-git-branch-local-action-transformer (actions _candidate)
  (when (= 1 (length (helm-marked-candidates)))
    (helm-make-actions "Checkout branch"
                       (lambda (_candidate)
                         (let ((marked (helm-marked-candidates)))
                           (dolist (f marked)
                             (vc-git-revert f)
                             (helm-aif (get-file-buffer f)
                                 (with-current-buffer it
                                   (revert-buffer t t)))))))
    actions))
\f
(defclass helm-git-local-source (helm-source-in-buffer)
  ((header-name :initform 'helm-ls-git-header-name)
   (init :initform
         (lambda ()
           (helm-init-candidates-in-buffer 'global
             (helm-git--local-branches))))
   (keymap :initform 'helm-git-branch-map)
   (action :initform (helm-make-actions "Git checkout"
                                        (lambda (_candidate)
                                          (helm-git-branch--checkout _candidate))))
   (filtered-candidate-transformer :initform 'helm-git-branch-local-transformer)
   (action-transformer :initform 'helm-git-branch-local-action-transformer)))

(defun helm-git-build-local-branches-source ()
  ;;(and (memq 'helm-source-ls-git-branches helm-ls-git-default-sources)
  (helm-make-source "Local branches" 'helm-git-local-source
    :fuzzy-match helm-git-branch-fuzzy-match
    :group 'helm
    :keymap helm-git-branch-map))

\f

(defun helm-git-branch--dirty-p ()
  (not (string-blank-p (helm-ls-git-status))))

(defun helm-git-branch--stash ()
  (helm-aif (helm-ls-git-root-dir)
      (with-helm-default-directory it
        (with-output-to-string
          (with-current-buffer standard-output
            (insert
             (call-process "git" nil t nil "stash" "save"
                           (when helm-git-branch-auto-stash-unstaged "-u")
                           (concat helm-git-branch-stash-prefix
                                   (helm-ls-git--branch)))))))))

(defun helm-git-branch--unstash ()
  (helm-aif (helm-ls-git-root-dir)
      (with-helm-default-directory it
        (with-output-to-string
          (with-current-buffer standard-output
            (insert (call-process "git" nil t nil "stash" "list"))
            (goto-char (point-min))
            (when (search-forward (concat helm-git-branch-stash-prefix
                                          (helm-ls-git--branch)) nil t)
              (goto-char (line-beginning-position))
              (search-forward "}" (line-end-position))
              (let ((stash (buffer-substring-no-properties
                            (line-beginning-position) (point))))
                (call-process "git" nil t nil "stash" "apply" stash)
                (call-process "git" nil t nil "stash" "drop" stash))))))))

(defun helm-git-branch--checkout (branch)
  (helm-aif (helm-ls-git-root-dir)
      (with-helm-default-directory it
        (with-output-to-string
          (with-current-buffer standard-output
            (when helm-git-branch-auto-save-on-change
              (save-some-buffers t 'save-some-buffers-root))
            (when (helm-git-branch--dirty-p)
              (helm-git-branch--stash))
            (insert (call-process "git" nil t nil "checkout" branch))
            (helm-git-branch--unstash))))))

\f
;;; Commands
;;;###autoload
(defun helm-git-local-branches (&optional arg)
  (interactive "p")
  (let ((helm-ff-default-directory
         (or helm-ff-default-directory
             default-directory)))
    (when (and arg (not (helm-ls-git-root-dir)))
      (error "Not inside a Git repository"))
    (setq helm-source-git-local-branches
          (helm-git-build-local-branches-source))
    (helm-set-local-variable
     'helm-ls-git--current-branch (helm-ls-git--branch))
    (helm :sources helm-source-git-local-branches
          :ff-transformer-show-only-basename nil
          :truncate-lines helm-buffers-truncate-lines
          :buffer "*helm branches*")))

(provide 'helm-git-branch)
;;; helm-git-branch.el ends here

^ permalink raw reply	[flat|nested] 22+ messages in thread

* bug#49980: 28.0.50; [PATCH] Should we have project-save-buffers?
  2021-08-14  2:46             ` Arthur Miller
@ 2021-08-16  0:37               ` Dmitry Gutov
  2021-08-16  1:19                 ` Arthur Miller
  0 siblings, 1 reply; 22+ messages in thread
From: Dmitry Gutov @ 2021-08-16  0:37 UTC (permalink / raw)
  To: Arthur Miller; +Cc: Giap Tran, 49980, Juri Linkov

On 14.08.2021 05:46, Arthur Miller wrote:
> It is ~200 sloc and most
> of it is helm boiler code, I am really interesting about opinion on
> stash/unstash strategy. I stash everything include untracked
> files.

Speaking of strategy, that sounds like something I routinely do by hand, 
so... it seems fine?

Though I usually keep unregistered files alone, because those can be 
both related to the current work I'm doing, or totally unrelated and be, 
for example, some new project settings I haven't checked in (and perhaps 
never intend to).





^ permalink raw reply	[flat|nested] 22+ messages in thread

* bug#49980: 28.0.50; [PATCH] Should we have project-save-buffers?
  2021-08-16  0:37               ` Dmitry Gutov
@ 2021-08-16  1:19                 ` Arthur Miller
  2021-08-16  3:06                   ` Dmitry Gutov
  0 siblings, 1 reply; 22+ messages in thread
From: Arthur Miller @ 2021-08-16  1:19 UTC (permalink / raw)
  To: Dmitry Gutov; +Cc: Giap Tran, 49980, Juri Linkov

Dmitry Gutov <dgutov@yandex.ru> writes:

> On 14.08.2021 05:46, Arthur Miller wrote:
>> It is ~200 sloc and most
>> of it is helm boiler code, I am really interesting about opinion on
>> stash/unstash strategy. I stash everything include untracked
>> files.
>
> Speaking of strategy, that sounds like something I routinely do by hand,
> so... it seems fine?
>
> Though I usually keep unregistered files alone, because those can be both
> related to the current work I'm doing, or totally unrelated and be, for example,
> some new project settings I haven't checked in (and perhaps never intend to).

And as Oscar F. wrote in another thread, can lead to many gigabytes of
data stashed away.

Yes, I agree, I stash with -u by default, but I do have var to turn it
off.

What do you think about checking out, between multiple different
branches? Switching two branches back and forth is no brainer, it should
always work fine, but switching multiple branches can lead to mess since
stashes are applied automatically. Any good strategy to automate this
case?

Honestly, I don't see much difference than doing it manually, but I am a
bit affraid of auto applying stashes.






^ permalink raw reply	[flat|nested] 22+ messages in thread

* bug#49980: 28.0.50; [PATCH] Should we have project-save-buffers?
  2021-08-16  1:19                 ` Arthur Miller
@ 2021-08-16  3:06                   ` Dmitry Gutov
  2021-08-16 13:22                     ` Arthur Miller
  0 siblings, 1 reply; 22+ messages in thread
From: Dmitry Gutov @ 2021-08-16  3:06 UTC (permalink / raw)
  To: Arthur Miller; +Cc: Giap Tran, 49980, Juri Linkov

On 16.08.2021 04:19, Arthur Miller wrote:
> What do you think about checking out, between multiple different
> branches? Switching two branches back and forth is no brainer, it should
> always work fine, but switching multiple branches can lead to mess since
> stashes are applied automatically. Any good strategy to automate this
> case?

I don't know. You're automating a case I have been handling manually 
(and hadn't been bothered by that, thus far).

You will most likely encounter some edge cases where the automation 
breaks, but it's hard to predict those in advance.

> Honestly, I don't see much difference than doing it manually, but I am a
> bit affraid of auto applying stashes.

As long as they're named ones (and thus you won't miss and accidentally 
pop an unrelated one), this should work fine.





^ permalink raw reply	[flat|nested] 22+ messages in thread

* bug#49980: 28.0.50; [PATCH] Should we have project-save-buffers?
  2021-08-16  3:06                   ` Dmitry Gutov
@ 2021-08-16 13:22                     ` Arthur Miller
  0 siblings, 0 replies; 22+ messages in thread
From: Arthur Miller @ 2021-08-16 13:22 UTC (permalink / raw)
  To: Dmitry Gutov; +Cc: Giap Tran, 49980, Juri Linkov

Dmitry Gutov <dgutov@yandex.ru> writes:

> On 16.08.2021 04:19, Arthur Miller wrote:
>> What do you think about checking out, between multiple different
>> branches? Switching two branches back and forth is no brainer, it should
>> always work fine, but switching multiple branches can lead to mess since
>> stashes are applied automatically. Any good strategy to automate this
>> case?
>
> I don't know. You're automating a case I have been handling manually (and hadn't
> been bothered by that, thus far).
>
> You will most likely encounter some edge cases where the automation breaks, but
> it's hard to predict those in advance.
>
>> Honestly, I don't see much difference than doing it manually, but I am a
>> bit affraid of auto applying stashes.
>
> As long as they're named ones (and thus you won't miss and accidentally pop an
> unrelated one), this should work fine.

Yes, they are named ones. I am trying to think out what could get
messed, but since everything is stashed away on every checkout, so I
don't think it should be more dangerous than doing it manually. Don't
time will tell me, I am using this myself, so I guess I'll notice.

thanks for the feedback





^ permalink raw reply	[flat|nested] 22+ messages in thread

end of thread, other threads:[~2021-08-16 13:22 UTC | newest]

Thread overview: 22+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2021-08-10  9:23 bug#49980: 28.0.50; [PATCH] Should we have project-save-buffers? Giap Tran
2021-08-11  6:52 ` Juri Linkov
2021-08-11  7:38   ` Giap Tran
2021-08-11 12:23   ` Dmitry Gutov
2021-08-12  7:55     ` Juri Linkov
2021-08-13  2:06       ` Dmitry Gutov
2021-08-13  7:12         ` Juri Linkov
2021-08-13  9:39         ` Arthur Miller
2021-08-13 16:05           ` Juri Linkov
2021-08-13 17:22             ` Arthur Miller
2021-08-14  2:25             ` Arthur Miller
2021-08-15  8:32               ` Juri Linkov
2021-08-15 10:44                 ` Arthur Miller
2021-08-13 23:54           ` Dmitry Gutov
2021-08-14  2:46             ` Arthur Miller
2021-08-16  0:37               ` Dmitry Gutov
2021-08-16  1:19                 ` Arthur Miller
2021-08-16  3:06                   ` Dmitry Gutov
2021-08-16 13:22                     ` Arthur Miller
2021-08-11 12:22 ` Dmitry Gutov
2021-08-11 13:40   ` Giap Tran
2021-08-13  2:11     ` Dmitry Gutov

Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).