{"thread":{"id":"7257","subject":"git emacs mode patch","startedAt":"2007-03-15T13:03:56Z","lastAt":"2007-03-26T10:02:29Z","messageCount":4,"participants":["Gábor Melis","Alexandre Julliard"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"37162","messageId":"200703151403.56552.mega@retes.hu","threadId":"7257","inReplyTo":null,"subject":"git emacs mode patch","fromName":"Gábor Melis","fromEmail":"mega@retes.hu","sentAt":"2007-03-15T13:03:56Z","receivedAt":"2007-03-15T13:03:56Z","isPatch":false,"sender":{"key":"mega@retes.hu","avatar":null},"body":"The attached patch makes it possible to toggle show/hide of files with \nup-to-date and unknown statuses with M-d and M-u.\n\nCheers,\nGábor Melis\n\nPlease CC me, I'm not on the list.\n\n\ndiff --git a/contrib/emacs/git.el b/contrib/emacs/git.el\nindex db87a37..2f993de 100644\n--- a/contrib/emacs/git.el\n+++ b/contrib/emacs/git.el\n@@ -97,6 +97,16 @@ if there is already one that displays the same directory.\"\n   :group 'git\n   :type 'string)\n \n+(defcustom git-hide-up-to-date t\n+  \"Hide files with up-to-date status by default.\"\n+  :group 'git\n+  :type 'boolean)\n+\n+(defcustom git-hide-unknown t\n+  \"Hide files with unknown status by default.\"\n+  :group 'git\n+  :type 'boolean)\n+\n \n (defface git-status-face\n   '((((class color) (background light)) (:foreground \"purple\")))\n@@ -428,6 +438,7 @@ and returns the process output as a string.\"\n     (?A 'added)\n     (?D 'deleted)\n     (?U 'unmerged)\n+    (?H 'uptodate)\n     (t nil)))\n \n (defun git-status-code-as-string (code)\n@@ -1017,15 +1028,18 @@ and returns the process output as a string.\"\n       (with-temp-buffer\n         (git-run-command t nil \"diff-index\" \"-z\" \"-M\" \"HEAD\")\n         (git-parse-status status)))\n+    (unless (member 'up-to-date hidden-statuses)\n       (with-temp-buffer\n-        (git-run-command t nil \"ls-files\" \"-z\" \"-u\")\n-        (git-parse-ls-unmerged status))\n+        (git-run-command t nil \"ls-files\" \"-z\" \"-t\")\n+        (git-parse-ls-files status 'unknown)))\n+    (unless (member 'unknown hidden-statuses)\n       (when (file-readable-p \".git/info/exclude\")\n         (with-temp-buffer\n           (git-run-command t nil \"ls-files\" \"-z\" \"-t\" \"-o\"\n                            \"--exclude-from=.git/info/exclude\"\n-                           (concat \"--exclude-per-directory=\" git-per-dir-ignore-file))\n-          (git-parse-ls-files status 'unknown)))\n+                           (concat \"--exclude-per-directory=\"\n+                                   git-per-dir-ignore-file))\n+          (git-parse-ls-files status 'unknown))))\n     (git-refresh-files)\n     (git-refresh-ewoc-hf status)\n     ; move point to the current file name if any\n@@ -1080,6 +1094,8 @@ and returns the process output as a string.\"\n     (define-key map \"U\"   'git-revert-file)\n     (define-key map \"v\"   'git-view-file)\n     (define-key map \"x\"   'git-remove-handled)\n+    (define-key map \"\\M-d\" 'git-toggle-up-to-date)\n+    (define-key map \"\\M-u\" 'git-toggle-unknown)\n     (define-key map \"\\C-?\" 'git-unmark-file-up)\n     (define-key map \"\\M-\\C-?\" 'git-unmark-all)\n     ; the diff submap\n@@ -1093,6 +1109,20 @@ and returns the process output as a string.\"\n     (define-key diff-map \"o\" 'git-diff-file-other)\n     (setq git-status-mode-map map)))\n \n+(defun git-toggle-up-to-date ()\n+  (interactive)\n+  (if (member 'up-to-date hidden-statuses)\n+      (setq hidden-statuses (remove 'up-to-date hidden-statuses))\n+    (push 'up-to-date hidden-statuses))\n+  (git-refresh-status))\n+\n+(defun git-toggle-unknown ()\n+  (interactive)\n+  (if (member 'unknown hidden-statuses)\n+      (setq hidden-statuses (remove 'unknown hidden-statuses))\n+    (push 'unknown hidden-statuses))\n+  (git-refresh-status))\n+\n ;; git mode should only run in the *git status* buffer\n (put 'git-status-mode 'mode-class 'special)\n \n@@ -1112,6 +1142,11 @@ Commands:\n   (let ((status (ewoc-create 'git-fileinfo-prettyprint \"\" \"\")))\n     (set (make-local-variable 'git-status) status))\n   (set (make-local-variable 'list-buffers-directory) default-directory)\n+  (set (make-local-variable 'hidden-statuses) ())\n+  (when git-hide-up-to-date\n+    (push 'up-to-date hidden-statuses))\n+  (when git-hide-unknown\n+    (push 'unknown hidden-statuses))\n   (run-hooks 'git-status-mode-hook)))\n \n (defun git-find-status-buffer (dir)\n"},{"id":"37307","messageId":"87y7lwxk2e.fsf@wine.dyndns.org","threadId":"7257","inReplyTo":"200703151403.56552.mega@retes.hu","subject":"Re: git emacs mode patch","fromName":"Alexandre Julliard","fromEmail":"julliard@winehq.org","sentAt":"2007-03-17T10:04:25Z","receivedAt":"2007-03-17T10:04:25Z","isPatch":false,"sender":{"key":"julliard@winehq.org","avatar":null},"body":"Gábor Melis <mega@retes.hu> writes:\n\n> +(defcustom git-hide-unknown t\n> +  \"Hide files with unknown status by default.\"\n> +  :group 'git\n> +  :type 'boolean)\n\nThis one should default to nil for backwards compatibility.\n\n> @@ -1017,15 +1028,18 @@ and returns the process output as a string.\"\n>        (with-temp-buffer\n>          (git-run-command t nil \"diff-index\" \"-z\" \"-M\" \"HEAD\")\n>          (git-parse-status status)))\n> +    (unless (member 'up-to-date hidden-statuses)\n>        (with-temp-buffer\n> -        (git-run-command t nil \"ls-files\" \"-z\" \"-u\")\n> -        (git-parse-ls-unmerged status))\n> +        (git-run-command t nil \"ls-files\" \"-z\" \"-t\")\n> +        (git-parse-ls-files status 'unknown)))\n> +    (unless (member 'unknown hidden-statuses)\n\nWhy are you removing the ls-files -u?  This will break the detection\nof unmerged files.\n\n> +(defun git-toggle-up-to-date ()\n> +  (interactive)\n> +  (if (member 'up-to-date hidden-statuses)\n> +      (setq hidden-statuses (remove 'up-to-date hidden-statuses))\n> +    (push 'up-to-date hidden-statuses))\n\nThe status should be named 'uptodate instead of 'up-to-date since\nthat's what's used for individual files. Having two different\nspellings for the same word would be very confusing.\n\n-- \nAlexandre Julliard\njulliard@winehq.org\n"},{"id":"38016","messageId":"200703251903.15333.mega@retes.hu","threadId":"7257","inReplyTo":"87y7lwxk2e.fsf@wine.dyndns.org","subject":"Re: git emacs mode patch","fromName":"Gábor Melis","fromEmail":"mega@retes.hu","sentAt":"2007-03-25T17:03:15Z","receivedAt":"2007-03-25T17:03:15Z","isPatch":false,"sender":{"key":"mega@retes.hu","avatar":null},"body":"On Saturday 17 March 2007 11:04, Alexandre Julliard wrote:\n> Gábor Melis <mega@retes.hu> writes:\n> > +(defcustom git-hide-unknown t\n> > +  \"Hide files with unknown status by default.\"\n> > +  :group 'git\n> > +  :type 'boolean)\n>\n> This one should default to nil for backwards compatibility.\n>\n> > @@ -1017,15 +1028,18 @@ and returns the process output as a\n> > string.\" (with-temp-buffer\n> >          (git-run-command t nil \"diff-index\" \"-z\" \"-M\" \"HEAD\")\n> >          (git-parse-status status)))\n> > +    (unless (member 'up-to-date hidden-statuses)\n> >        (with-temp-buffer\n> > -        (git-run-command t nil \"ls-files\" \"-z\" \"-u\")\n> > -        (git-parse-ls-unmerged status))\n> > +        (git-run-command t nil \"ls-files\" \"-z\" \"-t\")\n> > +        (git-parse-ls-files status 'unknown)))\n> > +    (unless (member 'unknown hidden-statuses)\n>\n> Why are you removing the ls-files -u?  This will break the detection\n> of unmerged files.\n>\n> > +(defun git-toggle-up-to-date ()\n> > +  (interactive)\n> > +  (if (member 'up-to-date hidden-statuses)\n> > +      (setq hidden-statuses (remove 'up-to-date hidden-statuses))\n> > +    (push 'up-to-date hidden-statuses))\n>\n> The status should be named 'uptodate instead of 'up-to-date since\n> that's what's used for individual files. Having two different\n> spellings for the same word would be very confusing.\n\nAttached updated patch that adresses these valid objections and only \nlists files once.\n\nGábor\n\n\ndiff --git a/contrib/emacs/git.el b/contrib/emacs/git.el\nindex 5f22dec..72d41bd 100644\n--- a/contrib/emacs/git.el\n+++ b/contrib/emacs/git.el\n@@ -97,6 +97,16 @@ if there is already one that displays the same directory.\"\n   :group 'git\n   :type 'string)\n \n+(defcustom git-hide-uptodate t\n+  \"Hide files with up-to-date status by default.\"\n+  :group 'git\n+  :type 'boolean)\n+\n+(defcustom git-hide-unknown nil\n+  \"Hide files with unknown status by default.\"\n+  :group 'git\n+  :type 'boolean)\n+\n \n (defface git-status-face\n   '((((class color) (background light)) (:foreground \"purple\")))\n@@ -437,6 +447,7 @@ and returns the process output as a string.\"\n       (setf (git-fileinfo->orig-name info) nil)\n       (setf (git-fileinfo->needs-refresh info) t))))\n \n+;;; This is an unholy mix of git-ls-files and git-diff-index state codes.\n (defun git-state-code (code)\n   \"Convert from a string to a added/deleted/modified state.\"\n   (case (string-to-char code)\n@@ -445,6 +456,7 @@ and returns the process output as a string.\"\n     (?A 'added)\n     (?D 'deleted)\n     (?U 'unmerged)\n+    (?H 'uptodate)\n     (t nil)))\n \n (defun git-status-code-as-string (code)\n@@ -515,15 +527,21 @@ and returns the process output as a string.\"\n       (setq node (ewoc-next status node)))\n     node))\n \n-(defun git-parse-ls-files (status default-state &optional skip-existing)\n+(defun git-parse-ls-files (status &optional default-state skip-existing)\n   \"Parse the output of git-ls-files in the current buffer.\"\n   (goto-char (point-min))\n   (let (infolist)\n     (while (re-search-forward \"\\\\([HMRCK?]\\\\) \\\\([^\\0]*\\\\)\\0\" nil t 1)\n-      (let ((state (match-string 1))\n-            (name (match-string 2)))\n-        (unless (and skip-existing (git-find-status-file status name))\n-          (push (git-create-fileinfo (or (git-state-code state) default-state) name) infolist))))\n+      (let* ((state (or default-state\n+                        (git-state-code (match-string 1))))\n+             (name (match-string 2))\n+             (node (git-find-status-file status name)))\n+        (if skip-existing\n+            (unless node\n+              (push (git-create-fileinfo state name) infolist))\n+          (if node\n+              (git-set-files-state (list (ewoc-data node)) state)\n+            (push (git-create-fileinfo state name) infolist)))))\n     (dolist (info (nreverse infolist))\n       (ewoc-enter-last status info))))\n \n@@ -1043,25 +1061,31 @@ and returns the process output as a string.\"\n     (git-clear-status status)\n     (git-run-command nil nil \"update-index\" \"--info-only\" \"--refresh\")\n     (if (git-empty-db-p)\n-        ; we need some special handling for an empty db\n+        ;; we need some special handling for an empty db\n         (with-temp-buffer\n           (git-run-command t nil \"ls-files\" \"-z\" \"-t\" \"-c\")\n           (git-parse-ls-files status 'added))\n       (with-temp-buffer\n         (git-run-command t nil \"diff-index\" \"-z\" \"-M\" \"HEAD\")\n         (git-parse-status status)))\n+    (with-temp-buffer\n+      (git-run-command t nil \"ls-files\" \"-z\" \"-u\")\n+      (git-parse-ls-unmerged status))\n+    (unless (member 'uptodate hidden-statuses)\n       (with-temp-buffer\n-        (git-run-command t nil \"ls-files\" \"-z\" \"-u\")\n-        (git-parse-ls-unmerged status))\n+        (git-run-command t nil \"ls-files\" \"-z\" \"-t\" \"-c\")\n+        (git-parse-ls-files status nil t)))\n+    (unless (member 'unknown hidden-statuses)\n       (when (file-readable-p \".git/info/exclude\")\n         (with-temp-buffer\n           (git-run-command t nil \"ls-files\" \"-z\" \"-t\" \"-o\"\n                            \"--exclude-from=.git/info/exclude\"\n-                           (concat \"--exclude-per-directory=\" git-per-dir-ignore-file))\n-          (git-parse-ls-files status 'unknown)))\n+                           (concat \"--exclude-per-directory=\"\n+                                   git-per-dir-ignore-file))\n+          (git-parse-ls-files status nil t))))\n     (git-refresh-files)\n     (git-refresh-ewoc-hf status)\n-    ; move point to the current file name if any\n+    ;; move point to the current file name if any\n     (let ((node (and cur-name (git-find-status-file status cur-name))))\n       (when node (ewoc-goto-node status node)))))\n \n@@ -1113,6 +1137,8 @@ and returns the process output as a string.\"\n     (define-key map \"U\"   'git-revert-file)\n     (define-key map \"v\"   'git-view-file)\n     (define-key map \"x\"   'git-remove-handled)\n+    (define-key map \"\\M-u\" 'git-toggle-uptodate)\n+    (define-key map \"\\M-k\" 'git-toggle-unknown)\n     (define-key map \"\\C-?\" 'git-unmark-file-up)\n     (define-key map \"\\M-\\C-?\" 'git-unmark-all)\n     ; the diff submap\n@@ -1126,6 +1152,20 @@ and returns the process output as a string.\"\n     (define-key diff-map \"o\" 'git-diff-file-other)\n     (setq git-status-mode-map map)))\n \n+(defun git-toggle-uptodate ()\n+  (interactive)\n+  (if (member 'uptodate hidden-statuses)\n+      (setq hidden-statuses (remove 'uptodate hidden-statuses))\n+    (push 'uptodate hidden-statuses))\n+  (git-refresh-status))\n+\n+(defun git-toggle-unknown ()\n+  (interactive)\n+  (if (member 'unknown hidden-statuses)\n+      (setq hidden-statuses (remove 'unknown hidden-statuses))\n+    (push 'unknown hidden-statuses))\n+  (git-refresh-status))\n+\n ;; git mode should only run in the *git status* buffer\n (put 'git-status-mode 'mode-class 'special)\n \n@@ -1145,6 +1185,11 @@ Commands:\n   (let ((status (ewoc-create 'git-fileinfo-prettyprint \"\" \"\")))\n     (set (make-local-variable 'git-status) status))\n   (set (make-local-variable 'list-buffers-directory) default-directory)\n+  (set (make-local-variable 'hidden-statuses) ())\n+  (when git-hide-uptodate\n+    (push 'uptodate hidden-statuses))\n+  (when git-hide-unknown\n+    (push 'unknown hidden-statuses))\n   (run-hooks 'git-status-mode-hook)))\n \n (defun git-find-status-buffer (dir)\n"},{"id":"38021","messageId":"878xdk491m.fsf@wine.dyndns.org","threadId":"7257","inReplyTo":"200703251903.15333.mega@retes.hu","subject":"Re: git emacs mode patch","fromName":"Alexandre Julliard","fromEmail":"julliard@winehq.org","sentAt":"2007-03-26T10:02:29Z","receivedAt":"2007-03-26T10:02:29Z","isPatch":false,"sender":{"key":"julliard@winehq.org","avatar":null},"body":"Gábor Melis <mega@retes.hu> writes:\n\n> @@ -515,15 +527,21 @@ and returns the process output as a string.\"\n>        (setq node (ewoc-next status node)))\n>      node))\n>  \n> -(defun git-parse-ls-files (status default-state &optional skip-existing)\n> +(defun git-parse-ls-files (status &optional default-state skip-existing)\n>    \"Parse the output of git-ls-files in the current buffer.\"\n>    (goto-char (point-min))\n>    (let (infolist)\n>      (while (re-search-forward \"\\\\([HMRCK?]\\\\) \\\\([^\\0]*\\\\)\\0\" nil t 1)\n> -      (let ((state (match-string 1))\n> -            (name (match-string 2)))\n> -        (unless (and skip-existing (git-find-status-file status name))\n> -          (push (git-create-fileinfo (or (git-state-code state) default-state) name) infolist))))\n> +      (let* ((state (or default-state\n> +                        (git-state-code (match-string 1))))\n> +             (name (match-string 2))\n> +             (node (git-find-status-file status name)))\n> +        (if skip-existing\n> +            (unless node\n> +              (push (git-create-fileinfo state name) infolist))\n> +          (if node\n> +              (git-set-files-state (list (ewoc-data node)) state)\n> +            (push (git-create-fileinfo state name) infolist)))))\n\nYou don't want to do a git-find-status-file in all cases, this is\nO(n^2) and becomes much too slow on a large project. That's the reason\nthere's a skip-existing flag, to avoid that cost in the common case.\n\n-- \nAlexandre Julliard\njulliard@winehq.org\n"}]}