X-Git-Url: https://git.distorted.org.uk/~mdw/stgit/blobdiff_plain/69db97142c4c1cd7b574a4d0e53203182955cb37..84e1850a7cb61f9afa61eda5fa75ca14f672eadf:/contrib/stgit.el diff --git a/contrib/stgit.el b/contrib/stgit.el index 86602be..d3d518d 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) @@ -943,7 +944,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 +951,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 +1005,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 +1148,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 @@ -1492,9 +1494,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) @@ -2211,6 +2220,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.