+ (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"
+ (let ((op (if (or (file-exists-p file) (file-symlink-p file))
+ '("add") '("rm" "-q"))))
+ (stgit-capture-output "*git output*"
+ (apply 'stgit-run-git (append op '("--") (list file))))))
+
+(defun stgit-remove-change-from-index (file)
+ "Unstages the change in FILE from the index"
+ (stgit-capture-output "*git output*"
+ (stgit-run-git "reset" "-q" "--" file)))
+
+(defun stgit-file-toggle-index ()
+ "Move modified file in or out of the index.
+
+Leaves the point where it is, but moves the mark to where the
+file ended up. You can then jump to the file with \
+\\[exchange-point-and-mark]."
+ (interactive)
+ (let ((patched-file (stgit-patched-file-at-point)))
+ (unless patched-file
+ (error "No file on the current line"))
+ (when (eq (stgit-file-status patched-file) 'unmerged)
+ (error (substitute-command-keys "Use \\[stgit-resolve-file] to move an unmerged file to the index")))
+ (when (eq (stgit-file-status patched-file) 'ignore)
+ (error "You cannot add ignored files to the index"))
+ (let* ((patch (stgit-patch-at-point))
+ (patch-name (stgit-patch-name patch))
+ (old-point (point))
+ next-file)
+
+ ;; find the next file in the patch, or the previous one if this
+ ;; was the last file
+ (and (zerop (forward-line 1))
+ (let ((f (stgit-patched-file-at-point)))
+ (and f (setq next-file (stgit-file-file f)))))
+ (goto-char old-point)
+ (unless next-file
+ (and (zerop (forward-line -1))
+ (let ((f (stgit-patched-file-at-point)))
+ (and f (setq next-file (stgit-file-file f)))))
+ (goto-char old-point))
+
+ (cond ((eq patch-name :work)
+ (stgit-move-change-to-index (stgit-file-file patched-file)))
+ ((eq patch-name :index)
+ (stgit-remove-change-from-index (stgit-file-file patched-file)))
+ (t
+ (error "Can only move files in the working tree to index")))
+ (stgit-refresh-worktree)
+ (stgit-refresh-index)
+ (stgit-goto-patch (if (eq patch-name :index) :work :index)
+ (stgit-file-file patched-file))
+ (push-mark nil t t)
+ (stgit-goto-patch patch-name next-file))))