1
0
mirror of https://github.com/m00natic/vlfi.git synced 2025-11-13 13:25:35 +00:00

21 Commits
0.9.1 ... 1.1

Author SHA1 Message Date
Andrey Kotlarski
371c560f4b Bump version and remove warning - save is now reliable. 2013-12-11 01:11:13 +02:00
Andrey Kotlarski
a3901b8f1a Fix deletion when moving to partially overlapping chunk and enable more
intelligent behaviour in cases of overlapping and modifications.
2013-12-09 01:55:41 +02:00
Andrey Kotlarski
f4ee23c07f Fix chunk end adjustment and save for current and older Emacsen. 2013-12-08 21:11:08 +02:00
Andrey Kotlarski
959bbc7661 Disable undo in cases of partial chunk move. 2013-12-08 17:22:23 +02:00
Andrey Kotlarski
0080991fa9 Fix chunk end adjustment and save for trunk Emacs. 2013-12-08 17:21:34 +02:00
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 372 additions and 349 deletions

View File

@@ -1,8 +1,8 @@
* View Large Files * View Large Files
An Emacs mode that allows viewing, editing and searching in large Emacs minor mode that allows viewing, editing and searching large
files in chunks. Batch size can be adjusted on the fly and bounds the files in batches. Batch size can be adjusted on the fly and bounds
memory that is to be used for operations on the file. 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 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: what it does in a nutshell:
@@ -41,64 +41,59 @@ integer value), VLF will probably not quite work.
*vlf-batch-size* bounds the memory used for all operations. *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 * Detail usage
** Control batch size ** 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 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 ** Move around
*M-PgUp* and *M-PgDn* move chunk by chunk. With positive prefix *C-c C-v PgUp* and *C-c C-v PgDn* move batch by batch. With positive
argument they move prefix number of batches. With negative - append prefix argument they move prefix number of batches. With negative -
prefix number of batches. 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 *C-c C-v [* and *C-c C-v ]* take you to the beginning and end of file
there are (using the current batch size), look at the bracketed part respectively.
of the buffer name, batch size is also there - at the end.
*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 ** Search whole file
*s* and *r* search forward and backward respectively over the whole *C-c C-v s* and *C-c C-v r* search forward and backward respectively
file. This is done chunk by chunk so if you have really huge file - over the whole file. This is done batch by batch so if you have
you'd better set somewhat bigger batch size beforehand. really huge file - you'd better set somewhat bigger batch size
beforehand.
** Occur over whole file ** Occur over whole file
*o* builds index for given regular expression just like occur-mode. *C-c C-v o* builds index for given regular expression just like
It does this chunk by chunk over the whole file. Note that even if *M-x occur*. It does this batch by batch over the whole file. Note
you prematurely stop it with *C-g*, it will still show index of what's that even if you prematurely stop it with *C-g*, it will still show
found so far. index of what's found so far.
** Jump to line ** Jump to line
*l* jumps to given line in file. This is done by searching from the *C-c C-v l* jumps to given line in file. This is done by searching
beginning, so again the bigger current batch size, the quicker. With from the beginning, so again the bigger current batch size, the
negative argument, lines are counted from the end of file. 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 *C-c C-v g* discards modifications (if such) and reloads chunk.
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
#+BEGIN_EXAMPLE ** Edit and save
(batch size + difference to the original chunk size) x 2
#+END_EXAMPLE 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.

603
vlf.el
View File

@@ -2,7 +2,7 @@
;; Copyright (C) 2006, 2012, 2013 Free Software Foundation, Inc. ;; Copyright (C) 2006, 2012, 2013 Free Software Foundation, Inc.
;; Version: 0.9.1 ;; Version: 1.1
;; Keywords: large files, utilities ;; Keywords: large files, utilities
;; Maintainer: Andrey Kotlarski <m00naticus@gmail.com> ;; Maintainer: Andrey Kotlarski <m00naticus@gmail.com>
;; Authors: 2006 Mathias Dahl <mathias.dahl@gmail.com> ;; Authors: 2006 Mathias Dahl <mathias.dahl@gmail.com>
@@ -61,9 +61,11 @@
(put 'vlf-file-size 'permanent-local t) (put 'vlf-file-size 'permanent-local t)
(defvar vlf-mode-map (defvar vlf-mode-map
(let ((map (make-sparse-keymap))) (let ((map-prefix (make-sparse-keymap))
(define-key map [M-next] 'vlf-next-batch) (map (make-sparse-keymap)))
(define-key map [M-prior] 'vlf-prev-batch) (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 "+" 'vlf-change-batch-size)
(define-key map "-" (define-key map "-"
(lambda () "Decrease vlf batch size by factor of 2." (lambda () "Decrease vlf batch size by factor of 2."
@@ -74,37 +76,57 @@
(define-key map "o" 'vlf-occur) (define-key map "o" 'vlf-occur)
(define-key map "[" 'vlf-beginning-of-file) (define-key map "[" 'vlf-beginning-of-file)
(define-key map "]" 'vlf-end-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 "j" 'vlf-jump-to-chunk)
(define-key map "l" 'vlf-goto-line) (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'.") "Keymap for `vlf-mode'.")
(define-derived-mode vlf-mode special-mode "VLF" (define-minor-mode vlf-mode
"Mode to browse large files in." "Mode to browse large files in."
(setq buffer-read-only t) :lighter " VLF"
(set-buffer-modified-p nil) :group 'vlf
(buffer-disable-undo) :keymap vlf-mode-map
(add-hook 'write-file-functions 'vlf-write nil t) (if vlf-mode
(make-local-variable 'revert-buffer-function) (progn
(setq revert-buffer-function 'vlf-revert) (set (make-local-variable 'require-final-newline) nil)
(make-local-variable 'vlf-batch-size) (add-hook 'write-file-functions 'vlf-write nil t)
(make-local-variable 'vlf-start-pos) (set (make-local-variable 'revert-buffer-function)
(make-local-variable 'vlf-end-pos) 'vlf-revert)
(make-local-variable 'vlf-file-size)) (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))))
(kill-local-variable 'require-final-newline)
(remove-hook 'write-file-functions 'vlf-write t)
(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))))
;;;###autoload ;;;###autoload
(defun vlf (file) (defun vlf (file)
"View Large FILE. "View Large FILE in batches.
Batches of the file data from FILE will be displayed in a read-only You can customize number of bytes displayed by customizing
buffer. You can customize number of bytes displayed by customizing
`vlf-batch-size'." `vlf-batch-size'."
(interactive "fFile to open: ") (interactive "fFile to open: ")
(with-current-buffer (generate-new-buffer "*vlf*") (with-current-buffer (generate-new-buffer "*vlf*")
(set-visited-file-name file) (set-visited-file-name file)
(vlf-mode) (set-buffer-modified-p nil)
(setq vlf-file-size (vlf-get-file-size buffer-file-name)) (vlf-mode 1)
(vlf-insert-file)
(switch-to-buffer (current-buffer)))) (switch-to-buffer (current-buffer))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@@ -156,17 +178,15 @@ OP-TYPE specifies the file operation being performed over FILENAME."
(defadvice scroll-up (around vlf-scroll-up (defadvice scroll-up (around vlf-scroll-up
activate compile) activate compile)
"Slide to next batch if at end of buffer in `vlf-mode'." "Slide to next batch if at end of buffer in `vlf-mode'."
(if (and (derived-mode-p 'vlf-mode) (if (and vlf-mode (pos-visible-in-window-p (point-max)))
(eobp))
(progn (vlf-next-batch 1) (progn (vlf-next-batch 1)
(goto-char (point-min))) (goto-char (point-min)))
ad-do-it)) ad-do-it))
(defadvice scroll-down (around vlf-scroll-down (defadvice scroll-down (around vlf-scroll-down
activate compile) activate compile)
"Slide to previous batch if at beginning of buffer in `vlf-mode'." "Slide to previous batch if at beginning of buffer in `vlf-mode'."
(if (and (derived-mode-p 'vlf-mode) (if (and vlf-mode (pos-visible-in-window-p (point-min)))
(bobp))
(progn (vlf-prev-batch 1) (progn (vlf-prev-batch 1)
(goto-char (point-max))) (goto-char (point-max)))
ad-do-it)) ad-do-it))
@@ -187,22 +207,18 @@ Normally, the value is doubled;
with the prefix argument DECREASE it is halved." with the prefix argument DECREASE it is halved."
(interactive "P") (interactive "P")
(setq vlf-batch-size (if decrease (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)) (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 () (defun vlf-update-buffer-name ()
"Update the current 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) (defun vlf-get-file-size (file)
"Get size in bytes of FILE." "Get size in bytes of FILE."
@@ -248,6 +264,21 @@ Ask for confirmation if NOCONFIRM is nil."
(interactive "nGoto to chunk: ") (interactive "nGoto to chunk: ")
(vlf-move-to-batch (* (1- n) vlf-batch-size))) (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 ;;; batch movement
@@ -260,7 +291,7 @@ When prefix argument is negative
(interactive "p") (interactive "p")
(vlf-verify-size) (vlf-verify-size)
(let* ((end (min (+ vlf-end-pos (* vlf-batch-size (let* ((end (min (+ vlf-end-pos (* vlf-batch-size
(abs append))) (abs append)))
vlf-file-size)) vlf-file-size))
(start (if (< append 0) (start (if (< append 0)
vlf-start-pos vlf-start-pos
@@ -277,7 +308,7 @@ When prefix argument is negative
(if (zerop vlf-start-pos) (if (zerop vlf-start-pos)
(error "Already at BOF")) (error "Already at BOF"))
(let* ((start (max 0 (- vlf-start-pos (* vlf-batch-size (let* ((start (max 0 (- vlf-start-pos (* vlf-batch-size
(abs prepend))))) (abs prepend)))))
(end (if (< prepend 0) (end (if (< prepend 0)
vlf-end-pos vlf-end-pos
(+ start vlf-batch-size)))) (+ start vlf-batch-size))))
@@ -294,6 +325,12 @@ When given MINIMAL flag, skip non important operations."
(setq start (max 0 (- end vlf-batch-size)))) (setq start (max 0 (- end vlf-batch-size))))
(vlf-move-to-chunk start end minimal))) (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 ;;; primitive chunk operations
@@ -304,11 +341,8 @@ If same as current chunk is requested, do nothing."
(unless (and (= start vlf-start-pos) (unless (and (= start vlf-start-pos)
(= end vlf-end-pos)) (= end vlf-end-pos))
(vlf-verify-size) (vlf-verify-size)
(if (buffer-modified-p) (if (vlf-move-to-chunk-1 start end)
(if (vlf-move-to-chunk-1 start end) (or minimal (vlf-update-buffer-name)))))
(or minimal (vlf-update-buffer-name)))
(vlf-move-to-chunk-2 start end)
(or minimal (vlf-update-buffer-name)))))
(defun vlf-move-to-chunk-1 (start end) (defun vlf-move-to-chunk-1 (start end)
"Move to chunk determined by START END keeping as much edits if any. "Move to chunk determined by START END keeping as much edits if any.
@@ -324,45 +358,60 @@ Return t if move hasn't been canceled."
t)) t))
((or (<= edit-end start) (<= end vlf-start-pos)) ((or (<= edit-end start) (<= end vlf-start-pos))
(when (or (not modified) (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
(set-buffer-modified-p nil)
(vlf-move-to-chunk-2 start end) (vlf-move-to-chunk-2 start end)
t)) t))
((or (and (<= start vlf-start-pos) (<= edit-end end)) ((or (and (<= start vlf-start-pos) (<= edit-end end))
(not modified) (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)) (let ((pos (+ (position-bytes (point)) vlf-start-pos))
(shift-start 0) (shift-start 0)
(shift-end 0) (shift-end 0)
(inhibit-read-only t)) (inhibit-read-only t))
(cond ((< end edit-end) (cond ((< end edit-end)
(delete-region (byte-to-position (1+ (let* ((del-pos (1+ (byte-to-position
(- end (- end vlf-start-pos))))
vlf-start-pos))) (del-len (length (encode-coding-region
(point-max))) del-pos (point-max)
buffer-file-coding-system
t))))
(setq end (- vlf-end-pos del-len))
(vlf-with-undo-disabled
(delete-region del-pos (point-max)))))
((< edit-end end) ((< edit-end end)
(let ((edit-end-pos (point-max))) (let ((edit-end-pos (point-max)))
(goto-char edit-end-pos) (goto-char edit-end-pos)
(insert-file-contents buffer-file-name nil (vlf-with-undo-disabled
vlf-end-pos end) (insert-file-contents buffer-file-name nil
(setq shift-end (cdr (vlf-adjust-chunk vlf-end-pos end)
vlf-end-pos end nil t (setq shift-end (cdr (vlf-adjust-chunk
edit-end-pos)))))) vlf-end-pos end nil t
edit-end-pos)))))))
(cond ((< vlf-start-pos start) (cond ((< vlf-start-pos start)
(delete-region (point-min) (byte-to-position (let* ((del-pos (1+ (byte-to-position
(- start vlf-start-pos)))) (- 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))))
((< start vlf-start-pos) ((< start vlf-start-pos)
(let ((edit-end-pos (point-max))) (let ((edit-end-pos (point-max)))
(goto-char edit-end-pos) (goto-char edit-end-pos)
(insert-file-contents buffer-file-name nil (vlf-with-undo-disabled
start vlf-start-pos) (insert-file-contents buffer-file-name nil
(setq shift-start (car start vlf-start-pos)
(vlf-adjust-chunk start (setq shift-start (car
(vlf-adjust-chunk start
vlf-start-pos vlf-start-pos
t nil t nil
edit-end-pos))) edit-end-pos)))
(goto-char (point-min)) (goto-char (point-min))
(insert (delete-and-extract-region edit-end-pos (insert (delete-and-extract-region edit-end-pos
(point-max)))))) (point-max)))))))
(setq vlf-start-pos (- start shift-start) (setq vlf-start-pos (- start shift-start)
vlf-end-pos (+ end shift-end)) vlf-end-pos (+ end shift-end))
(goto-char (or (byte-to-position (- pos vlf-start-pos)) (goto-char (or (byte-to-position (- pos vlf-start-pos))
@@ -376,63 +425,73 @@ Return t if move hasn't been canceled."
vlf-end-pos (min end vlf-file-size)) vlf-end-pos (min end vlf-file-size))
(let ((inhibit-read-only t) (let ((inhibit-read-only t)
(pos (position-bytes (point)))) (pos (position-bytes (point))))
(erase-buffer) (vlf-with-undo-disabled
(insert-file-contents buffer-file-name nil (erase-buffer)
vlf-start-pos vlf-end-pos) (insert-file-contents buffer-file-name nil
(let ((shifts (vlf-adjust-chunk vlf-start-pos vlf-end-pos t vlf-start-pos vlf-end-pos)
(let ((shifts (vlf-adjust-chunk vlf-start-pos vlf-end-pos t
t))) t)))
(setq vlf-start-pos (- vlf-start-pos (car shifts)) (setq vlf-start-pos (- vlf-start-pos (car shifts))
vlf-end-pos (+ vlf-end-pos (cdr shifts))) vlf-end-pos (+ vlf-end-pos (cdr shifts)))
(goto-char (or (byte-to-position (+ pos (car shifts))) (goto-char (or (byte-to-position (+ pos (car shifts)))
(point-max))))) (point-max))))))
(set-buffer-modified-p nil) (set-buffer-modified-p nil)
(set-visited-file-modtime)) (set-visited-file-modtime))
(defun vlf-adjust-chunk (start end &optional adjust-start adjust-end (defun vlf-adjust-chunk (start end &optional adjust-start adjust-end
position) position)
"Adjust chunk at absolute START to END till content can be \ "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 - add to the end. to the beginning, ADJUST-END - append to the end.
Use buffer POSITION as start if given. Use buffer POSITION as start if given.
Return number of bytes moved back for proper decoding and number of Return number of bytes moved back for proper decoding and number of
bytes added to the end." bytes added to the end."
(let ((position (or position (point-min))) (let ((shift-start 0)
(shift-start 0) (shift-end 0))
(shift-end 0)
(chunk-size (- end start)))
;; adjust beginning
(if adjust-start (if adjust-start
(while (and (not (zerop start)) (let ((position (or position (point-min)))
(< shift-start 4) (chunk-size (- end start)))
(< 4 (abs (- chunk-size (while (and (not (zerop start))
(length (encode-coding-region (< shift-start 4)
position (point-max) (< 4 (abs (- chunk-size
buffer-file-coding-system (length (encode-coding-region
t)))))) position (point-max)
(setq shift-start (1+ shift-start) buffer-file-coding-system
start (1- start) t))))))
chunk-size (1+ chunk-size)) (setq shift-start (1+ shift-start)
(delete-region position (point-max)) start (1- start)
(goto-char position) chunk-size (1+ chunk-size))
(insert-file-contents buffer-file-name nil start end))) (delete-region position (point-max))
;; adjust end (goto-char position)
(when (and adjust-end (< end vlf-file-size)) (insert-file-contents buffer-file-name nil start end))))
(let ((expected-size (buffer-size))) (if adjust-end
(while (and (= expected-size (buffer-size)) (cond ((vlf-partial-decode-shown-p) ;remove raw bytes from end
(< end vlf-file-size)) (goto-char (point-max))
(setq shift-end (1+ shift-end) (while (eq (char-charset (preceding-char)) 'eight-bit)
end (1+ end)) (setq shift-end (1- shift-end))
(delete-region position (point-max)) (delete-char -1)))
(goto-char position) ((< end vlf-file-size) ;add bytes until new character is displayed
(insert-file-contents buffer-file-name nil start end))) (let ((position (or position (point-min)))
(when (< end vlf-file-size) (expected-size (buffer-size)))
(setq shift-end (1- shift-end) (while (and (progn
end (1- end)) (setq shift-end (1+ shift-end)
(delete-region position (point-max)) end (1+ end))
(goto-char position) (delete-region position (point-max))
(insert-file-contents buffer-file-name nil start end))) (goto-char position)
(insert-file-contents buffer-file-name
nil start end)
(< end vlf-file-size))
(= expected-size (buffer-size))))))))
(cons shift-start shift-end))) (cons shift-start shift-end)))
(defun vlf-partial-decode-shown-p ()
"Determine if partial decode codes are displayed.
This seems to be the case with GNU/Emacs before 24.4."
(cond ((< emacs-major-version 24) t)
((< 24 emacs-major-version) nil)
(t ;; TODO: use (< emacs-minor-version 4) after 24.4 release
(string-lessp emacs-version "24.3.5"))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; search ;;; search
@@ -441,7 +500,8 @@ bytes added to the end."
BATCH-STEP is amount of overlap between successive chunks." BATCH-STEP is amount of overlap between successive chunks."
(if (<= count 0) (if (<= count 0)
(error "Count must be positive")) (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-chunk-end vlf-end-pos)
(match-start-pos (+ vlf-start-pos (position-bytes (point)))) (match-start-pos (+ vlf-start-pos (position-bytes (point))))
(match-end-pos match-start-pos) (match-end-pos match-start-pos)
@@ -452,81 +512,80 @@ BATCH-STEP is amount of overlap between successive chunks."
(- vlf-file-size vlf-end-pos) (- vlf-file-size vlf-end-pos)
vlf-start-pos) vlf-start-pos)
vlf-file-size))) vlf-file-size)))
(set-buffer-modified-p nil) (vlf-with-undo-disabled
(buffer-disable-undo) (unwind-protect
(unwind-protect (catch 'end-of-file
(catch 'end-of-file (if backward
(if backward (while (not (zerop to-find))
(while (not (zerop to-find)) (cond ((re-search-backward regexp nil t)
(cond ((re-search-backward regexp nil t) (setq to-find (1- to-find)
(setq to-find (1- to-find) match-chunk-start vlf-start-pos
match-chunk-start vlf-start-pos match-chunk-end vlf-end-pos
match-chunk-end vlf-end-pos match-start-pos (+ vlf-start-pos
match-start-pos (+ vlf-start-pos (position-bytes
(position-bytes (match-beginning 0)))
(match-beginning 0))) match-end-pos (+ vlf-start-pos
match-end-pos (+ vlf-start-pos (position-bytes
(position-bytes (match-end 0)))))
(match-end 0))))) ((zerop vlf-start-pos)
((zerop vlf-start-pos) (throw 'end-of-file nil))
(throw 'end-of-file nil)) (t (let ((batch-move (- vlf-start-pos
(t (let ((batch-move (- vlf-start-pos (- vlf-batch-size
(- vlf-batch-size batch-step))))
batch-step)))) (vlf-move-to-batch
(vlf-move-to-batch (if (< match-start-pos batch-move)
(if (< match-start-pos batch-move) (- match-start-pos vlf-batch-size)
(- match-start-pos vlf-batch-size) batch-move) t))
batch-move) t)) (goto-char (if (< match-start-pos
(goto-char (if (< match-start-pos vlf-end-pos)
vlf-end-pos) (or (byte-to-position
(or (byte-to-position (- match-start-pos
(- match-start-pos vlf-start-pos))
vlf-start-pos)) (point-max))
(point-max)) (point-max)))
(point-max))) (progress-reporter-update
(progress-reporter-update reporter (- vlf-file-size
reporter (- vlf-file-size vlf-start-pos)))))
vlf-start-pos))))) (while (not (zerop to-find))
(while (not (zerop to-find)) (cond ((re-search-forward regexp nil t)
(cond ((re-search-forward regexp nil t) (setq to-find (1- to-find)
(setq to-find (1- to-find) match-chunk-start vlf-start-pos
match-chunk-start vlf-start-pos match-chunk-end vlf-end-pos
match-chunk-end vlf-end-pos match-start-pos (+ vlf-start-pos
match-start-pos (+ vlf-start-pos (position-bytes
(position-bytes (match-beginning 0)))
(match-beginning 0))) match-end-pos (+ vlf-start-pos
match-end-pos (+ vlf-start-pos (position-bytes
(position-bytes (match-end 0)))))
(match-end 0))))) ((= vlf-end-pos vlf-file-size)
((= vlf-end-pos vlf-file-size) (throw 'end-of-file nil))
(throw 'end-of-file nil)) (t (let ((batch-move (- vlf-end-pos batch-step)))
(t (let ((batch-move (- vlf-end-pos batch-step))) (vlf-move-to-batch
(vlf-move-to-batch (if (< batch-move match-end-pos)
(if (< batch-move match-end-pos) match-end-pos
match-end-pos batch-move) t))
batch-move) t)) (goto-char (if (< vlf-start-pos match-end-pos)
(goto-char (if (< vlf-start-pos match-end-pos) (or (byte-to-position
(or (byte-to-position (- match-end-pos
(- match-end-pos vlf-start-pos))
vlf-start-pos)) (point-min))
(point-min)) (point-min)))
(point-min))) (progress-reporter-update reporter
(progress-reporter-update reporter vlf-end-pos)))))
vlf-end-pos))))) (progress-reporter-done reporter))
(progress-reporter-done reporter)) (set-buffer-modified-p nil)
(set-buffer-modified-p nil) (if backward
(if backward (vlf-goto-match match-chunk-start match-chunk-end
(vlf-goto-match match-chunk-start match-chunk-end
match-end-pos match-start-pos match-end-pos match-start-pos
count to-find) 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 match-start-pos match-end-pos
count to-find))))) count to-find))))))
(defun vlf-goto-match (match-chunk-start match-chunk-end (defun vlf-goto-match (match-chunk-start match-chunk-end
match-pos-start match-pos-start
match-pos-end match-pos-end
count to-find) count to-find)
"Move to MATCH-CHUNK-START MATCH-CHUNK-END surrounding \ "Move to MATCH-CHUNK-START MATCH-CHUNK-END surrounding \
MATCH-POS-START and MATCH-POS-END. MATCH-POS-START and MATCH-POS-END.
According to COUNT and left TO-FIND, show if search has been According to COUNT and left TO-FIND, show if search has been
@@ -554,31 +613,34 @@ successful. Return nil if nothing found."
(goto-char match-end) (goto-char match-end)
(message "Moved to the %d match which is last" (message "Moved to the %d match which is last"
(- count to-find))) (- count to-find)))
(unwind-protect (sit-for 5) (unwind-protect (sit-for 3)
(delete-overlay overlay)) (delete-overlay overlay))
t)))) t))))
(defun vlf-re-search-forward (regexp count) (defun vlf-re-search-forward (regexp count)
"Search forward for REGEXP prefix COUNT number of times. "Search forward for REGEXP prefix COUNT number of times.
Search is performed chunk by chunk in `vlf-batch-size' memory." Search is performed chunk by chunk in `vlf-batch-size' memory."
(interactive (list (read-regexp "Search whole file" (interactive (if (vlf-no-modifications)
(if regexp-history (list (read-regexp "Search whole file"
(car regexp-history))) (if regexp-history
(or current-prefix-arg 1))) (car regexp-history)))
(or current-prefix-arg 1))))
(vlf-re-search regexp count nil (/ vlf-batch-size 8))) (vlf-re-search regexp count nil (/ vlf-batch-size 8)))
(defun vlf-re-search-backward (regexp count) (defun vlf-re-search-backward (regexp count)
"Search backward for REGEXP prefix COUNT number of times. "Search backward for REGEXP prefix COUNT number of times.
Search is performed chunk by chunk in `vlf-batch-size' memory." Search is performed chunk by chunk in `vlf-batch-size' memory."
(interactive (list (read-regexp "Search whole file backward" (interactive (if (vlf-no-modifications)
(if regexp-history (list (read-regexp "Search whole file backward"
(car regexp-history))) (if regexp-history
(or current-prefix-arg 1))) (car regexp-history)))
(or current-prefix-arg 1))))
(vlf-re-search regexp count t (/ vlf-batch-size 8))) (vlf-re-search regexp count t (/ vlf-batch-size 8)))
(defun vlf-goto-line (n) (defun vlf-goto-line (n)
"Go to line N. If N is negative, count from the end of file." "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) (let ((start-pos vlf-start-pos)
(end-pos vlf-end-pos) (end-pos vlf-end-pos)
(pos (point)) (pos (point))
@@ -588,7 +650,7 @@ Search is performed chunk by chunk in `vlf-batch-size' memory."
(progn (vlf-beginning-of-file) (progn (vlf-beginning-of-file)
(goto-char (point-min)) (goto-char (point-min))
(setq success (vlf-re-search "[\n\C-m]" (1- n) (setq success (vlf-re-search "[\n\C-m]" (1- n)
nil 0))) nil 0)))
(vlf-end-of-file) (vlf-end-of-file)
(goto-char (point-max)) (goto-char (point-max))
(setq success (vlf-re-search "[\n\C-m]" (- n) t 0))) (setq success (vlf-re-search "[\n\C-m]" (- n) t 0)))
@@ -605,6 +667,7 @@ Search is performed chunk by chunk in `vlf-batch-size' memory."
(define-key map "n" 'vlf-occur-next-match) (define-key map "n" 'vlf-occur-next-match)
(define-key map "p" 'vlf-occur-prev-match) (define-key map "p" 'vlf-occur-prev-match)
(define-key map "\C-m" 'vlf-occur-visit) (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 [mouse-1] 'vlf-occur-visit)
(define-key map "o" 'vlf-occur-show) (define-key map "o" 'vlf-occur-show)
map) map)
@@ -644,10 +707,16 @@ EVENT may hold details of the invocation."
(vlf-occur-visit event) (vlf-occur-visit event)
(pop-to-buffer occur-buffer))) (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) (defun vlf-occur-visit (&optional event)
"Visit current `vlf-occur' link in a vlf buffer. "Visit current `vlf-occur' link in a vlf buffer.
If original VLF buffer has been killed, With prefix argument or if original VLF buffer has been killed,
open new VLF session each time. open new VLF session.
EVENT may hold details of the invocation." EVENT may hold details of the invocation."
(interactive (list last-nonmenu-event)) (interactive (list last-nonmenu-event))
(when event (when event
@@ -659,14 +728,23 @@ EVENT may hold details of the invocation."
(if file (if file
(let ((chunk-start (get-char-property pos 'chunk-start)) (let ((chunk-start (get-char-property pos 'chunk-start))
(chunk-end (get-char-property pos 'chunk-end)) (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) (match-pos (+ (get-char-property pos 'line-pos)
pos-relative))) pos-relative)))
(or (buffer-live-p buffer) (cond (current-prefix-arg
(let ((occur-buffer (current-buffer))) (setq vlf-buffer (vlf file))
(setq buffer (vlf file)) (switch-to-buffer occur-buffer))
(switch-to-buffer occur-buffer))) ((not (buffer-live-p vlf-buffer))
(pop-to-buffer 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) (vlf-move-to-chunk chunk-start chunk-end)
(goto-char match-pos))))) (goto-char match-pos)))))
@@ -676,21 +754,32 @@ Prematurely ending indexing will still show what's found so far."
(interactive (list (read-regexp "List lines matching regexp" (interactive (list (read-regexp "List lines matching regexp"
(if regexp-history (if regexp-history
(car regexp-history))))) (car regexp-history)))))
(let ((start-pos vlf-start-pos) (if (buffer-modified-p) ;use temporary buffer not to interfere with modifications
(end-pos vlf-end-pos) (let ((vlf-buffer (current-buffer))
(pos (point))) (file buffer-file-name)
(vlf-beginning-of-file) (batch-size vlf-batch-size))
(goto-char (point-min)) (with-temp-buffer
(set-buffer-modified-p nil) (setq buffer-file-name file)
(buffer-disable-undo) (set-buffer-modified-p nil)
(unwind-protect (vlf-build-occur regexp) (set (make-local-variable 'vlf-batch-size) batch-size)
(set-buffer-modified-p nil) (vlf-mode 1)
(vlf-move-to-chunk start-pos end-pos) (goto-char (point-min))
(goto-char pos)))) (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) (defun vlf-build-occur (regexp vlf-buffer)
"Build occur style index for REGEXP." "Build occur style index for REGEXP over VLF-BUFFER."
(let ((line 1) (let ((case-fold-search t)
(line 1)
(last-match-line 0) (last-match-line 0)
(last-line-pos (point-min)) (last-line-pos (point-min))
(file buffer-file-name) (file buffer-file-name)
@@ -698,7 +787,7 @@ Prematurely ending indexing will still show what's found so far."
(match-end-pos (+ vlf-start-pos (position-bytes (point)))) (match-end-pos (+ vlf-start-pos (position-bytes (point))))
(occur-buffer (generate-new-buffer (occur-buffer (generate-new-buffer
(concat "*VLF-occur " (file-name-nondirectory (concat "*VLF-occur " (file-name-nondirectory
buffer-file-name) buffer-file-name)
"*"))) "*")))
(line-regexp (concat "\\(?5:[\n\C-m]\\)\\|\\(?10:" (line-regexp (concat "\\(?5:[\n\C-m]\\)\\|\\(?10:"
regexp "\\)")) regexp "\\)"))
@@ -720,7 +809,6 @@ Prematurely ending indexing will still show what's found so far."
last-line-pos (point)) last-line-pos (point))
(let* ((chunk-start vlf-start-pos) (let* ((chunk-start vlf-start-pos)
(chunk-end vlf-end-pos) (chunk-end vlf-end-pos)
(vlf-buffer (current-buffer))
(line-pos (line-beginning-position)) (line-pos (line-beginning-position))
(line-text (buffer-substring (line-text (buffer-substring
line-pos (line-end-position)))) line-pos (line-end-position))))
@@ -762,8 +850,8 @@ Prematurely ending indexing will still show what's found so far."
(unless end-of-file (unless end-of-file
(let ((batch-move (- vlf-end-pos batch-step))) (let ((batch-move (- vlf-end-pos batch-step)))
(vlf-move-to-batch (if (< batch-move match-end-pos) (vlf-move-to-batch (if (< batch-move match-end-pos)
match-end-pos match-end-pos
batch-move) t)) batch-move) t))
(goto-char (if (< vlf-start-pos match-end-pos) (goto-char (if (< vlf-start-pos match-end-pos)
(or (byte-to-position (- match-end-pos (or (byte-to-position (- match-end-pos
vlf-start-pos)) vlf-start-pos))
@@ -773,6 +861,7 @@ Prematurely ending indexing will still show what's found so far."
last-line-pos (line-beginning-position)) last-line-pos (line-beginning-position))
(progress-reporter-update reporter vlf-end-pos)))) (progress-reporter-update reporter vlf-end-pos))))
(progress-reporter-done reporter)) (progress-reporter-done reporter))
(set-buffer-modified-p nil)
(if (zerop total-matches) (if (zerop total-matches)
(progn (with-current-buffer occur-buffer (progn (with-current-buffer occur-buffer
(set-buffer-modified-p nil)) (set-buffer-modified-p nil))
@@ -781,7 +870,7 @@ Prematurely ending indexing will still show what's found so far."
(with-current-buffer occur-buffer (with-current-buffer occur-buffer
(goto-char (point-min)) (goto-char (point-min))
(insert (propertize (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) in file: %s" total-matches line regexp file)
'face 'underline)) 'face 'underline))
(set-buffer-modified-p nil) (set-buffer-modified-p nil)
@@ -792,30 +881,11 @@ in file: %s" total-matches line regexp file)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; editing ;;; editing
(defvar vlf-edit-mode-map (defun vlf-refresh ()
(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 ()
"Discard edit and refresh chunk from file." "Discard edit and refresh chunk from file."
(interactive) (interactive)
(set-buffer-modified-p nil) (set-buffer-modified-p nil)
(vlf-move-to-chunk vlf-start-pos vlf-end-pos) (vlf-move-to-chunk-2 vlf-start-pos vlf-end-pos))
(vlf-mode)
(message "Switched to VLF mode."))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; saving ;;; saving
@@ -839,27 +909,26 @@ Save anyway? ")))
(vlf-file-shift-back size-change)) (vlf-file-shift-back size-change))
(t (vlf-file-shift-forward (- size-change)))) (t (vlf-file-shift-forward (- size-change))))
(vlf-move-to-chunk-2 vlf-start-pos vlf-end-pos) (vlf-move-to-chunk-2 vlf-start-pos vlf-end-pos)
(goto-char pos)) (goto-char pos)))
(vlf-mode))
t) t)
(defun vlf-file-shift-back (size-change) (defun vlf-file-shift-back (size-change)
"Shift file contents SIZE-CHANGE bytes back." "Shift file contents SIZE-CHANGE bytes back."
(write-region nil nil buffer-file-name vlf-start-pos t) (write-region nil nil buffer-file-name vlf-start-pos t)
(buffer-disable-undo)
(let ((read-start-pos vlf-end-pos) (let ((read-start-pos vlf-end-pos)
(coding-system-for-write 'no-conversion) (coding-system-for-write 'no-conversion)
(reporter (make-progress-reporter "Adjusting file content..." (reporter (make-progress-reporter "Adjusting file content..."
vlf-end-pos vlf-end-pos
vlf-file-size))) 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)) size-change))
(setq read-start-pos (+ read-start-pos vlf-batch-size)) (setq read-start-pos (+ read-start-pos vlf-batch-size))
(progress-reporter-update reporter read-start-pos)) (progress-reporter-update reporter read-start-pos))
;; pad end with space ;; pad end with space
(erase-buffer) (erase-buffer)
(vlf-verify-size) (vlf-verify-size)
(insert-char 32 size-change) (insert-char 32 size-change))
(write-region nil nil buffer-file-name (- vlf-file-size (write-region nil nil buffer-file-name (- vlf-file-size
size-change) t) size-change) t)
(progress-reporter-done reporter))) (progress-reporter-done reporter)))
@@ -879,26 +948,26 @@ back at WRITE-POS. Return nil if EOF is reached, t otherwise."
(defun vlf-file-shift-forward (size-change) (defun vlf-file-shift-forward (size-change)
"Shift file contents SIZE-CHANGE bytes forward. "Shift file contents SIZE-CHANGE bytes forward.
Done by saving content up front and then writing previous batch." Done by saving content up front and then writing previous batch."
(buffer-disable-undo) (let ((read-size (max (/ vlf-batch-size 2) size-change))
(let ((size (+ vlf-batch-size size-change))
(read-pos vlf-end-pos) (read-pos vlf-end-pos)
(write-pos vlf-start-pos) (write-pos vlf-start-pos)
(reporter (make-progress-reporter "Adjusting file content..." (reporter (make-progress-reporter "Adjusting file content..."
vlf-start-pos vlf-start-pos
vlf-file-size))) vlf-file-size)))
(when (vlf-shift-batches size read-pos write-pos t) (vlf-with-undo-disabled
(setq write-pos (+ read-pos size-change) (when (vlf-shift-batches read-size read-pos write-pos t)
read-pos (+ read-pos size)) (setq write-pos (+ read-pos size-change)
(progress-reporter-update reporter write-pos) read-pos (+ read-pos read-size))
(let ((coding-system-for-write 'no-conversion)) (progress-reporter-update reporter write-pos)
(while (vlf-shift-batches size read-pos write-pos nil) (let ((coding-system-for-write 'no-conversion))
(setq write-pos (+ read-pos size-change) (while (vlf-shift-batches read-size read-pos write-pos nil)
read-pos (+ read-pos size)) (setq write-pos (+ read-pos size-change)
(progress-reporter-update reporter write-pos)))) read-pos (+ read-pos read-size))
(progress-reporter-update reporter write-pos)))))
(progress-reporter-done reporter))) (progress-reporter-done reporter)))
(defun vlf-shift-batches (size read-pos write-pos hide-read) (defun vlf-shift-batches (read-size read-pos write-pos hide-read)
"Append SIZE bytes of file starting at READ-POS. "Append READ-SIZE bytes of file starting at READ-POS.
Then write initial buffer content to file at WRITE-POS. Then write initial buffer content to file at WRITE-POS.
If HIDE-READ is non nil, temporarily hide literal read content. If HIDE-READ is non nil, temporarily hide literal read content.
Return nil if EOF is reached, t otherwise." Return nil if EOF is reached, t otherwise."
@@ -909,8 +978,8 @@ Return nil if EOF is reached, t otherwise."
(when read-more (when read-more
(goto-char end-write-pos) (goto-char end-write-pos)
(insert-file-contents-literally buffer-file-name nil read-pos (insert-file-contents-literally buffer-file-name nil read-pos
(min vlf-file-size (+ read-pos (min vlf-file-size
size)))) (+ read-pos read-size))))
;; write ;; write
(if hide-read ; hide literal region if user has to choose encoding (if hide-read ; hide literal region if user has to choose encoding
(narrow-to-region start-write-pos end-write-pos)) (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