Skip to content

Commit

Permalink
Default to new racket-show-pseudo-tooltip; see #473
Browse files Browse the repository at this point in the history
  • Loading branch information
greghendershott committed May 21, 2020
1 parent 0db3e1b commit 025af90
Show file tree
Hide file tree
Showing 5 changed files with 117 additions and 11 deletions.
1 change: 1 addition & 0 deletions doc/generate.el
Expand Up @@ -97,6 +97,7 @@
racket-unvisit
racket-mode-start-faster
"Showing information"
racket-show-pseudo-tooltip
racket-show-echo-area
racket-show-header-line
racket-show-pos-tip
Expand Down
33 changes: 30 additions & 3 deletions doc/racket-mode.texi
Expand Up @@ -144,6 +144,7 @@ Other
Showing information
* racket-show-pseudo-tooltip::
* racket-show-echo-area::
* racket-show-header-line::
* racket-show-pos-tip::
Expand Down Expand Up @@ -1870,11 +1871,32 @@ error message due to the bytecode being different versions.
@section Showing information
@menu
* racket-show-pseudo-tooltip::
* racket-show-echo-area::
* racket-show-header-line::
* racket-show-pos-tip::
@end menu
@node racket-show-pseudo-tooltip
@subsection racket-show-pseudo-tooltip
Show using an overlay that resembles a tooltip.
This is nicer than @ref{racket-show-pos-tip} because it:
@itemize
@item
Doesn't flicker while navigating.
@item
Doesn't disappear after a timeout.
@item
Performs well when @code{x-gtk-use-system-tooltips} is nil.
@end itemize
On the other hand, this does not look as nice when displaying
text that spans multiple lines. In that case, we simply
left-justify everything and do not draw any border.
@node racket-show-echo-area
@subsection racket-show-echo-area
Expand Down Expand Up @@ -2274,10 +2296,12 @@ file-local variable.
A special hook variable to customize @code{racket-show}.
Example functions include
Example functions include:
@itemize
@item
@ref{racket-show-pseudo-tooltip}
@item
@ref{racket-show-echo-area}
@item
@ref{racket-show-pos-tip}
Expand All @@ -2301,8 +2325,11 @@ nil: Hide any persistent UI that might have been created to
show strings, such as by @ref{racket-show-header-line}.
@end itemize
POS is the buffer position for which to show the message, nil
meaning use some default position.
POS is the buffer position for which to show the message. It may
be nil only when VAL is nil or a blank string. When the buffer
content is a span, POS should be the end of the span. That way,
for example, a function that shows a tooltip can position it not
to hide the interesting span in the buffer.
@node Faces
@chapter Faces
Expand Down
17 changes: 10 additions & 7 deletions racket-custom.el
Expand Up @@ -397,13 +397,12 @@ level quieter. That way you can set the '* topic to a level like
:group 'racket-other)

(defcustom racket-show-functions
(list 'racket-show-echo-area
;; 'racket-show-header-line
'racket-show-pos-tip)
(list 'racket-show-pseudo-tooltip)
"A special hook variable to customize `racket-show'.
Example functions include
Example functions include:
- `racket-show-pseudo-tooltip'
- `racket-show-echo-area'
- `racket-show-pos-tip'
- `racket-show-header-line'
Expand All @@ -419,11 +418,15 @@ VAL is:
- nil: Hide any persistent UI that might have been created to
show strings, such as by `racket-show-header-line'.
POS is the buffer position for which to show the message, nil
meaning use some default position."
POS is the buffer position for which to show the message. It may
be nil only when VAL is nil or a blank string. When the buffer
content is a span, POS should be the end of the span. That way,
for example, a function that shows a tooltip can position it not
to hide the interesting span in the buffer."
:tag "Racket Show Functions"
:type 'hook
:options '(racket-show-echo-area
:options '(racket-show-pseudo-tooltip
racket-show-echo-area
racket-show-header-line
racket-show-pos-tip)
:safe #'functionp
Expand Down
73 changes: 73 additions & 0 deletions racket-show.el
Expand Up @@ -21,6 +21,7 @@
(require 'pos-tip)

(defun racket-show (val &optional pos)
"See the variable `racket-show-functions' for information about VAL and POS."
(dolist (f racket-show-functions)
(funcall f val pos)))

Expand Down Expand Up @@ -64,6 +65,78 @@ A value for the variable `racket-show-functions'."
(fboundp 'x-show-tip)
(not (memq window-system (list nil 'pc)))))

(defvar-local racket--pseudo-tooltip-overlay nil)

(defun racket-show-pseudo-tooltip (v &optional pos)
"Show using an overlay that resembles a tooltip.
This is nicer than `racket-show-pos-tip' because it:
- Doesn't flicker while navigating.
- Doesn't disappear after a timeout.
- Performs well when `x-gtk-use-system-tooltips' is nil.
On the other hand, this does not look as nice when displaying
text that spans multiple lines. In that case, we simply
left-justify everything and do not draw any border."
(cond ((racket--non-empty-string-p v)
(when racket--pseudo-tooltip-overlay
(delete-overlay racket--pseudo-tooltip-overlay))
(setq-local racket--pseudo-tooltip-overlay
(racket--make-pseudo-tooltip-overlay v pos)))
(racket--pseudo-tooltip-overlay
(delete-overlay racket--pseudo-tooltip-overlay)
(setq-local racket--pseudo-tooltip-overlay
nil))))

(defun racket--make-pseudo-tooltip-overlay (text pos)
(if (string-match-p "\n" text)
;; When text is multi-line, we don't try to simulate a tooltip,
;; exactly. Instead we simply "insert" the multiple lines left
;; justified, before the next line.
(let* ((text (propertize (concat text "\n")
'face
`(:inherit default
:foreground ,(face-foreground 'tooltip)
:background ,(face-background 'tooltip))))
(eol (save-excursion (goto-char pos) (point-at-eol)))
(ov (make-overlay eol (1+ eol))))
(overlay-put ov 'after-string text)
ov)
;; Otherwise we simulate a tooltip displayed one line below pos,
;; and one column right (although it might start further left
;; depending on window-width) "over" any existing text.
(pcase-let* ((text (propertize (concat " " text " ")
'face
`(:inherit default
:foreground ,(face-foreground 'tooltip)
:background ,(face-background 'tooltip)
:box (:line-width -1))))
(text-len (length text))
(bol (save-excursion (goto-char pos) (point-at-bol)))
(eol (save-excursion (goto-char pos) (point-at-eol)))
;; Position the tooltip on the next line, indented to
;; `pos' -- but not so far it ends off right edge.
(indent (max 0 (min (- pos bol)
(- (window-width) text-len))))
(beg (+ eol indent 1))
(next-eol (save-excursion (goto-char (1+ eol)) (point-at-eol))))
;; If the tip starts before next-eol, create an overlay with the
;; 'display property, covering the span of the tooltip text but
;; not beyond next-eol.
(if (< beg next-eol)
(let ((ov (make-overlay beg (min next-eol (+ beg text-len)))))
(overlay-put ov 'display text)
ov)
;; Else the tip starts after next-eol. So, create an overlay
;; on the newline, and use an after-string, where we prefix
;; enough blank spaces before the tooltip text itself to get
;; the desired indent.
(let* ((ov (make-overlay (1- next-eol) next-eol))
(blanks (make-string (- beg next-eol) 32)))
(overlay-put ov 'after-string (concat blanks text))
ov)))))

(provide 'racket-show)

;; racket-show.el ends here
4 changes: 3 additions & 1 deletion racket-xp.el
Expand Up @@ -368,7 +368,8 @@ or `racket-repl-describe'."
(pcase (get-text-property point 'help-echo)
((and s (pred racket--non-empty-string-p))
(racket-show s
(next-single-property-change point 'help-echo)))
(or (next-single-property-change point 'help-echo)
(point-max))))
(_ (racket-show "")))
(let ((def (get-text-property point 'racket-xp-def))
(use (get-text-property point 'racket-xp-use)))
Expand Down Expand Up @@ -776,6 +777,7 @@ manually."

(defun racket--xp-clear (&optional only-errors-p)
(with-silent-modifications
(racket-show "")
(racket--xp-clear-errors)
(racket--remove-overlays-in-buffer racket-xp-error-face)
(unless only-errors-p
Expand Down

0 comments on commit 025af90

Please sign in to comment.