From: Phil Sainty <psainty@orcon.net.nz>
To: Eli Zaretskii <eliz@gnu.org>
Cc: p.stephani2@gmail.com, 24837@debbugs.gnu.org,
21609@debbugs.gnu.org,
bug-gnu-emacs-bounces+psainty=orcon.net.nz@gnu.org
Subject: bug#21609: bug#24837: 26.0.50; term.el: In char mode, displayed and executed commands can differ
Date: Tue, 10 Oct 2017 03:04:24 +1300 [thread overview]
Message-ID: <33aed754-b4cf-a75d-837d-14ee596613b1@orcon.net.nz> (raw)
In-Reply-To: <fa207a80-eba1-280e-ad59-fb41d03e9e99@orcon.net.nz>
[-- Attachment #1: Type: text/plain, Size: 339 bytes --]
On 09/10/17 01:39, Phil Sainty wrote:
> I think the remaining task would be to add user options to disable
> the new behaviours, as some users might object to them?
This is now done, and rebased onto the emacs-26 branch. The new user
options are enabled by default, and a NEWS entry added. New patch is
attached; please review.
-Phil
[-- Attachment #2: 0001-Avoid-creating-inconsistent-buffer-states-in-term-ch.patch --]
[-- Type: text/x-patch, Size: 7949 bytes --]
From ecd56a565bd4260bcd88e63b0f99cd7eeec71714 Mon Sep 17 00:00:00 2001
From: Phil Sainty <psainty@orcon.net.nz>
Date: Sun, 3 Sep 2017 14:30:18 +1200
Subject: [PATCH] Avoid creating inconsistent buffer states in term-char-mode
(bug#24837)
* lisp/term.el (term-mode, term-char-mode, term-line-mode)
(term-emulate-terminal): Make buffer read-only in `term-char-mode',
except for the process filter's output. Use `read-only-mode-hook' to
track and restore the user-set state of `buffer-read-only' for
`term-line-mode'.
term-char-mode-buffer-read-only: New user option.
term-line-mode-buffer-read-only: New buffer-local variable.
(term-line-mode-buffer-read-only-update): New function.
(term-char-mode, term-line-mode): Use `term-set-goto-process-mark'
in pre-command-hook, and `term-goto-process-mark-maybe' in
post-command-hook to counter-act unexpected changes to point when
using `term-char-mode'.
term-char-mode-point-at-process-mark: New user option.
term-goto-process-mark: New buffer-local variable.
(term-set-goto-process-mark): New function.
(term-goto-process-mark-maybe): New function.
(term-process-mark): New function.
* etc/NEWS: Mention the new user options.
---
etc/NEWS | 12 ++++++++
lisp/term.el | 93 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 105 insertions(+)
diff --git a/etc/NEWS b/etc/NEWS
index a9a4bc6..2149829 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -1148,6 +1148,18 @@ languages. (Version 2.1.0 or later of Enchant is required.)
+++
*** Emacs no longer prompts the user before killing Flymake processes on exit.
+** Term
+
++++
+*** New user options `term-char-mode-buffer-read-only' and
+`term-char-mode-point-at-process-mark' are enabled by default to avoid
+buffer states being created in `term-char-mode' which are inconsistent
+with the terminal state expected by the inferior process.
+
+Respectively, these options prevent buffer changes which are not
+caused by the process filter, and counter-act movements of point away
+from the process mark (with the exception of mouse events).
+
\f
* New Modes and Packages in Emacs 26.1
diff --git a/lisp/term.el b/lisp/term.el
index c748c45..ffd0e92 100644
--- a/lisp/term.el
+++ b/lisp/term.el
@@ -427,6 +427,8 @@ term-old-mode-map
(defvar term-old-mode-line-format) ; Saves old mode-line-format while paging.
(defvar term-pager-old-local-map nil "Saves old keymap while paging.")
(defvar term-pager-old-filter) ; Saved process-filter while paging.
+(defvar-local term-line-mode-buffer-read-only nil
+ "The `buffer-read-only' state to set in `term-line-mode'.")
(defcustom explicit-shell-file-name nil
"If non-nil, is file name to use for explicitly requested inferior shell."
@@ -487,6 +489,36 @@ term-input-ring-file-name
:type 'boolean
:group 'term)
+(defcustom term-char-mode-buffer-read-only t
+ "If non-nil, only the process filter may modify the buffer in char mode.
+
+This makes the buffer read-only in char mode (except for the
+process filter), to prevent editing commands from causing a
+buffer state which is inconsistent with the state understood by
+the inferior process."
+ :type 'boolean
+ :group 'term)
+
+(defcustom term-char-mode-point-at-process-mark t
+ "If non-nil, keep point at the process mark in char mode.
+
+This prevents commands that move point from causing a buffer
+state which is inconsistent with the state understood by the
+inferior process.
+
+Takes effect during `post-command-hook', provided that the
+pre-command point position was also at the process mark.
+
+Mouse selection and other mouse events are ignored, so moving
+point is still possible in char mode via the mouse, and other
+commands can then be invoked at the mouse-selected point or
+region, until the process filter (or user) moves point to the
+process mark once again.
+
+This option has no effect in line mode."
+ :type 'boolean
+ :group 'term)
+
(defcustom term-scroll-to-bottom-on-output nil
"Controls whether interpreter output causes window to scroll.
If nil, then do not scroll. If t or `all', scroll all windows showing buffer.
@@ -1105,6 +1137,8 @@ term-mode
(term-reset-size (cdr size) (car size)))
size))
+ (add-hook 'read-only-mode-hook #'term-line-mode-buffer-read-only-update nil t)
+
(easy-menu-add term-terminal-menu)
(easy-menu-add term-signals-menu)
(or term-input-ring
@@ -1246,6 +1280,13 @@ term-char-mode
(easy-menu-add term-terminal-menu)
(easy-menu-add term-signals-menu)
+ ;; Don't allow changes to the buffer or to point which are not
+ ;; caused by the process filter.
+ (when term-char-mode-buffer-read-only
+ (setq buffer-read-only t))
+ (add-hook 'pre-command-hook #'term-set-goto-process-mark nil t)
+ (add-hook 'post-command-hook #'term-goto-process-mark-maybe nil t)
+
;; Send existing partial line to inferior (without newline).
(let ((pmark (process-mark (get-buffer-process (current-buffer))))
(save-input-sender term-input-sender))
@@ -1265,9 +1306,20 @@ term-line-mode
you type \\[term-send-input] which sends the current line to the inferior."
(interactive)
(when (term-in-char-mode)
+ (when term-char-mode-buffer-read-only
+ (setq buffer-read-only term-line-mode-buffer-read-only))
+ (remove-hook 'pre-command-hook #'term-set-goto-process-mark t)
+ (remove-hook 'post-command-hook #'term-goto-process-mark-maybe t)
(use-local-map term-old-mode-map)
(term-update-mode-line)))
+(defun term-line-mode-buffer-read-only-update ()
+ "Update the user-set state of `buffer-read-only' in `term-line-mode'.
+
+Called as a buffer-local `read-only-mode-hook' function."
+ (when (term-in-line-mode)
+ (setq term-line-mode-buffer-read-only buffer-read-only)))
+
(defun term-update-mode-line ()
(let ((term-mode
(if (term-in-char-mode)
@@ -2711,6 +2763,7 @@ term-emulate-terminal
count-bytes ; number of bytes
decoded-substring
save-point save-marker old-point temp win
+ (inhibit-read-only t)
(buffer-undo-list t)
(selected (selected-window))
last-win
@@ -3109,6 +3162,46 @@ term-emulate-terminal
(when (get-buffer-window (current-buffer))
(redisplay))))
+(defvar-local term-goto-process-mark t
+ "Whether to reset point to the current process mark after this command.
+
+Set in `pre-command-hook' in char mode by `term-set-goto-process-mark'.")
+
+(defun term-set-goto-process-mark ()
+ "Sets `term-goto-process-mark'.
+
+Always set to nil if `term-char-mode-point-at-process-mark' is nil.
+
+Called as a buffer-local `pre-command-hook' function in
+`term-char-mode' so that when point is equal to the process mark
+at the pre-command stage, we know to restore point to the process
+mark at the post-command stage.
+
+See also `term-goto-process-mark-maybe'."
+ (setq term-goto-process-mark
+ (and term-char-mode-point-at-process-mark
+ (eq (point) (marker-position (term-process-mark))))))
+
+(defun term-goto-process-mark-maybe ()
+ "Move point to the term buffer's process mark upon keyboard input.
+
+Called as a buffer-local `post-command-hook' function in
+`term-char-mode' to prevent commands from putting the buffer into
+an inconsistent state by unexpectedly moving point.
+
+Mouse events are ignored so that mouse selection is unimpeded.
+
+Only acts when the pre-command position of point was equal to the
+process mark, and the `term-char-mode-point-at-process-mark'
+option is enabled. See `term-set-goto-process-mark'."
+ (when term-goto-process-mark
+ (unless (mouse-event-p last-command-event)
+ (goto-char (term-process-mark)))))
+
+(defun term-process-mark ()
+ "The current `process-mark' for the term buffer process."
+ (process-mark (get-buffer-process (current-buffer))))
+
(defun term-handle-deferred-scroll ()
(let ((count (- (term-current-row) term-height)))
(when (>= count 0)
--
2.8.3
next prev parent reply other threads:[~2017-10-09 14:04 UTC|newest]
Thread overview: 25+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-10-31 14:10 bug#24837: 26.0.50; term.el: In char mode, displayed and executed commands can differ Philipp Stephani
2016-10-31 20:46 ` Phil Sainty
2016-11-23 19:44 ` Philipp Stephani
2016-11-23 20:08 ` bug#21609: " Phil Sainty
2016-11-23 20:21 ` Philipp Stephani
2017-09-02 14:14 ` Eli Zaretskii
2017-09-03 2:58 ` Phil Sainty
2017-09-03 3:09 ` bug#21609: " Phil Sainty
2017-09-04 9:55 ` Phil Sainty
2017-09-04 10:10 ` bug#24837: " Phil Sainty
2017-09-04 11:59 ` bug#21609: " Phil Sainty
2017-09-24 10:59 ` Philipp Stephani
2017-09-25 0:48 ` bug#21609: " Phil Sainty
2017-09-25 3:09 ` Phil Sainty
2017-09-29 8:37 ` Eli Zaretskii
2017-10-08 12:39 ` bug#21609: " Phil Sainty
2017-10-09 14:04 ` Phil Sainty [this message]
2017-10-09 15:32 ` Eli Zaretskii
2017-10-10 10:16 ` bug#28777: Clarifying the temporary documentation update marks in etc/NEWS Phil Sainty
2017-10-10 12:25 ` Eli Zaretskii
2017-10-10 11:11 ` bug#24837: bug#21609: bug#24837: 26.0.50; term.el: In char mode, displayed and executed commands can differ Phil Sainty
2017-10-10 12:35 ` Eli Zaretskii
2017-10-12 10:54 ` Phil Sainty
2017-10-12 12:04 ` bug#21609: " Eli Zaretskii
2017-10-21 8:20 ` Eli Zaretskii
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
List information: https://www.gnu.org/software/emacs/
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=33aed754-b4cf-a75d-837d-14ee596613b1@orcon.net.nz \
--to=psainty@orcon.net.nz \
--cc=21609@debbugs.gnu.org \
--cc=24837@debbugs.gnu.org \
--cc=bug-gnu-emacs-bounces+psainty=orcon.net.nz@gnu.org \
--cc=eliz@gnu.org \
--cc=p.stephani2@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
Code repositories for project(s) associated with this public inbox
https://git.savannah.gnu.org/cgit/emacs.git
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).