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

16 Commits
0.9.1 ... 1.0

Author SHA1 Message Date
Andrey Kotlarski
46e39a0fd8 Version 1.0. 2013-12-07 20:20:41 +02:00
Andrey Kotlarski
51d95ec0a3 Add command to display batch starting from point. 2013-12-07 20:18:07 +02:00
Andrey Kotlarski
d6c722376c Delete obsolete vlfi.el. 2013-12-07 19:50:19 +02:00
Andrey Kotlarski
a42247cac4 Automatically scroll to adjacent batch when start or end of chunk is
visible.
2013-12-04 15:11:04 +02:00
Andrey Kotlarski
3e8098af61 Rename vlf-discard-edit -> vlf-refresh. 2013-12-04 14:44:11 +02:00
Andrey Kotlarski
28646fbfee Reduce scope of vlf-with-undo-disabled usages. 2013-12-04 14:40:07 +02:00
Andrey Kotlarski
177c680288 Revert to showing batch size in buffer name instead of the mode-line. 2013-12-04 14:00:24 +02:00
Andrey Kotlarski
2ac3e7d577 Fix prematurely ending search/occur not to ask for modified buffer
confirmation.
2013-12-04 13:59:08 +02:00
Andrey Kotlarski
931ca52688 Stylistic refinements. 2013-12-04 00:20:02 +02:00
Andrey Kotlarski
42e581da61 Add command to unconditionally open fresh VLF buffer to visit occur
match.
2013-12-04 00:15:31 +02:00
Andrey Kotlarski
a65f3a431d Check for unsaved changes before search query and don't enable undo if
it was previously disabled.
2013-12-04 00:03:29 +02:00
Andrey Kotlarski
f34986a9b8 Update README. 2013-12-03 02:54:33 +02:00
Andrey Kotlarski
452b7eb42d Ensure there are no modifications when executing searches. 2013-12-03 02:37:13 +02:00
Andrey Kotlarski
2dba838015 In case original VLF buffer has been killed, try to find existing VLF
buffer for the same file when visiting occur results.
2013-12-03 02:04:27 +02:00
Andrey Kotlarski
cb47e19128 Use temporary buffer for occur in case of modifications. 2013-12-03 01:50:03 +02:00
Andrey Kotlarski
efae918a83 Turn vlf into minor mode. 2013-12-02 02:08:24 +02:00
3 changed files with 299 additions and 293 deletions

View File

@@ -1,8 +1,8 @@
* View Large Files
An Emacs mode that allows viewing, editing and searching in large
files in chunks. 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 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.
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:
@@ -41,64 +41,62 @@ integer value), VLF will probably not quite work.
*vlf-batch-size* bounds the memory used for all operations.
** Special mode
VLF is derived from special-mode and keeps all its properties. For
example you can directly press digits to enter prefix arguments.
** Change major mode
You can change major mode to whatever you like (for example
hexl-mode). Saving will insert contents as intended. You can return
to *vlf-mode* too.
* Detail usage
** Control batch size
*+* and *-* control current batch size by factors of 2.
*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 *g*.
refresh with *C-c C-v g*.
** Move around
*M-PgUp* and *M-PgDn* move chunk by chunk. With positive prefix
argument they move prefix number of batches. With negative - append
prefix number of batches.
*C-c C-v PgUp* and *C-c C-v PgDn* move batch by batch. With positive
prefix argument they move prefix number of batches. With negative -
append prefix number of batches.
*[* and *]* take you to the beginning and end of file respectively.
*C-c C-v n* displays batch starting from current point.
*j* jumps to given chunk. To see where you are in file and how many chunks
there are (using the current batch size), look at the bracketed part
of the buffer name, batch size is also there - at the end.
*C-c C-v [* and *C-c C-v ]* take you to the beginning and end of file
respectively.
*C-c C-v j* jumps to given chunk. To see where you are in file and
how many chunks there are (using the current batch size), look at the
parenthesized part of the buffer name, batch size is also indicated at
the end.
** Search whole file
*s* and *r* search forward and backward respectively over the whole
file. This is done chunk by chunk so if you have really huge file -
you'd better set somewhat bigger batch size beforehand.
*C-c C-v s* and *C-c C-v r* search forward and backward respectively
over the whole file. This is done batch by batch so if you have
really huge file - you'd better set somewhat bigger batch size
beforehand.
** Occur over whole file
*o* builds index for given regular expression just like occur-mode.
It does this chunk by chunk 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 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.
** Jump to line
*l* jumps to given line in file. This is done by searching from the
beginning, so again the bigger current batch size, the quicker. With
negative argument, lines are counted from the end of file.
*C-c C-v l* jumps to given line in file. This is done by searching
from the beginning, so again the bigger current batch size, the
quicker. With negative argument, lines are counted from the end of
file.
** Edit
** Reload
*e* enters VLF in edit mode. If editing doesn't change size of
the chunk, only this chunk is saved. Otherwise the remaining part of
the file is adjusted chunk by chunk, so again you'd better have bigger
current batch size. If chunk has been expanded the memory used is
*C-c C-v g* discards modifications (if such) and reloads chunk.
#+BEGIN_EXAMPLE
(batch size + difference to the original chunk size) x 2
#+END_EXAMPLE
** Edit and save
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.
*Warning* Saving changes to non-ASCII chunks is a bit risky right
now.

471
vlf.el
View File

@@ -2,7 +2,7 @@
;; Copyright (C) 2006, 2012, 2013 Free Software Foundation, Inc.
;; Version: 0.9.1
;; Version: 1.0
;; Keywords: large files, utilities
;; Maintainer: Andrey Kotlarski <m00naticus@gmail.com>
;; Authors: 2006 Mathias Dahl <mathias.dahl@gmail.com>
@@ -61,9 +61,11 @@
(put 'vlf-file-size 'permanent-local t)
(defvar vlf-mode-map
(let ((map (make-sparse-keymap)))
(define-key map [M-next] 'vlf-next-batch)
(define-key map [M-prior] 'vlf-prev-batch)
(let ((map-prefix (make-sparse-keymap))
(map (make-sparse-keymap)))
(define-key map [next] 'vlf-next-batch)
(define-key map [prior] 'vlf-prev-batch)
(define-key map "n" 'vlf-next-batch-from-point)
(define-key map "+" 'vlf-change-batch-size)
(define-key map "-"
(lambda () "Decrease vlf batch size by factor of 2."
@@ -74,37 +76,58 @@
(define-key map "o" 'vlf-occur)
(define-key map "[" 'vlf-beginning-of-file)
(define-key map "]" 'vlf-end-of-file)
(define-key map "e" 'vlf-edit-mode)
(define-key map "j" 'vlf-jump-to-chunk)
(define-key map "l" 'vlf-goto-line)
map)
(define-key map "g" 'vlf-refresh)
(define-key map-prefix "\C-c\C-v" map)
map-prefix)
"Keymap for `vlf-mode'.")
(define-derived-mode vlf-mode special-mode "VLF"
(define-minor-mode vlf-mode
"Mode to browse large files in."
(setq buffer-read-only t)
(set-buffer-modified-p nil)
(buffer-disable-undo)
(add-hook 'write-file-functions 'vlf-write nil t)
(make-local-variable 'revert-buffer-function)
(setq revert-buffer-function 'vlf-revert)
(make-local-variable 'vlf-batch-size)
(make-local-variable 'vlf-start-pos)
(make-local-variable 'vlf-end-pos)
(make-local-variable 'vlf-file-size))
:lighter " VLF"
:group 'vlf
:keymap vlf-mode-map
(if vlf-mode
(progn
(add-hook 'write-file-functions 'vlf-write nil t)
(set (make-local-variable 'revert-buffer-function)
'vlf-revert)
(make-local-variable 'vlf-batch-size)
(set (make-local-variable 'vlf-start-pos) -1)
(make-local-variable 'vlf-end-pos)
(set (make-local-variable 'vlf-file-size)
(vlf-get-file-size buffer-file-name))
(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)
(when (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))))
(remove-hook 'write-file-functions 'vlf-write t)
(let ((pos (+ vlf-start-pos (position-bytes (point)))))
(vlf-with-undo-disabled
(erase-buffer)
(insert-file-contents buffer-file-name))
(set-visited-file-modtime)
(set-buffer-modified-p nil)
(goto-char (byte-to-position pos)))
(rename-buffer (file-name-nondirectory buffer-file-name) t))))
;;;###autoload
(defun vlf (file)
"View Large FILE.
Batches of the file data from FILE will be displayed in a read-only
buffer. You can customize number of bytes displayed by customizing
"View Large FILE in batches.
You can customize number of bytes displayed by customizing
`vlf-batch-size'."
(interactive "fFile to open: ")
(with-current-buffer (generate-new-buffer "*vlf*")
(set-visited-file-name file)
(vlf-mode)
(setq vlf-file-size (vlf-get-file-size buffer-file-name))
(vlf-insert-file)
(set-buffer-modified-p nil)
(vlf-mode 1)
(switch-to-buffer (current-buffer))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@@ -156,17 +179,15 @@ OP-TYPE specifies the file operation being performed over FILENAME."
(defadvice scroll-up (around vlf-scroll-up
activate compile)
"Slide to next batch if at end of buffer in `vlf-mode'."
(if (and (derived-mode-p 'vlf-mode)
(eobp))
(if (and vlf-mode (pos-visible-in-window-p (point-max)))
(progn (vlf-next-batch 1)
(goto-char (point-min)))
ad-do-it))
(defadvice scroll-down (around vlf-scroll-down
activate compile)
"Slide to previous batch if at beginning of buffer in `vlf-mode'."
(if (and (derived-mode-p 'vlf-mode)
(bobp))
"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))
@@ -187,22 +208,18 @@ 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-batch-size 2)
(* vlf-batch-size 2)))
(vlf-move-to-batch vlf-start-pos))
(defun vlf-format-buffer-name ()
"Return format for vlf buffer name."
(format "%s(%s)[%d/%d](%d)"
(file-name-nondirectory buffer-file-name)
(file-size-human-readable vlf-file-size)
(/ vlf-end-pos vlf-batch-size)
(/ vlf-file-size vlf-batch-size)
vlf-batch-size))
(defun vlf-update-buffer-name ()
"Update the current buffer name."
(rename-buffer (vlf-format-buffer-name) t))
(rename-buffer (format "%s(%d/%d)[%s]"
(file-name-nondirectory buffer-file-name)
(/ vlf-end-pos vlf-batch-size)
(/ vlf-file-size vlf-batch-size)
(file-size-human-readable vlf-batch-size))
t))
(defun vlf-get-file-size (file)
"Get size in bytes of FILE."
@@ -248,6 +265,21 @@ Ask for confirmation if NOCONFIRM is nil."
(interactive "nGoto to chunk: ")
(vlf-move-to-batch (* (1- n) vlf-batch-size)))
(defmacro vlf-with-undo-disabled (&rest body)
"Execute BODY with temporarily disabled undo."
`(let ((undo-enabled (not (eq buffer-undo-list t))))
(if undo-enabled
(buffer-disable-undo))
(unwind-protect (progn ,@body)
(if undo-enabled
(buffer-enable-undo)))))
(defun vlf-no-modifications ()
"Ensure there are no buffer modifications."
(if (buffer-modified-p)
(error "Save or discard your changes first")
t))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; batch movement
@@ -260,7 +292,7 @@ When prefix argument is negative
(interactive "p")
(vlf-verify-size)
(let* ((end (min (+ vlf-end-pos (* vlf-batch-size
(abs append)))
(abs append)))
vlf-file-size))
(start (if (< append 0)
vlf-start-pos
@@ -277,7 +309,7 @@ When prefix argument is negative
(if (zerop vlf-start-pos)
(error "Already at BOF"))
(let* ((start (max 0 (- vlf-start-pos (* vlf-batch-size
(abs prepend)))))
(abs prepend)))))
(end (if (< prepend 0)
vlf-end-pos
(+ start vlf-batch-size))))
@@ -294,6 +326,12 @@ When given MINIMAL flag, skip non important operations."
(setq start (max 0 (- end vlf-batch-size))))
(vlf-move-to-chunk start end minimal)))
(defun vlf-next-batch-from-point ()
"Display batch of file data starting from current point."
(interactive)
(vlf-move-to-batch (+ vlf-start-pos (position-bytes (point)) -1))
(goto-char (point-min)))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; primitive chunk operations
@@ -324,12 +362,12 @@ Return t if move hasn't been canceled."
t))
((or (<= edit-end start) (<= end vlf-start-pos))
(when (or (not modified)
(y-or-n-p "Buffer modified, are you sure? ")) ; full chunk renewal
(y-or-n-p "Chunk modified, are you sure? ")) ;full chunk renewal
(vlf-move-to-chunk-2 start end)
t))
((or (and (<= start vlf-start-pos) (<= edit-end end))
(not modified)
(y-or-n-p "Buffer modified, are you sure? "))
(y-or-n-p "Chunk modified, are you sure? "))
(let ((pos (+ (position-bytes (point)) vlf-start-pos))
(shift-start 0)
(shift-end 0)
@@ -357,9 +395,9 @@ Return t if move hasn't been canceled."
start vlf-start-pos)
(setq shift-start (car
(vlf-adjust-chunk start
vlf-start-pos
t nil
edit-end-pos)))
vlf-start-pos
t nil
edit-end-pos)))
(goto-char (point-min))
(insert (delete-and-extract-region edit-end-pos
(point-max))))))
@@ -376,20 +414,21 @@ Return t if move hasn't been canceled."
vlf-end-pos (min end vlf-file-size))
(let ((inhibit-read-only t)
(pos (position-bytes (point))))
(erase-buffer)
(insert-file-contents buffer-file-name nil
vlf-start-pos vlf-end-pos)
(let ((shifts (vlf-adjust-chunk vlf-start-pos vlf-end-pos t
(vlf-with-undo-disabled
(erase-buffer)
(insert-file-contents buffer-file-name nil
vlf-start-pos vlf-end-pos)
(let ((shifts (vlf-adjust-chunk vlf-start-pos vlf-end-pos t
t)))
(setq vlf-start-pos (- vlf-start-pos (car shifts))
vlf-end-pos (+ vlf-end-pos (cdr shifts)))
(goto-char (or (byte-to-position (+ pos (car shifts)))
(point-max)))))
(setq vlf-start-pos (- vlf-start-pos (car shifts))
vlf-end-pos (+ vlf-end-pos (cdr shifts)))
(goto-char (or (byte-to-position (+ pos (car shifts)))
(point-max))))))
(set-buffer-modified-p nil)
(set-visited-file-modtime))
(defun vlf-adjust-chunk (start end &optional adjust-start adjust-end
position)
position)
"Adjust chunk at absolute START to END till content can be \
properly decoded. ADJUST-START determines if trying to prepend bytes\
to the beginning, ADJUST-END - add to the end.
@@ -441,7 +480,8 @@ bytes added to the end."
BATCH-STEP is amount of overlap between successive chunks."
(if (<= count 0)
(error "Count must be positive"))
(let* ((match-chunk-start vlf-start-pos)
(let* ((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)
@@ -452,81 +492,80 @@ BATCH-STEP is amount of overlap between successive chunks."
(- vlf-file-size vlf-end-pos)
vlf-start-pos)
vlf-file-size)))
(set-buffer-modified-p nil)
(buffer-disable-undo)
(unwind-protect
(catch 'end-of-file
(if backward
(while (not (zerop to-find))
(cond ((re-search-backward regexp nil t)
(setq to-find (1- to-find)
match-chunk-start vlf-start-pos
match-chunk-end vlf-end-pos
match-start-pos (+ vlf-start-pos
(position-bytes
(match-beginning 0)))
match-end-pos (+ vlf-start-pos
(position-bytes
(match-end 0)))))
((zerop vlf-start-pos)
(throw 'end-of-file nil))
(t (let ((batch-move (- vlf-start-pos
(- vlf-batch-size
batch-step))))
(vlf-move-to-batch
(if (< match-start-pos batch-move)
(- match-start-pos vlf-batch-size)
batch-move) t))
(goto-char (if (< match-start-pos
vlf-end-pos)
(or (byte-to-position
(- match-start-pos
vlf-start-pos))
(point-max))
(point-max)))
(progress-reporter-update
reporter (- vlf-file-size
vlf-start-pos)))))
(while (not (zerop to-find))
(cond ((re-search-forward regexp nil t)
(setq to-find (1- to-find)
match-chunk-start vlf-start-pos
match-chunk-end vlf-end-pos
match-start-pos (+ vlf-start-pos
(position-bytes
(match-beginning 0)))
match-end-pos (+ vlf-start-pos
(position-bytes
(match-end 0)))))
((= vlf-end-pos vlf-file-size)
(throw 'end-of-file nil))
(t (let ((batch-move (- vlf-end-pos batch-step)))
(vlf-move-to-batch
(if (< batch-move match-end-pos)
match-end-pos
batch-move) t))
(goto-char (if (< vlf-start-pos match-end-pos)
(or (byte-to-position
(- match-end-pos
vlf-start-pos))
(point-min))
(point-min)))
(progress-reporter-update reporter
vlf-end-pos)))))
(progress-reporter-done reporter))
(set-buffer-modified-p nil)
(if backward
(vlf-goto-match match-chunk-start match-chunk-end
(vlf-with-undo-disabled
(unwind-protect
(catch 'end-of-file
(if backward
(while (not (zerop to-find))
(cond ((re-search-backward regexp nil t)
(setq to-find (1- to-find)
match-chunk-start vlf-start-pos
match-chunk-end vlf-end-pos
match-start-pos (+ vlf-start-pos
(position-bytes
(match-beginning 0)))
match-end-pos (+ vlf-start-pos
(position-bytes
(match-end 0)))))
((zerop vlf-start-pos)
(throw 'end-of-file nil))
(t (let ((batch-move (- vlf-start-pos
(- vlf-batch-size
batch-step))))
(vlf-move-to-batch
(if (< match-start-pos batch-move)
(- match-start-pos vlf-batch-size)
batch-move) t))
(goto-char (if (< match-start-pos
vlf-end-pos)
(or (byte-to-position
(- match-start-pos
vlf-start-pos))
(point-max))
(point-max)))
(progress-reporter-update
reporter (- vlf-file-size
vlf-start-pos)))))
(while (not (zerop to-find))
(cond ((re-search-forward regexp nil t)
(setq to-find (1- to-find)
match-chunk-start vlf-start-pos
match-chunk-end vlf-end-pos
match-start-pos (+ vlf-start-pos
(position-bytes
(match-beginning 0)))
match-end-pos (+ vlf-start-pos
(position-bytes
(match-end 0)))))
((= vlf-end-pos vlf-file-size)
(throw 'end-of-file nil))
(t (let ((batch-move (- vlf-end-pos batch-step)))
(vlf-move-to-batch
(if (< batch-move match-end-pos)
match-end-pos
batch-move) t))
(goto-char (if (< vlf-start-pos match-end-pos)
(or (byte-to-position
(- match-end-pos
vlf-start-pos))
(point-min))
(point-min)))
(progress-reporter-update reporter
vlf-end-pos)))))
(progress-reporter-done reporter))
(set-buffer-modified-p nil)
(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
(vlf-goto-match match-chunk-start match-chunk-end
match-start-pos match-end-pos
count to-find)))))
count to-find))))))
(defun vlf-goto-match (match-chunk-start match-chunk-end
match-pos-start
match-pos-end
count to-find)
match-pos-start
match-pos-end
count to-find)
"Move to MATCH-CHUNK-START MATCH-CHUNK-END surrounding \
MATCH-POS-START and MATCH-POS-END.
According to COUNT and left TO-FIND, show if search has been
@@ -554,31 +593,34 @@ successful. Return nil if nothing found."
(goto-char match-end)
(message "Moved to the %d match which is last"
(- count to-find)))
(unwind-protect (sit-for 5)
(unwind-protect (sit-for 3)
(delete-overlay overlay))
t))))
(defun vlf-re-search-forward (regexp count)
"Search forward for REGEXP prefix COUNT number of times.
Search is performed chunk by chunk in `vlf-batch-size' memory."
(interactive (list (read-regexp "Search whole file"
(if regexp-history
(car regexp-history)))
(or current-prefix-arg 1)))
(interactive (if (vlf-no-modifications)
(list (read-regexp "Search whole file"
(if regexp-history
(car regexp-history)))
(or current-prefix-arg 1))))
(vlf-re-search regexp count nil (/ vlf-batch-size 8)))
(defun vlf-re-search-backward (regexp count)
"Search backward for REGEXP prefix COUNT number of times.
Search is performed chunk by chunk in `vlf-batch-size' memory."
(interactive (list (read-regexp "Search whole file backward"
(if regexp-history
(car regexp-history)))
(or current-prefix-arg 1)))
(interactive (if (vlf-no-modifications)
(list (read-regexp "Search whole file backward"
(if regexp-history
(car regexp-history)))
(or current-prefix-arg 1))))
(vlf-re-search regexp count t (/ vlf-batch-size 8)))
(defun vlf-goto-line (n)
"Go to line N. If N is negative, count from the end of file."
(interactive "nGo to line: ")
(interactive (if (vlf-no-modifications)
(list (read-number "Go to line: "))))
(let ((start-pos vlf-start-pos)
(end-pos vlf-end-pos)
(pos (point))
@@ -588,7 +630,7 @@ Search is performed chunk by chunk in `vlf-batch-size' memory."
(progn (vlf-beginning-of-file)
(goto-char (point-min))
(setq success (vlf-re-search "[\n\C-m]" (1- n)
nil 0)))
nil 0)))
(vlf-end-of-file)
(goto-char (point-max))
(setq success (vlf-re-search "[\n\C-m]" (- n) t 0)))
@@ -605,6 +647,7 @@ Search is performed chunk by chunk in `vlf-batch-size' memory."
(define-key map "n" 'vlf-occur-next-match)
(define-key map "p" 'vlf-occur-prev-match)
(define-key map "\C-m" 'vlf-occur-visit)
(define-key map "\M-\r" 'vlf-occur-visit-new-buffer)
(define-key map [mouse-1] 'vlf-occur-visit)
(define-key map "o" 'vlf-occur-show)
map)
@@ -644,10 +687,16 @@ EVENT may hold details of the invocation."
(vlf-occur-visit event)
(pop-to-buffer occur-buffer)))
(defun vlf-occur-visit-new-buffer ()
"Visit `vlf-occur' link in new vlf buffer."
(interactive)
(let ((current-prefix-arg t))
(vlf-occur-visit)))
(defun vlf-occur-visit (&optional event)
"Visit current `vlf-occur' link in a vlf buffer.
If original VLF buffer has been killed,
open new VLF session each time.
With prefix argument or if original VLF buffer has been killed,
open new VLF session.
EVENT may hold details of the invocation."
(interactive (list last-nonmenu-event))
(when event
@@ -659,14 +708,23 @@ EVENT may hold details of the invocation."
(if file
(let ((chunk-start (get-char-property pos 'chunk-start))
(chunk-end (get-char-property pos 'chunk-end))
(buffer (get-char-property pos 'buffer))
(vlf-buffer (get-char-property pos 'buffer))
(occur-buffer (current-buffer))
(match-pos (+ (get-char-property pos 'line-pos)
pos-relative)))
(or (buffer-live-p buffer)
(let ((occur-buffer (current-buffer)))
(setq buffer (vlf file))
(switch-to-buffer occur-buffer)))
(pop-to-buffer buffer)
(cond (current-prefix-arg
(setq vlf-buffer (vlf file))
(switch-to-buffer occur-buffer))
((not (buffer-live-p vlf-buffer))
(or (catch 'found
(dolist (buf (buffer-list))
(set-buffer buf)
(and vlf-mode (equal file buffer-file-name)
(setq vlf-buffer buf)
(throw 'found t))))
(setq vlf-buffer (vlf file)))
(switch-to-buffer occur-buffer)))
(pop-to-buffer vlf-buffer)
(vlf-move-to-chunk chunk-start chunk-end)
(goto-char match-pos)))))
@@ -676,21 +734,32 @@ Prematurely ending indexing will still show what's found so far."
(interactive (list (read-regexp "List lines matching regexp"
(if regexp-history
(car regexp-history)))))
(let ((start-pos vlf-start-pos)
(end-pos vlf-end-pos)
(pos (point)))
(vlf-beginning-of-file)
(goto-char (point-min))
(set-buffer-modified-p nil)
(buffer-disable-undo)
(unwind-protect (vlf-build-occur regexp)
(set-buffer-modified-p nil)
(vlf-move-to-chunk start-pos end-pos)
(goto-char pos))))
(if (buffer-modified-p) ;use temporary buffer not to interfere with modifications
(let ((vlf-buffer (current-buffer))
(file buffer-file-name)
(batch-size vlf-batch-size))
(with-temp-buffer
(setq buffer-file-name file)
(set-buffer-modified-p nil)
(set (make-local-variable 'vlf-batch-size) batch-size)
(vlf-mode 1)
(goto-char (point-min))
(vlf-with-undo-disabled
(vlf-build-occur regexp vlf-buffer))))
(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
(unwind-protect (vlf-build-occur regexp (current-buffer))
(vlf-move-to-chunk start-pos end-pos)
(goto-char pos))))))
(defun vlf-build-occur (regexp)
"Build occur style index for REGEXP."
(let ((line 1)
(defun vlf-build-occur (regexp vlf-buffer)
"Build occur style index for REGEXP over VLF-BUFFER."
(let ((case-fold-search t)
(line 1)
(last-match-line 0)
(last-line-pos (point-min))
(file buffer-file-name)
@@ -698,7 +767,7 @@ Prematurely ending indexing will still show what's found so far."
(match-end-pos (+ vlf-start-pos (position-bytes (point))))
(occur-buffer (generate-new-buffer
(concat "*VLF-occur " (file-name-nondirectory
buffer-file-name)
buffer-file-name)
"*")))
(line-regexp (concat "\\(?5:[\n\C-m]\\)\\|\\(?10:"
regexp "\\)"))
@@ -720,7 +789,6 @@ Prematurely ending indexing will still show what's found so far."
last-line-pos (point))
(let* ((chunk-start vlf-start-pos)
(chunk-end vlf-end-pos)
(vlf-buffer (current-buffer))
(line-pos (line-beginning-position))
(line-text (buffer-substring
line-pos (line-end-position))))
@@ -762,8 +830,8 @@ Prematurely ending indexing will still show what's found so far."
(unless end-of-file
(let ((batch-move (- vlf-end-pos batch-step)))
(vlf-move-to-batch (if (< batch-move match-end-pos)
match-end-pos
batch-move) t))
match-end-pos
batch-move) t))
(goto-char (if (< vlf-start-pos match-end-pos)
(or (byte-to-position (- match-end-pos
vlf-start-pos))
@@ -773,6 +841,7 @@ Prematurely ending indexing will still show what's found so far."
last-line-pos (line-beginning-position))
(progress-reporter-update reporter vlf-end-pos))))
(progress-reporter-done reporter))
(set-buffer-modified-p nil)
(if (zerop total-matches)
(progn (with-current-buffer occur-buffer
(set-buffer-modified-p nil))
@@ -781,7 +850,7 @@ Prematurely ending indexing will still show what's found so far."
(with-current-buffer occur-buffer
(goto-char (point-min))
(insert (propertize
(format "%d matches from %d lines for \"%s\" \
(format "%d matches in %d lines for \"%s\" \
in file: %s" total-matches line regexp file)
'face 'underline))
(set-buffer-modified-p nil)
@@ -792,30 +861,11 @@ in file: %s" total-matches line regexp file)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; editing
(defvar vlf-edit-mode-map
(let ((map (make-sparse-keymap)))
(set-keymap-parent map text-mode-map)
(define-key map "\C-c\C-c" 'vlf-write)
(define-key map "\C-c\C-q" 'vlf-discard-edit)
(define-key map "\C-v" vlf-mode-map)
map)
"Keymap for command `vlf-edit-mode'.")
(define-derived-mode vlf-edit-mode vlf-mode "VLF[edit]"
"Major mode for editing large file chunks."
(setq buffer-read-only nil)
(buffer-enable-undo)
(message (substitute-command-keys
"Editing: Type \\[vlf-write] to write chunk \
or \\[vlf-discard-edit] to discard changes.")))
(defun vlf-discard-edit ()
(defun vlf-refresh ()
"Discard edit and refresh chunk from file."
(interactive)
(set-buffer-modified-p nil)
(vlf-move-to-chunk vlf-start-pos vlf-end-pos)
(vlf-mode)
(message "Switched to VLF mode."))
(vlf-move-to-chunk vlf-start-pos vlf-end-pos))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; saving
@@ -839,27 +889,26 @@ Save anyway? ")))
(vlf-file-shift-back size-change))
(t (vlf-file-shift-forward (- size-change))))
(vlf-move-to-chunk-2 vlf-start-pos vlf-end-pos)
(goto-char pos))
(vlf-mode))
(goto-char pos)))
t)
(defun vlf-file-shift-back (size-change)
"Shift file contents SIZE-CHANGE bytes back."
(write-region nil nil buffer-file-name vlf-start-pos t)
(buffer-disable-undo)
(let ((read-start-pos vlf-end-pos)
(coding-system-for-write 'no-conversion)
(reporter (make-progress-reporter "Adjusting file content..."
vlf-end-pos
vlf-file-size)))
(while (vlf-shift-batch read-start-pos (- read-start-pos
(vlf-with-undo-disabled
(while (vlf-shift-batch read-start-pos (- read-start-pos
size-change))
(setq read-start-pos (+ read-start-pos vlf-batch-size))
(progress-reporter-update reporter read-start-pos))
;; pad end with space
(erase-buffer)
(vlf-verify-size)
(insert-char 32 size-change)
(setq read-start-pos (+ read-start-pos vlf-batch-size))
(progress-reporter-update reporter read-start-pos))
;; pad end with space
(erase-buffer)
(vlf-verify-size)
(insert-char 32 size-change))
(write-region nil nil buffer-file-name (- vlf-file-size
size-change) t)
(progress-reporter-done reporter)))
@@ -879,26 +928,26 @@ back at WRITE-POS. Return nil if EOF is reached, t otherwise."
(defun vlf-file-shift-forward (size-change)
"Shift file contents SIZE-CHANGE bytes forward.
Done by saving content up front and then writing previous batch."
(buffer-disable-undo)
(let ((size (+ vlf-batch-size size-change))
(let ((read-size (max (/ vlf-batch-size 2) size-change))
(read-pos vlf-end-pos)
(write-pos vlf-start-pos)
(reporter (make-progress-reporter "Adjusting file content..."
vlf-start-pos
vlf-file-size)))
(when (vlf-shift-batches size read-pos write-pos t)
(setq write-pos (+ read-pos size-change)
read-pos (+ read-pos size))
(progress-reporter-update reporter write-pos)
(let ((coding-system-for-write 'no-conversion))
(while (vlf-shift-batches size read-pos write-pos nil)
(setq write-pos (+ read-pos size-change)
read-pos (+ read-pos size))
(progress-reporter-update reporter write-pos))))
(vlf-with-undo-disabled
(when (vlf-shift-batches read-size read-pos write-pos t)
(setq write-pos (+ read-pos size-change)
read-pos (+ read-pos read-size))
(progress-reporter-update reporter write-pos)
(let ((coding-system-for-write 'no-conversion))
(while (vlf-shift-batches read-size read-pos write-pos nil)
(setq write-pos (+ read-pos size-change)
read-pos (+ read-pos read-size))
(progress-reporter-update reporter write-pos)))))
(progress-reporter-done reporter)))
(defun vlf-shift-batches (size read-pos write-pos hide-read)
"Append SIZE bytes of file starting at READ-POS.
(defun vlf-shift-batches (read-size read-pos write-pos hide-read)
"Append READ-SIZE bytes of file starting at READ-POS.
Then write initial buffer content to file at WRITE-POS.
If HIDE-READ is non nil, temporarily hide literal read content.
Return nil if EOF is reached, t otherwise."
@@ -909,8 +958,8 @@ Return nil if EOF is reached, t otherwise."
(when read-more
(goto-char end-write-pos)
(insert-file-contents-literally buffer-file-name nil read-pos
(min vlf-file-size (+ read-pos
size))))
(min vlf-file-size
(+ read-pos read-size))))
;; write
(if hide-read ; hide literal region if user has to choose encoding
(narrow-to-region start-write-pos end-write-pos))

41
vlfi.el
View File

@@ -1,41 +0,0 @@
;;; vlfi.el --- Obsolete - install vlf instead!
;; Copyright (C) 2006, 2012, 2013 Free Software Foundation, Inc.
;; Version: 0.9.1.1
;; Keywords: large files, utilities
;; Maintainer: Andrey Kotlarski <m00naticus@gmail.com>
;; Authors: 2006 Mathias Dahl <mathias.dahl@gmail.com>
;; 2012 Sam Steingold <sds@gnu.org>
;; 2013 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 2, 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 used to provide the M-x vlfi command, which visited
;; part of a large file without loading the entire file.
;; However, it has been merged back to the vlf package,
;; so use that instead.
;;; Code:
;;;###autoload
(error
"vlfi package has been merged with vlf: please install that instead")
;;; vlfi.el ends here