From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.io!.POSTED.blaine.gmane.org!not-for-mail From: Arthur Miller Newsgroups: gmane.emacs.devel Subject: Re: On the adoption of transient.el Date: Mon, 16 Aug 2021 03:05:37 +0200 Message-ID: References: <877di4on3d.fsf@posteo.net> <87im1oy6mw.fsf@posteo.net> <87czquisme.fsf@bernoul.li> <87wnoofapr.fsf@telefonica.net> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="=-=-=" Injection-Info: ciao.gmane.io; posting-host="blaine.gmane.org:116.202.254.214"; logging-data="25711"; mail-complaints-to="usenet@ciao.gmane.io" User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/28.0.50 (gnu/linux) Cc: =?utf-8?Q?=C3=93scar?= Fuentes , Emacs developers To: John Yates Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane-mx.org@gnu.org Mon Aug 16 03:07:17 2021 Return-path: Envelope-to: ged-emacs-devel@m.gmane-mx.org Original-Received: from lists.gnu.org ([209.51.188.17]) by ciao.gmane.io with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1mFR5w-0006T0-3z for ged-emacs-devel@m.gmane-mx.org; Mon, 16 Aug 2021 03:07:17 +0200 Original-Received: from localhost ([::1]:52472 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mFR5u-0005Ke-3H for ged-emacs-devel@m.gmane-mx.org; Sun, 15 Aug 2021 21:07:14 -0400 Original-Received: from eggs.gnu.org ([2001:470:142:3::10]:48490) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1mFR4W-0004eg-Cg for emacs-devel@gnu.org; Sun, 15 Aug 2021 21:05:48 -0400 Original-Received: from mail-am7eur06olkn2091.outbound.protection.outlook.com ([40.92.16.91]:4048 helo=EUR06-AM7-obe.outbound.protection.outlook.com) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1mFR4R-0003qU-2t for emacs-devel@gnu.org; Sun, 15 Aug 2021 21:05:48 -0400 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=WmyW60HkKwYhr+RGaU9EOG5i1sARxb28Dgq7KWBT9pMRlNIpzvfpata6dYiFlB5IZdtm58HRqUNFO7iFWx/GvRvcJ7aG0wcl+szIWhBjoWXw2dfibgxUrzY40zv3LJuu8Q741JaRBroMxzp/FVVPlIJJjpFkynVsh5GX5wMwjNsHE9W+6bAmdzVyhGYasleXFFuO3OVYhBxJ2knAwiC77MOE7TV8nuMVd9yBlnHxAGbscXUxnjOQe3kv5ezZtSUx9qstjIgH90FhoWLp1zwbP9G0OT+w67jAUXoqZIu5VwhiQCYk8xtomnZH3uvFF3lkOB4UIOsqkHRgGzGNMUNFkw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=wQHcHKxbTD+RJUKlABuBGYfl8o8cfxtZCVVgR3bKuX0=; b=JTfY1tLstv8APdDD5GaOEL0ES8RI+6MEjiI0FuTaZ/nhcqS38MvkGEqhQlGT2mt+C5NL/5VL8GqSNOPoK3BmwXyu4mBLRBXFVGn6cqrzsBVVljhoSsNlOAtfoSClSnKNSQzLBLxKEZESgD7SkJsTXPamzUTSJ1wJp+rcoxnuFuPBa5GI9YZjUPvoluwkK1HtbkEp1dd7hGZR3/a7NkyD0EwYPPGZdxRIut2isXKIXjreYxIw14RDBcZXItA//Gd8DkAytpeZz2MSFHCYkKvLGr827hLRhroIfV2ylRHcUAQHZFhC53BE7hqEYxn4bC8TZfIVqfXOqHUNvKA2ySY/Lw== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=none; dmarc=none; dkim=none; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=live.com; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=wQHcHKxbTD+RJUKlABuBGYfl8o8cfxtZCVVgR3bKuX0=; b=dotk0GMNvRYuSzn3XJNSVxgn+fGOZy+ysf9WAs0O0cuNb92egJoyrf+SmnP2gC+YJPUJ2bKmiY1SHNd/OgtPxYvbrmePO8RoP6GY5N//cfKGqKha0arCzrDFsjC0LsJEr9dQrTQDB7NmBDyz8F4P4i3i0sYDdfTgPO+6zsj7I6qxCGFaOlb+kNj+vo+OCv0VnbfvnlUOv9BFtx31lQ1LPtI/LOmwC9rwwNmfoCXVgh0Lnt+3fsJdqNW5UQSPFGNMrXq0jSb1PckaB43g1CBYMeAsp2BHXGxsggtqw4mtLju1DJBssQo/3VifVB/EGKfRWUMoLG3j6DRAz3uwmxzcIw== Original-Received: from VI1EUR06FT023.eop-eur06.prod.protection.outlook.com (2a01:111:e400:fc37::41) by VI1EUR06HT210.eop-eur06.prod.protection.outlook.com (2a01:111:e400:fc37::305) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.4415.16; Mon, 16 Aug 2021 01:05:39 +0000 Original-Received: from AM9PR09MB4977.eurprd09.prod.outlook.com (2a01:111:e400:fc37::40) by VI1EUR06FT023.mail.protection.outlook.com (2a01:111:e400:fc37::205) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.4415.16 via Frontend Transport; Mon, 16 Aug 2021 01:05:39 +0000 X-IncomingTopHeaderMarker: OriginalChecksum:DA39E34450EB7699A30FD94E3A79B142C4099D12C119BDEAFFBEC3EB5AC96873; UpperCasedChecksum:319EC91A866AFA30C86C6EE24366AEFA220A5B553D3AD2A5FC0197AC0CED401B; SizeAsReceived:9125; Count:46 Original-Received: from AM9PR09MB4977.eurprd09.prod.outlook.com ([fe80::6558:f201:6d1a:3f39]) by AM9PR09MB4977.eurprd09.prod.outlook.com ([fe80::6558:f201:6d1a:3f39%2]) with mapi id 15.20.4415.023; Mon, 16 Aug 2021 01:05:39 +0000 In-Reply-To: (John Yates's message of "Sun, 15 Aug 2021 17:57:27 -0400") X-TMN: [dLNnLpb91WJkw6Fm6z7k/S3VSL6GRvFu] X-ClientProxiedBy: BEXP281CA0017.DEUP281.PROD.OUTLOOK.COM (2603:10a6:b10::27) To AM9PR09MB4977.eurprd09.prod.outlook.com (2603:10a6:20b:304::20) X-Microsoft-Original-Message-ID: <875yw6jj1a.fsf@live.com> X-MS-Exchange-MessageSentRepresentingType: 1 Original-Received: from pascal.homepc (81.232.177.30) by BEXP281CA0017.DEUP281.PROD.OUTLOOK.COM (2603:10a6:b10::27) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.4436.8 via Frontend Transport; Mon, 16 Aug 2021 01:05:38 +0000 X-MS-PublicTrafficType: Email X-IncomingHeaderCount: 46 X-EOPAttributedMessage: 0 X-MS-Office365-Filtering-Correlation-Id: ff2b6ebf-4a42-4f14-6ec3-08d96051f62d X-MS-TrafficTypeDiagnostic: VI1EUR06HT210: X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: tLQ1dXXVD04UyssbWjyuQxTmZVJFTYFefuabddPCEfstebON8nP96BYL64K2HN4YB1PWbcOpONcXSADv8gQhsHweEQ4G3BZT4T+7eql0XNQGxaRST6iV3LftTTzr2aQv2V1+TTsm/gTJTizOhcUUF87cFojI/03JbnI6EgG5v2btdit604/SQGc9OkrfD4FIuq9Ey0DuTbL+hpsJoA1LgLiaD7DnE3p/Z9Y8Vj394OVemQ+fZ32dxAxD6UO2zIdMdSXDpZq49ipdfyOE2GXACSSgYRjkdV6pLTf0PKtmjjUjzPW3vmAv+1TALHUITV6mrqA+/sckrsgKpeCEY8zSn7dOaxB2As/1soME+WPlVvrPd6vrqaswcbVSp/pePlcAK6zJyArXUcEtt3Ug5HA6Urr7M0HOns5TAKcGE9HMoXFoikRlGtuYMVNl7XM6A7GxZKJbukQ5mShmvAXApWFcgz+bN4Jm17kgLZtUWulAI8U= X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: UQseeC/Wf/FmENc0326Ogh3mCii1Q7fCc15OxS/uX5q0qZjDnWr36WrQnrFMLXiHZJ3cqE0G9+v7P46fc43HgWh3mXVXjLM4Us997b2JdFNXxbGYElJgEnpvrVcfwhL3t91yxN0SFJukPp2L3hIJzA== X-OriginatorOrg: live.com X-MS-Exchange-CrossTenant-Network-Message-Id: ff2b6ebf-4a42-4f14-6ec3-08d96051f62d X-MS-Exchange-CrossTenant-OriginalArrivalTime: 16 Aug 2021 01:05:39.1442 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 84df9e7f-e9f6-40af-b435-aaaaaaaaaaaa X-MS-Exchange-CrossTenant-AuthSource: VI1EUR06FT023.eop-eur06.prod.protection.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: Internet X-MS-Exchange-CrossTenant-RMS-PersistedConsumerOrg: 00000000-0000-0000-0000-000000000000 X-MS-Exchange-Transport-CrossTenantHeadersStamped: VI1EUR06HT210 Received-SPF: pass client-ip=40.92.16.91; envelope-from=arthur.miller@live.com; helo=EUR06-AM7-obe.outbound.protection.outlook.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FROM=0.001, MSGID_FROM_MTA_HEADER=0.001, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H2=-0.001, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: "Emacs development discussions." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: emacs-devel-bounces+ged-emacs-devel=m.gmane-mx.org@gnu.org Original-Sender: "Emacs-devel" Xref: news.gmane.io gmane.emacs.devel:272420 Archived-At: --=-=-= Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable John Yates writes: > On Sat, Aug 14, 2021 at 8:55 AM =C3=93scar Fuentes wrote= : >> Arthur Miller writes: >> > The strategy is to stash save all buffers belonging to the project, >> > stash everything, inclusive untracked files, and than checkout to the >> > other branch. When checked back, the stash is applied back. I don't kn= ow >> > if you have something like that in magit or if it is something general= ly >> > desirable, but I always wanted something simple and dirty to be able t= o >> > switch fast when I need it. >> >> How would Magit know that when you "return back" to a branch it must >> apply a certain stash? > > Rather than use a stash I would have a script that does two things: > * Creates an undo script for the next step > * Saves everything important as a new commit on the current branch. > This would include, among other things, all untracked files and the > undo script mentioned in the first step. I had thoughts of implementing commit strategy too :-). I even have prepared a variable that I have planned to use for this. My motivation was mostly to see if it is somewhat faster than stashing and reaplying changes, but I haven't really got to that yet. After more thoughts I am also not sure if that would be any better than stash to be honest. Stashes are meant for something like this, and it is a normal strategy people use. Can you give me some reason why would it be better to commit changes instead of stashing away them? When it comes to tracked/untracked files, I do have from the beginning a variable to switch what is stashed away. I agree with what you wrote in your last replay, that it is not always desirable to stash untracked files. I was just not in the mood for explaining in details what I am doing, so I wrote just very short notice to not use this strategy :). > Now with the workspace in a clean state you can switch away to some Isn't that what stashing away also does? > other branch. When you return to the original branch you run the undo > script. It backs out the last commit. This would included performing > > git rm --cached I do delete the stash after applying it. Pop can't be reliably used in an automated script like this, so I apply the specially named stash and than throw it away, which si similar to pop. > * Creates an undo script for the next step The undo script would be an interesting addition indeed. I am not sure if we think of same thing, but what I am doing is saving all open and modified file buffers belonging to git root and subfolders, before I do stashing. What would be nice, is to undo saved changes in buffers that were modified, so that they appear as modified after checking out old branch again. Currently they are just saved, so when they are checked out again, they don't appear as modified again. I am not sure where to look to implement something like that, is there some variable in buffer I can check for modifications sine last save, so I could use it to save some state somewhere? Thanks you for the comment, this was constructive. If you are interested to take a look I have attached the code, and the poject is here with some additional info in readme: https://github.com/amno1/helm-git-branch --=-=-= Content-Type: text/plain Content-Disposition: attachment; filename=helm-git-branch.el ;;; helm-git-branch.el --- Switch git branch with Helm interface. -*- lexical-binding: t; -*- ;; Copyright (C) 2021 Arthur Miller ;; Author: Arthur Miller ;; 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 . ;;; 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 (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) (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)) ;;; 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)) (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)) (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 (lambda () (file-in-directory-p default-directory (helm-ls-git-root-dir))))) (when (helm-git-branch--dirty-p) (helm-git-branch--stash)) (insert (call-process "git" nil t nil "checkout" branch)) (helm-git-branch--unstash)))))) ;;; 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 --=-=-=--