emacs-devel
[Top][All Lists]
Advanced

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

Show show-paren context in a child frame


From: Tassilo Horn
Subject: Show show-paren context in a child frame
Date: Sat, 05 Feb 2022 13:33:22 +0100
User-agent: mu4e 1.7.7; emacs 29.0.50

Hi all,

today I've discovered `show-paren-context-when-offscreen' which displays
the context around the opening paren in the echo area.  That's a very
nice feature, however it competes with eldoc, i.e., it'll show the
context in the echo area and a fraction of a second later, that's
repressed by eldoc's text (or the other way round depending on the
delays one uses).

Therefore, I've experimented with adding a special `child-frame' value
for `show-paren-context-when-offscreen' which displays the context in a
child frame.  This works pretty well although setting up a child frame
with corresponding buffer for a kind of tooltip pane requires quite some
gymnastics in frame parameters and buffer-local variables which I've
copied from vertico.  Comments welcome!

Bye,
Tassilo

>From f3300f0cffd5344c013e3be0690f2ff1b50a1703 Mon Sep 17 00:00:00 2001
From: Tassilo Horn <tsdh@gnu.org>
Date: Sat, 5 Feb 2022 13:22:55 +0100
Subject: [PATCH] Allow showing show-paren context in child frame

---
 lisp/paren.el | 91 ++++++++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 87 insertions(+), 4 deletions(-)

diff --git a/lisp/paren.el b/lisp/paren.el
index 0065bba72e..f8a56ddf24 100644
--- a/lisp/paren.el
+++ b/lisp/paren.el
@@ -260,6 +260,86 @@ show-paren--default
                  (if (= dir 1) pos (1+ pos))
                  mismatch)))))))
 
+(defvar show-paren--context-child-frame nil)
+
+(defun show-paren--context-child-frame-buffer (text)
+  (with-current-buffer
+      (get-buffer-create " *show-paren context*")
+    (dolist (var '((mode-line-format . nil)
+                   (header-line-format . nil)
+                   (tab-line-format . nil)
+                   (tab-bar-format . nil) ;; Emacs 28 tab-bar-format
+                   (frame-title-format . "")
+                   (truncate-lines . t)
+                   (cursor-in-non-selected-windows . nil)
+                   (cursor-type . nil)
+                   (show-trailing-whitespace . nil)
+                   (display-line-numbers . nil)
+                   (left-fringe-width . nil)
+                   (right-fringe-width . nil)
+                   (left-margin-width . 0)
+                   (right-margin-width . 0)
+                   (fringes-outside-margins . 0)
+                   (buffer-read-only . t)))
+      (set (make-local-variable (car var)) (cdr var)))
+    (let ((inhibit-modification-hooks t)
+          (inhibit-read-only t))
+      (erase-buffer)
+      (insert text)
+      (goto-char (point-min)))
+    (current-buffer)))
+
+(defun show-paren--show-context-in-child-frame (text)
+  (let ((minibuffer (minibuffer-window (window-frame)))
+        (buffer (show-paren--context-child-frame-buffer text))
+        (x (window-pixel-left))
+        (y (window-pixel-top)))
+    (show-paren--delete-context-child-frame)
+    (setq show-paren--context-child-frame
+          (make-frame
+           `((parent-frame . ,(window-frame))
+             (minibuffer . ,minibuffer)
+             (visibility . nil)
+             (width . 0)
+             (height . 0)
+             (no-accept-focus . t)
+             (no-focus-on-map . t)
+             (min-width . t)
+             (min-height . t)
+             (border-width . 0)
+             (child-frame-border-width . 1)
+             (left-fringe . 0)
+             (right-fringe . 0)
+             (vertical-scroll-bars . nil)
+             (horizontal-scroll-bars . nil)
+             (menu-bar-lines . 0)
+             (tool-bar-lines . 0)
+             (tab-bar-lines . 0)
+             (no-other-frame . t)
+             (no-other-window . t)
+             (no-delete-other-windows . t)
+             (unsplittable . t)
+             (undecorated . t)
+             (cursor-type . nil)
+             (no-special-glyphs . t)
+             (desktop-dont-save . t))))
+    (let ((win (frame-root-window show-paren--context-child-frame))
+          (window-min-height 0)
+          (window-min-width 0))
+      (set-window-buffer win buffer)
+      (set-window-dedicated-p win t)
+      (set-frame-size show-paren--context-child-frame
+                      (string-width text)
+                      (length (string-lines text)))
+      (set-frame-position show-paren--context-child-frame x y)
+      (make-frame-visible show-paren--context-child-frame)
+      (add-hook 'post-command-hook #'show-paren--delete-context-child-frame))))
+
+(defun show-paren--delete-context-child-frame ()
+  (when show-paren--context-child-frame
+    (delete-frame show-paren--context-child-frame))
+  (remove-hook 'post-command-hook #'show-paren--delete-context-child-frame))
+
 (defun show-paren-function ()
   "Highlight the parentheses until the next input arrives."
   (let ((data (and show-paren-mode (funcall show-paren-data-function))))
@@ -299,8 +379,8 @@ show-paren-function
         ;; Otherwise, turn off any such highlighting.
         (if (or (not here-beg)
                 (and (not show-paren-highlight-openparen)
-                    (> here-end (point))
-                    (<= here-beg (point))
+                     (> here-end (point))
+                     (<= here-beg (point))
                      (integerp there-beg)))
             (delete-overlay show-paren--overlay-1)
           (move-overlay show-paren--overlay-1
@@ -315,7 +395,7 @@ show-paren-function
             (delete-overlay show-paren--overlay)
           (if highlight-expression
               (move-overlay show-paren--overlay
-                           (if (< there-beg here-beg) here-end here-beg)
+                            (if (< there-beg here-beg) here-end here-beg)
                             (if (< there-beg here-beg) there-beg there-end)
                             (current-buffer))
             (move-overlay show-paren--overlay
@@ -330,7 +410,10 @@ show-paren-function
                 (let ((open-paren-line-string
                        (blink-paren-open-paren-line-string openparen))
                       (message-log-max nil))
-                  (minibuffer-message "Matches %s" open-paren-line-string))))
+                  (if (and (eq show-paren-context-when-offscreen 'child-frame)
+                           (display-graphic-p))
+                      (show-paren--show-context-in-child-frame 
open-paren-line-string)
+                    (minibuffer-message "Matches %s" 
open-paren-line-string)))))
           ;; Always set the overlay face, since it varies.
           (overlay-put show-paren--overlay 'priority show-paren-priority)
           (overlay-put show-paren--overlay 'face face))))))
-- 
2.35.1


reply via email to

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