[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[elpa] externals/coterm 2358124 48/80: Try to enter and leave char-mode
From: |
ELPA Syncer |
Subject: |
[elpa] externals/coterm 2358124 48/80: Try to enter and leave char-mode automatically |
Date: |
Wed, 13 Oct 2021 18:57:34 -0400 (EDT) |
branch: externals/coterm
commit 23581244de3f74ac1d8ed4f1236fcd1e218e8408
Author: m <>
Commit: m <>
Try to enter and leave char-mode automatically
---
coterm.el | 233 ++++++++++++++++++++++++++++++++++++++++++++++++++++----------
1 file changed, 195 insertions(+), 38 deletions(-)
diff --git a/coterm.el b/coterm.el
index b6c46cf..1754728 100644
--- a/coterm.el
+++ b/coterm.el
@@ -1,6 +1,8 @@
;;; coterm.el --- Terminal emulation for comint -*- lexical-binding: t; -*-
(require 'term)
+(eval-when-compile
+ (require 'cl-lib))
;;; Mode functions and configuration
@@ -85,13 +87,13 @@ if [ $1 = .. ]; then shift; fi; exec \"$@\"" null-device)
(setq coterm-term-environment-function #'comint-term-environment)
(setq coterm-start-process-function #'start-file-process)))
-;;; Raw mode
+;;; Char mode
(defvar coterm-char-mode-map
(let ((map (make-sparse-keymap)))
(set-keymap-parent map term-raw-map)
- (define-key map [remap term-char-mode] #'coterm-char-mode)
- (define-key map [remap term-line-mode] #'coterm-char-mode)
+ (define-key map [remap term-char-mode] #'coterm-char-mode-cycle)
+ (define-key map [remap term-line-mode] #'coterm-char-mode-cycle)
map))
(define-minor-mode coterm-char-mode
@@ -107,8 +109,7 @@ customize it."
(define-minor-mode coterm-scroll-snap-mode
"Keep scroll synchronized.
-Usually enabled for full-screen terminal programs to keep them on
-screen."
+Useful for full-screen terminal programs to keep them on screen."
:keymap nil
(if coterm-scroll-snap-mode
(progn
@@ -117,7 +118,8 @@ screen."
(cons scroll-margin
(local-variable-p 'scroll-margin)))
(setq-local scroll-margin 0))
- (add-hook 'coterm-t-after-insert-hook #'coterm--scroll-snap nil t))
+ (add-hook 'coterm-t-after-insert-hook #'coterm--scroll-snap 'append t)
+ (coterm--scroll-snap))
(when-let ((margin coterm--char-old-scroll-margin))
(setq coterm--char-old-scroll-margin nil)
(if (cdr margin)
@@ -126,30 +128,193 @@ screen."
(remove-hook 'coterm-t-after-insert-hook #'coterm--scroll-snap t)))
(defun coterm--scroll-snap ()
- (let* ((buf (current-buffer))
- (pmark (process-mark (get-buffer-process buf)))
- (sel-win (selected-window))
- (w sel-win))
- ;; Avoid infinite loop in strange case where minibuffer window
- ;; is selected but not active.
- (while (window-minibuffer-p w)
- (setq w (next-window w nil t)))
- (while
- (progn
- (when (and (eq buf (window-buffer w))
- ;; Only snap if point is on pmark
- (= (window-point w) pmark))
- (if (eq sel-win w)
- (progn
+ ;; We need to check for `coterm-scroll-snap-mode' because a function in
+ ;; `coterm-t-after-insert-hook' might have changed it
+ (when coterm-scroll-snap-mode
+ (let* ((buf (current-buffer))
+ (pmark (process-mark (get-buffer-process buf)))
+ (sel-win (selected-window))
+ (w sel-win))
+ ;; Avoid infinite loop in strange case where minibuffer window
+ ;; is selected but not active.
+ (while (window-minibuffer-p w)
+ (setq w (next-window w nil t)))
+ (while
+ (progn
+ (when (and (eq buf (window-buffer w))
+ ;; Only snap if point is on pmark
+ (= (window-point w) pmark))
+ (if (eq sel-win w)
+ (progn
+ (coterm--t-goto 0 0)
+ (recenter 0)
+ (goto-char pmark))
+ (with-selected-window w
(coterm--t-goto 0 0)
(recenter 0)
- (goto-char pmark))
- (with-selected-window w
- (coterm--t-goto 0 0)
- (recenter 0)
- (goto-char pmark))))
- (setq w (next-window w nil t))
- (not (eq w sel-win))))))
+ (goto-char pmark))))
+ (setq w (next-window w nil t))
+ (not (eq w sel-win)))))))
+
+(defvar coterm-auto-char-mode)
+
+(defun coterm-char-mode-cycle ()
+ "Cycle between char mode on, off and auto.
+
+If `coterm-auto-char-mode' is enabled, disable it and enable
+both `coterm-char-mode' and `coterm-scroll-snap-mode'.
+
+If `coterm-char-mode' is enabled, disable it along with
+`coterm-scroll-snap-mode'.
+
+If it is disabled, enable `coterm-auto-char-mode'."
+ (interactive)
+ (cond
+ (coterm-auto-char-mode
+ ;; Interactively to show the message.
+ (funcall-interactively #'coterm-auto-char-mode -1)
+ (coterm-char-mode 1)
+ (coterm-scroll-snap-mode 1))
+ (coterm-char-mode
+ (coterm-char-mode -1)
+ (coterm-scroll-snap-mode -1))
+ (t (funcall-interactively #'coterm-auto-char-mode 1))))
+
+;;;; Automatic entry to char mode
+
+(define-minor-mode coterm-auto-char-mode
+ "Whether we should enter or leave char mode automatically.
+If enabled, `coterm-auto-char-functions' are consulted to set
+`coterm-char-mode' and `coterm-scroll-snap-mode' automatically."
+ :global nil
+ (if coterm-auto-char-mode
+ (progn
+ (add-hook 'coterm-t-after-insert-hook #'coterm--auto-char nil t)
+ (add-hook 'post-command-hook #'coterm--auto-char nil t)
+ (coterm--auto-char))
+ (remove-hook 'coterm-t-after-insert-hook #'coterm--auto-char t)
+ (remove-hook 'post-command-hook #'coterm--auto-char t)))
+
+(defvar coterm-auto-char-functions
+ (list #'coterm--auto-char-less-prompt
+ #'coterm--auto-char-mpv-prompt
+ #'coterm--auto-char-not-eob
+ #'coterm--auto-char-leave-both)
+ "Abnormal hook to enter or leave `coterm-char-mode'.
+This hook is run after every command and process output, if
+`coterm-auto-char-mode' enabled. It is only called if point is
+on process's mark.
+
+Each function is called with zero argumets and with `point-max'
+on the end of process output until one returns non-nil.")
+
+(defun coterm--auto-char ()
+ "Automatically enter or leave `coterm-char-mode'.
+If point is not on process mark, leave `coterm-char-mode' and
+`coterm-scroll-snap-mode'. Otherwise, call functions from
+`coterm-auto-char-functions' until one returns non-nil."
+ (let* ((proc (get-buffer-process (current-buffer)))
+ (pmark (and proc (process-mark proc)))
+ (opoint))
+ (if (and pmark (= (setq opoint (point)) pmark))
+ (save-restriction
+ (coterm--narrow-to-process-output pmark)
+ (goto-char opoint)
+ (run-hook-with-args-until-success 'coterm-auto-char-functions))
+ (when coterm-char-mode (coterm-char-mode -1))
+ (when coterm-scroll-snap-mode (coterm-scroll-snap-mode -1)))))
+
+(defun coterm--auto-char-less-prompt ()
+ (when (eobp)
+ (let ((opoint (point)))
+ (forward-line 0)
+ (prog1
+ (and
+ (looking-at
+ (concat
+ ":\\|"
+ "(END)\\|"
+ "byte [0-9]+\\|"
+ "100%\\|"
+ "\\(?:[^\n]* \\)?" "[0-9]?[0-9]%\\|"
+ "[^\n]*(press h for help or q to quit)"))
+ (when (= opoint (match-end 0))
+ (unless coterm-char-mode (coterm-char-mode 1))
+ (unless coterm-scroll-snap-mode (coterm-scroll-snap-mode 1))
+ t))
+ (goto-char opoint)))))
+
+(defun coterm--auto-char-mpv-prompt ()
+ (when (coterm--auto-char-mpv-prompt-1)
+ ;; (unless coterm-char-mode (coterm-char-mode 1))
+ ;; (when coterm-scroll-snap-mode (coterm-scroll-snap-mode -1))
+ (coterm-char-mode 1)
+ (cl-labels
+ ((hook ()
+ (or (coterm--auto-char-mpv-prompt-1)
+ (and (eobp) (bolp))
+ (ignore (rem-hook))))
+ (rem-hook ()
+ (remove-hook 'coterm-auto-char-functions #'hook t)
+ (remove-hook 'coterm-auto-char-mode-hook #'rem-hook t)))
+ (add-hook 'coterm-auto-char-functions #'hook nil t)
+ (add-hook 'coterm-auto-char-mode-hook #'rem-hook nil t)
+ (add-hook 'coterm-char-mode-hook #'rem-hook nil t)
+ (add-hook 'coterm-scroll-snap-mode-hook #'rem-hook nil t))
+ t))
+
+(defun coterm--auto-char-mpv-prompt-1 ()
+ "Return t if mpv is likely running."
+ (when (bolp)
+ (let ((opoint (point)))
+ (forward-line -1)
+ (prog1 (looking-at
+ (concat "\\(?:[^\n]*\n\\)?"
+ "AV?: "
+ "[0-9][0-9]:[0-9][0-9]:[0-9][0-9] / "
+ "[0-9][0-9]:[0-9][0-9]:[0-9][0-9] "
+ "([0-9]?[0-9]%)"
+ "\\(?:"
+ "\n\\[-*\\+-*\\]"
+ "\\)?"
+ "\\'"))
+ (goto-char opoint)))))
+
+(defun coterm--auto-char-not-eob ()
+ (when (looking-at "\\(?:.*\n\\)\\{9,\\}")
+ ;; (unless coterm-char-mode (coterm-char-mode 1))
+ ;; (unless coterm-scroll-snap-mode (coterm-scroll-snap-mode 1))
+ (coterm-char-mode 1)
+ (coterm-scroll-snap-mode 1)
+ (cl-labels
+ ((hook ()
+ (or (looking-at ".*\n.")
+ (ignore (rem-hook))))
+ (rem-hook ()
+ (remove-hook 'coterm-auto-char-functions #'hook t)
+ (remove-hook 'coterm-auto-char-mode-hook #'rem-hook t)))
+ (add-hook 'coterm-auto-char-functions #'hook nil t)
+ (add-hook 'coterm-auto-char-mode-hook #'rem-hook nil t)
+ (add-hook 'coterm-char-mode-hook #'rem-hook nil t)
+ (add-hook 'coterm-scroll-snap-mode-hook #'rem-hook nil t))
+ t))
+
+(defun coterm--auto-char-leave-both ()
+ (when coterm-char-mode (coterm-char-mode -1))
+ (when coterm-scroll-snap-mode (coterm-scroll-snap-mode -1))
+ t)
+
+(defun coterm--narrow-to-process-output (pmark)
+ "Narrow to process output and move point to the end of it.
+If there is no user input at end of buffer, simply widen. PMARK
+is the process mark."
+ (widen)
+ (unless (eq (get-char-property (max 1 (1- (point-max))) 'field)
+ 'output)
+ (goto-char (point-max))
+ (text-property-search-backward 'field 'output)
+ (when (<= pmark (point))
+ (narrow-to-region (point-min) (point)))))
;;; Terminal emulation
@@ -230,6 +395,7 @@ In sync with variables `coterm--t-home-marker',
(setq-local comint-inhibit-carriage-motion t)
(add-hook 'comint-output-filter-functions #'coterm--comint-strip-CR nil t)
+ (coterm-auto-char-mode)
(add-function :filter-return
(local 'window-adjust-process-window-size-function)
@@ -499,16 +665,7 @@ buffer and the scrolling region must cover the whole
screen."
(setq old-pmark (copy-marker pmark window-point-insertion-type))
(coterm--t-adjust-from-pmark pmark)
(save-restriction
- (widen)
- (goto-char (point-max))
- ;; Use narrowing to prevent modification of user input at end of
- ;; buffer
- (unless (eq (get-char-property (max 1 (1- (point-max))) 'field)
- 'output)
- (goto-char (point-max))
- (text-property-search-backward 'field 'output)
- (when (<= pmark (point))
- (narrow-to-region (point-min) (point))))
+ (coterm--narrow-to-process-output pmark)
(while (setq match (string-match coterm--t-control-seq-regexp
string ctl-end))
- [elpa] externals/coterm 8a5ffd9 68/80: Fix 'coterm--t-goto' for column zero, (continued)
- [elpa] externals/coterm 8a5ffd9 68/80: Fix 'coterm--t-goto' for column zero, ELPA Syncer, 2021/10/13
- [elpa] externals/coterm 11a9594 78/80: [auto-char] Detect prompts from "less -M", ELPA Syncer, 2021/10/13
- [elpa] externals/coterm 8ca9291 71/80: Minor fixes to description, ELPA Syncer, 2021/10/13
- [elpa] externals/coterm 07a2570 69/80: Work around a line wrapping issue with "less", ELPA Syncer, 2021/10/13
- [elpa] externals/coterm 139e8d0 79/80: Fix for Emacs 27, ELPA Syncer, 2021/10/13
- [elpa] externals/coterm 5aea1c8 25/80: Fixup some comments, ELPA Syncer, 2021/10/13
- [elpa] externals/coterm f48ef18 26/80: Fix \e[M and \e[L outside scrolling region, ELPA Syncer, 2021/10/13
- [elpa] externals/coterm 3599955 35/80: Fixes for documentation and compiler warnings, ELPA Syncer, 2021/10/13
- [elpa] externals/coterm c535023 36/80: Safeguard against negative values in move-to-column, ELPA Syncer, 2021/10/13
- [elpa] externals/coterm b35e077 40/80: Reorganize file, ELPA Syncer, 2021/10/13
- [elpa] externals/coterm 2358124 48/80: Try to enter and leave char-mode automatically,
ELPA Syncer <=
- [elpa] externals/coterm 13dd76a 51/80: Adjust mpv prompt detecting regexp, ELPA Syncer, 2021/10/13
- [elpa] externals/coterm 34d8808 54/80: Improve less prompt regexp, ELPA Syncer, 2021/10/13
- [elpa] externals/coterm dd06737 55/80: Improve regexp matching mpv prompt, ELPA Syncer, 2021/10/13
- [elpa] externals/coterm da8019b 80/80: Simplify narrowing to process output, ELPA Syncer, 2021/10/13
- [elpa] externals/coterm ab99084 76/80: [auto-char] "less" prompt may be an empty line if it is slow, ELPA Syncer, 2021/10/13
- [elpa] externals/coterm be23cf4 72/80: Prepare submission to ELPA, ELPA Syncer, 2021/10/13