emacs-devel
[Top][All Lists]
Advanced

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

Re: compare-windows - synchronize points


From: Juri Linkov
Subject: Re: compare-windows - synchronize points
Date: 14 Aug 2003 08:33:10 +0300
User-agent: Gnus/5.1002 (Gnus v5.10.2) Emacs/21.3 (gnu/linux)

Richard Stallman <address@hidden> writes:
> I think that end-of-defun would move too far--the end of the defun can
> easily be 100 lines down.  This would be quite likely to overlook
> further interesting differences.

I agree.  The end-of-defun is useless on large functions.

>     Currently the variable compare-windows-sync has no -function suffix,
>     because it can hold whether a function or a regexp.
> 
> Have you found the regexp case to be useful in any real situation?

Yes, the regexp is useful.  For example, if different files contain
changes separated by some fixed string (as e.g. field separators
in comma-separated value lists, etc.)

>     > Another idea I have for syncing up is that a program could use a
>     > simple quadratic algorithm to find the first matching 4-character
>     > string in the two buffers, and move there.  This might get painfully
>     > slow when there are substantial insertions, though.
> 
> If it tried syncing up by comparing entire lines, it could handle
> even quite large changes fairly fast.  Would you like to give that a try?

OK, here is quick implementation of simple quadratic algorithm.
Seems, it works well on small differences, but fails on big ones.
Increasing the default numbers improves the situation,
but function starts to get more slow.

(defvar compare-windows-sync-string-size 4)
(defvar compare-windows-sync-region-size 200)
(defvar compare-windows-sync-point nil)
(defvar compare-windows-sync 'compare-windows-sync-default-function)

;; Function works in two passes: one call on each window.
;; On first call both matching points are computed,
;; and one of them is stored in compare-windows-sync-point
;; to be used when this function is called on second window.
(defun compare-windows-sync-default-function ()
  (if compare-windows-sync-point
      (progn
        (if (numberp compare-windows-sync-point)
            (goto-char compare-windows-sync-point))
        (setq compare-windows-sync-point nil))
    (let* ((case-fold-search compare-ignore-case)
           (w2 (next-window (selected-window)))
           (b2 (window-buffer w2))
           (op2 (1+ (window-point w2)))
           (op1 (point))
           (p1 (1+ op1))
           (bound1 (- (min (+ p1 compare-windows-sync-region-size)
                           (point-max))
                      compare-windows-sync-string-size))
           (bound2 (- (min (+ op2 compare-windows-sync-region-size)
                           (with-current-buffer b2 (point-max)))
                      compare-windows-sync-string-size))
           s1 p2 p2s pp)
      (while (< p1 bound1)
        (setq s1 (buffer-substring-no-properties
                  p1
                  (+ p1 compare-windows-sync-string-size)))
        (setq p2 (with-current-buffer b2
                   (goto-char op2)
                   (search-forward s1 bound2 t)))
        (when p2
          (setq p2 (- p2 compare-windows-sync-string-size))
          ;; calculate the distance between two matching points
          (setq p2s (cons (list (sqrt (+ (expt (- p1 op1) 2)
                                         (expt (- p2 op2) 2))) p1 p2)
                          p2s)))
        (setq p1 (1+ p1)))
      ;; use matching points with minimal distance
      (when p2s
        (setq pp (cdr (assoc (apply 'min (mapcar 'car p2s)) p2s)))
        (goto-char (car pp)))
      (setq compare-windows-sync-point (or (cadr pp) t)))))

-- 
http://www.jurta.org/emacs/





reply via email to

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