]> git.eshelyaron.com Git - emacs.git/commitdiff
New shell-mode command to narrow to the command under point
authorPierre Neidhardt <mail@ambrevar.xyz>
Sat, 17 Oct 2020 11:16:24 +0000 (13:16 +0200)
committerLars Ingebrigtsen <larsi@gnus.org>
Sat, 17 Oct 2020 11:16:24 +0000 (13:16 +0200)
* lisp/shell.el (shell--prompt-end-position)
(shell--prompt-begin-position): Helper functions.

* lisp/shell.el (shell-narrow-to-prompt): New command and
keystroke (bug#41784).

etc/NEWS
lisp/shell.el

index 1838b6b38a78cf2e1852f48d97f66a45b730a870..0519451e969741b4baf3f6bd4e092fb3253807c7 100644 (file)
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -1143,6 +1143,11 @@ window after starting).  This variable defaults to nil.
 
 ** Miscellaneous
 
+---
+*** New command in 'shell-mode': 'narrow-to-prompt'.
+This is bound to 'C-x n d' in 'shell-mode' buffers, and narrows to the
+command line under point (and any following output).
+
 ---
 *** New user option 'compilation-search-all-directories'.
 When doing parallel builds, directories and compilation errors may
index 226bdf4d9198db7847a4dc2fc2de35211586b393..43ad58774b84df5a4557fbac8c89b225087dd559 100644 (file)
@@ -334,6 +334,7 @@ Thus, this does not include the shell's current directory.")
     (define-key map "\t" 'completion-at-point)
     (define-key map (kbd "M-RET") 'shell-resync-dirs)
     (define-key map "\M-?" 'comint-dynamic-list-filename-completions)
+    (define-key map (kbd "C-x n d") 'shell-narrow-to-prompt)
     (define-key map [menu-bar completion]
       (cons "Complete"
            (copy-keymap (lookup-key comint-mode-map [menu-bar completion]))))
@@ -1366,6 +1367,48 @@ Returns t if successful."
   (let ((f (shell-c-a-p-replace-by-expanded-directory)))
     (if f (funcall f))))
 
+(defun shell--prompt-begin-position ()
+  ;; We need this convoluted function because `looking-at-p' does not work on
+  ;; multiline regexps _and_ `re-search-backward' skips the current line.
+  (save-excursion
+    (let ((old-point (point)))
+      (max
+       (save-excursion
+         ;; Right result if not on prompt.
+         (call-interactively #'comint-previous-prompt)
+         (re-search-backward comint-prompt-regexp)
+         (point))
+       (save-excursion
+         ;; Right result if on first char after prompt.
+         (re-search-backward comint-prompt-regexp)
+         (point))
+       (save-excursion
+         ;; Right result if on prompt.
+         (call-interactively #'comint-next-prompt)
+         (re-search-backward comint-prompt-regexp)
+         (if (<= (point) old-point)
+             (point)
+           (point-min)))))))
+
+(defun shell--prompt-end-position ()
+  (save-excursion
+    (goto-char (shell--prompt-begin-position))
+    (comint-next-prompt 1)
+    (point)))
+
+(defun shell-narrow-to-prompt ()
+  "Narrow buffer to the command line (and any following command output) at point."
+  (interactive)
+  (let ((begin (shell--prompt-begin-position)))
+    (narrow-to-region
+     begin
+     (save-excursion
+       (goto-char (shell--prompt-end-position))
+       (call-interactively #'comint-next-prompt)
+       (if (= begin (shell--prompt-begin-position))
+           (point-max)
+         (shell--prompt-begin-position))))))
+
 (provide 'shell)
 
 ;;; shell.el ends here