[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))