Skip to content

Commit 990cc18

Browse files
committed
Remove fake newlines in copy mode
when vterm-copy-mode-remove-fake-newlines is not nil. See #497 .
1 parent 0d190d1 commit 990cc18

File tree

2 files changed

+86
-17
lines changed

2 files changed

+86
-17
lines changed

README.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -470,6 +470,16 @@ will ask the user whether to build the module when `vterm` is first called. To
470470
avoid this question and always compile the module, set
471471
`vterm-always-compile-module` to `t`.
472472
473+
## `vterm-copy-mode-remove-fake-newlines`
474+
475+
When not-nil fake newlines are removed on entering copy mode.
476+
vterm inserts fake-newlines purely for rendering. When using
477+
`vterm-copy-mode` these are in conflict with many emacs functions
478+
like isearch-forward. if this varialbe is not-nil the
479+
fake-newlines are removed on entering copy-mode and re-inserted
480+
on leaving copy mode. Also truncate-lines is set to t on entering
481+
copy-mode and set to nil on leaving.
482+
473483
## Keybindings
474484
475485
If you want a key to be sent to the terminal, bind it to `vterm--self-insert`,

vterm.el

Lines changed: 76 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -409,6 +409,18 @@ not require any shell-side configuration. See
409409
:type 'boolean
410410
:group 'vterm)
411411

412+
(defcustom vterm-copy-mode-remove-fake-newlines nil
413+
"When not-nil fake newlines are removed on entering copy mode.
414+
415+
vterm inserts \\='fake\\=' newlines purely for rendering. When using
416+
vterm-copy-mode these are in conflict with many emacs functions
417+
like isearch-forward. if this varialbe is not-nil the
418+
fake-newlines are removed on entering copy-mode and re-inserted
419+
on leaving copy mode. Also truncate-lines is set to t on entering
420+
copy-mode and set to nil on leaving."
421+
:type 'boolean
422+
:group 'vterm)
423+
412424
;;; Faces
413425

414426
(defface vterm-color-black
@@ -506,6 +518,8 @@ Only background is used."
506518
(defvar-local vterm--delete-char-function (symbol-function #'delete-char))
507519
(defvar-local vterm--delete-region-function (symbol-function #'delete-region))
508520
(defvar-local vterm--undecoded-bytes nil)
521+
(defvar-local vterm--copy-mode-fake-newlines nil)
522+
509523

510524
(defvar vterm-timer-delay 0.1
511525
"Delay for refreshing the buffer after receiving updates from libvterm.
@@ -833,6 +847,24 @@ Optional argument RESET clears all the errors."
833847

834848
;;; Copy Mode
835849

850+
(defun vterm--enter-copy-mode ()
851+
(use-local-map nil)
852+
(vterm-send-stop)
853+
(when vterm-copy-mode-remove-fake-newlines
854+
(save-excursion
855+
(setq truncate-lines nil)
856+
(vterm--remove-fake-newlines t))))
857+
858+
859+
(defun vterm--exit-copy-mode ()
860+
(when vterm-copy-mode-remove-fake-newlines
861+
(save-excursion
862+
(setq truncate-lines t)
863+
(vterm--reinsert-fake-newlines)))
864+
(vterm-reset-cursor-point)
865+
(use-local-map vterm-mode-map)
866+
(vterm-send-start))
867+
836868
(define-minor-mode vterm-copy-mode
837869
"Toggle `vterm-copy-mode'.
838870
@@ -849,12 +881,8 @@ A conventient way to exit `vterm-copy-mode' is with
849881
:keymap vterm-copy-mode-map
850882
(if (equal major-mode 'vterm-mode)
851883
(if vterm-copy-mode
852-
(progn ;enable vterm-copy-mode
853-
(use-local-map nil)
854-
(vterm-send-stop))
855-
(vterm-reset-cursor-point)
856-
(use-local-map vterm-mode-map)
857-
(vterm-send-start))
884+
(vterm--enter-copy-mode)
885+
(vterm--exit-copy-mode))
858886
(user-error "You cannot enable vterm-copy-mode outside vterm buffers")))
859887

860888
(defun vterm-copy-mode-done (arg)
@@ -1732,26 +1760,57 @@ Effectively toggle between the two positions."
17321760
(save-excursion
17331761
(vterm-reset-cursor-point))))
17341762

1735-
(defun vterm--remove-fake-newlines ()
1763+
(defun vterm--reinsert-fake-newlines ()
1764+
"Reinsert fake newline from `vterm--copy-mode-fake-newlines'."
1765+
(let ((inhibit-read-only t)
1766+
(inhibit-redisplay t)
1767+
(fake-newline-text "\n")
1768+
fake-newline-pos)
1769+
(add-text-properties 0 1 '(vterm-line-wrap t rear-nonsticky t)
1770+
fake-newline-text)
1771+
(while vterm--copy-mode-fake-newlines
1772+
(setq fake-newline-pos (car vterm--copy-mode-fake-newlines))
1773+
(setq vterm--copy-mode-fake-newlines (cdr vterm--copy-mode-fake-newlines))
1774+
(goto-char fake-newline-pos)
1775+
(insert fake-newline-text))))
1776+
1777+
(defun vterm--remove-fake-newlines (&optional remembering-pos-p)
17361778
"Filter out injected newlines were injected when rendering the terminal.
17371779
17381780
These newlines were tagged with \\='vterm-line-wrap property so we
1739-
can find them and remove them."
1740-
(goto-char (point-min))
1741-
(let (fake-newline)
1742-
(while (setq fake-newline (next-single-property-change (point)
1743-
'vterm-line-wrap))
1744-
(goto-char fake-newline)
1745-
(cl-assert (eq ?\n (char-after)))
1746-
(let ((inhibit-read-only t))
1747-
(vterm--delete-char 1)))))
1781+
can find them and remove them.
1782+
If REMEMBERING-POS-P is not nil remembering their positions in a buffer-local
1783+
`vterm--copy-mode-fake-newlines'."
1784+
(let (fake-newline
1785+
(inhibit-read-only t)
1786+
(inhibit-redisplay t))
1787+
(when remembering-pos-p
1788+
(setq vterm--copy-mode-fake-newlines nil))
17481789

1790+
(goto-char (point-max))
1791+
(when (and (bolp)
1792+
(get-text-property (1- (point)) 'vterm-line-wrap))
1793+
(forward-char -1)
1794+
(when remembering-pos-p
1795+
(setq vterm--copy-mode-fake-newlines
1796+
(cons (point) vterm--copy-mode-fake-newlines)))
1797+
(vterm--delete-char 1))
1798+
1799+
(while (and (not (bobp))
1800+
(setq fake-newline (previous-single-property-change
1801+
(point) 'vterm-line-wrap)))
1802+
(goto-char (1- fake-newline))
1803+
(cl-assert (eq ?\n (char-after)))
1804+
(when remembering-pos-p
1805+
(setq vterm--copy-mode-fake-newlines
1806+
(cons (point) vterm--copy-mode-fake-newlines)))
1807+
(vterm--delete-char 1))))
17491808

17501809
(defun vterm--filter-buffer-substring (content)
17511810
"Filter string CONTENT of fake/injected newlines."
17521811
(with-temp-buffer
17531812
(vterm--insert content)
1754-
(vterm--remove-fake-newlines)
1813+
(vterm--remove-fake-newlines nil)
17551814
(buffer-string)))
17561815

17571816

0 commit comments

Comments
 (0)