emacs-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

compare-windows - synchronize points


From: Juri Linkov
Subject: compare-windows - synchronize points
Date: 11 Aug 2003 22:59:15 +0300
User-agent: Gnus/5.1002 (Gnus v5.10.2) Emacs/21.3 (gnu/linux)

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  <address@hidden>

        * 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/





reply via email to

[Prev in Thread] Current Thread [Next in Thread]