stgit.el: Add "B" for stgit-branch
[stgit] / contrib / stgit.el
index acad87b..7fd3786 100644 (file)
@@ -350,6 +350,15 @@ find copied files."
         (insert "    <no files>\n"))
       (put-text-property start (point) 'stgit-file-patchsym patchsym))))
 
+(defun stgit-collapse-patch (patchsym)
+  "Collapse the patch with name PATCHSYM after the line at point."
+  (save-excursion
+    (forward-line)
+    (let ((start (point)))
+      (while (eq (get-text-property (point) 'stgit-file-patchsym) patchsym)
+        (forward-line))
+      (delete-region start (point)))))
+
 (defun stgit-rescan ()
   "Rescan the status buffer."
   (save-excursion
@@ -398,23 +407,33 @@ find copied files."
                (propertize "no patches in series"
                            'face 'stgit-description-face))))))
 
+(defun stgit-select-file ()
+  (let ((patched-file (stgit-patched-file-at-point)))
+    (unless patched-file
+      (error "No patch or file on the current line"))
+    (let ((filename (expand-file-name (cdr patched-file))))
+      (unless (file-exists-p filename)
+        (error "File does not exist"))
+      (find-file filename))))
+
+(defun stgit-toggle-patch-file-list (curpath)
+  (let ((inhibit-read-only t))
+    (if (memq curpatch stgit-expanded-patches)
+        (save-excursion
+          (setq stgit-expanded-patches (delq curpatch stgit-expanded-patches))
+          (stgit-collapse-patch curpatch))
+      (progn
+        (setq stgit-expanded-patches (cons curpatch stgit-expanded-patches))
+        (stgit-expand-patch curpatch)))))
+
 (defun stgit-select ()
   "Expand or collapse the current entry"
   (interactive)
   (let ((curpatch (stgit-patch-at-point)))
-    (if (not curpatch)
-        (let ((patched-file (stgit-patched-file-at-point)))
-          (unless patched-file
-            (error "No patch or file on the current line"))
-          (let ((filename (expand-file-name (cdr patched-file))))
-            (unless (file-exists-p filename)
-              (error "File does not exist"))
-            (find-file filename)))
-      (setq stgit-expanded-patches
-            (if (memq curpatch stgit-expanded-patches)
-                (delq curpatch stgit-expanded-patches)
-              (cons curpatch stgit-expanded-patches)))
-      (stgit-reload))))
+    (if curpatch
+        (stgit-toggle-patch-file-list curpatch)
+      (stgit-select-file))))
+
 
 (defun stgit-find-file-other-window ()
   "Open file at point in other window"
@@ -522,7 +541,8 @@ find copied files."
           ("D" .        stgit-delete)
           ([(control ?/)] . stgit-undo)
           ("\C-_" .     stgit-undo)
-          ("q" . stgit-quit))))
+          ("B" .        stgit-branch)
+          ("q" .        stgit-quit))))
 
 (defun stgit-mode ()
   "Major mode for interacting with StGit.
@@ -658,16 +678,36 @@ If that patch cannot be found, return nil."
     (stgit-run "repair"))
   (stgit-reload))
 
-(defun stgit-commit ()
-  "Run stg commit."
-  (interactive)
-  (stgit-capture-output nil (stgit-run "commit"))
+(defun stgit-available-branches ()
+  "Returns a list of the available stg branches"
+  (let ((output (with-output-to-string
+                  (stgit-run "branch" "--list")))
+        (start 0)
+        result)
+    (while (string-match "^>?\\s-+s\\s-+\\(\\S-+\\)" output start)
+      (setq result (cons (match-string 1 output) result))
+      (setq start (match-end 0)))
+    result))
+
+(defun stgit-branch (branch)
+  "Switch to branch BRANCH."
+  (interactive (list (completing-read "Switch to branch: "
+                                      (stgit-available-branches))))
+  (stgit-capture-output nil (stgit-run "branch" "--" branch))
+  (stgit-reload))
+
+(defun stgit-commit (count)
+  "Run stg commit on COUNT commits.
+Interactively, the prefix argument is used as COUNT."
+  (interactive "p")
+  (stgit-capture-output nil (stgit-run "commit" "-n" count))
   (stgit-reload))
 
-(defun stgit-uncommit (arg)
-  "Run stg uncommit. Numeric arg determines number of patches to uncommit."
+(defun stgit-uncommit (count)
+  "Run stg uncommit on COUNT commits.
+Interactively, the prefix argument is used as COUNT."
   (interactive "p")
-  (stgit-capture-output nil (stgit-run "uncommit" "-n" arg))
+  (stgit-capture-output nil (stgit-run "uncommit" "-n" count))
   (stgit-reload))
 
 (defun stgit-push-next (npatches)
@@ -802,18 +842,28 @@ end of the patch."
            (substring patch 0 20))
           (t patch))))
 
-(defun stgit-delete (patchsyms)
+(defun stgit-delete (patchsyms &optional spill-p)
   "Delete the patches in PATCHSYMS.
-Interactively, delete the marked patches, or the patch at point."
-  (interactive (list (stgit-patches-marked-or-at-point)))
+Interactively, delete the marked patches, or the patch at point.
+
+With a prefix argument, or SPILL-P, spill the patch contents to
+the work tree and index."
+  (interactive (list (stgit-patches-marked-or-at-point)
+                     current-prefix-arg))
+  (unless patchsyms
+    (error "No patches to delete"))
   (let ((npatches (length patchsyms)))
-    (if (zerop npatches)
-        (error "No patches to delete")
-      (when (yes-or-no-p (format "Really delete %d patch%s? "
-                                 npatches
-                                 (if (= 1 npatches) "" "es")))
+    (when (yes-or-no-p (format "Really delete %d patch%s%s? "
+                              npatches
+                              (if (= 1 npatches) "" "es")
+                               (if spill-p
+                                   " (spilling contents to index)"
+                                 "")))
+      (let ((args (if spill-p 
+                      (cons "--spill" patchsyms)
+                    patchsyms)))
         (stgit-capture-output nil
-          (apply 'stgit-run "delete" patchsyms))
+          (apply 'stgit-run "delete" args))
         (stgit-reload)))))
 
 (defun stgit-coalesce (patchsyms)