unofficial mirror of bug-gnu-emacs@gnu.org 
 help / color / mirror / code / Atom feed
From: miha--- via "Bug reports for GNU Emacs, the Swiss army knife of text editors" <bug-gnu-emacs@gnu.org>
To: Lars Ingebrigtsen <larsi@gnus.org>
Cc: 3735@debbugs.gnu.org, dsb@smart.net, Chong Yidong <cyd@gnu.org>,
	18135@debbugs.gnu.org, Don Hopkins <don@donhopkins.com>
Subject: bug#18135: bug#3735: shell-mode editing, movement, and command entry broken by prompt/output changes
Date: Tue, 07 Dec 2021 17:57:34 +0100	[thread overview]
Message-ID: <878rww4akh.fsf@miha-pc> (raw)
In-Reply-To: <8735n6svhn.fsf@gnus.org>


[-- Attachment #1.1: Type: text/plain, Size: 1305 bytes --]

Lars Ingebrigtsen <larsi@gnus.org> writes:

> miha@kamnitnik.top writes:
>
>> Reproducer:
>>
>> - copy " -la" into kill ring
>> - type "echo ls" into M-x shell
>> - (Shell gives output line "ls".)
>> - Go up to output line "ls" (C-p).
>> - yank " -la"
>> - press C-b
>> - the line now "ls -la" with point after "l"
>> - press RET
>>
>> Only " -la" is sent to the process instead of "ls -la"
>
> Thanks; with that I'm also able to reproduce the problem.
>
>> I am willing to write up a patch to fix this. I'm thinking of having
>> comint-mode register a function in after-change-functions to mark text
>> inserted in the 'output' field as 'output'. Would this be okay or are
>> there any obvious flaws with this approach?
>
> I think that sounds like a promising approach, but I wonder whether
> something could be done with rear-nonsticky here. `field' isn't
> rear-sticky here for probably good reasons, but perhaps something
> could be tweaked there? (I haven't actually tried, though.)

Yeah I thought about that too. However, commands such as 'yank' or
'just-one-space' use insert rather than insert-and-inherit and thus
always bypass inheritance of surrounding text properties regardless of
it's stickiness. That is why I settled for using the
'insert-in-front-hooks' text property, patch attached.


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1.2: 0001-Improve-yanking-in-the-middle-of-comint-process-outp.patch --]
[-- Type: text/x-patch, Size: 4576 bytes --]

From 7914fe85ba096f93d4b6817bc0d7b7976f3d316a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Miha=20Rihtar=C5=A1i=C4=8D?= <miha@kamnitnik.top>
Date: Tue, 7 Dec 2021 16:59:39 +0100
Subject: [PATCH] Improve yanking in the middle of comint process output

* lisp/comint.el
(comint--unmark-string-as-output): New function to remove unwanted
properties from text yanked from comint buffers.

(comint-mode): Use it as a 'filter-buffer-substring-function'.

(comint-output-filter): Set 'insert-in-front-hooks' text property on
process output such that text yanked by the user in the middle of
process output is marked as process output (Bug#3735).

(comint--mark-as-output): New function.
(comint--mark-yanked-as-output): New function.
---
 lisp/comint.el | 54 +++++++++++++++++++++++++++++++++++++++++---------
 1 file changed, 45 insertions(+), 9 deletions(-)

diff --git a/lisp/comint.el b/lisp/comint.el
index 544f0b8b82..5f99f560cf 100644
--- a/lisp/comint.el
+++ b/lisp/comint.el
@@ -730,6 +730,8 @@ comint-mode
               (or (file-remote-p default-directory) ""))
   (setq-local comint-accum-marker (make-marker))
   (setq-local font-lock-defaults '(nil t))
+  (add-function :filter-return (local 'filter-buffer-substring-function)
+                #'comint--unmark-string-as-output)
   (add-hook 'change-major-mode-hook 'font-lock-defontify nil t)
   (add-hook 'isearch-mode-hook 'comint-history-isearch-setup nil t)
   (add-hook 'completion-at-point-functions 'comint-completion-at-point nil t)
@@ -1815,7 +1817,8 @@ comint-add-to-input-history
     (ring-insert comint-input-ring cmd)))
 
 (defconst comint--prompt-rear-nonsticky
-  '(field inhibit-line-move-field-capture read-only font-lock-face)
+  '( field inhibit-line-move-field-capture read-only font-lock-face
+     insert-in-front-hooks)
   "Text properties we set on the prompt and don't want to leak past it.")
 
 (defun comint-send-input (&optional no-newline artificial)
@@ -2152,14 +2155,7 @@ comint-output-filter
 	    (goto-char (process-mark process)) ; In case a filter moved it.
 
 	    (unless comint-use-prompt-regexp
-              (with-silent-modifications
-                (add-text-properties comint-last-output-start (point)
-                                     `(rear-nonsticky
-				       ,comint--prompt-rear-nonsticky
-				       front-sticky
-				       (field inhibit-line-move-field-capture)
-				       field output
-				       inhibit-line-move-field-capture t))))
+              (comint--mark-as-output comint-last-output-start (point)))
 
 	    ;; Highlight the prompt, where we define `prompt' to mean
 	    ;; the most recent output that doesn't end with a newline.
@@ -2191,6 +2187,46 @@ comint-output-filter
 	                             ,comint--prompt-rear-nonsticky)))
 	    (goto-char saved-point)))))))
 
+(defun comint--mark-as-output (beg end)
+  (with-silent-modifications
+    (add-text-properties
+     beg end
+     `(rear-nonsticky
+       ,comint--prompt-rear-nonsticky
+       front-sticky
+       (field inhibit-line-move-field-capture)
+       field output
+       inhibit-line-move-field-capture t
+       ;; Text inserted by a user in the middle of process output
+       ;; should be marked as output.  This is needed for commands
+       ;; such as `yank' or `just-one-space' which don't use
+       ;; `insert-and-inherit' and thus bypass default text property
+       ;; inheritance.
+       insert-in-front-hooks
+       (,#'comint--mark-as-output ,#'comint--mark-yanked-as-output)))))
+
+(defun comint--mark-yanked-as-output (beg end)
+  ;; `yank' removes the field text property from the text it inserts
+  ;; due to `yank-excluded-properties', so arrange for this text
+  ;; property to be reapplied in the `after-change-functions'.
+  (let (fun)
+    (setq
+     fun
+     (lambda (beg1 end1 _len1)
+       (remove-hook 'after-change-functions fun t)
+       (when (and (= beg beg1)
+                  (= end end1))
+         (comint--mark-as-output beg1 end1))))
+    (add-hook 'after-change-functions fun nil t)))
+
+(defun comint--unmark-string-as-output (string)
+  (remove-list-of-text-properties
+   0 (length string)
+   '( rear-nonsticky front-sticky field
+      inhibit-line-move-field-capture insert-in-front-hooks)
+   string)
+  string)
+
 (defun comint-preinput-scroll-to-bottom ()
   "Go to the end of buffer in all windows showing it.
 Movement occurs if point in the selected window is not after the process mark,
-- 
2.34.1


[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 861 bytes --]

  reply	other threads:[~2021-12-07 16:57 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-07-28 12:52 bug#18135: Emacs bug # 3735 definitely not fixed (5 years later) Don Hopkins
2017-05-06 14:46 ` Chong Yidong
2021-12-04 21:15   ` bug#18135: bug#3735: shell-mode editing, movement, and command entry broken by prompt/output changes Lars Ingebrigtsen
2021-12-04 22:18     ` Don Hopkins
2021-12-05 16:13       ` miha--- via Bug reports for GNU Emacs, the Swiss army knife of text editors
2021-12-05 19:27         ` Lars Ingebrigtsen
2021-12-07 16:57           ` miha--- via Bug reports for GNU Emacs, the Swiss army knife of text editors [this message]
2021-12-07 20:16             ` bug#3735: " Lars Ingebrigtsen
2021-12-08  0:20               ` Don Hopkins

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=878rww4akh.fsf@miha-pc \
    --to=bug-gnu-emacs@gnu.org \
    --cc=18135@debbugs.gnu.org \
    --cc=3735@debbugs.gnu.org \
    --cc=cyd@gnu.org \
    --cc=don@donhopkins.com \
    --cc=dsb@smart.net \
    --cc=larsi@gnus.org \
    --cc=miha@kamnitnik.top \
    /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).