1
0
mirror of https://github.com/m00natic/vlfi.git synced 2025-11-11 04:15:38 +00:00

33 Commits
1.3 ... 1.5

Author SHA1 Message Date
Andrey Kotlarski
1f9ba7ce5f Use derived-mode-p. 2014-02-23 18:18:26 +02:00
Andrey Kotlarski
8ba5bead36 Don't run vlf-after-batch-functions hook in vlf-build-occur. 2014-02-23 17:18:07 +02:00
Andrey Kotlarski
ee19f811ae Load hexl advices after load and move vlf group definition. 2014-02-23 00:40:20 +02:00
Andrey Kotlarski
6476c1be6a Update README, wording, add links and information on hooks. 2014-02-23 00:32:11 +02:00
Andrey Kotlarski
2c231dfb15 Disable hexl-save-buffer and hexl revert when vlf-mode is active. 2014-02-15 02:40:31 +02:00
Andrey Kotlarski
6bb60b72ad Fix hexl scroll up called from scroll down behavior. 2014-02-15 02:35:46 +02:00
Andrey Kotlarski
b235cf907c Execute vlf-after-batch-functions hook even on user quit command before
end of search.  Update buffer name after unsuccessful goto line.
2014-02-15 02:32:43 +02:00
Andrey Kotlarski
859c1e4c45 Fix hook names. 2014-02-15 02:32:05 +02:00
Andrey Kotlarski
8c61b776d6 Fix when batch hooks are run for occur and save. 2014-02-14 12:34:31 +02:00
Andrey Kotlarski
074f9e960d Play nicely with hexl-mode. 2014-02-14 02:49:02 +02:00
Andrey Kotlarski
b05255b225 Add hooks to run around chunk moves and batch operations. Don't err
when tramp hasn't been loaded yet.
2014-02-14 02:47:37 +02:00
Andrey Kotlarski
924d6b18fa Revert to using insert-file-contents instead of manual decoding. 2014-02-14 02:44:43 +02:00
Andrey Kotlarski
0199c2468a Lower tramp verbosity level when dealing with multiple batches. 2014-01-30 01:58:57 +02:00
Andrey Kotlarski
ffac6972ed Keep undo list after occur or unsuccessful line search. 2014-01-27 02:15:56 +02:00
Andrey Kotlarski
a71ee32508 Skip adjustment in some cases of overlapping chunk. 2014-01-27 01:18:07 +02:00
Andrey Kotlarski
9510c70860 Retry decoding when the initial attempt seems wrong. 2014-01-27 01:16:00 +02:00
Andrey Kotlarski
cc9b115486 Update docstring for vlf-ediff-adjust. 2014-01-23 02:30:02 +02:00
Andrey Kotlarski
f83a212c52 Temporarily disable font-lock during multiple batch operations. 2014-01-23 02:11:44 +02:00
Andrey Kotlarski
1a1ce27d37 Add progress reporters for the optimized part of line search. 2014-01-23 02:10:52 +02:00
Andrey Kotlarski
5c604c48a4 Optimize vlf-goto-line not to decode batches as long as possible. 2014-01-22 02:42:52 +02:00
Andrey Kotlarski
0fa8e8d6bf Update buffer name on user interruption during ediff. 2014-01-22 02:40:53 +02:00
Andrey Kotlarski
d7766f2a3b Update documentation and mark autoloaded functions as interactive. 2014-01-21 01:34:32 +02:00
Andrey Kotlarski
30d2bb0d25 VLF buffer ediff now starts from the current chunks. 2014-01-21 01:33:04 +02:00
Andrey Kotlarski
c533bce956 Add command to set batch size explicitly. 2014-01-21 01:32:21 +02:00
Andrey Kotlarski
5d30eb4826 Use single ediff pass to adjust borders. Protect against user
interruption while searching for difference.
2014-01-21 01:29:37 +02:00
Andrey Kotlarski
d5d9cd71ee Improve refining of differences and readjustment. 2014-01-20 02:40:26 +02:00
Andrey Kotlarski
e747de4495 Unify and optimize deletion. 2014-01-20 02:37:51 +02:00
Andrey Kotlarski
82fd5b943b Refine diff adjustment and in case of equality after it - make another
search for difference.
2014-01-18 16:26:25 +02:00
Andrey Kotlarski
9646b00215 Adjust chunk borders to minimize shift differences and optimize
detection of identical batches when ediff-ing.
2014-01-17 03:01:41 +02:00
Andrey Kotlarski
27e3bbb320 Reuse initial ediff session for all chunks. 2014-01-15 02:17:33 +02:00
Andrey Kotlarski
117935db98 Add progress reporter when searching for difference. 2014-01-14 01:11:59 +02:00
Andrey Kotlarski
38e8f6c4e1 Update file size when moving to end of buffer. 2014-01-14 01:11:07 +02:00
Andrey Kotlarski
98ddc3afd9 Add by batch Ediff functionality. 2014-01-13 01:36:20 +02:00
8 changed files with 777 additions and 233 deletions

View File

@@ -1,25 +1,31 @@
* View Large Files
Emacs minor mode that allows viewing, editing and searching large
files in batches. Batch size can be adjusted on the fly and bounds
the memory that is to be used for operations on the file.
Emacs minor mode that allows viewing, editing, searching and comparing
large files in batches. Batch size can be adjusted on the fly and
bounds the memory that is to be used for operations on the file. This
way multiple large files (like terabytes or whatever) can be instantly
and simultaneously accessed without swapping and degraded
performance.
This is development version of the GNU ELPA [[http://elpa.gnu.org/packages/vlf][vlf.el]] package. Here's
what it does in a nutshell:
This is development version of the GNU ELPA [[http://elpa.gnu.org/packages/vlf][VLF]] package. Here's what
it offers in a nutshell:
- regular expression search on whole file (in constant memory
determined by current batch size)
- chunk editing (if size has changed, saving is done in constant
memory determined by current batch size)
- occur like indexing
- [[http://www.emacswiki.org/emacs/OccurMode][Occur]] like indexing
- options to jump to beginning, end or arbitrary file chunk
- ability to jump/insert given number of batches at once
- newly added content is acknowledged if file has changed size
meanwhile
- automatic scrolling of batches
- as VLF is minor mode, font locking and functionality of the
respective major mode is also present
- VLF is added as an option when opening large files
- as a minor mode, font locking and functionality of the respective
major mode is also present
- by batch [[http://www.emacswiki.org/emacs/EdiffMode][Ediff]] comparison
- can be added as option to automatically open large files
- smooth integration with [[http://www.emacswiki.org/emacs/HexlMode][hexl-mode]]
- works with [[http://www.emacswiki.org/emacs/TrampMode][TRAMP]] so accessing network files is fine
GNU Emacs 23 and 24 are supported.
@@ -31,12 +37,12 @@ M-x vlf PATH-TO-FILE
Emacs' Unicode support is leveraged so you'll not see bare bytes but
characters decoded as if file is normally opened. This holds for
editing, search and indexing.
editing, search, indexing and comparison.
** 32-bit GNU Emacs
Regular Emacs integers are used, so if you use 32-bit Emacs without
bignum support, VLF will not work with files over 512 MB (maximum
bignum support, *VLF* will not work with files over 512 MB (maximum
integer value).
** Memory control
@@ -53,12 +59,12 @@ To have *vlf* offered as choice when opening large files:
(require 'vlf-integrate)
#+END_EXAMPLE
You can control when vlf-mode is invoked or offered with the
*vlf-application* customization option. By default it will offer VLF
when opening large files. There are also options to never use it (you
can still call *vlf* command explicitly); to use it without asking for
large files or to invoke it on all files. Here's example setup such
that vlf-mode automatically launches for large files:
You can control when *vlf-mode* is invoked or offered with the
*vlf-application* customization option. By default it will offer
*VLF* when opening large files. There are also options to never use
it (you can still call *vlf* command explicitly); to use it without
asking for large files or to invoke it on all files. Here's example
setup such that *vlf-mode* automatically launches for large files:
#+BEGIN_EXAMPLE
(custom-set-variables
@@ -67,12 +73,12 @@ that vlf-mode automatically launches for large files:
*** Disable for specific mode
To disable automatic usage of VLF for a major mode, add it to
To disable automatic usage of *VLF* for a major mode, add it to
*vlf-forbidden-modes-list*.
*** Disable for specific function
To disable automatic usage of VLF for a function, for example named
To disable automatic usage of *VLF* for a function, for example named
*func* defined in file *file.el*:
#+BEGIN_EXAMPLE
@@ -81,8 +87,8 @@ To disable automatic usage of VLF for a function, for example named
** Keymap
All VLF operations are grouped under the *C-c C-v* prefix by default.
Here's example how to add another prefix (*C-x v*):
All *VLF* operations are grouped under the *C-c C-v* prefix by
default. Here's example how to add another prefix (*C-x v*):
#+BEGIN_EXAMPLE
(eval-after-load "vlf"
@@ -91,12 +97,12 @@ Here's example how to add another prefix (*C-x v*):
** Control batch size
Use *M-x vlf-set-batch-size* to change batch size and update chunk
immediately.
*C-c C-v +* and *C-c C-v -* control current batch size by factors
of 2.
You can also set by hand local variable *vlf-batch-size* and then
refresh with *C-c C-v g*.
** Move around
Scrolling automatically triggers moving to previous or next chunk at
@@ -130,10 +136,10 @@ beforehand.
** Occur over whole file
*C-c C-v o* builds index for given regular expression just like
*M-x occur*. It does this batch by batch over the whole file. Note
that even if you prematurely stop it with *C-g*, it will still show
index of what's found so far.
*C-c C-v o* builds index for given regular expression just like M-x
occur*. It does so batch by batch over the whole file. Note that
even if you prematurely stop it with *C-g*, it will still show index
of what's found so far.
** Jump to line
@@ -147,3 +153,27 @@ file.
If editing doesn't change size of the chunk, only this chunk is saved.
Otherwise the remaining part of the file is adjusted batch by batch,
so again you'd better have bigger current batch size.
** By batch Ediff
Use *M-x vlf-ediff-files* and *M-x vlf-ediff-buffers* to compare
files/buffers batch by batch (batch size is queried in case of files
or taken from the first buffer in case of buffers). Moving after the
last difference in current chunk searches for following one with
difference. The other way around if looking for difference before the
first one.
* Extending
** Move hooks
A couple of hooks are run whenever updating chunk:
*vlf-before-chunk-update* and *vlf-after-chunk-update*.
** Batch move hooks
Some operations may trigger multiple chunk moves. There are a couple
of hooks that run in such cases: *vlf-before-batch-functions* and
*vlf-after-batch-functions*. They are passed one argument that
specifies type of operation that runs. Possible values are the
symbols: *write*, *ediff*, *occur*, *search* and *goto-line*.

View File

@@ -27,17 +27,19 @@
;;; Code:
(defgroup vlf nil
"View Large Files in Emacs."
:prefix "vlf-"
:group 'files)
(defcustom vlf-batch-size 1024
"Defines how large each batch of file data is (in bytes)."
:group 'vlf
:type 'integer)
:group 'vlf :type 'integer)
(put 'vlf-batch-size 'permanent-local t)
(defcustom vlf-before-chunk-update nil
"Hook that runs before chunk update."
:group 'vlf :type 'hook)
(defcustom vlf-after-chunk-update nil
"Hook that runs after chunk update."
:group 'vlf :type 'hook)
;;; Keep track of file position.
(defvar vlf-start-pos 0
"Absolute position of the visible chunk start.")
@@ -94,13 +96,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)
(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)))
shifts))))
(defun vlf-move-to-chunk-1 (start end)
"Move to chunk enclosed by START END keeping as much edits if any.
@@ -128,66 +144,73 @@ bytes added to the end."
((or (and (<= start vlf-start-pos) (<= edit-end end))
(not modified)
(y-or-n-p "Chunk modified, are you sure? "))
(run-hooks 'vlf-before-chunk-update)
(let ((shift-start 0)
(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
(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))
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)))))
(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))
(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) del-pos))
(vlf-shift-undo-list (- (point-min) del-pos))))
(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)
(run-hooks 'vlf-after-chunk-update)
(cons shift-start shift-end))))))
(defun vlf-move-to-chunk-2 (start end)
"Unconditionally move to chunk enclosed by START END bytes.
Return number of bytes moved back for proper decoding and number of
bytes added to the end."
(run-hooks 'vlf-before-chunk-update)
(vlf-verify-size t)
(setq vlf-start-pos (max 0 start)
vlf-end-pos (min end vlf-file-size))
@@ -203,13 +226,15 @@ bytes added to the end."
(goto-char (or (byte-to-position (+ pos (car shifts)))
(point-max)))))
(set-buffer-modified-p nil)
(setq buffer-undo-list nil)
(or (eq buffer-undo-list t)
(setq buffer-undo-list nil))
(run-hooks 'vlf-after-chunk-update)
shifts))
(defun vlf-insert-file-contents (start end adjust-start adjust-end
&optional position)
"Adjust chunk at absolute START to END till content can be\
properly decoded. ADJUST-START determines if trying to prepend bytes\
properly decoded. ADJUST-START determines if trying to prepend bytes
to the beginning, ADJUST-END - append to the end.
Use buffer POSITION as start if given.
Return number of bytes moved back for proper decoding and number of
@@ -227,11 +252,19 @@ 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))
(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)
"Extract decoded file bytes START to END."
(insert-file-contents buffer-file-name nil start end))
(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,8 +276,8 @@ 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
safe-start sample-end position)
(while (and (progn (vlf-insert-file-contents-1 safe-start
sample-end)
(not (zerop safe-start)))
(< shift 3)
(let ((diff (- chunk-size
@@ -259,53 +292,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)
(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-safe safe-start end position)))
(vlf-insert-file-contents-1 safe-start end))
(- 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)
(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)))
(cut-point (point-max))
(cut-len 0))
(while (< expected-size current-size)
(setq cut-len (length (encode-coding-region
(1- cut-point) cut-point
(+ 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)
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)
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))
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."

328
vlf-ediff.el Normal file
View File

@@ -0,0 +1,328 @@
;;; vlf-ediff.el --- VLF ediff functionality -*- lexical-binding: t -*-
;; Copyright (C) 2014 Free Software Foundation, Inc.
;; Keywords: large files, compare, ediff
;; Author: Andrey Kotlarski <m00naticus@gmail.com>
;; 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)
(run-hook-with-args 'vlf-before-batch-functions 'ediff)
(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)
(run-hook-with-args 'vlf-before-batch-functions 'ediff)
(setq buffer-B (current-buffer)
min-file-size (min min-file-size vlf-file-size))
(let ((tramp-verbose (if (boundp 'tramp-verbose)
(min tramp-verbose 2)))
(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))
(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))
(set-buffer buffer-A)
(if font-lock-A (font-lock-mode 1))
(run-hook-with-args 'vlf-after-batch-functions 'ediff)
(set-buffer buffer-B)
(if font-lock-B (font-lock-mode 1))
(run-hook-with-args 'vlf-after-batch-functions 'ediff)))))
(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

View File

@@ -26,10 +26,8 @@
;;; Code:
(defgroup vlf nil
"View Large Files in Emacs."
:prefix "vlf-"
:group 'files)
(defgroup vlf nil "View Large Files in Emacs."
:prefix "vlf-" :group 'files)
(defcustom vlf-application 'ask
"Determines when `vlf' will be offered on opening files.
@@ -37,8 +35,7 @@ Possible values are: nil to never use it;
`ask' offer `vlf' when file size is beyond `large-file-warning-threshold';
`dont-ask' automatically use `vlf' for large files;
`always' use `vlf' for all files."
:group 'vlf
:type '(radio (const :format "%v " nil)
:group 'vlf :type '(radio (const :format "%v " nil)
(const :format "%v " ask)
(const :format "%v " dont-ask)
(const :format "%v" always)))
@@ -47,8 +44,7 @@ Possible values are: nil to never use it;
'(archive-mode tar-mode jka-compr git-commit-mode image-mode
doc-view-mode doc-view-mode-maybe ebrowse-tree-mode)
"Major modes which VLF will not be automatically applied to."
:group 'vlf
:type '(list symbol))
:group 'vlf :type '(list symbol))
(unless (fboundp 'file-size-human-readable)
(defun file-size-human-readable (file-size)

View File

@@ -131,21 +131,27 @@ Prematurely ending indexing will still show what's found so far."
(set (make-local-variable 'vlf-batch-size) batch-size)
(vlf-mode 1)
(goto-char (point-min))
(run-hook-with-args 'vlf-before-batch-functions 'occur)
(vlf-with-undo-disabled
(vlf-build-occur regexp vlf-buffer))))
(vlf-build-occur regexp vlf-buffer))
(run-hook-with-args 'vlf-after-batch-functions 'occur)))
(run-hook-with-args 'vlf-before-batch-functions 'occur)
(let ((start-pos vlf-start-pos)
(end-pos vlf-end-pos)
(pos (point)))
(vlf-with-undo-disabled
(vlf-beginning-of-file)
(goto-char (point-min))
(vlf-with-undo-disabled
(unwind-protect (vlf-build-occur regexp (current-buffer))
(vlf-move-to-chunk start-pos end-pos)
(goto-char pos))))))
(goto-char pos))))
(run-hook-with-args 'vlf-after-batch-functions 'occur)))
(defun vlf-build-occur (regexp vlf-buffer)
"Build occur style index for REGEXP over VLF-BUFFER."
(let ((case-fold-search t)
(let ((tramp-verbose (if (boundp 'tramp-verbose)
(min tramp-verbose 2)))
(case-fold-search t)
(line 1)
(last-match-line 0)
(last-line-pos (point-min))

View File

@@ -34,18 +34,23 @@
BATCH-STEP is amount of overlap between successive chunks."
(if (<= count 0)
(error "Count must be positive"))
(let* ((case-fold-search t)
(run-hook-with-args 'vlf-before-batch-functions 'search)
(let* ((tramp-verbose (if (boundp 'tramp-verbose)
(min tramp-verbose 2)))
(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,13 +113,15 @@ 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
count to-find)
(vlf-goto-match match-chunk-start match-chunk-end
match-start-pos match-end-pos
count to-find))))))
count to-find))
(run-hook-with-args 'vlf-after-batch-functions 'search)))))
(defun vlf-goto-match (match-chunk-start match-chunk-end
match-pos-start
@@ -175,23 +182,76 @@ 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)
(run-hook-with-args 'vlf-before-batch-functions 'goto-line)
(vlf-verify-size)
(let ((tramp-verbose (if (boundp 'tramp-verbose)
(min tramp-verbose 2)))
(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)
(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))
(setq success (vlf-re-search "[\n\C-m]" (1- n)
nil 0)))
(vlf-end-of-file)
(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))
(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)))))
(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))
(vlf-update-buffer-name)
(goto-char pos)
(message "Unable to find line"))
(run-hook-with-args 'vlf-after-batch-functions 'goto-line))))
(provide 'vlf-search)

View File

@@ -33,13 +33,13 @@
"Write current chunk to file. Always return true to disable save.
If changing size of chunk, shift remaining file content."
(interactive)
(and (buffer-modified-p)
(when (and (buffer-modified-p)
(or (verify-visited-file-modtime (current-buffer))
(y-or-n-p "File has changed since visited or saved.\
Save anyway? "))
Save anyway? ")))
(run-hook-with-args 'vlf-before-batch-functions 'write)
(if (zerop vlf-file-size) ;new file
(progn
(write-region nil nil buffer-file-name vlf-start-pos t)
(progn (write-region nil nil buffer-file-name vlf-start-pos t)
(setq vlf-file-size (vlf-get-file-size
buffer-file-truename)
vlf-end-pos vlf-file-size)
@@ -52,17 +52,23 @@ 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 (if (boundp 'tramp-verbose)
(min tramp-verbose 2)))
(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)
(+ vlf-start-pos vlf-batch-size)
vlf-end-pos))
(vlf-update-buffer-name)
(goto-char pos))))))
(goto-char pos)))))
(run-hook-with-args 'vlf-after-batch-functions 'write))
t)
(defun vlf-file-shift-back (size-change)

131
vlf.el
View File

@@ -2,7 +2,7 @@
;; Copyright (C) 2006, 2012-2014 Free Software Foundation, Inc.
;; Version: 1.3
;; Version: 1.5
;; Keywords: large files, utilities
;; Maintainer: Andrey Kotlarski <m00naticus@gmail.com>
;; Authors: 2006 Mathias Dahl <mathias.dahl@gmail.com>
@@ -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)
@@ -39,20 +39,36 @@
;;; Code:
(defgroup vlf nil "View Large Files in Emacs."
:prefix "vlf-" :group 'files)
(defcustom vlf-before-batch-functions nil
"Hook that runs before multiple batch operations.
One argument is supplied that specifies current action. Possible
values are: `write', `ediff', `occur', `search', `goto-line'."
:group 'vlf :type 'hook)
(defcustom vlf-after-batch-functions nil
"Hook that runs after multiple batch operations.
One argument is supplied that specifies current action. Possible
values are: `write', `ediff', `occur', `search', `goto-line'."
:group 'vlf :type 'hook)
(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 +87,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)
@@ -84,11 +101,8 @@
(define-minor-mode vlf-mode
"Mode to browse large files in."
:lighter " VLF"
:group 'vlf
:keymap vlf-prefix-map
(if vlf-mode
(progn
:lighter " VLF" :group 'vlf :keymap vlf-prefix-map
(cond (vlf-mode
(set (make-local-variable 'require-final-newline) nil)
(add-hook 'write-file-functions 'vlf-write nil t)
(set (make-local-variable 'revert-buffer-function)
@@ -100,27 +114,42 @@
(let* ((pos (position-bytes (point)))
(start (* (/ pos vlf-batch-size) vlf-batch-size)))
(goto-char (byte-to-position (- pos start)))
(vlf-move-to-batch start)))
(kill-local-variable 'revert-buffer-function)
(vlf-stop-follow)
(when (or (not large-file-warning-threshold)
(vlf-move-to-batch start))
(add-hook 'after-change-major-mode-hook 'vlf-keep-alive t t)
(vlf-keep-alive))
((or (not large-file-warning-threshold)
(< vlf-file-size large-file-warning-threshold)
(y-or-n-p (format "Load whole file (%s)? "
(file-size-human-readable
vlf-file-size))))
(kill-local-variable 'revert-buffer-function)
(vlf-stop-follow)
(kill-local-variable 'require-final-newline)
(remove-hook 'write-file-functions 'vlf-write t)
(remove-hook 'after-change-major-mode-hook
'vlf-keep-alive t)
(let ((hexl (derived-mode-p 'hexl-mode)))
(if hexl (hexl-mode-exit))
(let ((pos (+ vlf-start-pos (position-bytes (point)))))
(vlf-with-undo-disabled
(insert-file-contents buffer-file-name t nil nil t))
(goto-char (byte-to-position pos)))
(rename-buffer (file-name-nondirectory buffer-file-name) t))))
(if hexl (hexl-mode)))
(rename-buffer (file-name-nondirectory buffer-file-name) t))
(t (setq vlf-mode t))))
(defun vlf-keep-alive ()
"Keep `vlf-mode' on major mode change."
(if (derived-mode-p 'hexl-mode)
(set (make-local-variable 'revert-buffer-function) 'vlf-revert))
(setq vlf-mode t))
;;;###autoload
(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)
@@ -177,6 +206,51 @@ When prefix argument is negative
(goto-char (point-max)))
ad-do-it))
;; hexl mode integration
(defun vlf-hexl-before (&optional operation)
"Temporarily disable `hexl-mode' for OPERATION."
(when (derived-mode-p 'hexl-mode)
(hexl-mode-exit)
(set (make-local-variable 'vlf-restore-hexl-mode) operation)))
(defun vlf-hexl-after (&optional operation)
"Re-enable `hexl-mode' if active before OPERATION."
(when (and (boundp 'vlf-restore-hexl-mode)
(eq vlf-restore-hexl-mode operation))
(hexl-mode)
(kill-local-variable 'vlf-restore-hexl-mode)))
(add-hook 'vlf-before-batch-functions 'vlf-hexl-before)
(add-hook 'vlf-after-batch-functions 'vlf-hexl-after)
(add-hook 'vlf-before-chunk-update 'vlf-hexl-before)
(add-hook 'vlf-after-chunk-update 'vlf-hexl-after)
(eval-after-load "hexl"
'(progn
(defadvice hexl-save-buffer (around vlf-hexl-save
activate compile)
"Prevent hexl save if `vlf-mode' is active."
(if vlf-mode
(vlf-write)
ad-do-it))
(defadvice hexl-scroll-up (around vlf-hexl-scroll-up
activate compile)
"Slide to next batch if at end of buffer in `vlf-mode'."
(if (and vlf-mode (pos-visible-in-window-p (point-max))
(or (not (numberp arg)) (< 0 arg)))
(progn (vlf-next-batch 1)
(goto-char (point-min)))
ad-do-it))
(defadvice hexl-scroll-down (around vlf-hexl-scroll-down
activate compile)
"Slide to previous batch if at beginning of buffer in `vlf-mode'."
(if (and vlf-mode (pos-visible-in-window-p (point-min)))
(progn (vlf-prev-batch 1)
(goto-char (point-max)))
ad-do-it))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; utilities
@@ -185,9 +259,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 +276,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)