From: Alain Schneble <a.s@realize.ch>
To: <emacs-devel@gnu.org>
Subject: Show Paren mode: New prelude style
Date: Thu, 27 Oct 2016 14:27:59 +0200 [thread overview]
Message-ID: <86lgxa2cz4.fsf@realize.ch> (raw)
[-- Attachment #1: Type: text/plain, Size: 1150 bytes --]
Below you will find a patch to extend show-paren-mode with a new
`prelude' style. It's an extension of `parenthesis' style. If the
matching opening paren is not visible, it will show the line of text
containing it as an overlay on the window's start line. I think it's
pretty useful, as it helps in keeping context when working e.g. in
defuns with many lines of code -- all without having to scroll up and
down.
If this extension sounds useful to be included for some of you as well,
I would be very happy to get some feedback. There for sure are things
to improve. (It actually works quite well with the use cases I tried.)
To try it out:
- emacs -Q
- In scratch buffer, enter some long lisp expressions that overlap the
window.
- (setq show-paren-style 'prelude)
- (show-paren-mode)
Note 1: There may already be such functionality available that I'm not
aware of. Please let me know if that is the case.
Note 2: When the fade-in line contains multiple opening parens, the
matching one is highlighted.
Note 3: I'm not too sure about the colors to choose for the new
`show-paren-prelude' face.
Any feedback is welcome.
Thanks,
Alain
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: New prelude style for Show Paren mode --]
[-- Type: text/x-patch, Size: 8217 bytes --]
From 5e5164ab6de8167004bf3ecac5937106984d64f9 Mon Sep 17 00:00:00 2001
From: Alain Schneble <a.s@realize.ch>
Date: Thu, 27 Oct 2016 13:47:18 +0200
Subject: [PATCH] New `prelude' style for show-paren-mode
* lisp/paren.el (show-paren-style): Add new prelude style to the list of
admissible styles.
* lisp/paren.el (show-paren--overlay-prelude): New overlay object.
* lisp/paren.el (show-paren-function): Implement new prelude style logic
to show line of text containing the matching opening paren on the
window's starting line, if it is not already visible.
* lisp/faces.el (show-paren-prelude): New defface to decorate new
show-paren--overlay-prelude overlay line.
* etc/NEWS (Show Paren mode): Add news entry for Show Paren mode, to
describe new style.
* doc/emacs/programs.texi (Matching): Update manual to include
description of new style.
---
doc/emacs/programs.texi | 5 +++-
etc/NEWS | 8 +++++++
lisp/faces.el | 10 ++++++++
lisp/paren.el | 61 ++++++++++++++++++++++++++++++++++++++++++-------
4 files changed, 75 insertions(+), 9 deletions(-)
diff --git a/doc/emacs/programs.texi b/doc/emacs/programs.texi
index 0c79d9c..20f9e97 100644
--- a/doc/emacs/programs.texi
+++ b/doc/emacs/programs.texi
@@ -851,7 +851,10 @@ Matching
@code{parenthesis} (show the matching paren), @code{expression}
(highlight the entire expression enclosed by the parens), and
@code{mixed} (highlight the matching paren if it is visible, the
-expression otherwise).
+expression otherwise). Furthermore, there is @code{prelude}, an
+extension of @code{parenthesis}, that shows the line of text
+containing the matching opening paren as an overlay on the window's
+start line, if it is not already visible.
@item
@code{show-paren-when-point-inside-paren}, when non-@code{nil}, causes
diff --git a/etc/NEWS b/etc/NEWS
index d9973c0..e78fce7 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -479,6 +479,14 @@ contents of the buffer to determine whether it's a C or C++ source
file.
\f
+** Show Paren mode
+
+*** New style 'prelude' to fade-in invisible lines of text.
+If point is at a closing paren and the matching opening paren is not
+visible, show line of text containing the opening paren as an overlay
+on the window's start line.
+
+\f
* New Modes and Packages in Emacs 26.1
** New Elisp data-structure library 'radix-tree'.
diff --git a/lisp/faces.el b/lisp/faces.el
index d6ec98b..20f1b02 100644
--- a/lisp/faces.el
+++ b/lisp/faces.el
@@ -2807,6 +2807,16 @@ show-paren-mismatch
"Face used for a mismatching paren."
:group 'paren-showing-faces)
+(defface show-paren-prelude
+ '((((class color) (background light))
+ :background "lightblue")
+ (((class color) (background dark))
+ :background "darkblue")
+ (t
+ :inherit underline))
+ "Face used to fade-in invisible lines of text."
+ :group 'paren-showing-faces)
+
\f
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; Manipulating font names.
diff --git a/lisp/paren.el b/lisp/paren.el
index e37cace..af5908c 100644
--- a/lisp/paren.el
+++ b/lisp/paren.el
@@ -40,10 +40,12 @@ paren-showing
(defcustom show-paren-style 'parenthesis
"Style used when showing a matching paren.
Valid styles are `parenthesis' (meaning show the matching paren),
-`expression' (meaning show the entire expression enclosed by the paren) and
+`expression' (meaning show the entire expression enclosed by the paren),
`mixed' (meaning show the matching paren if it is visible, and the expression
-otherwise)."
- :type '(choice (const parenthesis) (const expression) (const mixed)))
+otherwise) and `prelude' (meaning show the matching paren if it is
+visible, or the line of text containing the matching opening paren
+as an overlay in the window's start line)."
+ :type '(choice (const parenthesis) (const expression) (const mixed) (const prelude)))
(defcustom show-paren-delay 0.125
"Time in seconds to delay before showing a matching paren.
@@ -95,6 +97,9 @@ show-paren--overlay
(defvar show-paren--overlay-1
(let ((ol (make-overlay (point) (point) nil t))) (delete-overlay ol) ol)
"Overlay used to highlight the paren at point.")
+(defvar show-paren--overlay-prelude
+ (let ((ol (make-overlay (point) (point) nil t))) (delete-overlay ol) ol)
+ "Overlay used to show the line of text containing the opening paren.")
;;;###autoload
@@ -118,7 +123,8 @@ show-paren-mode
#'show-paren-function))
(unless show-paren-mode
(delete-overlay show-paren--overlay)
- (delete-overlay show-paren--overlay-1)))
+ (delete-overlay show-paren--overlay-1)
+ (delete-overlay show-paren--overlay-prelude)))
(defun show-paren--unescaped-p (pos)
"Determine whether the paren after POS is unescaped."
@@ -234,10 +240,12 @@ show-paren-function
(let ((data (and show-paren-mode (funcall show-paren-data-function))))
(if (not data)
(progn
- ;; If show-paren-mode is nil in this buffer or if not at a paren that
- ;; has a match, turn off any previous paren highlighting.
+ ;; If show-paren-mode is nil in this buffer or if not at a
+ ;; paren that has a match, turn off any previous paren
+ ;; highlighting and/or prelude overlay.
(delete-overlay show-paren--overlay)
- (delete-overlay show-paren--overlay-1))
+ (delete-overlay show-paren--overlay-1)
+ (delete-overlay show-paren--overlay-prelude))
;; Found something to highlight.
(let* ((here-beg (nth 0 data))
@@ -287,7 +295,44 @@ show-paren-function
there-beg there-end (current-buffer)))
;; Always set the overlay face, since it varies.
(overlay-put show-paren--overlay 'priority show-paren-priority)
- (overlay-put show-paren--overlay 'face face))))))
+ (overlay-put show-paren--overlay 'face face))
+ ;;
+ ;; If point is at a closing paren and the matching opening
+ ;; paren is not visible, show line of text containing the
+ ;; opening paren as an overlay on the window's start line.
+ (if (and (eq show-paren-style 'prelude)
+ there-beg ; Matching paren found?
+ (> here-beg there-beg) ; Point placed after closing paren?
+ ;; Point not on topmost line?
+ (> (line-number-at-pos here-end) (line-number-at-pos (window-start)))
+ ;; Opening paren not visible?
+ (not (pos-visible-in-window-p there-beg)))
+ (let* ((prelude-overlay-beg (window-start))
+ (prelude-overlay-end
+ ;; Include trailing newline to enable overlays to
+ ;; work properly on empty lines.
+ (1+ (line-end-position (- (- (count-lines prelude-overlay-beg here-end) 2)))))
+ (prelude-line-dist (- (- (count-lines there-beg here-end) 2)))
+ (prelude-text
+ (buffer-substring
+ (line-beginning-position prelude-line-dist)
+ ;; Again, include newline.
+ (1+ (line-end-position prelude-line-dist))))
+ ;; Translate opening paren pos to relative pos in
+ ;; overlay text.
+ (prelude-text-paren-beg
+ (- there-beg (line-beginning-position prelude-line-dist))))
+ ;; Highlight opening paren in overlay text.
+ (put-text-property
+ prelude-text-paren-beg (+ prelude-text-paren-beg (- there-end there-beg))
+ 'face 'show-paren-match prelude-text)
+ ;; Refresh overlay.
+ (move-overlay show-paren--overlay-prelude
+ prelude-overlay-beg prelude-overlay-end (current-buffer))
+ (overlay-put show-paren--overlay-prelude 'display prelude-text)
+ (overlay-put show-paren--overlay-prelude 'priority show-paren-priority)
+ (overlay-put show-paren--overlay-prelude 'face 'show-paren-prelude))
+ (delete-overlay show-paren--overlay-prelude))))))
(provide 'paren)
--
2.9.1
next reply other threads:[~2016-10-27 12:27 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-10-27 12:27 Alain Schneble [this message]
2016-10-27 12:51 ` Show Paren mode: New prelude style Alain Schneble
2016-10-31 19:30 ` Richard Copley
2016-10-31 19:57 ` Evgeny Roubinchtein
2016-10-27 15:26 ` Eli Zaretskii
2016-10-27 17:15 ` Alain Schneble
2016-10-27 17:31 ` Eli Zaretskii
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=86lgxa2cz4.fsf@realize.ch \
--to=a.s@realize.ch \
--cc=emacs-devel@gnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
Code repositories for project(s) associated with this external index
https://git.savannah.gnu.org/cgit/emacs.git
https://git.savannah.gnu.org/cgit/emacs/org-mode.git
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.