@@ -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
17381780These 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