stgit.el: Default to showing index and work tree
[stgit] / contrib / stgit.el
index e19be33..ae74b46 100644 (file)
@@ -9,6 +9,9 @@
 ;;
 ;; To start: `M-x stgit'
 
+(when (< emacs-major-version 22)
+  (error "Emacs older than 22 is not supported by stgit.el"))
+
 (require 'git nil t)
 (require 'cl)
 (require 'ewoc)
@@ -79,7 +82,9 @@ directory DIR or `default-directory'"
         (insert (propertize (if (eq status 'index) "Index" "Work tree")
                             'face face))
       (insert (format "%-30s"
-                      (propertize (symbol-name name) 'face face))
+                      (propertize (symbol-name name)
+                                  'face face
+                                  'syntax-table (string-to-syntax "w")))
               "  "
               (if (stgit-patch-empty patch) "(empty) " "")
               (propertize (or (stgit-patch-desc patch) "")
@@ -716,8 +721,10 @@ file for (applied) copies and renames."
             ("G" .        stgit-goto)
             ("=" .        stgit-diff)
             ("D" .        stgit-delete)
-            ([(control ?/)] . stgit-undo)
+            ([?\C-/] .    stgit-undo)
             ("\C-_" .     stgit-undo)
+            ([?\C-c ?\C-/] . stgit-redo)
+            ("\C-c\C-_" . stgit-redo)
             ("B" .        stgit-branch)
             ("t" .        ,toggle-map)
             ("d" .        ,diff-map)
@@ -739,6 +746,7 @@ Commands:
   (set (make-local-variable 'stgit-show-worktree) stgit-default-show-worktree)
   (set (make-local-variable 'stgit-index-node) nil)
   (set (make-local-variable 'stgit-worktree-node) nil)
+  (set (make-local-variable 'parse-sexp-lookup-properties) t)
   (set-variable 'truncate-lines 't)
   (add-hook 'after-save-hook 'stgit-update-saved-file)
   (run-hooks 'stgit-mode-hook))
@@ -1038,85 +1046,89 @@ If PATCHSYM is a keyword, returns PATCHSYM unmodified."
        (error "Cannot find commit id for %s" patchsym))
       (match-string 1 result))))
 
-(defun stgit-show-patch (unmerged-stage)
+(defun stgit-show-patch (unmerged-stage ignore-whitespace)
   "Show the patch on the current line.
 
 UNMERGED-STAGE is the argument to `git-diff' that that selects
 which stage to diff against in the case of unmerged files."
-  (stgit-capture-output "*StGit patch*"
-    (case (get-text-property (point) 'entry-type)
-      ('file
-       (let* ((patched-file (stgit-patched-file-at-point))
-              (patch-name (stgit-patch-name-at-point))
-              (patch-id (let ((id (stgit-id patch-name)))
-                          (if (and (eq id :index)
-                                   (eq (stgit-file-status patched-file)
-                                       'unmerged))
-                              :work
-                            id)))
-              (args (append (and (stgit-file-cr-from patched-file)
-                                 (list (stgit-find-copies-harder-diff-arg)))
-                            (cond ((eq patch-id :index)
-                                   '("--cached"))
-                                  ((eq patch-id :work)
-                                   (list unmerged-stage))
-                                  (t
-                                   (list (concat patch-id "^") patch-id)))
-                            '("--")
+  (let ((space-arg (when (numberp ignore-whitespace)
+                     (cond ((> ignore-whitespace 4)
+                            "--ignore-all-space")
+                           ((> ignore-whitespace 1)
+                            "--ignore-space-change"))))
+        (patch-name (stgit-patch-name-at-point t)))
+    (stgit-capture-output "*StGit patch*"
+      (case (get-text-property (point) 'entry-type)
+        ('file
+         (let* ((patched-file (stgit-patched-file-at-point))
+                (patch-id (let ((id (stgit-id patch-name)))
+                            (if (and (eq id :index)
+                                     (eq (stgit-file-status patched-file)
+                                         'unmerged))
+                                :work
+                              id)))
+                (args (append (and space-arg (list space-arg))
+                              (and (stgit-file-cr-from patched-file)
+                                   (list (stgit-find-copies-harder-diff-arg)))
+                              (cond ((eq patch-id :index)
+                                     '("--cached"))
+                                    ((eq patch-id :work)
+                                     (list unmerged-stage))
+                                    (t
+                                     (list (concat patch-id "^") patch-id)))
+                              '("--")
                               (if (stgit-file-copy-or-rename patched-file)
                                   (list (stgit-file-cr-from patched-file)
                                         (stgit-file-cr-to patched-file))
                                 (list (stgit-file-file patched-file))))))
-         (apply 'stgit-run-git "diff" args)))
-      ('patch
-       (let* ((patch-name (stgit-patch-name-at-point))
-              (patch-id (stgit-id patch-name)))
-         (if (or (eq patch-id :index) (eq patch-id :work))
-             (apply 'stgit-run-git "diff"
-                    (stgit-find-copies-harder-diff-arg)
-                    (if (eq patch-id :index)
-                        '("--cached")
-                      (list unmerged-stage)))
-           (stgit-run "show" "-O" "--patch-with-stat" "-O" "-M"
-                      (stgit-patch-name-at-point)))))
-      (t
-       (error "No patch or file at point")))
-    (with-current-buffer standard-output
-      (goto-char (point-min))
-      (diff-mode))))
-
-(defun stgit-diff ()
-  "Show the patch on the current line."
-  (interactive)
-  (stgit-show-patch "--ours"))
-
-(defun stgit-diff-ours ()
-  "Show the patch on the current line.
-
-For unmerged files, diff against our branch."
-  (interactive)
-  (stgit-show-patch "--ours"))
-
-(defun stgit-diff-theirs ()
-  "Show the patch on the current line.
-
-For unmerged files, diff against their branch."
-  (interactive)
-  (stgit-show-patch "--theirs"))
-
-(defun stgit-diff-base ()
-  "Show the patch on the current line.
-
-For unmerged files, diff against the base version."
-  (interactive)
-  (stgit-show-patch "--base"))
-
-(defun stgit-diff-combined ()
-  "Show the patch on the current line.
-
-For unmerged files, show a combined diff."
-  (interactive)
-  (stgit-show-patch "--cc"))
+           (apply 'stgit-run-git "diff" args)))
+        ('patch
+         (let* ((patch-id (stgit-id patch-name)))
+           (if (or (eq patch-id :index) (eq patch-id :work))
+               (apply 'stgit-run-git "diff"
+                      (stgit-find-copies-harder-diff-arg)
+                      (append (and space-arg (list space-arg))
+                              (if (eq patch-id :index)
+                                  '("--cached")
+                                (list unmerged-stage))))
+             (let ((args (append '("show" "-O" "--patch-with-stat" "-O" "-M")
+                                 (and space-arg (list "-O" space-arg))
+                                 (list (stgit-patch-name-at-point)))))
+               (apply 'stgit-run args)))))
+         (t
+          (error "No patch or file at point")))
+      (with-current-buffer standard-output
+        (goto-char (point-min))
+        (diff-mode)))))
+
+(defmacro stgit-define-diff (name diff-arg &optional unmerged-action)
+  `(defun ,name (&optional ignore-whitespace)
+     ,(format "Show the patch on the current line.
+
+%sWith a prefix argument, ignore whitespace. With a prefix argument
+greater than four (e.g., \\[universal-argument] \
+\\[universal-argument] \\[%s]), ignore all whitespace."
+              (if unmerged-action
+                  (format "For unmerged files, %s.\n\n" unmerged-action)
+                "")
+              name)
+     (interactive "p")
+     (stgit-show-patch ,diff-arg ignore-whitespace)))
+
+(stgit-define-diff stgit-diff
+                   "--ours" nil)
+(stgit-define-diff stgit-diff-ours
+                   "--ours"
+                   "diff against our branch")
+(stgit-define-diff stgit-diff-theirs
+                   "--theirs"
+                   "diff against their branch")
+(stgit-define-diff stgit-diff-base
+                   "--base"
+                   "diff against the merge base")
+(stgit-define-diff stgit-diff-combined
+                   "--cc"
+                   "show a combined diff")
 
 (defun stgit-move-change-to-index (file)
   "Copies the workspace state of FILE to index, using git add or git rm"
@@ -1385,7 +1397,9 @@ deepest patch had before the squash."
 
 (defun stgit-undo (&optional arg)
   "Run stg undo.
-With prefix argument, run it with the --hard flag."
+With prefix argument, run it with the --hard flag.
+
+See also `stgit-redo'."
   (interactive "P")
   (stgit-capture-output nil
     (if arg
@@ -1393,6 +1407,18 @@ With prefix argument, run it with the --hard flag."
       (stgit-run "undo")))
   (stgit-reload))
 
+(defun stgit-redo (&optional arg)
+  "Run stg redo.
+With prefix argument, run it with the --hard flag.
+
+See also `stgit-undo'."
+  (interactive "P")
+  (stgit-capture-output nil
+    (if arg
+        (stgit-run "redo" "--hard")
+      (stgit-run "redo")))
+  (stgit-reload))
+
 (defun stgit-refresh (&optional arg)
   "Run stg refresh.
 If the index contains any changes, only refresh from index.
@@ -1430,7 +1456,7 @@ See also `stgit-show-worktree'."
   :group 'stgit)
 
 (defcustom stgit-default-show-worktree
-  nil
+  t
   "Set to non-nil to by default show the working tree in a new stgit buffer.
 
 This value is used as the default value for `stgit-show-worktree'."