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

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

[nongnu] elpa/inf-ruby cd50ce8432 249/265: Creating eval overlay feature


From: ELPA Syncer
Subject: [nongnu] elpa/inf-ruby cd50ce8432 249/265: Creating eval overlay feature
Date: Sat, 9 Jul 2022 21:59:30 -0400 (EDT)

branch: elpa/inf-ruby
commit cd50ce8432d5ff77ec1b16aaaf75dac316d7acb5
Author: tunnes <ayrton.tunes@outlook.com>
Commit: tunnes <ayrton.tunes@outlook.com>

    Creating eval overlay feature
    
    Currently we have the print feature built in inf-ruby mode that inserts the 
result of a inferior Ruby evaluation
    on the current buffer, but this feature does not provide a similar 
experience that we might find on Lisp family
    languages so given that we decided on this issue to 
https://github.com/nonsequitur/inf-ruby/issues/148 to bring
    this feature more close to this behaviour using the Cider overlays 
implementation
    https://github.com/clojure-emacs/cider/blob/master/cider-eval.el#L829-L844
    
    Also we dicussed about the chain evaluation on Ruby that might by 
problematic evaluating onluy the last expression
    so to solve that we decided to implement the ruby-send-last-stmt on this 
comment
    https://github.com/nonsequitur/inf-ruby/issues/148#issuecomment-1007841475, 
please noticed that the support to
    enh-ruby-mode was not priorized on this first moment but we are open to 
community support to improve that.
    
     # Please enter the commit message for your changes. Lines starting
---
 inf-ruby.el | 131 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 130 insertions(+), 1 deletion(-)

diff --git a/inf-ruby.el b/inf-ruby.el
index b35f7d9495..2a82f5c4ff 100755
--- a/inf-ruby.el
+++ b/inf-ruby.el
@@ -62,6 +62,7 @@
 
 ;;; Code:
 
+(require 'cl-lib)
 (require 'comint)
 (require 'compile)
 (require 'ruby-mode)
@@ -505,10 +506,138 @@ Must not contain ruby meta characters.")
     (comint-send-string (inf-ruby-proc) (concat "\n" term "\n"))
     (when print (ruby-print-result))))
 
+(defface inf-ruby-result-overlay-face
+  '((((class color) (background light)) :background "black" :box (:line-width 
-1 :color "yellow")))
+  "Face used to display evaluation results at the end of line.")
+
+;; Overlay
+
+(defun inf-ruby--make-overlay (l r type &rest props)
+  "Place an overlay between L and R and return it.
+TYPE is a symbol put on the overlay's category property.  It is
+used to easily remove all overlays from a region with:
+    (remove-overlays start end 'category TYPE)
+PROPS is a plist of properties and values to add to the overlay."
+  (let ((o (make-overlay l (or r l) (current-buffer))))
+    (overlay-put o 'category type)
+    (overlay-put o 'inf-ruby-temporary t)
+    (while props (overlay-put o (pop props) (pop props)))
+    (push #'inf-ruby--delete-overlay (overlay-get o 'modification-hooks))
+    o))
+
+(defun inf-ruby--delete-overlay (ov &rest _)
+  "Safely delete overlay OV.
+Never throws errors, and can be used in an overlay's
+modification-hooks."
+  (ignore-errors (delete-overlay ov)))
+
+(cl-defun inf-ruby--make-result-overlay (value &rest props &key where duration 
(type 'result)
+                                           (format (concat " => %s "))
+                                           (prepend-face 
'inf-ruby-result-overlay-face)
+                                           &allow-other-keys)
+  "Place an overlay displaying VALUE at the end of line.
+VALUE is used as the overlay's after-string property, meaning it
+is displayed at the end of the overlay.  The overlay itself is
+placed from beginning to end of current line.
+Return nil if the overlay was not placed or if it might not be
+visible, and return the overlay otherwise.
+Return the overlay if it was placed successfully, and nil if it
+failed.
+This function takes some optional keyword arguments:
+- If WHERE is a number or a marker, apply the overlay over the
+  entire line at that place (defaulting to `point').  If it is a
+  cons cell, the car and cdr determine the start and end of the
+  overlay.
+- TYPE is passed to `inf-ruby--make-overlay' (defaults to `result').
+- FORMAT is a string passed to `format'.  It should have exactly
+  one %s construct (for VALUE).
+All arguments beyond these (PROPS) are properties to be used on
+the overlay."
+  (declare (indent 1))
+  (while (keywordp (car props))
+    (setq props (cddr props)))
+  ;; If the marker points to a dead buffer, don't do anything.
+  (let ((buffer (cond
+                 ((markerp where) (marker-buffer where))
+                 ((markerp (car-safe where)) (marker-buffer (car where)))
+                 (t (current-buffer)))))
+    (with-current-buffer buffer
+      (save-excursion
+        (when (number-or-marker-p where)
+          (goto-char where))
+        ;; Make sure the overlay is actually at the end of the sexp.
+        (skip-chars-backward "\r\n[:blank:]")
+        (let* ((beg (if (consp where)
+                        (car where)
+                      (save-excursion
+                        (backward-sexp 1)
+                        (point))))
+               (end (if (consp where)
+                        (cdr where)
+                      (line-end-position)))
+               (display-string (format format value))
+               (o nil))
+          (remove-overlays beg end 'category type)
+          (funcall #'put-text-property
+                   0 (length display-string)
+                   'face prepend-face
+                   display-string)
+          ;; If the display spans multiple lines or is very long, display it at
+          ;; the beginning of the next line.
+          (when (or (string-match "\n." display-string)
+                    (> (string-width display-string)
+                       (- (window-width) (current-column))))
+            (setq display-string (concat " \n" display-string)))
+          ;; Put the cursor property only once we're done manipulating the
+          ;; string, since we want it to be at the first char.
+          (put-text-property 0 1 'cursor 0 display-string)
+          (when (> (string-width display-string) (* 3 (window-width)))
+            (setq display-string
+                  (concat (substring display-string 0 (* 3 (window-width)))
+                          "...\nResult truncated.")))
+          ;; Create the result overlay.
+          (setq o (apply #'inf-ruby--make-overlay
+                         beg end type
+                         'after-string display-string
+                         props))
+          (pcase duration
+            ((pred numberp) (run-at-time duration nil 
#'inf-ruby--delete-overlay o))
+            (`command (if this-command
+                          (add-hook 'pre-command-hook
+                                    #'inf-ruby--remove-result-overlay
+                                    nil 'local)
+                        (inf-ruby--remove-result-overlay))))
+          (let ((win (get-buffer-window buffer)))
+            ;; Left edge is visible.
+            (when (and win
+                       (<= (window-start win) (point))
+                       ;; In 24.3 `<=' is still a binary predicate.
+                       (<= (point) (window-end win))
+                       ;; Right edge is visible. This is a little conservative
+                       ;; if the overlay contains line breaks.
+                       (or (< (+ (current-column) (string-width value))
+                              (window-width win))
+                           (not truncate-lines)))
+              o)))))))
+
+(defun inf-ruby--remove-result-overlay ()
+  "Remove result overlay from current buffer.
+This function also removes itself from `pre-command-hook'."
+  (remove-hook 'pre-command-hook #'inf-ruby--remove-result-overlay 'local)
+  (remove-overlays nil nil 'category 'result))
+
+(defun inf-ruby--eval-overlay (value)
+  "Make overlay for VALUE at POINT."
+  (inf-ruby--make-result-overlay (format "%S" value)
+                            :where (point)
+                            :duration 'command)
+  value)
+
+
 (defun ruby-print-result ()
   "Print the result of the last evaluation in the current buffer."
   (let ((proc (inf-ruby-proc)))
-    (insert
+    (inf-ruby--eval-overlay
      (with-current-buffer (or (inf-ruby-buffer)
                               inf-ruby-buffer)
        (while (not (and comint-last-prompt



reply via email to

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