emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

master 3b105e978c 5/5: Input indentation for M-x shell


From: Lars Ingebrigtsen
Subject: master 3b105e978c 5/5: Input indentation for M-x shell
Date: Fri, 9 Sep 2022 14:14:46 -0400 (EDT)

branch: master
commit 3b105e978c42973fb5810a74681f263889fc23c0
Author: Miha Rihtaršič <miha@kamnitnik.top>
Commit: Lars Ingebrigtsen <larsi@gnus.org>

    Input indentation for M-x shell
    
    * lisp/comint.el
    (comint-indent-input-line):
    (comint-indent-input-line-default):
    (comint-indent-input-region):
    (comint-indent-input-region-default): New functions that implement a
    general mechanism for input indentation through an indirect buffer in
    comint derived major modes.
    * lisp/shell.el (shell-mode): Set up input indentation according to
    sh-mode (bug#51940).
---
 lisp/comint.el | 93 +++++++++++++++++++++++++++++++++++++++++++++++++++++-----
 lisp/shell.el  |  4 +++
 2 files changed, 89 insertions(+), 8 deletions(-)

diff --git a/lisp/comint.el b/lisp/comint.el
index 4fcfb500e1..751e561d3e 100644
--- a/lisp/comint.el
+++ b/lisp/comint.el
@@ -4012,21 +4012,21 @@ This function is intended to be included as an entry of
              (cons (point-marker) (match-string-no-properties 1 text)))))
 
 
-;;; Input fontification through an indirect buffer
+;;; Input fontification and indentation through an indirect buffer
 ;;============================================================================
 ;;
-;; Modes derived from `comint-mode' can set up fontification input
-;; text with the help of an indirect buffer whose major mode and
-;; font-lock settings are set accordingly.
+;; Modes derived from `comint-mode' can set up fontification and
+;; indentation of input text with the help of an indirect buffer whose
+;; major mode and font-lock settings are set accordingly.
 
 (defvar-local comint-indirect-setup-function nil
   "Function to set up an indirect comint fontification buffer.
 This function is called by `comint-indirect-buffer' with zero
 arguments after making an indirect buffer.  It is usually set to
-a major-mode command whose font-locking is desired for input
-text.  In order to prevent possible mode hooks from running, the
-variable `delay-mode-hooks' is set to t prior to calling this
-function and `change-major-mode-hook' along with
+a major-mode command whose font-locking and indentation are
+desired for input text.  In order to prevent possible mode hooks
+from running, the variable `delay-mode-hooks' is set to t prior
+to calling this function and `change-major-mode-hook' along with
 `after-change-major-mode-hook' are bound to nil.")
 
 (defcustom comint-indirect-setup-hook nil
@@ -4191,6 +4191,83 @@ function called, or nil, if no function was called (if 
BEG = END)."
     (when return-beg
       (cons (car return-beg) (car return-end)))))
 
+(defun comint-indent-input-line (fun)
+  "Indent current line from comint process output or input.
+If point is on output, call FUN, otherwise indent the current
+line in the indirect buffer created by `comint-indirect-buffer',
+which see."
+  (if (or comint-use-prompt-regexp
+          (eq (get-text-property (point) 'field) 'output))
+      (funcall fun)
+    (let ((point (point))
+          (min (point-min))
+          (max (point-max)))
+      (unwind-protect
+          (with-current-buffer (comint-indirect-buffer)
+            (narrow-to-region min max)
+            (goto-char point)
+            (narrow-to-region (field-beginning) (field-end))
+            (unwind-protect (funcall indent-line-function)
+              (setq point (point))))
+        (goto-char point)))))
+
+(defun comint-indent-input-region (fun start end)
+  "Indent comint process output and input between START and END.
+Output text between START and END is indented with FUN and input
+text is indented in the indirect buffer created by
+`comint-indirect-buffer', which see."
+  (if comint-use-prompt-regexp
+      (funcall fun start end)
+    (let ((opoint (copy-marker (point)))
+          final-point)
+      (unwind-protect
+          (comint--intersect-regions
+           (lambda (start end)
+             (goto-char opoint)
+             (if (= opoint (point))
+                 (unwind-protect (funcall fun start end)
+                   (setq final-point (copy-marker (point))))
+               (funcall fun start end)))
+           (lambda (start end)
+             (let ((min (point-min))
+                   (max (point-max))
+                   (final-point1 nil))
+               (unwind-protect
+                   (with-current-buffer (comint-indirect-buffer)
+                     (narrow-to-region min max)
+                     (goto-char opoint)
+                     (if (= opoint (point))
+                         (unwind-protect
+                             (funcall indent-region-function start end)
+                           (setq final-point1 (point)))
+                       (funcall indent-region-function start end)))
+                 (when final-point1
+                   (setq final-point (copy-marker final-point1))))))
+           start end)
+        (if final-point
+            (progn
+              (goto-char final-point)
+              (set-marker final-point nil))
+          (goto-char opoint))
+        (set-marker opoint nil)))))
+
+(defun comint-indent-input-line-default ()
+  "Indent current line from comint process output or input.
+If point is on output, indent the current line according to the
+default value of `indent-line-function', otherwise indent the
+current line in the indirect buffer created by
+`comint-indirect-buffer', which see."
+  (comint-indent-input-line (default-value 'indent-line-function)))
+
+(defun comint-indent-input-region-default (start end)
+  "Indent comint process output and input between START and END.
+Output text between START and END is indented according to the
+default value of `indent-region-function' and input text is
+indented in the indirect buffer created by
+`comint-indirect-buffer', which see."
+  (comint-indent-input-region (default-value 'indent-line-function)
+                              start end))
+
 (defun comint-indirect-buffer (&optional no-create)
   "Return an indirect comint fontification buffer.
 If an indirect buffer for the current buffer already exists,
diff --git a/lisp/shell.el b/lisp/shell.el
index e8ae1c9738..b65792e10a 100644
--- a/lisp/shell.el
+++ b/lisp/shell.el
@@ -653,6 +653,10 @@ command."
                  (message-log-max nil))
               (sh-mode)))))
 
+  (setq-local indent-line-function #'comint-indent-input-line-default)
+  (setq-local indent-region-function
+              #'comint-indent-input-region-default)
+
   ;; This is not really correct, since the shell buffer does not really
   ;; edit this directory.  But it is useful in the buffer list and menus.
   (setq list-buffers-directory (expand-file-name default-directory))



reply via email to

[Prev in Thread] Current Thread [Next in Thread]