X-Git-Url: https://git.distorted.org.uk/~mdw/stgit/blobdiff_plain/ea696de91d6b8e99497cf9c67c3385d0709f242c..62548eec1a46e229c82b4c793b5120480473ccac:/contrib/stgit.el diff --git a/contrib/stgit.el b/contrib/stgit.el index 234dcaa..b0d1ec9 100644 --- a/contrib/stgit.el +++ b/contrib/stgit.el @@ -14,6 +14,7 @@ (require 'git nil t) (require 'cl) +(require 'comint) (require 'ewoc) (require 'easymenu) (require 'format-spec) @@ -843,6 +844,8 @@ See also `stgit-expand'." (stgit-process-files (lambda (f) (setq node (ewoc-enter-after ewoc node f)))))) + (move-to-column (stgit-goal-column)) + (let ((inhibit-read-only t)) (put-text-property start end 'patch-data patch)))) @@ -943,7 +946,6 @@ file for (applied) copies and renames." (unless stgit-mode-map (let ((diff-map (make-sparse-keymap)) (toggle-map (make-sparse-keymap))) - (suppress-keymap diff-map) (mapc (lambda (arg) (define-key diff-map (car arg) (cdr arg))) '(("b" . stgit-diff-base) ("c" . stgit-diff-combined) @@ -951,7 +953,6 @@ file for (applied) copies and renames." ("o" . stgit-diff-ours) ("r" . stgit-diff-range) ("t" . stgit-diff-theirs))) - (suppress-keymap toggle-map) (mapc (lambda (arg) (define-key toggle-map (car arg) (cdr arg))) '(("n" . stgit-toggle-patch-names) ("t" . stgit-toggle-worktree) @@ -1006,7 +1007,8 @@ file for (applied) copies and renames." ("\C-c\C-b" . stgit-rebase) ("t" . ,toggle-map) ("d" . ,diff-map) - ("q" . stgit-quit)))) + ("q" . stgit-quit) + ("!" . stgit-execute)))) (let ((at-unmerged-file '(let ((file (stgit-patched-file-at-point))) (and file (eq (stgit-file->status file) @@ -1148,6 +1150,8 @@ Basic commands: \\[stgit-git-status] Run `git-status' (if available) +\\[stgit-execute] Run an stg shell command + Movement commands: \\[stgit-previous-line] Move to previous line \\[stgit-next-line] Move to next line @@ -1434,7 +1438,7 @@ PATCHSYM." (stgit-assert-mode) (let ((old-patchsym (stgit-patch-name-at-point t t))) (stgit-capture-output nil - (stgit-run "rename" old-patchsym name)) + (stgit-run "rename" "--" old-patchsym name)) (let ((name-sym (intern name))) (when (memq old-patchsym stgit-expanded-patches) (setq stgit-expanded-patches @@ -1492,9 +1496,16 @@ If ALL is not nil, also return non-stgit branches." ((not (string-match stgit-allowed-branch-name-re branch)) (error "Invalid branch name")) ((yes-or-no-p (format "Create branch \"%s\"? " branch)) - (stgit-capture-output nil (stgit-run "branch" "--create" "--" - branch)) - t)) + (let ((branch-point (completing-read + "Branch from (default current branch): " + (stgit-available-branches)))) + (stgit-capture-output nil + (apply 'stgit-run + `("branch" "--create" "--" + ,branch + ,@(unless (zerop (length branch-point)) + (list branch-point))))) + t))) (stgit-reload))) (defun stgit-available-refs (&optional omit-stgit) @@ -1535,7 +1546,7 @@ what git-config branch..stgit.parentbranch is set to." nil nil (stgit-parent-branch)))) (stgit-assert-mode) - (stgit-capture-output nil (stgit-run "rebase" new-base)) + (stgit-capture-output nil (stgit-run "rebase" "--" new-base)) (stgit-reload)) (defun stgit-commit (count) @@ -1756,7 +1767,7 @@ patches if used on a line after or before all patches." (:top (stgit-push-or-pop-patches t t)) (:bottom (stgit-push-or-pop-patches nil t)) (t (stgit-capture-output nil - (stgit-run "goto" patchsym)) + (stgit-run "goto" "--" patchsym)) (stgit-reload))))) (defun stgit-id (patchsym) @@ -1765,7 +1776,7 @@ If PATCHSYM is a keyword, returns PATCHSYM unmodified." (if (keywordp patchsym) patchsym (let ((result (with-output-to-string - (stgit-run-silent "id" patchsym)))) + (stgit-run-silent "id" "--" patchsym)))) (unless (string-match "^\\([0-9A-Fa-f]\\{40\\}\\)$" result) (error "Cannot find commit id for %s" patchsym)) (match-string 1 result)))) @@ -1818,6 +1829,7 @@ which stage to diff against in the case of unmerged files." (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 @@ -1984,14 +1996,14 @@ file ended up. You can then jump to the file with \ (setq default-directory dir) (let ((standard-output edit-buf)) (save-excursion - (stgit-run-silent "edit" "--save-template=-" patchsym))))) + (stgit-run-silent "edit" "--save-template=-" "--" patchsym))))) (defun stgit-confirm-edit () (interactive) (let ((file (make-temp-file "stgit-edit-"))) (write-region (point-min) (point-max) file) (stgit-capture-output nil - (stgit-run "edit" "-f" file stgit-edit-patchsym)) + (stgit-run "edit" "-f" file "--" stgit-edit-patchsym)) (with-current-buffer log-edit-parent-buffer (stgit-reload)))) @@ -2076,9 +2088,9 @@ the work tree and index." (if spill-p " (spilling contents to index)" ""))) - (let ((args (if spill-p - (cons "--spill" patchsyms) - patchsyms))) + (let ((args (append (when spill-p '("--spill")) + '("--") + patchsyms))) (stgit-capture-output nil (apply 'stgit-run "delete" args)) (stgit-reload))))) @@ -2146,7 +2158,7 @@ Interactively, move the marked patches to where the point is." (let ((sorted-patchsyms (stgit-sort-patches patchsyms))) (stgit-capture-output nil (if (eq target-patch :top) - (apply 'stgit-run "float" sorted-patchsyms) + (apply 'stgit-run "float" "--" sorted-patchsyms) (apply 'stgit-run "sink" (append (unless (eq target-patch :bottom) @@ -2176,7 +2188,7 @@ deepest patch had before the squash." (let ((result (let ((standard-output edit-buf)) (save-excursion (apply 'stgit-run-silent "squash" - "--save-template=-" sorted-patchsyms))))) + "--save-template=-" "--" sorted-patchsyms))))) ;; stg squash may have reordered the patches or caused conflicts (with-current-buffer stgit-buffer @@ -2194,7 +2206,7 @@ deepest patch had before the squash." (let ((file (make-temp-file "stgit-edit-"))) (write-region (point-min) (point-max) file) (stgit-capture-output nil - (apply 'stgit-run "squash" "-f" file stgit-patchsyms)) + (apply 'stgit-run "squash" "-f" file "--" stgit-patchsyms)) (with-current-buffer log-edit-parent-buffer (stgit-clear-marks) ;; Go to first marked patch and stay there @@ -2210,6 +2222,75 @@ deepest patch had before the squash." (interactive) (describe-function 'stgit-mode)) +(defun stgit-execute-process-sentinel (process sentinel) + (let (old-sentinel stgit-buf) + (with-current-buffer (process-buffer process) + (setq old-sentinel old-process-sentinel + stgit-buf stgit-buffer)) + (and (memq (process-status process) '(exit signal)) + (buffer-live-p stgit-buf) + (with-current-buffer stgit-buf + (stgit-reload))) + (funcall old-sentinel process sentinel))) + +(defun stgit-execute-process-filter (process output) + (with-current-buffer (process-buffer process) + (let* ((old-point (point)) + (pmark (process-mark process)) + (insert-at (marker-position pmark)) + (at-pmark (= insert-at old-point))) + (goto-char insert-at) + (insert-before-markers output) + (comint-carriage-motion insert-at (point)) + (set-marker pmark (point)) + (unless at-pmark + (goto-char old-point))))) + +(defun stgit-execute () + "Prompt for an stg command to execute in a shell. + +The names of any marked patches or the patch at point are +inserted in the command to be executed. + +If the command ends in an ampersand, run it asynchronously. + +When the command has finished, reload the stgit buffer." + (interactive) + (stgit-assert-mode) + (let* ((patches (stgit-patches-marked-or-at-point nil t)) + (patch-names (mapcar 'symbol-name patches)) + (hyphens (find-if (lambda (s) (string-match "^-" s)) patch-names)) + (defaultcmd (if patches + (concat "stg " + (and hyphens "-- ") + (mapconcat 'identity patch-names " ")) + "stg ")) + (cmd (read-from-minibuffer "Shell command: " (cons defaultcmd 5) + nil nil 'shell-command-history)) + (async (string-match "&[ \t]*\\'" cmd)) + (buffer (get-buffer-create + (if async + "*Async Shell Command*" + "*Shell Command Output*")))) + ;; cannot use minibuffer as stgit-reload would overwrite it; if we + ;; show the buffer, shell-command will not use the minibuffer + (display-buffer buffer) + (shell-command cmd) + (if async + (let ((old-buffer (current-buffer))) + (with-current-buffer buffer + (let ((process (get-buffer-process buffer))) + (set (make-local-variable 'old-process-sentinel) + (process-sentinel process)) + (set (make-local-variable 'stgit-buffer) + old-buffer) + (set-process-filter process 'stgit-execute-process-filter) + (set-process-sentinel process 'stgit-execute-process-sentinel)))) + (with-current-buffer buffer + (comint-carriage-motion (point-min) (point-max))) + (shrink-window-if-larger-than-buffer (get-buffer-window buffer)) + (stgit-reload)))) + (defun stgit-undo-or-redo (redo hard) "Run stg undo or, if REDO is non-nil, stg redo.