Emacs mode: Improve the output buffer state
[stgit] / contrib / stgit.el
index cce0c0e..82f0d38 100644 (file)
@@ -41,13 +41,20 @@ Argument DIR is the repository path."
 
 (defmacro stgit-capture-output (name &rest body)
   "Capture StGit output and show it in a window at the end"
-  `(let ((output-buf (get-buffer-create ,(or name "*StGit output*"))))
+  `(let ((output-buf (get-buffer-create ,(or name "*StGit output*")))
+         (stgit-dir default-directory)
+         (inhibit-read-only t))
      (with-current-buffer output-buf
-       (erase-buffer))
+       (erase-buffer)
+       (setq default-directory stgit-dir)
+       (setq buffer-read-only t))
      (let ((standard-output output-buf))
        ,@body)
-     (if (with-current-buffer output-buf (< (point-min) (point-max)))
-         (display-buffer output-buf t))))
+     (with-current-buffer output-buf
+       (set-buffer-modified-p nil)
+       (setq buffer-read-only t)
+       (if (< (point-min) (point-max))
+           (display-buffer output-buf t)))))
 (put 'stgit-capture-output 'lisp-indent-function 1)
 
 (defun stgit-run (&rest args)
@@ -62,7 +69,7 @@ Argument DIR is the repository path."
     (erase-buffer)
     (insert "Branch: ")
     (stgit-run "branch")
-    (stgit-run "series")
+    (stgit-run "series" "--description")
     (if curpatch
         (stgit-goto-patch curpatch)
       (goto-line curline))))
@@ -81,7 +88,9 @@ Argument DIR is the repository path."
   (define-key stgit-mode-map "g"   'stgit-refresh)
   (define-key stgit-mode-map "r"   'stgit-rename)
   (define-key stgit-mode-map ">"   'stgit-push-next)
-  (define-key stgit-mode-map "<"   'stgit-pop)
+  (define-key stgit-mode-map "<"   'stgit-pop-next)
+  (define-key stgit-mode-map "P"   'stgit-push-or-pop)
+  (define-key stgit-mode-map "G"   'stgit-goto)
   (define-key stgit-mode-map "="   'stgit-show))
 
 (defun stgit-mode ()
@@ -95,13 +104,14 @@ Commands:
         goal-column 2)
   (use-local-map stgit-mode-map)
   (set (make-local-variable 'list-buffers-directory) default-directory)
+  (set-variable 'truncate-lines 't)
   (run-hooks 'stgit-mode-hook))
 
 (defun stgit-patch-at-point ()
   "Return the patch name on the current line"
   (save-excursion
     (beginning-of-line)
-    (if (looking-at "[>+-] \\(.*\\)")
+    (if (looking-at "[>+-] \\([^ ]*\\)")
         (match-string 1)
       nil)))
 
@@ -109,7 +119,7 @@ Commands:
   "Move point to the line containing PATCH"
   (let ((p (point)))
     (goto-char (point-min))
-    (if (re-search-forward (concat "[>+-] " (regexp-quote patch) "$") nil t)
+    (if (re-search-forward (concat "[>+-] " (regexp-quote patch) " ") nil t)
         (progn (move-to-column goal-column)
                t)
       (goto-char p)
@@ -127,22 +137,39 @@ Commands:
     (stgit-goto-patch name)))
 
 (defun stgit-push-next ()
-  "Push the patch on the line after pos"
+  "Push the first unapplied patch"
   (interactive)
-  (forward-line 1)
-  (let ((patch (stgit-patch-at-point)))
+  (stgit-capture-output nil (stgit-run "push"))
+  (stgit-refresh))
+
+(defun stgit-pop-next ()
+  "Pop the topmost applied patch"
+  (interactive)
+  (stgit-capture-output nil (stgit-run "pop"))
+  (stgit-refresh))
+
+(defun stgit-applied-at-point ()
+  "Is the patch on the current line applied?"
+  (save-excursion
+    (beginning-of-line)
+    (looking-at "[>+]")))
+
+(defun stgit-push-or-pop ()
+  "Push or pop the patch on the current line"
+  (interactive)
+  (let ((patch (stgit-patch-at-point))
+        (applied (stgit-applied-at-point)))
     (stgit-capture-output nil
-      (stgit-run "push" patch))
+       (stgit-run (if applied "pop" "push") patch))
     (stgit-refresh)))
 
-(defun stgit-pop ()
-  "Pop the patch on the current line"
+(defun stgit-goto ()
+  "Go to the patch on the current line"
   (interactive)
   (let ((patch (stgit-patch-at-point)))
     (stgit-capture-output nil
-      (stgit-run "pop" patch))
-    (stgit-refresh)
-    (previous-line)))
+       (stgit-run "goto" patch))
+    (stgit-refresh)))
 
 (defun stgit-show ()
   "Show the patch on the current line"