Skip to content

Commit

Permalink
Limit right prompt detection logic to the prompt.
Browse files Browse the repository at this point in the history
Before this change, output containing tabs or otherwise skip characters
would trigger the right prompt detection logic, which would then attempt
to remove from the yanked text what it sees as part of the prompt.

This change restricts right prompt detection to the prompt, the section
with bracketed-paste turned on, so that command output is left alone.

Fixes #21
  • Loading branch information
szermatt committed Sep 30, 2024
1 parent e3ea40f commit 144b651
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 12 deletions.
26 changes: 14 additions & 12 deletions mistty-term.el
Original file line number Diff line number Diff line change
Expand Up @@ -392,8 +392,7 @@ mistty-reverse-input-decode-map.el to `xterm-function-map'.")
This variable evaluates to true when bracketed paste is turned on
by the command that controls, to false otherwise.
This variable is available in the work buffer.")

This variable is available in both the work and term buffers.")

(defvar-local mistty--term-properties-to-add-alist nil
"An alist of id to text properties to add to the term buffer.
Expand Down Expand Up @@ -464,11 +463,13 @@ into `mistty-bracketed-paste' in the buffer WORK-BUFFER.
(unless (eq ?\n (char-before (point)))
(add-text-properties (mistty--bol (point)) (point) props))
(mistty-register-text-properties 'mistty-bracketed-paste props))
(setq mistty-bracketed-paste t)
(mistty--with-live-buffer work-buffer
(setq mistty-bracketed-paste t)))
((equal ext "[?2004l") ; disable bracketed paste
(term-emulate-terminal proc (substring str start seq-end))
(mistty-unregister-text-properties 'mistty-bracketed-paste)
(setq mistty-bracketed-paste nil)
(mistty--with-live-buffer work-buffer
(setq mistty-bracketed-paste nil)))
((equal ext "[?25h") ; make cursor visible
Expand Down Expand Up @@ -596,22 +597,23 @@ BEG and END define the region that was modified."
(put-text-property pos fake-nl-end 'yank-handler '(nil "" nil nil))
(setq beg fake-nl-end)))

;; Detect and mark right prompts.
(let ((bol (mistty--bol beg))
(eol (mistty--eol beg)))
(when (and (> beg bol)
(<= end eol)
(get-text-property (1- beg) 'mistty-skip)
(not (get-text-property bol 'mistty-skip)))
(add-text-properties
beg end '(mistty-skip t mistty-right-prompt t yank-handler (nil "" nil nil))))))
(when mistty-bracketed-paste
;; Detect and mark right prompts.
(let ((bol (mistty--bol beg))
(eol (mistty--eol beg)))
(when (and (> beg bol)
(<= end eol)
(get-text-property (1- beg) 'mistty-skip)
(not (get-text-property bol 'mistty-skip)))
(add-text-properties
beg end '(mistty-skip t mistty-right-prompt t yank-handler (nil "" nil nil)))))))

(defun mistty--around-move-to-column (orig-fun &rest args)
"Add property \\='mistty-skip t to spaces added when just moving.
ORIG-FUN is the original `move-to-column' function that's being
advised and ARGS are its arguments."
(if (eq 'term-mode major-mode)
(if (and (eq 'term-mode major-mode) mistty-bracketed-paste)
(let ((initial-end (line-end-position)))
(apply orig-fun args)
(when (> (point) initial-end)
Expand Down
11 changes: 11 additions & 0 deletions test/mistty-test.el
Original file line number Diff line number Diff line change
Expand Up @@ -2823,6 +2823,17 @@
(yank)
(should (equal "$ echo hello" (mistty-test-content))))))

(ert-deftest mistty-test-not-right-prompt-yank-in-output ()
(mistty-with-test-buffer (:shell fish)
(mistty-send-string "printf 'foo\\t") ; \t would confuse mistty-send-text
(mistty-send-text "bar\n'")
(let ((start (point)))
(mistty-send-and-wait-for-prompt)
(copy-region-as-kill (mistty--bol start 2) (mistty--eol start 2)))
(with-temp-buffer
(yank)
(should (equal "foo bar" (mistty-test-content))))))

(ert-deftest mistty-test-fish-right-prompt-skip-empty-spaces-at-prompt ()
(mistty-with-test-buffer (:shell fish :selected t)
(mistty-setup-fish-right-prompt)
Expand Down

2 comments on commit 144b651

@dcolascione
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't it legal for a program to enable bracketed paste mode after printing the prompt? Aren't there more explicit prompt-marking control codes?

@szermatt
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There aren't any official prompt-marking control codes; this is just not a concept in a terminal. Shells and commands do whatever they want in whatever way they want as long as it eventually looks and feels reasonable to users.

This is a heuristic MisTTY uses, one of many. Bracketed past mode on and fullscreen mode off indicates that a specific region of the screen accepts user input - that's what a prompt basically is. This particular heuristic seems to work for at least recent version of bash, zsh and fish (older versions didn't support bracketed paste mode).

There are absolutely no doubts that some shells or command out there violate this heuristic - just like all heuristics MistTTY is built on.

Please sign in to comment.