From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!.POSTED!not-for-mail From: Alain Schneble Newsgroups: gmane.emacs.devel Subject: Show Paren mode: New prelude style Date: Thu, 27 Oct 2016 14:27:59 +0200 Message-ID: <86lgxa2cz4.fsf@realize.ch> NNTP-Posting-Host: blaine.gmane.org Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="=-=-=" X-Trace: blaine.gmane.org 1477571360 24953 195.159.176.226 (27 Oct 2016 12:29:20 GMT) X-Complaints-To: usenet@blaine.gmane.org NNTP-Posting-Date: Thu, 27 Oct 2016 12:29:20 +0000 (UTC) To: Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Thu Oct 27 14:29:16 2016 Return-path: Envelope-to: ged-emacs-devel@m.gmane.org Original-Received: from lists.gnu.org ([208.118.235.17]) by blaine.gmane.org with esmtp (Exim 4.84_2) (envelope-from ) id 1bzjnj-0003ZW-4J for ged-emacs-devel@m.gmane.org; Thu, 27 Oct 2016 14:28:55 +0200 Original-Received: from localhost ([::1]:41050 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bzjnl-0003to-L8 for ged-emacs-devel@m.gmane.org; Thu, 27 Oct 2016 08:28:57 -0400 Original-Received: from eggs.gnu.org ([2001:4830:134:3::10]:46999) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bzjnW-0003ns-MN for emacs-devel@gnu.org; Thu, 27 Oct 2016 08:28:44 -0400 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1bzjnS-0001FD-KY for emacs-devel@gnu.org; Thu, 27 Oct 2016 08:28:42 -0400 Original-Received: from clientmail.realize.ch ([46.140.89.53]:4137) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1bzjnS-0001Bf-6Y for emacs-devel@gnu.org; Thu, 27 Oct 2016 08:28:38 -0400 Original-Received: from rintintin.hq.realize.ch.lan.rit (Unknown [192.168.0.105]) by clientmail.realize.ch with ESMTP ; Thu, 27 Oct 2016 14:28:32 +0200 Original-Received: from myngb (192.168.66.64) by rintintin.hq.realize.ch.lan.rit (192.168.0.105) with Microsoft SMTP Server (TLS) id 15.0.516.32; Thu, 27 Oct 2016 14:28:00 +0200 X-ClientProxiedBy: rintintin.hq.realize.ch.lan.rit (192.168.0.105) To rintintin.hq.realize.ch.lan.rit (192.168.0.105) X-detected-operating-system: by eggs.gnu.org: Windows NT kernel [generic] X-Received-From: 46.140.89.53 X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: "Emacs development discussions." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Original-Sender: "Emacs-devel" Xref: news.gmane.org gmane.emacs.devel:208868 Archived-At: --=-=-= Content-Type: text/plain 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 --=-=-= Content-Type: text/x-patch Content-Disposition: inline; filename="0001-New-prelude-style-for-show-paren-mode.patch" Content-Description: New prelude style for Show Paren mode >From 5e5164ab6de8167004bf3ecac5937106984d64f9 Mon Sep 17 00:00:00 2001 From: Alain Schneble 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. +** 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. + + * 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) + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; 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 --=-=-=--