From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!not-for-mail From: Juri Linkov Newsgroups: gmane.emacs.devel Subject: Occur multi-line matches Date: Tue, 23 Mar 2010 09:27:33 +0200 Organization: JURTA Message-ID: <87fx3rmrie.fsf@mail.jurta.org> NNTP-Posting-Host: lo.gmane.org Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii X-Trace: dough.gmane.org 1269329420 28850 80.91.229.12 (23 Mar 2010 07:30:20 GMT) X-Complaints-To: usenet@dough.gmane.org NNTP-Posting-Date: Tue, 23 Mar 2010 07:30:20 +0000 (UTC) To: emacs-devel@gnu.org Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Tue Mar 23 08:30:12 2010 Return-path: Envelope-to: ged-emacs-devel@m.gmane.org Original-Received: from lists.gnu.org ([199.232.76.165]) by lo.gmane.org with esmtp (Exim 4.69) (envelope-from ) id 1NtyYz-0007gT-CE for ged-emacs-devel@m.gmane.org; Tue, 23 Mar 2010 08:30:09 +0100 Original-Received: from localhost ([127.0.0.1]:50985 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1NtyYy-0002np-8n for ged-emacs-devel@m.gmane.org; Tue, 23 Mar 2010 03:30:08 -0400 Original-Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1NtyYD-0002mu-V4 for emacs-devel@gnu.org; Tue, 23 Mar 2010 03:29:22 -0400 Original-Received: from [140.186.70.92] (port=37877 helo=eggs.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1NtyXu-0002j6-B0 for emacs-devel@gnu.org; Tue, 23 Mar 2010 03:29:18 -0400 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.69) (envelope-from ) id 1NtyXh-0002as-Ua for emacs-devel@gnu.org; Tue, 23 Mar 2010 03:29:01 -0400 Original-Received: from smtp-out1.starman.ee ([85.253.0.3]:42961 helo=mx1.starman.ee) by eggs.gnu.org with esmtp (Exim 4.69) (envelope-from ) id 1NtyXh-0002aJ-5U for emacs-devel@gnu.org; Tue, 23 Mar 2010 03:28:49 -0400 X-Virus-Scanned: by Amavisd-New at mx1.starman.ee Original-Received: from mail.starman.ee (82.131.30.14.cable.starman.ee [82.131.30.14]) by mx1.starman.ee (Postfix) with ESMTP id 88DCB3F407F for ; Tue, 23 Mar 2010 09:28:41 +0200 (EET) User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/24.0.50 (x86_64-pc-linux-gnu) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.6, seldom 2.4 (older, 4) X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "Emacs development discussions." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Original-Sender: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Errors-To: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Xref: news.gmane.org gmane.emacs.devel:122533 Archived-At: To reduce the size of etc/TODO, I implemented one of the two related tasks: ** Make occur correctly handle matches that span more than one line, as well as overlapping matches. ** Make occur handle multi-line matches cleanly with context. and fixed all problems of multi-line matches discussed in http://thread.gmane.org/gmane.emacs.devel/38918 with the following patch (I'll try to do the second task for context lines later): === modified file 'lisp/replace.el' --- lisp/replace.el 2010-03-22 23:02:56 +0000 +++ lisp/replace.el 2010-03-23 07:27:03 +0000 @@ -1045,7 +1045,7 @@ (defun occur-rename-buffer (&optional un (defun occur (regexp &optional nlines) "Show all lines in the current buffer containing a match for REGEXP. -This function can not handle matches that span more than one line. +If a match spreads across multiple lines, all those lines are shown. Each line is displayed with NLINES lines before and after, or -NLINES before if NLINES is negative. @@ -1210,11 +1210,14 @@ (defun occur-engine (regexp buffers out- (when (setq endpt (re-search-forward regexp nil t)) (setq matches (1+ matches)) ;; increment match count (setq matchbeg (match-beginning 0)) - (setq lines (+ lines (1- (count-lines origpt endpt)))) + ;; Get beginning of first match line and end of the last. (save-excursion (goto-char matchbeg) - (setq begpt (line-beginning-position) - endpt (line-end-position))) + (setq begpt (line-beginning-position)) + (goto-char endpt) + (setq endpt (line-end-position))) + ;; Sum line numbers up to the first match line. + (setq lines (+ lines (count-lines origpt begpt))) (setq marker (make-marker)) (set-marker marker matchbeg) (setq curstring (occur-engine-line begpt endpt)) @@ -1234,24 +1237,33 @@ (defun occur-engine (regexp buffers out- curstring) (setq start (match-end 0)))) ;; Generate the string to insert for this match - (let* ((out-line + (let* ((match-prefix + ;; Using 7 digits aligns tabs properly. + (apply #'propertize (format "%7d:" lines) + (append + (when prefix-face + `(font-lock-face prefix-face)) + `(occur-prefix t mouse-face (highlight) + occur-target ,marker follow-link t + help-echo "mouse-2: go to this occurrence")))) + (match-str + ;; We don't put `mouse-face' on the newline, + ;; because that loses. And don't put it + ;; on context lines to reduce flicker. + (propertize curstring 'mouse-face (list 'highlight) + 'occur-target marker + 'follow-link t + 'help-echo + "mouse-2: go to this occurrence")) + (out-line (concat - ;; Using 7 digits aligns tabs properly. - (apply #'propertize (format "%7d:" lines) - (append - (when prefix-face - `(font-lock-face prefix-face)) - `(occur-prefix t mouse-face (highlight) - occur-target ,marker follow-link t - help-echo "mouse-2: go to this occurrence"))) - ;; We don't put `mouse-face' on the newline, - ;; because that loses. And don't put it - ;; on context lines to reduce flicker. - (propertize curstring 'mouse-face (list 'highlight) - 'occur-target marker - 'follow-link t - 'help-echo - "mouse-2: go to this occurrence") + match-prefix + ;; Add non-numeric prefix to all non-first lines + ;; of multi-line matches. + (replace-regexp-in-string + "\n" + "\n :" + match-str) ;; Add marker at eol, but no mouse props. (propertize "\n" 'occur-target marker))) (data @@ -1270,7 +1282,11 @@ (defun occur-engine (regexp buffers out- (goto-char endpt)) (if endpt (progn - (setq lines (1+ lines)) + ;; Sum line numbers between first and last match lines. + (setq lines (+ lines (count-lines begpt endpt) + ;; Add 1 for empty last match line since + ;; count-lines returns 1 line less. + (if (and (bolp) (eolp)) 1 0))) ;; On to the next match... (forward-line 1)) (goto-char (point-max)))))) -- Juri Linkov http://www.jurta.org/emacs/