From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!not-for-mail From: Alan Mackenzie Newsgroups: gmane.emacs.devel Subject: Re: Proposed extension of show-paren-mode: Highlight parens when point is in L or R margin. Date: Sun, 12 Oct 2014 10:04:16 +0000 Message-ID: <20141012100416.GC3148@acm.acm> References: <20141011134312.GA4148@acm.acm> NNTP-Posting-Host: plane.gmane.org Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii X-Trace: ger.gmane.org 1413108636 26280 80.91.229.3 (12 Oct 2014 10:10:36 GMT) X-Complaints-To: usenet@ger.gmane.org NNTP-Posting-Date: Sun, 12 Oct 2014 10:10:36 +0000 (UTC) Cc: emacs-devel@gnu.org To: Stefan Monnier Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Sun Oct 12 12:10:30 2014 Return-path: Envelope-to: ged-emacs-devel@m.gmane.org Original-Received: from lists.gnu.org ([208.118.235.17]) by plane.gmane.org with esmtp (Exim 4.69) (envelope-from ) id 1XdG6f-0001m6-Jm for ged-emacs-devel@m.gmane.org; Sun, 12 Oct 2014 12:10:29 +0200 Original-Received: from localhost ([::1]:56733 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1XdG6e-00027Y-Tw for ged-emacs-devel@m.gmane.org; Sun, 12 Oct 2014 06:10:28 -0400 Original-Received: from eggs.gnu.org ([2001:4830:134:3::10]:38832) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1XdG6H-00023y-JD for emacs-devel@gnu.org; Sun, 12 Oct 2014 06:10:12 -0400 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1XdG6B-000750-7Y for emacs-devel@gnu.org; Sun, 12 Oct 2014 06:10:05 -0400 Original-Received: from colin.muc.de ([193.149.48.1]:61979 helo=mail.muc.de) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1XdG6A-00074u-Tl for emacs-devel@gnu.org; Sun, 12 Oct 2014 06:09:59 -0400 Original-Received: (qmail 11234 invoked by uid 3782); 12 Oct 2014 10:09:57 -0000 Original-Received: from acm.muc.de (pD951B032.dip0.t-ipconnect.de [217.81.176.50]) by colin.muc.de (tmda-ofmipd) with ESMTP; Sun, 12 Oct 2014 12:09:56 +0200 Original-Received: (qmail 3584 invoked by uid 1000); 12 Oct 2014 10:04:16 -0000 Content-Disposition: inline In-Reply-To: User-Agent: Mutt/1.5.21 (2010-09-15) X-Delivery-Agent: TMDA/1.1.12 (Macallan) X-Primary-Address: acm@muc.de X-detected-operating-system: by eggs.gnu.org: FreeBSD 8.x X-Received-From: 193.149.48.1 X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1.14 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-bounces+ged-emacs-devel=m.gmane.org@gnu.org Xref: news.gmane.org gmane.emacs.devel:175285 Archived-At: Hi, Stefan. On Sun, Oct 12, 2014 at 12:12:12AM -0400, Stefan Monnier wrote: > > So: If point is in the LH margin of the code, highlight the first paren > > on the line and its match, or failing that, the last paren on the line > > with its match. > Related ideas: > - show matching paren when point is right after the open paren or right > before the close paren. (see > http://stackoverflow.com/questions/25648067/emacs-matching-parenthesis-when-cursor-is-on-closing-parenthesis > for a 5-liner which does that). > - show matching paren, when there's only whitespace between point and > the open/close paren. Maybe for later! > This second idea is a superset of the one you suggest. I personally > don't use show-paren-mode because I find it distracting, so maybe > a superset would be too distracting. > > Then again, why not do the same if point is in a line comment? > Sorry, I don't know what "in a line comment" means. In a comment which extends to EOL, e.g. "//..." in C++, or ";..." in Lisp. > As for your patch, I'd rather see the new code moved to a new function. Done. > See more detailed comments below. > > + (defcustom show-paren-when-point-in-margin nil > Please don't call it "margin". OK. It's now called "periphery". [ .... ] > It's not at all clear to me why there has to be so many different cases > (IOW we'd need a comment that explains why we need such complexity). I've condensed these cases into a new function (see amended patch below). [ .... ] > This is a code duplication. Please move it to a separate helper function. No it's not. It appears just once, after my patch is applied. Here's the amended version, incorporating suggestions from you, Eli, and David. === modified file 'lisp/paren.el' *** lisp/paren.el 2014-02-10 01:34:22 +0000 --- lisp/paren.el 2014-10-12 09:46:33 +0000 *************** *** 72,77 **** --- 72,85 ---- :group 'paren-showing :version "20.3") + (defcustom show-paren-when-point-in-periphery nil + "If non-nil, show parens when point is in the line's periphery. + The periphery is either the whitespace at the beginning of a + line, or a comment \(or whitespace) at the end of a line." + :type 'boolean + :group 'paren-showing + :version "25.1") + (define-obsolete-face-alias 'show-paren-match-face 'show-paren-match "22.1") (define-obsolete-face-alias 'show-paren-mismatch-face *************** *** 112,117 **** --- 120,138 ---- (delete-overlay show-paren--overlay) (delete-overlay show-paren--overlay-1))) + (defun show-paren--categorize-paren (pos) + "Determine whether the character after POS has paren syntax, + and if so, return a cons (DIR . OUTSIDE). For an open paren, DIR + is 1 and OUTSIDE is the position before the paren. For a close + paren, DIR is -1 and OUTSIDE is the position after the paren. If + the character isn't a paren, return nil." + (cond + ((eq (syntax-class (syntax-after pos)) 4) + (cons 1 pos)) + ((eq (syntax-class (syntax-after pos)) 5) + (cons -1 (1+ pos))) + (t nil))) + (defvar show-paren-data-function #'show-paren--default "Function to find the opener/closer at point and its match. The function is called with no argument and should return either nil *************** *** 120,141 **** Where HERE-BEG..HERE-END is expected to be around point.") (defun show-paren--default () ! (let* ((oldpos (point)) ! (dir (cond ((eq (syntax-class (syntax-after (1- (point)))) 5) -1) ! ((eq (syntax-class (syntax-after (point))) 4) 1))) ! (unescaped ! (when dir ! ;; Verify an even number of quoting characters precede the paren. ! ;; Follow the same logic as in `blink-matching-open'. ! (= (if (= dir -1) 1 0) ! (logand 1 (- (point) ! (save-excursion ! (if (= dir -1) (forward-char -1)) ! (skip-syntax-backward "/\\") ! (point))))))) ! (here-beg (if (eq dir 1) (point) (1- (point)))) ! (here-end (if (eq dir 1) (1+ (point)) (point))) ! pos mismatch) ;; ;; Find the other end of the sexp. (when unescaped --- 141,190 ---- Where HERE-BEG..HERE-END is expected to be around point.") (defun show-paren--default () ! (let* ((ind-pos (save-excursion (back-to-indentation) (point))) ! (bol-pos (save-excursion (beginning-of-line) (point))) ! (eol-pos (save-excursion (end-of-line) ! (let ((s (syntax-ppss))) ! (if (nth 4 s) ! (goto-char (max (nth 8 s) ! (point-min)))) ! (skip-chars-backward " \t")) ! (point))) ! (oldpos (point)) ! dir paren-details unescaped pos mismatch here-beg here-end) ! (cond ! ;; Point is at a paren. ! ((eq (syntax-class (syntax-after (1- (point)))) 5) ! (setq dir -1)) ! ((eq (syntax-class (syntax-after (point))) 4) ! (setq dir 1)) ! ;; Point is in the WS before the code. ! ((and show-paren-when-point-in-periphery ! (< (point) ind-pos)) ! (setq paren-details ! (or (show-paren--categorize-paren ind-pos) ! (show-paren--categorize-paren (1- eol-pos))))) ! ;; Point is in a comment or whitespace after the code. ! ((and show-paren-when-point-in-periphery ! (>= (point) eol-pos)) ! (setq paren-details ! (or (show-paren--categorize-paren (1- eol-pos)) ! (show-paren--categorize-paren ind-pos))))) ! (when paren-details ! (setq dir (car paren-details) ! oldpos (cdr paren-details))) ! ! (when dir ! (setq unescaped ! (= (if (= dir -1) 1 0) ! (logand 1 (- oldpos ! (save-excursion ! (goto-char oldpos) ! (if (= dir -1) (backward-char)) ! (skip-syntax-backward "/\\") ! (point))))))) ! (setq here-beg (if (eq dir 1) oldpos (1- oldpos)) ! here-end (if (eq dir 1) (1+ oldpos) oldpos)) ;; ;; Find the other end of the sexp. (when unescaped *************** *** 149,155 **** ;; Scan across one sexp within that range. ;; Errors or nil mean there is a mismatch. (condition-case () ! (setq pos (scan-sexps (point) dir)) (error (setq pos t mismatch t))) ;; Move back the other way and verify we get back to the ;; starting point. If not, these two parens don't really match. --- 198,204 ---- ;; Scan across one sexp within that range. ;; Errors or nil mean there is a mismatch. (condition-case () ! (setq pos (scan-sexps oldpos dir)) (error (setq pos t mismatch t))) ;; Move back the other way and verify we get back to the ;; starting point. If not, these two parens don't really match. *************** *** 157,163 **** ;; or one is inside a comment. (when (integerp pos) (unless (condition-case () ! (eq (point) (scan-sexps pos (- dir))) (error nil)) (setq pos nil))) ;; If found a "matching" paren, see if it is the right --- 206,212 ---- ;; or one is inside a comment. (when (integerp pos) (unless (condition-case () ! (eq oldpos (scan-sexps pos (- dir))) (error nil)) (setq pos nil))) ;; If found a "matching" paren, see if it is the right *************** *** 215,221 **** ;; Otherwise, turn off any such highlighting. (if (or (not here-beg) (and (not show-paren-highlight-openparen) ! (> here-end (point)) (integerp there-beg))) (delete-overlay show-paren--overlay-1) (move-overlay show-paren--overlay-1 --- 264,270 ---- ;; Otherwise, turn off any such highlighting. (if (or (not here-beg) (and (not show-paren-highlight-openparen) ! (= here-beg (point)) (integerp there-beg))) (delete-overlay show-paren--overlay-1) (move-overlay show-paren--overlay-1 > Stefan -- Alan Mackenzie (Nuremberg, Germany).