X-Git-Url: https://git.distorted.org.uk/~mdw/stgit/blobdiff_plain/b894e68096692a391421d7ab4ba2e4d9f382c01e..210a2a52e4ba8ea095bcad3917a1b7c6d9413b92:/contrib/stgit.el diff --git a/contrib/stgit.el b/contrib/stgit.el index 0a1aefb..cfc71dd 100644 --- a/contrib/stgit.el +++ b/contrib/stgit.el @@ -164,6 +164,17 @@ Returns nil if there was no output." "Returns non-nil if the index contains no changes from HEAD." (zerop (stgit-run-git-silent "diff-index" "--cached" "--quiet" "HEAD"))) +(defvar stgit-index-node nil) +(defvar stgit-worktree-node nil) + +(defun stgit-refresh-index () + (when stgit-index-node + (ewoc-invalidate (car stgit-index-node) (cdr stgit-index-node)))) + +(defun stgit-refresh-worktree () + (when stgit-worktree-node + (ewoc-invalidate (car stgit-worktree-node) (cdr stgit-worktree-node)))) + (defun stgit-run-series (ewoc) (let ((first-line t)) (with-temp-buffer @@ -191,19 +202,21 @@ Returns nil if there was no output." :desc (match-string 5) :empty (string= (match-string 1) "0")))) (setq first-line nil) - (forward-line 1)) - (ewoc-enter-last ewoc - (make-stgit-patch - :status 'index - :name :index - :desc nil - :empty nil)) - (ewoc-enter-last ewoc - (make-stgit-patch - :status 'work - :name :work - :desc nil - :empty nil))))))) + (forward-line 1))))) + (if stgit-show-worktree + (setq stgit-index-node (cons ewoc (ewoc-enter-last ewoc + (make-stgit-patch + :status 'index + :name :index + :desc nil + :empty nil))) + stgit-worktree-node (cons ewoc (ewoc-enter-last ewoc + (make-stgit-patch + :status 'work + :name :work + :desc nil + :empty nil)))) + (setq stgit-worktree-node nil)))) (defun stgit-reload () @@ -221,7 +234,12 @@ Returns nil if there was no output." (buffer-substring (point-min) (1- (point-max)))) 'face 'bold) "\n") - "--") + (if stgit-show-worktree + "--" + (propertize + (substitute-command-keys "--\n\"\\[stgit-toggle-worktree]\"\ + shows the working tree\n") + 'face 'stgit-description-face))) (stgit-run-series stgit-ewoc) (if curpatch (stgit-goto-patch curpatch) @@ -429,6 +447,8 @@ find copied files." "-C"))) (ewoc (ewoc-create #'stgit-file-pp nil nil t))) (setf (stgit-patch-files-ewoc patch) ewoc) + (when (eq patchsym :work) + (setq stgit-work-ewoc ewoc)) (with-temp-buffer (apply 'stgit-run-git (cond ((eq patchsym :work) @@ -564,46 +584,52 @@ find copied files." "Keymap for StGit major mode.") (unless stgit-mode-map - (setq stgit-mode-map (make-keymap)) - (suppress-keymap stgit-mode-map) - (mapc (lambda (arg) (define-key stgit-mode-map (car arg) (cdr arg))) - '((" " . stgit-mark) - ("m" . stgit-mark) - ("\d" . stgit-unmark-up) - ("u" . stgit-unmark-down) - ("?" . stgit-help) - ("h" . stgit-help) - ("\C-p" . stgit-previous-line) - ("\C-n" . stgit-next-line) - ([up] . stgit-previous-line) - ([down] . stgit-next-line) - ("p" . stgit-previous-patch) - ("n" . stgit-next-patch) - ("\M-{" . stgit-previous-patch) - ("\M-}" . stgit-next-patch) - ("s" . stgit-git-status) - ("g" . stgit-reload) - ("r" . stgit-refresh) - ("\C-c\C-r" . stgit-rename) - ("e" . stgit-edit) - ("M" . stgit-move-patches) - ("S" . stgit-squash) - ("N" . stgit-new) - ("R" . stgit-repair) - ("C" . stgit-commit) - ("U" . stgit-uncommit) - ("\r" . stgit-select) - ("o" . stgit-find-file-other-window) - (">" . stgit-push-next) - ("<" . stgit-pop-next) - ("P" . stgit-push-or-pop) - ("G" . stgit-goto) - ("=" . stgit-show) - ("D" . stgit-delete) - ([(control ?/)] . stgit-undo) - ("\C-_" . stgit-undo) - ("B" . stgit-branch) - ("q" . stgit-quit)))) + (let ((toggle-map (make-keymap))) + (suppress-keymap toggle-map) + (mapc (lambda (arg) (define-key toggle-map (car arg) (cdr arg))) + '(("t" . stgit-toggle-worktree))) + (setq stgit-mode-map (make-keymap)) + (suppress-keymap stgit-mode-map) + (mapc (lambda (arg) (define-key stgit-mode-map (car arg) (cdr arg))) + `((" " . stgit-mark) + ("m" . stgit-mark) + ("\d" . stgit-unmark-up) + ("u" . stgit-unmark-down) + ("?" . stgit-help) + ("h" . stgit-help) + ("\C-p" . stgit-previous-line) + ("\C-n" . stgit-next-line) + ([up] . stgit-previous-line) + ([down] . stgit-next-line) + ("p" . stgit-previous-patch) + ("n" . stgit-next-patch) + ("\M-{" . stgit-previous-patch) + ("\M-}" . stgit-next-patch) + ("s" . stgit-git-status) + ("g" . stgit-reload) + ("r" . stgit-refresh) + ("\C-c\C-r" . stgit-rename) + ("e" . stgit-edit) + ("M" . stgit-move-patches) + ("S" . stgit-squash) + ("N" . stgit-new) + ("R" . stgit-repair) + ("C" . stgit-commit) + ("U" . stgit-uncommit) + ("\r" . stgit-select) + ("o" . stgit-find-file-other-window) + ("i" . stgit-file-toggle-index) + (">" . stgit-push-next) + ("<" . stgit-pop-next) + ("P" . stgit-push-or-pop) + ("G" . stgit-goto) + ("=" . stgit-show) + ("D" . stgit-delete) + ([(control ?/)] . stgit-undo) + ("\C-_" . stgit-undo) + ("B" . stgit-branch) + ("t" . ,toggle-map) + ("q" . stgit-quit))))) (defun stgit-mode () "Major mode for interacting with StGit. @@ -618,6 +644,7 @@ Commands: (set (make-local-variable 'list-buffers-directory) default-directory) (set (make-local-variable 'stgit-marked-patches) nil) (set (make-local-variable 'stgit-expanded-patches) nil) + (set (make-local-variable 'stgit-show-worktree) stgit-default-show-worktree) (set-variable 'truncate-lines 't) (add-hook 'after-save-hook 'stgit-update-saved-file) (run-hooks 'stgit-mode-hook)) @@ -630,8 +657,7 @@ Commands: (buffer (and gitdir (stgit-find-buffer gitdir)))) (when buffer (with-current-buffer buffer - ;; FIXME: just invalidate ewoc node - (stgit-reload))))) + (stgit-refresh-worktree))))) (defun stgit-add-mark (patchsym) "Mark the patch PATCHSYM." @@ -855,6 +881,35 @@ If PATCHSYM is a keyword, returns PATCHSYM unmodified." (goto-char (point-min)) (diff-mode)))) +(defun stgit-move-change-to-index (file status) + "Copies the workspace state of FILE to index, using git add or git rm" + (let ((op (if (file-exists-p file) "add" "rm"))) + (stgit-capture-output "*git output*" + (stgit-run-git op "--" file)))) + +(defun stgit-remove-change-from-index (file status) + "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." + (interactive) + (let ((patched-file (stgit-patched-file-at-point))) + (unless patched-file + (error "No file on the current line")) + (let ((patch-name (stgit-patch-name-at-point))) + (cond ((eq patch-name :work) + (stgit-move-change-to-index (stgit-file-file patched-file) + (stgit-file-status patched-file))) + ((eq patch-name :index) + (stgit-remove-change-from-index (stgit-file-file patched-file) + (stgit-file-status patched-file))) + (t + (error "Can only move files in the working tree to index"))))) + (stgit-refresh-worktree) + (stgit-refresh-index)) + (defun stgit-edit () "Edit the patch on the current line." (interactive) @@ -1087,4 +1142,29 @@ With prefix argument, refresh the marked patch or the patch under point." (stgit-refresh-git-status)) (stgit-reload)) +(defcustom stgit-default-show-worktree + nil + "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'." + :type 'boolean + :group 'stgit) + +(defvar stgit-show-worktree nil + "Show work tree and index in the stgit buffer. + +See `stgit-default-show-worktree' for its default value.") + +(defun stgit-toggle-worktree (&optional arg) + "Toggle the visibility of the work tree. +With arg, show the work tree if arg is positive. + +Its initial setting is controlled by `stgit-default-show-worktree'." + (interactive) + (setq stgit-show-worktree + (if (numberp arg) + (> arg 0) + (not stgit-show-worktree))) + (stgit-reload)) + (provide 'stgit)