1
0
mirror of https://github.com/m00natic/vlfi.git synced 2025-11-10 20:05:34 +00:00

17 Commits
0.4 ... 0.5

Author SHA1 Message Date
Andrey Kotlarski
db3d2af04a Update version, README and commentary section. 2013-04-08 01:08:15 +03:00
Andrey Kotlarski
995a7a0988 Change some VLFI key-bindings not to override special-mode ones. 2013-04-08 00:57:53 +03:00
Andrey Kotlarski
1948f3ea4e Make VLFI edit mode actually working. 2013-04-08 00:56:42 +03:00
Andrey Kotlarski
0ff2f3eb9b Merge branch 'master' into edit 2013-04-07 18:54:40 +03:00
Andrey Kotlarski
03f323337b Don't reinsert content and move on successful search. 2013-04-07 18:53:50 +03:00
Andrey Kotlarski
9abee0425a Merge branch 'master' into edit 2013-04-05 00:43:15 +03:00
Andrey Kotlarski
80ca6b638b Fix vlfi invocation when prompted for large files. 2013-04-04 11:49:19 +03:00
Andrey Kotlarski
8a33dbfb89 Add something like edit minor mode. 2013-04-02 02:55:53 +03:00
Andrey Kotlarski
e387ed5f09 Add forgotten local variable statement and documentation. 2013-04-02 01:46:45 +03:00
Andrey Kotlarski
c36db11b86 Return correct search success status. 2013-04-01 14:38:50 +03:00
Andrey Kotlarski
ab20671a93 Abstract batch overlapping during search and optimize a bit. 2013-04-01 14:32:10 +03:00
Andrey Kotlarski
ac382e90dc Add temporary highlight of match. 2013-04-01 12:57:58 +03:00
Andrey Kotlarski
670561e811 Optimize search a bit. 2013-04-01 12:06:48 +03:00
Andrey Kotlarski
88cf03caba Interactive change of batch size immediately updates content. 2013-04-01 11:47:49 +03:00
Andrey Kotlarski
8e65e13dd9 Refactor and simplify search procedures. Always use batch sized
chunks.
2013-04-01 03:09:32 +03:00
Andrey Kotlarski
090cebc2ab Add procedure to insert strictly batch sized chunk (if possible). 2013-04-01 03:08:14 +03:00
Andrey Kotlarski
748fd1406e More key-binding simplification. 2013-04-01 03:07:20 +03:00
2 changed files with 168 additions and 131 deletions

View File

@@ -5,6 +5,7 @@ that builds on the GNU ELPA vlf.el. It adds the following
improvements:
- by chunk search
- chunk editing
- options to jump to end or beginning of file
- ability to jump/insert given number of batches at once
- ability to view newly added content if the file has grown meanwhile

298
vlfi.el
View File

@@ -3,7 +3,7 @@
;; Copyright (C) 2006, 2012, 2013 Free Software Foundation, Inc.
;; Version: 0.4
;; Version: 0.5
;; Keywords: large files, utilities
;; Authors: 2006 Mathias Dahl <mathias.dahl@gmail.com>
;; 2012 Sam Steingold <sds@gnu.org>
@@ -28,10 +28,8 @@
;; This package provides the M-x vlfi command, which visits part of a
;; large file in a read-only buffer without visiting the entire file.
;; The buffer uses VLFI mode, which defines the commands M-<next>
;; (vlfi-next-batch) and M-<prior> (vlfi-prev-batch) to visit other
;; parts of the file. The option `vlfi-batch-size' specifies the size
;; of each batch, in bytes.
;; The buffer uses VLFI mode, which defines several commands for
;; moving around, searching and editing selected chunk of file.
;; This package is an improved fork of the vlf.el package.
@@ -47,28 +45,31 @@
:type 'integer
:group 'vlfi)
;; Keep track of file position.
(defvar vlfi-start-pos)
(defvar vlfi-end-pos)
(defvar vlfi-file-size)
;;; Keep track of file position.
(defvar vlfi-start-pos 0
"Absolute position of the visible chunk start.")
(defvar vlfi-end-pos vlfi-batch-size
"Absolute position of the visible chunk end.")
(defvar vlfi-file-size 0 "Total size of presented file.")
(defvar vlfi-mode-map
(let ((map (make-sparse-keymap)))
(define-key map [M-next] 'vlfi-next-batch)
(define-key map [M-prior] 'vlfi-prev-batch)
(define-key map (kbd "M-+") 'vlfi-change-batch-size)
(define-key map (kbd "M--")
(define-key map "+" 'vlfi-change-batch-size)
(define-key map "-"
(lambda () "Decrease vlfi batch size by factor of 2."
(interactive)
(vlfi-change-batch-size t)))
(define-key map "s" 'vlfi-re-search-forward)
(define-key map "r" 'vlfi-re-search-backward)
(define-key map ">" (lambda () "Jump to end of file content."
(define-key map "]" (lambda () "Jump to end of file content."
(interactive)
(vlfi-insert-file buffer-file-name t)))
(define-key map "<" (lambda () "Jump to beginning of file content."
(define-key map "[" (lambda () "Jump to beginning of file content."
(interactive)
(vlfi-insert-file buffer-file-name)))
(define-key map "e" 'vlfi-edit-mode)
map)
"Keymap for `vlfi-mode'.")
@@ -76,9 +77,15 @@
"Mode to browse large files in."
(setq buffer-read-only t)
(set-buffer-modified-p nil)
(buffer-disable-undo)
(make-local-variable 'vlfi-batch-size)
(put 'vlfi-batch-size 'permanent-local t)
(make-local-variable 'vlfi-start-pos)
(make-local-variable 'vlfi-file-size))
(put 'vlfi-start-pos 'permanent-local t)
(make-local-variable 'vlfi-end-pos)
(put 'vlfi-end-pos 'permanent-local t)
(make-local-variable 'vlfi-file-size)
(put 'vlfi-file-size 'permanent-local t))
(defun vlfi-change-batch-size (decrease)
"Change the buffer-local value of `vlfi-batch-size'.
@@ -87,11 +94,10 @@ with the prefix argument DECREASE it is halved."
(interactive "P")
(or (assq 'vlfi-batch-size (buffer-local-variables))
(error "%s is not local in this buffer" 'vlfi-batch-size))
(setq vlfi-batch-size
(if decrease
(/ vlfi-batch-size 2)
(* vlfi-batch-size 2)))
(vlfi-update-buffer-name))
(setq vlfi-batch-size (if decrease
(/ vlfi-batch-size 2)
(* vlfi-batch-size 2)))
(vlfi-move-to-batch vlfi-start-pos))
(defun vlfi-format-buffer-name ()
"Return format for vlfi buffer name."
@@ -164,6 +170,23 @@ When prefix argument is negative
(set-buffer-modified-p nil)
(vlfi-update-buffer-name))
(defun vlfi-move-to-batch (start)
"Move to batch determined by START.
Adjust according to file start/end and show `vlfi-batch-size' bytes."
(setq vlfi-start-pos (max 0 start)
vlfi-end-pos (+ vlfi-start-pos vlfi-batch-size))
(if (< vlfi-file-size vlfi-end-pos) ; re-check file size
(setq vlfi-file-size
(nth 7 (file-attributes buffer-file-name))
vlfi-end-pos (min vlfi-end-pos vlfi-file-size)
vlfi-start-pos (max 0 (- vlfi-end-pos vlfi-batch-size))))
(let ((inhibit-read-only t))
(erase-buffer)
(insert-file-contents buffer-file-name nil
vlfi-start-pos vlfi-end-pos))
(set-buffer-modified-p nil)
(vlfi-update-buffer-name))
(defun vlfi-move-to-chunk (start end)
"Move to chunk determined by START END."
(if (< vlfi-file-size end) ; re-check file size
@@ -196,7 +219,6 @@ buffer. You can customize number of bytes displayed by customizing
`vlfi-batch-size'."
(interactive "fFile to open: \nP")
(with-current-buffer (generate-new-buffer "*vlfi*")
(buffer-disable-undo)
(setq buffer-file-name file
vlfi-file-size (nth 7 (file-attributes file)))
(vlfi-insert-file file from-end)
@@ -234,7 +256,7 @@ OP-TYPE specifies the file operation being performed over FILENAME."
'(?o ?O ?v ?V ?a ?A))))
(cond ((memq char '(?o ?O)))
((memq char '(?v ?V))
(vlfi nil filename)
(vlfi filename nil)
(error ""))
((memq char '(?a ?A))
(error "Aborted"))))))
@@ -243,6 +265,94 @@ OP-TYPE specifies the file operation being performed over FILENAME."
;;;###autoload
(fset 'abort-if-file-too-large 'vlfi-if-file-too-large)
;;; search
(defun vlfi-re-search (regexp count backward)
"Search for REGEXP COUNT number of times forward or BACKWARD."
(let* ((match-start-pos (+ vlfi-start-pos (point)))
(match-end-pos match-start-pos)
(to-find count)
(search-reporter (make-progress-reporter
(concat "Searching for " regexp)
(if backward
(- vlfi-file-size vlfi-end-pos)
vlfi-start-pos)
vlfi-file-size))
(batch-step (/ vlfi-batch-size 8))) ; amount of chunk overlap
(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-start-pos (+ vlfi-start-pos
(match-beginning 0))
match-end-pos (+ vlfi-start-pos
(match-end 0))))
((zerop vlfi-start-pos)
(throw 'end-of-file nil))
(t (let ((batch-move (- vlfi-start-pos
(- vlfi-batch-size
batch-step))))
(vlfi-move-to-batch
(if (< match-start-pos batch-move)
(- match-start-pos vlfi-batch-size)
batch-move)))
(goto-char (if (< match-start-pos
vlfi-end-pos)
(- match-start-pos
vlfi-start-pos)
(point-max)))
(progress-reporter-update search-reporter
vlfi-start-pos))))
(while (not (zerop to-find))
(cond ((re-search-forward regexp nil t)
(setq to-find (1- to-find)
match-start-pos (+ vlfi-start-pos
(match-beginning 0))
match-end-pos (+ vlfi-start-pos
(match-end 0))))
((= vlfi-end-pos vlfi-file-size)
(throw 'end-of-file nil))
(t (let ((batch-move (- vlfi-end-pos batch-step)))
(vlfi-move-to-batch
(if (< batch-move match-end-pos)
match-end-pos
batch-move)))
(goto-char (if (< vlfi-start-pos match-end-pos)
(- match-end-pos vlfi-start-pos)
(point-min)))
(progress-reporter-update search-reporter
vlfi-end-pos)))))
(progress-reporter-done search-reporter))
(if backward
(vlfi-goto-match match-end-pos match-start-pos
count to-find)
(vlfi-goto-match match-start-pos match-end-pos
count to-find)))))
(defun vlfi-goto-match (match-pos-start match-pos-end count to-find)
"Move to chunk surrounding MATCH-POS-START and MATCH-POS-END.
According to COUNT and left TO-FIND, show if search has been
successful. Return nil if nothing found."
(let ((success (zerop to-find)))
(or success
(vlfi-move-to-batch (- match-pos-start
(/ vlfi-batch-size 2))))
(let* ((match-end (- match-pos-end vlfi-start-pos))
(overlay (make-overlay (- match-pos-start vlfi-start-pos)
match-end)))
(overlay-put overlay 'face 'region)
(or success (goto-char match-end))
(prog1 (cond (success t)
((< to-find count)
(message "Moved to the %d match which is last"
(- count to-find))
t)
(t (message "Not found")
nil))
(sit-for 0.1)
(delete-overlay overlay)))))
(defun vlfi-re-search-forward (regexp count)
"Search forward for REGEXP prefix COUNT number of times."
(interactive (list (read-regexp "Search whole file"
@@ -250,124 +360,50 @@ OP-TYPE specifies the file operation being performed over FILENAME."
(car regexp-history))
'regexp-history)
(or current-prefix-arg 1)))
(let ((match-chunk-start vlfi-start-pos)
(match-chunk-end vlfi-end-pos)
(match-start-pos (point))
(match-end-pos (point))
(to-find count)
(search-reporter (make-progress-reporter
(concat "Searching for " regexp)
vlfi-start-pos vlfi-file-size))
(initial-chunk t))
(unwind-protect
(catch 'end-of-file
(while (not (zerop to-find))
(cond ((re-search-forward regexp nil t)
(setq to-find (if (= match-start-pos
(match-beginning 0))
to-find
(1- to-find))
match-start-pos (match-beginning 0)
match-end-pos (match-end 0)
match-chunk-start vlfi-start-pos
match-chunk-end vlfi-end-pos)
(if (and (< vlfi-batch-size match-start-pos)
(> (- vlfi-end-pos vlfi-start-pos)
vlfi-batch-size))
(setq match-chunk-start
(+ match-chunk-start vlfi-batch-size)
match-start-pos (- match-start-pos
vlfi-batch-size)
match-end-pos (- match-end-pos
vlfi-batch-size))))
((= vlfi-end-pos vlfi-file-size)
(throw 'end-of-file nil))
(t (if initial-chunk
(progn (setq initial-chunk nil)
(vlfi-next-batch -1))
(vlfi-move-to-chunk (+ vlfi-start-pos
vlfi-batch-size)
(+ vlfi-end-pos
vlfi-batch-size)))
(goto-char (if (< vlfi-start-pos match-chunk-end)
match-start-pos
(point-min)))
(goto-char match-start-pos)
(progress-reporter-update search-reporter
vlfi-end-pos))))
(progress-reporter-done search-reporter))
(vlfi-end-search match-chunk-start match-chunk-end
match-end-pos count to-find))))
(vlfi-re-search regexp count nil))
(defun vlfi-re-search-backward (regexp count)
"Search backward for REGEXP prefix COUNT number of times."
(interactive (list (read-regexp "Search whole file"
(interactive (list (read-regexp "Search whole file backward"
(if regexp-history
(car regexp-history))
'regexp-history)
(or current-prefix-arg 1)))
(let ((match-chunk-start vlfi-start-pos)
(match-chunk-end vlfi-end-pos)
(match-start-pos (point))
(match-end-pos (point))
(to-find count)
(search-reporter (make-progress-reporter
(concat "Searching for " regexp)
(- vlfi-file-size vlfi-end-pos)
vlfi-file-size))
(initial-chunk t))
(unwind-protect
(catch 'start-of-file
(while (not (zerop to-find))
(cond ((re-search-backward regexp nil t)
(setq to-find (if (= match-end-pos
(match-end 0))
to-find
(1- to-find))
match-start-pos (match-beginning 0)
match-end-pos (match-end 0)
match-chunk-start vlfi-start-pos
match-chunk-end vlfi-end-pos)
(if (and (< match-end-pos vlfi-batch-size)
(> (- vlfi-end-pos vlfi-start-pos)
vlfi-batch-size))
(setq match-chunk-end
(- match-chunk-end
vlfi-batch-size))))
((zerop vlfi-start-pos)
(throw 'start-of-file nil))
(t (if initial-chunk
(progn (setq initial-chunk nil)
(vlfi-prev-batch -1))
(vlfi-move-to-chunk (- vlfi-start-pos
vlfi-batch-size)
(- vlfi-end-pos
vlfi-batch-size)))
(goto-char (if (< match-chunk-start vlfi-end-pos)
match-end-pos
(point-max)))
(setq last-chunk-match nil)
(progress-reporter-update search-reporter
(- vlfi-file-size
vlfi-start-pos)))))
(progress-reporter-done search-reporter))
(vlfi-end-search match-chunk-start match-chunk-end
match-start-pos count to-find))))
(vlfi-re-search regexp count t))
(defun vlfi-end-search (match-chunk-start match-chunk-end
match-pos count to-find)
"Move to chunk determined by MATCH-CHUNK-START and MATCH-CHUNK-END.
Go to MATCH-POS and according to COUNT and left TO-FIND show if search
has been successful. Return nil if nothing found."
(vlfi-move-to-chunk match-chunk-start match-chunk-end)
(goto-char match-pos)
(cond ((zerop to-find) t)
((< to-find count)
(message "Moved to the %d match which is last found"
(- count to-find))
t)
(t (message "Not found")
nil)))
;;; editing
(defvar vlfi-edit-mode-map
(let ((map (make-sparse-keymap)))
(set-keymap-parent map text-mode-map)
(define-key map "\C-c\C-c" 'vlfi-write)
(define-key map "\C-c\C-q" 'vlfi-discard-edit)
map)
"Keymap for command `vlfi-edit-mode'.")
(define-derived-mode vlfi-edit-mode vlfi-mode "VLFI[edit]"
"Major mode for editing large file chunks."
(setq buffer-read-only nil)
(buffer-enable-undo)
(message (substitute-command-keys
"Editing: Type \\[vlfi-write] to write chunk \
or \\[vlfi-discard-edit] to discard changes.")))
(defun vlfi-write ()
"Write current chunk to file. May overwrite existing content."
(interactive)
(when (or (= (buffer-size) (- vlfi-end-pos vlfi-start-pos))
(y-or-n-p "Changed size of original chunk. \
End of chunk will be garbled. Continue? "))
(write-region nil nil buffer-file-name vlfi-start-pos)
(vlfi-move-to-chunk vlfi-start-pos vlfi-end-pos)
(vlfi-mode)))
(defun vlfi-discard-edit ()
"Discard edit and refresh chunk from file."
(interactive)
(vlfi-move-to-chunk vlfi-start-pos vlfi-end-pos)
(vlfi-mode)
(message "Switched to VLFI mode."))
(provide 'vlfi)