From mboxrd@z Thu Jan 1 00:00:00 1970 Path: main.gmane.org!not-for-mail From: Juri Linkov Newsgroups: gmane.emacs.devel Subject: compare-windows - synchronize points Date: 11 Aug 2003 22:59:15 +0300 Organization: JURTA Sender: emacs-devel-bounces+emacs-devel=quimby.gnus.org@gnu.org Message-ID: <87adagx8x8.fsf@mail.jurta.org> NNTP-Posting-Host: deer.gmane.org Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii X-Trace: sea.gmane.org 1060633137 32474 80.91.224.253 (11 Aug 2003 20:18:57 GMT) X-Complaints-To: usenet@sea.gmane.org NNTP-Posting-Date: Mon, 11 Aug 2003 20:18:57 +0000 (UTC) Original-X-From: emacs-devel-bounces+emacs-devel=quimby.gnus.org@gnu.org Mon Aug 11 22:18:55 2003 Return-path: Original-Received: from quimby.gnus.org ([80.91.224.244]) by deer.gmane.org with esmtp (Exim 3.35 #1 (Debian)) id 19mJ83-0006sX-00 for ; Mon, 11 Aug 2003 22:18:55 +0200 Original-Received: from monty-python.gnu.org ([199.232.76.173]) by quimby.gnus.org with esmtp (Exim 3.12 #1 (Debian)) id 19mJFR-0002jX-00 for ; Mon, 11 Aug 2003 22:26:34 +0200 Original-Received: from localhost ([127.0.0.1] helo=monty-python.gnu.org) by monty-python.gnu.org with esmtp (Exim 4.20) id 19mJ1Z-0005Bp-Un for emacs-devel@quimby.gnus.org; Mon, 11 Aug 2003 16:12:13 -0400 Original-Received: from list by monty-python.gnu.org with tmda-scanned (Exim 4.20) id 19mJ19-000521-Ud for emacs-devel@gnu.org; Mon, 11 Aug 2003 16:11:47 -0400 Original-Received: from mail by monty-python.gnu.org with spam-scanned (Exim 4.20) id 19mJ0d-0004tE-7O for emacs-devel@gnu.org; Mon, 11 Aug 2003 16:11:46 -0400 Original-Received: from [64.246.52.22] (helo=ns5.tangramltd.com) by monty-python.gnu.org with esmtp (Exim 4.20) id 19mJ0c-0004tA-S1 for emacs-devel@gnu.org; Mon, 11 Aug 2003 16:11:14 -0400 Original-Received: from 80-235-40-35-dsl.mus.estpak.ee ([80.235.40.35] helo=mail.jurta.org) by ns5.tangramltd.com with esmtp (Exim 4.20) id 19mJ0U-00032G-7j for emacs-devel@gnu.org; Mon, 11 Aug 2003 23:11:06 +0300 Original-To: emacs-devel@gnu.org User-Agent: Gnus/5.1002 (Gnus v5.10.2) Emacs/21.3 (gnu/linux) Original-Lines: 258 X-AntiAbuse: This header was added to track abuse, please include it with any abuse report X-AntiAbuse: Primary Hostname - ns5.tangramltd.com X-AntiAbuse: Original Domain - gnu.org X-AntiAbuse: Originator/Caller UID/GID - [47 12] / [47 12] X-AntiAbuse: Sender Address Domain - jurta.org X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1.2 Precedence: list List-Id: Emacs development discussions. List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: emacs-devel-bounces+emacs-devel=quimby.gnus.org@gnu.org Xref: main.gmane.org gmane.emacs.devel:15888 X-Report-Spam: http://spam.gmane.org/gmane.emacs.devel:15888 Mostly, for comparing buffers Ediff is the best choice. But in some cases compare-windows is more useful. For example, when buffers contain very long lines with comma-separated fields, it's more convenient to enable lines truncation and use compare-windows to interactively browse the differences. However, when compare-windows finds the difference, it takes too much work to manually synchronize points between two windows. This patch allows to automatically synchronize points according to user-defined variable `compare-windows-sync'. If the value of this variable is a regexp, then the points in both windows are advanced to the next occurrence of this regexp. If the value of this variable is a function, then this function is called to advance points. This function is called only when points are already located on the mismatch position. The current behavior in such case is simply to call `ding' to beep or flash the screen. So successive calls of `compare-windows' will work in interlaced mode: on first call it advances points to the next difference, on second call it synchronizes points by skipping the difference, on third call it again advances points to the next difference and so on. The default value of the customizable variable `compare-windows-sync' is nil. So this patch will not change the current behavior (i.e. beeping if points are unmatched). The useful values of the variable `compare-windows-sync' could be functions `forward-word', `forward-sentence', `forward-paragraph', `end-of-defun' or regexp containing some field separator or a newline, depending on the nature of the difference units separator. The variable can be made buffer-local. Note also that if the command `compare-windows' is bound to a single key (for example, C-=), then this patch allows to browse all differences repeatedly with a single keystroke. This patch also fixes some minor documentation issues, such as moving a key sequence substitute \\[compare-windows] to the part of docstring where it actually talks about calling the `compare-windows', etc. 2003-08-11 Juri Linkov * compare-w.el (compare-windows-sync): New variable. (compare-windows): Use compare-windows-sync. (compare-windows-sync-regexp): New function. (compare-windows-whitespace): Doc fix. Index: emacs/lisp/compare-w.el =================================================================== RCS file: /cvsroot/emacs/emacs/lisp/compare-w.el,v retrieving revision 1.22 diff -c -r1.22 compare-w.el *** emacs/lisp/compare-w.el 16 Jul 2002 13:33:13 -0000 1.22 --- emacs/lisp/compare-w.el 11 Aug 2003 19:55:15 -0000 *************** *** 1,6 **** ;;; compare-w.el --- compare text between windows for Emacs ! ;; Copyright (C) 1986, 1989, 1993, 1997 Free Software Foundation, Inc. ;; Maintainer: FSF ;; Keywords: convenience files --- 1,6 ---- ;;; compare-w.el --- compare text between windows for Emacs ! ;; Copyright (C) 1986, 1989, 1993, 1997, 2003 Free Software Foundation, Inc. ;; Maintainer: FSF ;; Keywords: convenience files *************** *** 37,58 **** :group 'tools) (defcustom compare-windows-whitespace "\\(\\s-\\|\n\\)+" ! "*Regexp that defines whitespace sequences for \\[compare-windows]. That command optionally ignores changes in whitespace. The value of `compare-windows-whitespace' is normally a regexp, but it can also be a function. The function's job is to categorize any whitespace around (including before) point; it should also advance ! past any whitespace. The function is called in each buffer, with point at the current scanning point. It gets one argument, the point ! where `compare-windows' was originally called; it should not look at any text before that point. ! If the function returns the same value for both buffers, then the whitespace is considered to match, and is skipped." :type '(choice regexp function) :group 'compare-w) (defcustom compare-ignore-case nil "*Non-nil means \\[compare-windows] ignores case differences." :type 'boolean --- 37,78 ---- :group 'tools) (defcustom compare-windows-whitespace "\\(\\s-\\|\n\\)+" ! "*Regexp or function that defines whitespace sequences for `compare-windows'. That command optionally ignores changes in whitespace. The value of `compare-windows-whitespace' is normally a regexp, but it can also be a function. The function's job is to categorize any whitespace around (including before) point; it should also advance ! past any whitespace. The function is called in each window, with point at the current scanning point. It gets one argument, the point ! where \\[compare-windows] was originally called; it should not look at any text before that point. ! If the function returns the same value for both windows, then the whitespace is considered to match, and is skipped." :type '(choice regexp function) :group 'compare-w) + (defcustom compare-windows-sync nil + "*Regexp or function that defines synchronization sequences for the + case when points are already located on the mismatch position after + calling `compare-windows'. + + If the value of `compare-windows-sync' is a regexp, then the points + in both windows are advanced to the next occurrence of this regexp. + + The value of `compare-windows-sync' can also be a function. The + function's job is to advance points in both windows to the next + synchronization point. + + The useful values of this variable could be such functions as + `forward-word', `forward-sentence', `forward-paragraph', `end-of-defun' + or regexp containing some field separator or a newline, depending on + the nature of the difference units separator. The variable can be + made buffer-local." + :type '(choice regexp function) + :group 'compare-w) + (defcustom compare-ignore-case nil "*Non-nil means \\[compare-windows] ignores case differences." :type 'boolean *************** *** 72,78 **** A prefix arg means ignore changes in whitespace. The variable `compare-windows-whitespace' controls how whitespace is skipped. ! If `compare-ignore-case' is non-nil, changes in case are also ignored." (interactive "P") (let* (p1 p2 maxp1 maxp2 b1 b2 w2 (progress 1) --- 92,104 ---- A prefix arg means ignore changes in whitespace. The variable `compare-windows-whitespace' controls how whitespace is skipped. ! If `compare-ignore-case' is non-nil, changes in case are also ignored. ! ! If `compare-windows-sync' is non-nil, then successive calls of ! this command work in interlaced mode: ! on first call it advances points to the next difference, ! on second call it synchronizes points by skipping the difference, ! on third call it again advances points to the next difference and so on." (interactive "P") (let* (p1 p2 maxp1 maxp2 b1 b2 w2 (progress 1) *************** *** 81,87 **** (skip-func (if ignore-whitespace (if (stringp compare-windows-whitespace) 'compare-windows-skip-whitespace ! compare-windows-whitespace)))) (setq p1 (point) b1 (current-buffer)) (setq w2 (next-window (selected-window))) (if (eq w2 (selected-window)) --- 107,116 ---- (skip-func (if ignore-whitespace (if (stringp compare-windows-whitespace) 'compare-windows-skip-whitespace ! compare-windows-whitespace))) ! (sync-func (if (stringp compare-windows-sync) ! 'compare-windows-sync-regexp ! compare-windows-sync))) (setq p1 (point) b1 (current-buffer)) (setq w2 (next-window (selected-window))) (if (eq w2 (selected-window)) *************** *** 99,107 **** (push-mark) (while (> progress 0) ! ;; If both buffers have whitespace next to point, ;; optionally skip over it. - (and skip-func (save-excursion (let (p1a p2a w1 w2 result1 result2) --- 128,135 ---- (push-mark) (while (> progress 0) ! ;; If both windows have whitespace next to point, ;; optionally skip over it. (and skip-func (save-excursion (let (p1a p2a w1 w2 result1 result2) *************** *** 127,133 **** (set-window-point w2 p2)) (if (= (point) opoint1) ! (ding)))) ;; Move forward over whatever might be called whitespace. ;; compare-windows-whitespace is a regexp that matches whitespace. --- 155,176 ---- (set-window-point w2 p2)) (if (= (point) opoint1) ! (if (not sync-func) ! (ding) ! ;; If points are not advanced (i.e. already on mismatch position), ! ;; then synchronize points between both windows ! (save-excursion ! (funcall sync-func) ! (setq p1 (point)) ! (set-buffer b2) ! (goto-char p2) ! (funcall sync-func) ! (setq p2 (point))) ! (goto-char p1) ! (set-window-point w2 p2) ! ;; If points are still not synchronized, then ding ! (if (= (point) opoint1) ! (ding)))))) ;; Move forward over whatever might be called whitespace. ;; compare-windows-whitespace is a regexp that matches whitespace. *************** *** 135,141 **** ;; and find the latest point at which a match ends. ;; Don't try starting points before START, though. ;; Value is non-nil if whitespace is found. - ;; If there is whitespace before point, but none after, ;; then return t, but don't advance point. (defun compare-windows-skip-whitespace (start) --- 178,183 ---- *************** *** 158,163 **** --- 200,210 ---- (goto-char end) (or (/= beg opoint) (/= end opoint)))) + + ;; Move forward to the next synchronization regexp. + (defun compare-windows-sync-regexp () + (if (stringp compare-windows-sync) + (re-search-forward compare-windows-sync nil t))) (provide 'compare-w) =================================================================== PS: I have not signed legal papers yet, but I want to contribute more to the development of Emacs. -- http://www.jurta.org/emacs/