emacs-elpa-diffs
[Top][All Lists]
Advanced

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

[elpa] 04/04: * packages/vlf: Version 1.4. Add Ediff integration.


From: Andrey Kotlarski
Subject: [elpa] 04/04: * packages/vlf: Version 1.4. Add Ediff integration.
Date: Sat, 01 Feb 2014 20:08:38 +0000

m00natic pushed a commit to branch master
in repository elpa.

commit 694254bbc5ca27dce88f5ba9cecbd15ca2092816
Author: Andrey Kotlarski <address@hidden>
Date:   Sat Feb 1 21:58:53 2014 +0200

        * packages/vlf: Version 1.4.  Add Ediff integration.
    
        * vlf-ediff.el: New file.
    
        * vlf.el: Fix autoload declarations.
        (vlf-ediff-buffers): Add autoload declaration.
        (vlf-mode-map): Add binding for `vlf-ediff-buffers'.
        (vlf): Update docstring.
        (vlf-set-batch-size): New command.
        (vlf-change-batch-size): Use it.
        (vlf-end-of-file): Update file size information.
    
        * vlf-write.el (vlf-write): Temporarily lower tramp verbosity
        and turn off font lock.
    
        * vlf-search.el (vlf-re-search): Temporarily lower tramp verbosity
        and turn off font lock.
    
        * vlf-occur.el (vlf-occur): Restore undo information.
        (vlf-build-occur): Temporarily lower tramp verbosity.
    
        * vlf-base.el (vlf-move-to-chunk): Handle cases where chunk
        outside file size is requested.
        (vlf-delete-region): New function.
        (vlf-move-to-chunk-1): Use it.  Optimize jumps to next/previous
        chunk.
        (vlf-insert-file-contents-safe): Rename to `vlf-insert-file-contents-1'.
        (vlf-adjust-start): Simplify.
        (vlf-adjust-end): Remove.
---
 packages/vlf/vlf-base.el   |  218 ++++++++++++++++++------------
 packages/vlf/vlf-ediff.el  |  325 ++++++++++++++++++++++++++++++++++++++++++++
 packages/vlf/vlf-occur.el  |    7 +-
 packages/vlf/vlf-search.el |   79 +++++++++--
 packages/vlf/vlf-write.el  |    6 +-
 packages/vlf/vlf.el        |   40 ++++--
 6 files changed, 556 insertions(+), 119 deletions(-)

diff --git a/packages/vlf/vlf-base.el b/packages/vlf/vlf-base.el
index a2ad0e0..2a530f8 100644
--- a/packages/vlf/vlf-base.el
+++ b/packages/vlf/vlf-base.el
@@ -94,13 +94,27 @@ When given MINIMAL flag, skip non important operations.
 If same as current chunk is requested, do nothing.
 Return number of bytes moved back for proper decoding and number of
 bytes added to the end."
-  (unless (and (= start vlf-start-pos)
-               (= end vlf-end-pos))
-    (vlf-verify-size)
-    (let ((shifts (vlf-move-to-chunk-1 start end)))
-      (and shifts (not minimal)
-           (vlf-update-buffer-name))
-      shifts)))
+  (vlf-verify-size)
+  (cond ((or (<= end start) (<= end 0)
+             (<= vlf-file-size start))
+         (when (or (not (buffer-modified-p))
+                   (y-or-n-p "Chunk modified, are you sure? "))
+           (erase-buffer)
+           (set-buffer-modified-p nil)
+           (let ((place (if (<= vlf-file-size start)
+                            vlf-file-size
+                          0)))
+             (setq vlf-start-pos place
+                   vlf-end-pos place)
+             (if (not minimal)
+                 (vlf-update-buffer-name))
+             (cons (- start place) (- place end)))))
+        ((or (/= start vlf-start-pos)
+             (/= end vlf-end-pos))
+         (let ((shifts (vlf-move-to-chunk-1 start end)))
+           (and shifts (not minimal)
+                (vlf-update-buffer-name))
+           shifts))))
 
 (defun vlf-move-to-chunk-1 (start end)
   "Move to chunk enclosed by START END keeping as much edits if any.
@@ -132,54 +146,58 @@ bytes added to the end."
             (shift-end 0))
         (let ((pos (+ (position-bytes (point)) vlf-start-pos))
               (inhibit-read-only t))
-          (cond ((< end edit-end)
-                 (let* ((del-pos (1+ (or (byte-to-position
-                                          (- end vlf-start-pos))
-                                         0)))
-                        (del-len (length (encode-coding-region
-                                          del-pos (point-max)
-                                          buffer-file-coding-system
-                                          t))))
-                   (setq end (- (if (zerop vlf-end-pos)
-                                    vlf-file-size
-                                  vlf-end-pos)
-                                del-len))
-                   (vlf-with-undo-disabled
-                    (delete-region del-pos (point-max)))))
+          (cond ((= end vlf-start-pos)
+                 (or (eq buffer-undo-list t)
+                     (setq buffer-undo-list nil))
+                 (vlf-with-undo-disabled (erase-buffer))
+                 (setq modified nil))
+                ((< end edit-end)
+                 (setq end (car (vlf-delete-region
+                                 (point-min) vlf-start-pos edit-end
+                                 end (min (or (byte-to-position
+                                               (- end vlf-start-pos))
+                                              (point-min))
+                                          (point-max))
+                                 nil))))
                 ((< edit-end end)
                  (vlf-with-undo-disabled
                   (setq shift-end (cdr (vlf-insert-file-contents
-                                        vlf-end-pos end
-                                        (/= start vlf-end-pos) t
+                                        vlf-end-pos end nil t
                                         (point-max)))))))
-          (cond ((< vlf-start-pos start)
-                 (let* ((del-pos (1+ (byte-to-position
-                                      (- start vlf-start-pos))))
-                        (del-len (length (encode-coding-region
-                                          (point-min) del-pos
-                                          buffer-file-coding-system
-                                          t))))
-                   (setq start (+ vlf-start-pos del-len))
-                   (vlf-with-undo-disabled
-                    (delete-region (point-min) del-pos))
-                   (vlf-shift-undo-list (- (point-min) del-pos))))
+          (setq vlf-end-pos (+ end shift-end))
+          (cond ((= start edit-end)
+                 (or (eq buffer-undo-list t)
+                     (setq buffer-undo-list nil))
+                 (vlf-with-undo-disabled
+                  (delete-region (point-min) (point)))
+                 (setq modified nil))
+                ((< vlf-start-pos start)
+                 (let ((del-info (vlf-delete-region
+                                  (point-min) vlf-start-pos
+                                  vlf-end-pos start
+                                  (min (or (byte-to-position
+                                            (- start vlf-start-pos))
+                                           (point))
+                                       (point-max)) t)))
+                   (setq start (car del-info))
+                   (vlf-shift-undo-list (- (point-min)
+                                           (cdr del-info)))))
                 ((< start vlf-start-pos)
                  (let ((edit-end-pos (point-max)))
                    (vlf-with-undo-disabled
                     (setq shift-start (car (vlf-insert-file-contents
-                                            start vlf-start-pos t
-                                            (/= end vlf-start-pos)
+                                            start vlf-start-pos t nil
                                             edit-end-pos)))
                     (goto-char (point-min))
                     (insert (delete-and-extract-region
                              edit-end-pos (point-max))))
-                   (vlf-shift-undo-list (- (point-max) edit-end-pos)))))
+                   (vlf-shift-undo-list (- (point-max)
+                                           edit-end-pos)))))
           (setq start (- start shift-start))
           (goto-char (or (byte-to-position (- pos start))
                          (byte-to-position (- pos vlf-start-pos))
                          (point-max)))
-          (setq vlf-start-pos start
-                vlf-end-pos (+ end shift-end)))
+          (setq vlf-start-pos start))
         (set-buffer-modified-p modified)
         (set-visited-file-modtime)
         (cons shift-start shift-end))))))
@@ -227,11 +245,33 @@ bytes added to the end."
         (setq shift-start (vlf-adjust-start start safe-end position
                                             adjust-end)
               start (- start shift-start))
-      (vlf-insert-file-contents-safe start safe-end position))
+      (vlf-insert-file-contents-1 start safe-end position))
     (if adjust-end
-        (setq shift-end (vlf-adjust-end start end position)))
+        (setq shift-end (- (car (vlf-delete-region position start
+                                                   safe-end end
+                                                   (point-max)
+                                                   nil 'start))
+                           end)))
     (cons shift-start shift-end)))
 
+(defun vlf-insert-file-contents-1 (start end position)
+  "Extract decoded file bytes START to END at POSITION."
+  (let ((coding buffer-file-coding-system))
+    (insert-file-contents-literally buffer-file-name nil start end)
+    (let ((coding-system-for-read coding))
+      (decode-coding-inserted-region position (point-max)
+                                     buffer-file-name nil start end)))
+  (when (eq (detect-coding-region position (min (+ position
+                                                   vlf-sample-size)
+                                                (point-max)) t)
+            'no-conversion)
+    (delete-region position (point-max))
+    (insert-file-contents-literally buffer-file-name nil start end)
+    (let ((coding-system-for-read nil))
+      (decode-coding-inserted-region position (point-max)
+                                     buffer-file-name nil start end)))
+  (setq buffer-file-coding-system last-coding-system-used))
+
 (defun vlf-adjust-start (start end position adjust-end)
   "Adjust chunk beginning at absolute START to END till content can\
 be properly decoded.  Use buffer POSITION as start.
@@ -243,7 +283,7 @@ Return number of bytes moved back for proper decoding."
          (strict (or (= sample-end vlf-file-size)
                      (and (not adjust-end) (= sample-end end))))
          (shift 0))
-    (while (and (progn (vlf-insert-file-contents-safe
+    (while (and (progn (vlf-insert-file-contents-1
                         safe-start sample-end position)
                        (not (zerop safe-start)))
                 (< shift 3)
@@ -259,53 +299,59 @@ Return number of bytes moved back for proper decoding."
             safe-start (1- safe-start)
             chunk-size (1+ chunk-size))
       (delete-region position (point-max)))
-    (let ((cut-pos position)
-          (cut-len 0))
-      (while (< safe-start start)
-        (setq cut-len (length (encode-coding-region
-                               cut-pos (1+ cut-pos)
-                               buffer-file-coding-system t))
-              cut-pos (1+ cut-pos)
-              safe-start (+ safe-start cut-len)))
-      (if (< start safe-start)
-          (setq safe-start (- safe-start cut-len)
-                cut-pos (1- cut-pos)))
-      (if (= sample-end end)
-          (delete-region position cut-pos)
-        (delete-region position (point-max))
-        (vlf-insert-file-contents-safe safe-start end position)))
+    (setq safe-start (car (vlf-delete-region position safe-start
+                                             sample-end start
+                                             position t 'start)))
+    (unless (= sample-end end)
+      (delete-region position (point-max))
+      (vlf-insert-file-contents-1 safe-start end position))
     (- start safe-start)))
 
-(defun vlf-adjust-end (start end position)
-  "Adjust chunk end at absolute START to END starting at POSITION.
-Remove characters from the end until length is closest to expected.
-Return number of bytes added over expected."
-  (let ((expected-size (- end start))
-        (current-size (length (encode-coding-region
-                               position (point-max)
-                               buffer-file-coding-system t)))
-        (cut-point (point-max))
-        (cut-len 0))
-    (while (< expected-size current-size)
-      (setq cut-len (length (encode-coding-region
-                             (1- cut-point) cut-point
+(defun vlf-delete-region (position start end border cut-point from-start
+                                   &optional encode-direction)
+  "Delete from chunk starting at POSITION enclosing absolute file\
+positions START to END at absolute position BORDER.  Start search for
+best cut at CUT-POINT.  Delete from buffer beginning if FROM-START is
+non nil or up to buffer end otherwise.  ENCODE-DIRECTION determines
+which side of the region to use to calculate cut position's absolute
+file position.  Possible values are: `start' - from the beginning;
+`end' - from end; nil - the shorter side.
+Return actual absolute position of new border and buffer point at
+which deletion was performed."
+  (let* ((encode-from-end (if encode-direction
+                              (eq encode-direction 'end)
+                            (< (- end border) (- border start))))
+         (dist (if encode-from-end
+                   (- end (length (encode-coding-region
+                                   cut-point (point-max)
+                                   buffer-file-coding-system t)))
+                 (+ start (length (encode-coding-region
+                                   position cut-point
+                                   buffer-file-coding-system t)))))
+         (len 0))
+    (if (< border dist)
+        (while (< border dist)
+          (setq len (length (encode-coding-region
+                             cut-point (1- cut-point)
                              buffer-file-coding-system t))
-            cut-point (1- cut-point)
-            current-size (- current-size cut-len)))
-    (if (< current-size expected-size)
-        (setq cut-point (1+ cut-point)
-              current-size (+ current-size cut-len)))
-    (delete-region cut-point (point-max))
-    (- current-size expected-size)))
-
-(defun vlf-insert-file-contents-safe (start end position)
-  "Extract decoded file bytes START to END at POSITION."
-  (let ((coding buffer-file-coding-system))
-    (insert-file-contents-literally buffer-file-name nil start end)
-    (let ((coding-system-for-read coding))
-      (decode-coding-inserted-region position (point-max)
-                                     buffer-file-name nil start end)))
-  (setq buffer-file-coding-system last-coding-system-used))
+                cut-point (1- cut-point)
+                dist (- dist len)))
+      (while (< dist border)
+        (setq len (length (encode-coding-region
+                           cut-point (1+ cut-point)
+                           buffer-file-coding-system t))
+              cut-point (1+ cut-point)
+              dist (+ dist len)))
+      (or (= dist border)
+          (setq cut-point (1- cut-point)
+                dist (- dist len))))
+    (and (not from-start) (/= dist border)
+         (setq cut-point (1+ cut-point)
+               dist (+ dist len)))
+    (vlf-with-undo-disabled
+     (if from-start (delete-region position cut-point)
+       (delete-region cut-point (point-max))))
+    (cons dist (1+ cut-point))))
 
 (defun vlf-shift-undo-list (n)
   "Shift undo list element regions by N."
diff --git a/packages/vlf/vlf-ediff.el b/packages/vlf/vlf-ediff.el
new file mode 100644
index 0000000..51c8aec
--- /dev/null
+++ b/packages/vlf/vlf-ediff.el
@@ -0,0 +1,325 @@
+;;; vlf-ediff.el --- VLF ediff functionality
+
+;; Copyright (C) 2014 Free Software Foundation, Inc.
+
+;; Keywords: large files, compare, ediff
+;; Author: Andrey Kotlarski <address@hidden>
+;; URL: https://github.com/m00natic/vlfi
+
+;; This file is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3, or (at your option)
+;; any later version.
+
+;; This file is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING.  If not, write to
+;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+;;; Commentary:
+;; This package provides ediff functionality for VLF managed buffers
+;; in face of the `vlf-ediff-buffers' and `vlf-ediff-files' commands.
+
+;;; Code:
+
+(require 'vlf)
+(require 'ediff)
+
+(defvar vlf-ediff-session nil
+  "If non nil, specifies that ediff is done over VLF buffers.")
+(make-variable-buffer-local 'vlf-ediff-session)
+
+;;;###autoload
+(defun vlf-ediff-buffers (buffer-A buffer-B)
+  "Run batch by batch ediff over VLF buffers BUFFER-A and BUFFER-B.
+Batch size is determined by the size in BUFFER-A.
+Requesting next or previous difference at the end or beginning
+respectively of difference list, runs ediff over the adjacent chunks."
+  (interactive
+   (let (bf)
+     (list (setq bf (read-buffer "Buffer A to compare: "
+                                 (ediff-other-buffer "") t))
+           (read-buffer "Buffer B to compare: "
+                        (progn
+                          ;; realign buffers so that two visible bufs will be
+                          ;; at the top
+                          (save-window-excursion (other-window 1))
+                          (ediff-other-buffer bf))
+                        t))))
+  (set-buffer buffer-A)
+  (setq buffer-A (current-buffer)) ;names change, so reference by buffer object
+  (let ((batch-size vlf-batch-size))
+    (set-buffer buffer-B)
+    (setq buffer-B (current-buffer))
+    (vlf-set-batch-size batch-size))
+  (ediff-buffers buffer-A buffer-B
+                 '((lambda () (setq vlf-ediff-session t)
+                     (vlf-ediff-next ediff-buffer-A ediff-buffer-B
+                                     ediff-control-buffer
+                                     'vlf-next-chunk)))))
+
+;;;###autoload
+(defun vlf-ediff-files (file-A file-B batch-size)
+  "Run batch by batch ediff over FILE-A and FILE-B.
+Files are processed with VLF with BATCH-SIZE chunks.
+Requesting next or previous difference at the end or beginning
+respectively of difference list, runs ediff over the adjacent chunks."
+  (interactive
+   (let ((dir-A (if ediff-use-last-dir
+                    ediff-last-dir-A
+                  default-directory))
+         dir-B f)
+     (list (setq f (ediff-read-file-name
+                    "File A to compare"
+                    dir-A
+                    (ediff-get-default-file-name)
+                    'no-dirs))
+           (ediff-read-file-name "File B to compare"
+                                 (setq dir-B
+                                       (if ediff-use-last-dir
+                                           ediff-last-dir-B
+                                         (file-name-directory f)))
+                                 (progn
+                                   (ediff-add-to-history
+                                    'file-name-history
+                                    (ediff-abbreviate-file-name
+                                     (expand-file-name
+                                      (file-name-nondirectory f)
+                                      dir-B)))
+                                   (ediff-get-default-file-name f 1)))
+           (read-number "Batch size (in bytes): " vlf-batch-size))))
+  (let ((buffer-A (vlf file-A)))
+    (set-buffer buffer-A)
+    (vlf-set-batch-size batch-size)
+    (let ((buffer-B (vlf file-B)))
+      (vlf-ediff-buffers buffer-A buffer-B))))
+
+(defadvice ediff-next-difference (around vlf-ediff-next-difference
+                                         compile activate)
+  "Move to the next VLF chunk and search for difference if at the end\
+of difference list."
+  (if (and vlf-ediff-session
+           (<= (1- ediff-number-of-differences)
+               ediff-current-difference))
+      (let ((buffer-A ediff-buffer-A)
+            (buffer-B ediff-buffer-B)
+            (ediff-buffer (current-buffer)))
+        (save-excursion
+          (set-buffer buffer-A)
+          (vlf-next-chunk)
+          (set-buffer buffer-B)
+          (vlf-next-chunk)
+          (vlf-ediff-next buffer-A buffer-B ediff-buffer
+                          'vlf-next-chunk))
+        (or (zerop ediff-number-of-differences)
+            (ediff-jump-to-difference 1)))
+    ad-do-it))
+
+(defadvice ediff-previous-difference (around vlf-ediff-prev-difference
+                                             compile activate)
+  "Move to the previous VLF chunk and search for difference if at the\
+beginning of difference list."
+  (if (and vlf-ediff-session
+           (<= ediff-current-difference 0))
+      (let ((buffer-A ediff-buffer-A)
+            (buffer-B ediff-buffer-B)
+            (ediff-buffer (current-buffer)))
+        (save-excursion
+          (set-buffer buffer-A)
+          (vlf-prev-chunk)
+          (set-buffer buffer-B)
+          (vlf-prev-chunk)
+          (vlf-ediff-next buffer-A buffer-B ediff-buffer
+                          'vlf-prev-chunk))
+        (or (zerop ediff-number-of-differences)
+            (ediff-jump-to-difference -1)))
+    ad-do-it))
+
+(defun vlf-next-chunk ()
+  "Move to next chunk."
+  (vlf-move-to-chunk vlf-end-pos (+ vlf-end-pos vlf-batch-size) t))
+
+(defun vlf-prev-chunk ()
+  "Move to previous chunk."
+  (vlf-move-to-chunk (- vlf-start-pos vlf-batch-size) vlf-start-pos t))
+
+(defun vlf-ediff-next (buffer-A buffer-B ediff-buffer
+                                &optional next-func)
+  "Find next pair of chunks that differ in BUFFER-A and BUFFER-B\
+governed by EDIFF-BUFFER.  NEXT-FUNC is used to jump to the next
+logical chunks in case there is no difference at the current ones."
+  (set-buffer buffer-A)
+  (setq buffer-A (current-buffer)) ;names change, so reference by buffer object
+  (let ((end-A (= vlf-start-pos vlf-end-pos))
+        (chunk-A (cons vlf-start-pos vlf-end-pos))
+        (point-max-A (point-max))
+        (font-lock-A font-lock-mode)
+        (min-file-size vlf-file-size)
+        (forward-p (eq next-func 'vlf-next-chunk)))
+    (font-lock-mode 0)
+    (set-buffer buffer-B)
+    (setq buffer-B (current-buffer)
+          min-file-size (min min-file-size vlf-file-size))
+    (let ((tramp-verbose (min 2 tramp-verbose))
+          (end-B (= vlf-start-pos vlf-end-pos))
+          (chunk-B (cons vlf-start-pos vlf-end-pos))
+          (font-lock-B font-lock-mode)
+          (done nil)
+          (reporter (make-progress-reporter
+                     "Searching for difference..."
+                     (if forward-p vlf-start-pos
+                       (- min-file-size vlf-end-pos))
+                     min-file-size)))
+      (font-lock-mode 0)
+      (unwind-protect
+          (progn
+            (while (and (or (not end-A) (not end-B))
+                        (or (zerop (compare-buffer-substrings
+                                    buffer-A (point-min) point-max-A
+                                    buffer-B (point-min) (point-max)))
+                            (with-current-buffer ediff-buffer
+                              (ediff-update-diffs)
+                              (and (not end-A) (not end-B)
+                                   (vlf-ediff-refine buffer-A
+                                                     buffer-B))
+                              (zerop ediff-number-of-differences))))
+              (funcall next-func)
+              (setq end-B (= vlf-start-pos vlf-end-pos))
+              (with-current-buffer buffer-A
+                (funcall next-func)
+                (setq end-A (= vlf-start-pos vlf-end-pos)
+                      point-max-A (point-max)))
+              (progress-reporter-update reporter
+                                        (if forward-p vlf-end-pos
+                                          (- vlf-file-size
+                                             vlf-start-pos))))
+            (progress-reporter-done reporter)
+            (if (or (not end-A) (not end-B))
+                (progn (vlf-update-buffer-name)
+                       (set-buffer buffer-A)
+                       (vlf-update-buffer-name))
+              (if forward-p
+                  (let ((max-file-size vlf-file-size))
+                    (vlf-move-to-chunk (- max-file-size vlf-batch-size)
+                                       max-file-size)
+                    (set-buffer buffer-A)
+                    (setq max-file-size (max max-file-size
+                                             vlf-file-size))
+                    (vlf-move-to-chunk (- max-file-size
+                                          vlf-batch-size)
+                                       max-file-size))
+                (vlf-beginning-of-file)
+                (set-buffer buffer-A)
+                (vlf-beginning-of-file))
+              (set-buffer ediff-buffer)
+              (ediff-update-diffs)
+              (if (or (not forward-p)
+                      (and (not end-A) (not end-B)))
+                  (vlf-ediff-refine buffer-A buffer-B)))
+            (setq done t))
+        (when font-lock-A
+          (set-buffer buffer-A)
+          (font-lock-mode 1))
+        (when font-lock-B
+          (set-buffer buffer-B)
+          (font-lock-mode 1))
+        (unless done
+          (set-buffer buffer-A)
+          (set-buffer-modified-p nil)
+          (vlf-move-to-chunk (car chunk-A) (cdr chunk-A))
+          (set-buffer buffer-B)
+          (set-buffer-modified-p nil)
+          (vlf-move-to-chunk (car chunk-B) (cdr chunk-B))
+          (set-buffer ediff-buffer)
+          (ediff-update-diffs)
+          (vlf-ediff-refine buffer-A buffer-B))))))
+
+(defun vlf-ediff-refine (buffer-A buffer-B)
+  "Try to minimize differences between BUFFER-A and BUFFER-B.
+This can happen if first or last difference is at the start/end of
+buffer."
+  (or (zerop ediff-number-of-differences)
+      (let ((adjust-p (vlf-ediff-adjust buffer-A buffer-B)))
+        (setq adjust-p (or (vlf-ediff-adjust buffer-A buffer-B t)
+                           adjust-p))
+        (if adjust-p (ediff-update-diffs)))))
+
+(defun vlf-ediff-adjust (buf-A buf-B &optional end)
+  "Additionally adjust buffer borders for BUF-A and BUF-B.
+Adjust beginning if END is nil.  Return t if refining is needed,
+nil otherwise."
+  (let* ((diff-num (if end (1- ediff-number-of-differences) 0))
+         (diff-A (ediff-get-diff-overlay diff-num 'A))
+         (diff-B (ediff-get-diff-overlay diff-num 'B))
+         diff-A-str diff-B-str adjust-p)
+    (with-current-buffer buf-A
+      (setq adjust-p (if end (= (overlay-end diff-A) (point-max))
+                       (= (overlay-start diff-A) (point-min)))
+            diff-A-str (and adjust-p (buffer-substring-no-properties
+                                      (overlay-start diff-A)
+                                      (overlay-end diff-A))))
+      (set-buffer buf-B)
+      (setq adjust-p (and adjust-p
+                          (if end (= (overlay-end diff-B) (point-max))
+                            (= (overlay-start diff-B) (point-min))))
+            diff-B-str (and adjust-p (buffer-substring-no-properties
+                                      (overlay-start diff-B)
+                                      (overlay-end diff-B))))
+      (if adjust-p
+          (let ((len-A (length diff-A-str))
+                (len-B (length diff-B-str))
+                (adjust-func (if end 'vlf-ediff-adjust-end
+                               'vlf-ediff-adjust-start)))
+            (cond
+             ((< len-A len-B)
+              (or (funcall adjust-func diff-A-str diff-B-str buf-B)
+                  (setq adjust-p nil)))
+             ((< len-B len-A)
+              (or (funcall adjust-func diff-B-str diff-A-str buf-A)
+                  (setq adjust-p nil)))
+             (t (setq adjust-p nil))))))
+    adjust-p))
+
+(defun vlf-ediff-adjust-start (diff-short diff-long vlf-buffer)
+  "Remove difference between DIFF-SHORT and DIFF-LONG from beginning\
+of VLF-BUFFER."
+  (when (string-suffix-p diff-short diff-long)
+    (set-buffer vlf-buffer)
+    (vlf-move-to-chunk (+ vlf-start-pos
+                          (length (encode-coding-string
+                                   (substring diff-long 0
+                                              (- (length diff-long)
+                                                 (length diff-short)))
+                                   buffer-file-coding-system t)))
+                       vlf-end-pos)))
+
+(defun vlf-ediff-adjust-end (diff-short diff-long vlf-buffer)
+  "Remove difference between DIFF-SHORT and DIFF-LONG from the end of\
+VLF-BUFFER."
+  (when (string-prefix-p diff-short diff-long)
+    (set-buffer vlf-buffer)
+    (vlf-move-to-chunk vlf-start-pos
+                       (- vlf-end-pos
+                          (length (encode-coding-string
+                                   (substring diff-long
+                                              (length diff-short))
+                                   buffer-file-coding-system t))))))
+
+(unless (fboundp 'string-suffix-p)
+  (defun string-suffix-p (suffix string  &optional ignore-case)
+    "Return non-nil if SUFFIX is a suffix of STRING.
+If IGNORE-CASE is non-nil, the comparison is done without paying
+attention to case differences."
+    (let ((start-pos (- (length string) (length suffix))))
+      (and (>= start-pos 0)
+           (eq t (compare-strings suffix nil nil string start-pos nil
+                                  ignore-case))))))
+
+(provide 'vlf-ediff)
+
+;;; vlf-ediff.el ends here
diff --git a/packages/vlf/vlf-occur.el b/packages/vlf/vlf-occur.el
index 10f8d6a..3b7be85 100644
--- a/packages/vlf/vlf-occur.el
+++ b/packages/vlf/vlf-occur.el
@@ -136,16 +136,17 @@ Prematurely ending indexing will still show what's found 
so far."
     (let ((start-pos vlf-start-pos)
           (end-pos vlf-end-pos)
           (pos (point)))
-      (vlf-beginning-of-file)
-      (goto-char (point-min))
       (vlf-with-undo-disabled
+       (vlf-beginning-of-file)
+       (goto-char (point-min))
        (unwind-protect (vlf-build-occur regexp (current-buffer))
          (vlf-move-to-chunk start-pos end-pos)
          (goto-char pos))))))
 
 (defun vlf-build-occur (regexp vlf-buffer)
   "Build occur style index for REGEXP over VLF-BUFFER."
-  (let ((case-fold-search t)
+  (let ((tramp-verbose (min 2 tramp-verbose))
+        (case-fold-search t)
         (line 1)
         (last-match-line 0)
         (last-line-pos (point-min))
diff --git a/packages/vlf/vlf-search.el b/packages/vlf/vlf-search.el
index 0db5ba5..8fa2ce4 100644
--- a/packages/vlf/vlf-search.el
+++ b/packages/vlf/vlf-search.el
@@ -34,18 +34,21 @@
 BATCH-STEP is amount of overlap between successive chunks."
   (if (<= count 0)
       (error "Count must be positive"))
-  (let* ((case-fold-search t)
+  (let* ((tramp-verbose (min 2 tramp-verbose))
+         (case-fold-search t)
          (match-chunk-start vlf-start-pos)
          (match-chunk-end vlf-end-pos)
          (match-start-pos (+ vlf-start-pos (position-bytes (point))))
          (match-end-pos match-start-pos)
          (to-find count)
+         (font-lock font-lock-mode)
          (reporter (make-progress-reporter
                     (concat "Searching for " regexp "...")
                     (if backward
                         (- vlf-file-size vlf-end-pos)
                       vlf-start-pos)
                     vlf-file-size)))
+    (font-lock-mode 0)
     (vlf-with-undo-disabled
      (unwind-protect
          (catch 'end-of-file
@@ -108,6 +111,7 @@ BATCH-STEP is amount of overlap between successive chunks."
                                                   vlf-end-pos)))))
            (progress-reporter-done reporter))
        (set-buffer-modified-p nil)
+       (if font-lock (font-lock-mode 1))
        (if backward
            (vlf-goto-match match-chunk-start match-chunk-end
                            match-end-pos match-start-pos
@@ -175,23 +179,72 @@ Search is performed chunk by chunk in `vlf-batch-size' 
memory."
   "Go to line N.  If N is negative, count from the end of file."
   (interactive (if (vlf-no-modifications)
                    (list (read-number "Go to line: "))))
-  (let ((start-pos vlf-start-pos)
+  (vlf-verify-size)
+  (let ((tramp-verbose (min 2 tramp-verbose))
+        (start-pos vlf-start-pos)
         (end-pos vlf-end-pos)
         (pos (point))
+        (font-lock font-lock-mode)
         (success nil))
+    (font-lock-mode 0)
     (unwind-protect
         (if (< 0 n)
-            (progn (vlf-beginning-of-file)
-                   (goto-char (point-min))
-                   (setq success (vlf-re-search "[\n\C-m]" (1- n)
-                                                nil 0)))
-          (vlf-end-of-file)
-          (goto-char (point-max))
-          (setq success (vlf-re-search "[\n\C-m]" (- n) t 0)))
-      (if success
-          (message "Onto line %s" n)
-        (vlf-move-to-chunk start-pos end-pos)
-        (goto-char pos)))))
+            (let ((start 0)
+                  (end (min vlf-batch-size vlf-file-size))
+                  (reporter (make-progress-reporter
+                             (concat "Searching for line "
+                                     (number-to-string n) "...")
+                             0 vlf-file-size))
+                  (inhibit-read-only t))
+              (setq n (1- n))
+              (vlf-with-undo-disabled
+               (while (and (< (- end start) n)
+                           (< n (- vlf-file-size start)))
+                 (erase-buffer)
+                 (insert-file-contents-literally buffer-file-name
+                                                 nil start end)
+                 (goto-char (point-min))
+                 (while (re-search-forward "[\n\C-m]" nil t)
+                   (setq n (1- n)))
+                 (vlf-verify-size)
+                 (setq start end
+                       end (min vlf-file-size
+                                (+ start vlf-batch-size)))
+                 (progress-reporter-update reporter start))
+               (when (< n (- vlf-file-size end))
+                 (vlf-move-to-chunk-2 start end)
+                 (goto-char (point-min))
+                 (setq success (vlf-re-search "[\n\C-m]" n nil 0)))))
+          (let ((start (max 0 (- vlf-file-size vlf-batch-size)))
+                (end vlf-file-size)
+                (reporter (make-progress-reporter
+                           (concat "Searching for line -"
+                                   (number-to-string n) "...")
+                           0 vlf-file-size))
+                (inhibit-read-only t))
+            (setq n (- n))
+            (vlf-with-undo-disabled
+             (while (and (< (- end start) n) (< n end))
+               (erase-buffer)
+               (insert-file-contents-literally buffer-file-name nil
+                                               start end)
+               (goto-char (point-max))
+               (while (re-search-backward "[\n\C-m]" nil t)
+                 (setq n (1- n)))
+               (setq end start
+                     start (max 0 (- end vlf-batch-size)))
+               (progress-reporter-update reporter
+                                         (- vlf-file-size end)))
+             (when (< n end)
+               (vlf-move-to-chunk-2 start end)
+               (goto-char (point-max))
+               (setq success (vlf-re-search "[\n\C-m]" n t 0))))))
+      (if font-lock (font-lock-mode 1))
+      (unless success
+        (vlf-with-undo-disabled
+         (vlf-move-to-chunk-2 start-pos end-pos))
+        (goto-char pos)
+        (message "Unable to find line")))))
 
 (provide 'vlf-search)
 
diff --git a/packages/vlf/vlf-write.el b/packages/vlf/vlf-write.el
index 7e9d069..e8549a7 100644
--- a/packages/vlf/vlf-write.el
+++ b/packages/vlf/vlf-write.el
@@ -52,10 +52,14 @@ Save anyway? "))
                                 region-length)))
            (if (zerop size-change)
                (write-region nil nil buffer-file-name vlf-start-pos t)
-             (let ((pos (point)))
+             (let ((tramp-verbose (min 2 tramp-verbose))
+                   (pos (point))
+                   (font-lock font-lock-mode))
+               (font-lock-mode 0)
                (if (< 0 size-change)
                    (vlf-file-shift-back size-change)
                  (vlf-file-shift-forward (- size-change)))
+               (if font-lock (font-lock-mode 1))
                (vlf-move-to-chunk-2 vlf-start-pos
                                     (if (< (- vlf-end-pos vlf-start-pos)
                                            vlf-batch-size)
diff --git a/packages/vlf/vlf.el b/packages/vlf/vlf.el
index c567854..18f274b 100644
--- a/packages/vlf/vlf.el
+++ b/packages/vlf/vlf.el
@@ -2,7 +2,7 @@
 
 ;; Copyright (C) 2006, 2012-2014 Free Software Foundation, Inc.
 
-;; Version: 1.3
+;; Version: 1.4
 ;; Keywords: large files, utilities
 ;; Maintainer: Andrey Kotlarski <address@hidden>
 ;; Authors: 2006 Mathias Dahl <address@hidden>
@@ -27,9 +27,9 @@
 
 ;;; Commentary:
 ;; This package provides the M-x vlf command, which visits part of
-;; large file without loading it entirely.
-;; The buffer uses VLF mode, which provides several commands for
-;; moving around, searching and editing selected part of file.
+;; large file without loading it entirely.  The buffer uses VLF mode,
+;; which provides several commands for moving around, searching,
+;; comparing and editing selected part of file.
 ;; To have it offered when opening large files:
 ;; (require 'vlf-integrate)
 
@@ -41,18 +41,19 @@
 
 (require 'vlf-base)
 
-(autoload 'vlf-write "vlf-write" "Write current chunk to file.")
+(autoload 'vlf-write "vlf-write" "Write current chunk to file." t)
 (autoload 'vlf-re-search-forward "vlf-search"
-  "Search forward for REGEXP prefix COUNT number of times.")
+  "Search forward for REGEXP prefix COUNT number of times." t)
 (autoload 'vlf-re-search-backward "vlf-search"
-  "Search backward for REGEXP prefix COUNT number of times.")
-(autoload 'vlf-goto-line "vlf-search" "Go to line.")
+  "Search backward for REGEXP prefix COUNT number of times." t)
+(autoload 'vlf-goto-line "vlf-search" "Go to line." t)
 (autoload 'vlf-occur "vlf-occur"
-  "Make whole file occur style index for REGEXP.")
+  "Make whole file occur style index for REGEXP." t)
 (autoload 'vlf-toggle-follow "vlf-follow"
-  "Toggle continuous chunk recenter around current point.")
-(autoload 'vlf-stop-follow "vlf-follow"
-  "Stop continuous recenter.")
+  "Toggle continuous chunk recenter around current point." t)
+(autoload 'vlf-stop-follow "vlf-follow" "Stop continuous recenter." t)
+(autoload 'vlf-ediff-buffers "vlf-ediff"
+  "Run batch by batch ediff over VLF buffers." t)
 
 (defvar vlf-mode-map
   (let ((map (make-sparse-keymap)))
@@ -71,6 +72,7 @@
     (define-key map "]" 'vlf-end-of-file)
     (define-key map "j" 'vlf-jump-to-chunk)
     (define-key map "l" 'vlf-goto-line)
+    (define-key map "e" 'vlf-ediff-buffers)
     (define-key map "f" 'vlf-toggle-follow)
     (define-key map "g" 'vlf-revert)
     map)
@@ -120,7 +122,8 @@
 (defun vlf (file)
   "View Large FILE in batches.
 You can customize number of bytes displayed by customizing
-`vlf-batch-size'."
+`vlf-batch-size'.
+Return newly created buffer."
   (interactive "fFile to open: ")
   (let ((vlf-buffer (generate-new-buffer "*vlf*")))
     (set-buffer vlf-buffer)
@@ -185,9 +188,13 @@ When prefix argument is negative
 Normally, the value is doubled;
 with the prefix argument DECREASE it is halved."
   (interactive "P")
-  (setq vlf-batch-size (if decrease
-                           (/ vlf-batch-size 2)
-                         (* vlf-batch-size 2)))
+  (vlf-set-batch-size (if decrease (/ vlf-batch-size 2)
+                        (* vlf-batch-size 2))))
+
+(defun vlf-set-batch-size (size)
+  "Set batch to SIZE bytes and update chunk."
+  (interactive (list (read-number "Size in bytes: " vlf-batch-size)))
+  (setq vlf-batch-size size)
   (vlf-move-to-batch vlf-start-pos))
 
 (defun vlf-beginning-of-file ()
@@ -198,6 +205,7 @@ with the prefix argument DECREASE it is halved."
 (defun vlf-end-of-file ()
   "Jump to end of file content."
   (interactive)
+  (vlf-verify-size)
   (vlf-move-to-batch vlf-file-size))
 
 (defun vlf-revert (&optional _ignore-auto noconfirm)



reply via email to

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