emacs-elpa-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[nongnu] elpa/racket-mode 22dc95ced1 3/3: Improve racket-repl after-chan


From: ELPA Syncer
Subject: [nongnu] elpa/racket-mode 22dc95ced1 3/3: Improve racket-repl after-change behavior; fixes #731
Date: Fri, 6 Dec 2024 16:00:35 -0500 (EST)

branch: elpa/racket-mode
commit 22dc95ced15a1c153386bc9ec12635b3b0225113
Author: Greg Hendershott <git@greghendershott.com>
Commit: Greg Hendershott <git@greghendershott.com>

    Improve racket-repl after-change behavior; fixes #731
    
    Reduce the number and extent of calls to after-change-functions.
    
    - Use inhibit-modification-hooks when using remove-text-properties on
    rear-nonsticky text properties for the entire buffer. Our back end
    hash-lang object doesn't need this huge, meaningless change. Nor do
    things like jit-lock-after change. This mitigates the proximate cause
    of #731.
    
    - Consolidate newline+insert into insert (the "fresh line" stuff).
    
    - Non-substantive: Rewrite cl-case as pcase.
    
    Also, in racket-hash-lang.el, some non-substantive changes:
    
    - Fix prose in doc string for racket--hash-lang-repl-buffer-string.
    
    - Rename racket--hash-lang-after-change-hook to
    racket--hash-lang-after-change -- for brevity, but also because
    technically it's not a value for a hook, it's a value for the variable
    `after-change-functions`.
---
 racket-hash-lang.el |  35 +++++++++--------
 racket-repl.el      | 111 +++++++++++++++++++++++++++-------------------------
 2 files changed, 76 insertions(+), 70 deletions(-)

diff --git a/racket-hash-lang.el b/racket-hash-lang.el
index 35c9fb1e44..125a68a316 100644
--- a/racket-hash-lang.el
+++ b/racket-hash-lang.el
@@ -297,7 +297,7 @@ A discussion of the information provided by a Racket 
language:
        (setq-local racket--hash-lang-id maybe-id)
        ;; These need non-nil `racket--hash-lang-id':
        (setq-local font-lock-fontify-region-function 
#'racket--hash-lang-fontify-region)
-       (add-hook 'after-change-functions #'racket--hash-lang-after-change-hook 
t t)
+       (add-hook 'after-change-functions #'racket--hash-lang-after-change t t)
        (add-hook 'kill-buffer-hook #'racket--hash-lang-delete t t)
        (add-hook 'change-major-mode-hook #'racket--hash-lang-delete t t)
        (setq-local buffer-read-only nil))
@@ -342,8 +342,8 @@ live back end, downgrade them all to `prog-mode'."
 ;;; Updates: Front end --> back end
 
 (defun racket--hash-lang-repl-buffer-string (beg end)
-  "Like `buffer-substring-no-properties' treat as whitespace,
-preserving only line breaks for indentation, everything that is
+  "Like `buffer-substring-no-properties' but treat as whitespace --
+preserving only line breaks for indentation -- everything that is
 not a value output since the last run, or input after the last
 live prompt."
   (let ((result-str ""))
@@ -362,21 +362,22 @@ live prompt."
                                               raw)))))))
     result-str))
 
-(defun racket--hash-lang-after-change-hook (beg end len)
-  ;;;(message "racket--hash-lang-after-change-hook %s %s %s" beg end len)
+(defun racket--hash-lang-after-change (beg end len)
+  ;;;(message "racket--hash-lang-after-change %s %s %s" beg end len)
   ;; This might be called as frequently as once per single changed
   ;; character.
   (when racket--hash-lang-id
-    (racket--cmd/async
-     nil
-     `(hash-lang update
-                 ,racket--hash-lang-id
-                 ,(cl-incf racket--hash-lang-generation)
-                 ,beg
-                 ,len
-                 ,(if (eq major-mode 'racket-repl-mode)
-                      (racket--hash-lang-repl-buffer-string beg end)
-                    (buffer-substring-no-properties beg end))))))
+    (let ((str (if (eq major-mode 'racket-repl-mode)
+                   (racket--hash-lang-repl-buffer-string beg end)
+                 (buffer-substring-no-properties beg end))))
+      (racket--cmd/async
+       nil
+       `(hash-lang update
+                   ,racket--hash-lang-id
+                   ,(cl-incf racket--hash-lang-generation)
+                   ,beg
+                   ,len
+                   ,str)))))
 
 ;;; Notifications: Front end <-- back end
 
@@ -913,8 +914,8 @@ rhombus\"."
                   (with-current-buffer edit-buffer forward-sexp-function))
       (racket-hash-lang-repl-mode (if hash-lang-p 1 -1)) ;keybindings
       (if hash-lang-p
-          (add-hook 'after-change-functions 
#'racket--hash-lang-after-change-hook t t)
-        (remove-hook 'after-change-functions  
#'racket--hash-lang-after-change-hook t))
+          (add-hook 'after-change-functions #'racket--hash-lang-after-change t 
t)
+        (remove-hook 'after-change-functions  #'racket--hash-lang-after-change 
t))
       (setq-local racket-repl-submit-function
                   (if hash-lang-p #'racket-hash-lang-submit nil)))))
 
diff --git a/racket-repl.el b/racket-repl.el
index 878f475318..80b5825936 100644
--- a/racket-repl.el
+++ b/racket-repl.el
@@ -239,79 +239,84 @@ live prompt this marker will be at `point-max'.")
 (defun racket--repl-insert-output (kind value)
   (let ((moving (= (point) racket--repl-output-mark))
         (inhibit-read-only t))
+    ;; Previous chunks of output may have ended with a rear-nonsticky
+    ;; property to allow input to follow. Now that we're adding more
+    ;; output, remove that property so there are no read/write "seams"
+    ;; between chunks.
+    (let ((inhibit-modification-hooks t)) ;avoid after-change: #731
+      (remove-text-properties (point-min)
+                              (point-max)
+                              '(rear-nonsticky nil)))
     (save-excursion
       (goto-char racket--repl-output-mark)
       (let ((pt (point)))
-        ;; Previous chunks of output may have ended with a
-        ;; rear-nonsticky property to allow input to follow. Now that
-        ;; we're adding more output, remove that property so there are
-        ;; no read/write "seams" between chunks.
-        (remove-text-properties (point-min) (point) '(rear-nonsticky nil))
         (cl-flet*
-            ((fresh-line () (unless (bolp) (newline)))
-             (faced (str face) (propertize str 'font-lock-face face))
-             (insert-faced (str face) (insert (faced str face)))
-             (insert-filtered (str face) (insert (racket--repl-filter-output
-                                                  (faced str face)))))
-          (cl-case kind
-            ((run)
+            ((faced (str face)
+               (propertize str 'font-lock-face face))
+             (insert-faced (str face &optional no-fresh-line)
+               (let ((str (faced str face)))
+                 (insert (if (or no-fresh-line (bolp))
+                             str
+                           (concat "\n" str)))))
+             (insert-filtered (str face)
+               (insert (racket--repl-filter-output
+                        (faced str face)))))
+          (pcase kind
+            ('run
              (racket--repl-delete-prompt-mark 'abandon)
              (unless (equal value "")
-               (fresh-line)
                (insert-faced (format "————— run %s —————\n" value) 
'racket-repl-message)))
-            ((prompt)
+            ('prompt
              (racket--repl-make-prompt-mark value))
-            ((message)
-             (fresh-line)
+            ('message
              (insert-faced value 'racket-repl-message)
              (unless (bolp) (newline)))
-            ((exit)
+            ('exit
              (racket--repl-delete-prompt-mark 'abandon)
-             (fresh-line)
              (insert-faced value 'racket-repl-message)
              (unless (bolp) (newline))
-             (setq moving t) ;leave point after, for tests
+             (setq moving t)        ;leave point after, for tests
              (setq racket--repl-session-id nil))
-            ((value)
-             (insert-faced value 'racket-repl-value))
-            ((value-special)
+            ('value
+             (insert-faced value 'racket-repl-value t))
+            ('value-special
              (pcase-let ((`(image . ,file) value))
                (racket--repl-insert-image file)))
-            ((error)
+            ('error
              (pcase value
                (`(,msg ,srclocs (,context-kind . ,context-names-and-locs))
-                (fresh-line)
-                (insert-faced msg 'racket-repl-error-message)
-                (newline)
-                ;; Heuristic: When something supplies exn-srclocs,
-                ;; show those only. Otherwise show context if any.
-                ;; This seems to work well for most runtime
-                ;; exceptions, as well as for rackunit test failures
-                ;; (where the srcloc suffices and the context esp
-                ;; w/errortrace is useless noise).
-                (cond (srclocs
-                       (dolist (loc srclocs)
-                         (insert " ")
-                         (insert (racket--format-error-location loc))
-                         (newline)))
-                      (context-names-and-locs
-                       (insert-faced (format "Context (%s):" context-kind)
-                                     'racket-repl-error-message)
-                       (newline)
-                       (dolist (v context-names-and-locs)
-                         (pcase-let ((`(,name . ,loc) v))
-                           (insert " ")
-                           (insert (racket--format-error-location loc))
-                           (insert " ")
-                           (when name
-                             (insert-faced name 'racket-repl-error-label)))
-                         (newline)))))))
-            ((stdout)
+                (combine-after-change-calls
+                  (insert-faced msg 'racket-repl-error-message)
+                  (newline)
+                  ;; Heuristic: When something supplies exn-srclocs,
+                  ;; show those only. Otherwise show context if any.
+                  ;; This seems to work well for most runtime
+                  ;; exceptions, as well as for rackunit test failures
+                  ;; (where the srcloc suffices and the context esp
+                  ;; w/errortrace is useless noise).
+                  (cond
+                   (srclocs
+                    (dolist (loc srclocs)
+                      (insert " ")
+                      (insert (racket--format-error-location loc))
+                      (newline)))
+                   (context-names-and-locs
+                    (insert-faced (format "Context (%s):" context-kind)
+                                  'racket-repl-error-message)
+                    (newline)
+                    (dolist (v context-names-and-locs)
+                      (pcase-let ((`(,name . ,loc) v))
+                        (insert " ")
+                        (insert (racket--format-error-location loc))
+                        (insert " ")
+                        (when name
+                          (insert-faced name 'racket-repl-error-label t)))
+                      (newline))))))))
+            ('stdout
              (insert-filtered value 'racket-repl-stdout))
-            ((stderr)
+            ('stderr
              (insert-filtered value 'racket-repl-stderr))
-            (otherwise
-             (fresh-line)
+            (_
              (insert-faced value 'racket-repl-message))))
         (unless (eq kind 'prompt)
           (add-text-properties pt (point)



reply via email to

[Prev in Thread] Current Thread [Next in Thread]