1
0
mirror of https://github.com/m00natic/vlfi.git synced 2024-10-05 18:30:51 +01:00

Simplify detection of buffer size change.

This commit is contained in:
Andrey Kotlarski 2013-04-13 01:29:12 +03:00
parent 8787186619
commit 8f6299c6c2

342
vlfi.el
View File

@ -50,7 +50,6 @@
(defvar vlfi-end-pos vlfi-batch-size (defvar vlfi-end-pos vlfi-batch-size
"Absolute position of the visible chunk end.") "Absolute position of the visible chunk end.")
(defvar vlfi-file-size 0 "Total size of presented file.") (defvar vlfi-file-size 0 "Total size of presented file.")
(defvar vlfi-buffer-size 0 "Buffer size of current chunk.")
(defvar vlfi-mode-map (defvar vlfi-mode-map
(let ((map (make-sparse-keymap))) (let ((map (make-sparse-keymap)))
@ -59,8 +58,8 @@
(define-key map "+" 'vlfi-change-batch-size) (define-key map "+" 'vlfi-change-batch-size)
(define-key map "-" (define-key map "-"
(lambda () "Decrease vlfi batch size by factor of 2." (lambda () "Decrease vlfi batch size by factor of 2."
(interactive) (interactive)
(vlfi-change-batch-size t))) (vlfi-change-batch-size t)))
(define-key map "s" 'vlfi-re-search-forward) (define-key map "s" 'vlfi-re-search-forward)
(define-key map "r" 'vlfi-re-search-backward) (define-key map "r" 'vlfi-re-search-backward)
(define-key map "[" 'vlfi-beginning-of-file) (define-key map "[" 'vlfi-beginning-of-file)
@ -83,9 +82,7 @@
(make-local-variable 'vlfi-end-pos) (make-local-variable 'vlfi-end-pos)
(put 'vlfi-end-pos 'permanent-local t) (put 'vlfi-end-pos 'permanent-local t)
(make-local-variable 'vlfi-file-size) (make-local-variable 'vlfi-file-size)
(put 'vlfi-file-size 'permanent-local t) (put 'vlfi-file-size 'permanent-local t))
(make-local-variable 'vlfi-buffer-size)
(put 'vlfi-buffer-size 'permanent-local t))
(defun vlfi-change-batch-size (decrease) (defun vlfi-change-batch-size (decrease)
"Change the buffer-local value of `vlfi-batch-size'. "Change the buffer-local value of `vlfi-batch-size'.
@ -95,18 +92,18 @@ with the prefix argument DECREASE it is halved."
(or (assq 'vlfi-batch-size (buffer-local-variables)) (or (assq 'vlfi-batch-size (buffer-local-variables))
(error "%s is not local in this buffer" 'vlfi-batch-size)) (error "%s is not local in this buffer" 'vlfi-batch-size))
(setq vlfi-batch-size (if decrease (setq vlfi-batch-size (if decrease
(/ vlfi-batch-size 2) (/ vlfi-batch-size 2)
(* vlfi-batch-size 2))) (* vlfi-batch-size 2)))
(vlfi-move-to-batch vlfi-start-pos)) (vlfi-move-to-batch vlfi-start-pos))
(defun vlfi-format-buffer-name () (defun vlfi-format-buffer-name ()
"Return format for vlfi buffer name." "Return format for vlfi buffer name."
(format "%s(%s)[%d/%d](%d)" (format "%s(%s)[%d/%d](%d)"
(file-name-nondirectory buffer-file-name) (file-name-nondirectory buffer-file-name)
(file-size-human-readable vlfi-file-size) (file-size-human-readable vlfi-file-size)
(/ vlfi-end-pos vlfi-batch-size) (/ vlfi-end-pos vlfi-batch-size)
(/ vlfi-file-size vlfi-batch-size) (/ vlfi-file-size vlfi-batch-size)
vlfi-batch-size)) vlfi-batch-size))
(defun vlfi-update-buffer-name () (defun vlfi-update-buffer-name ()
"Update the current buffer name." "Update the current buffer name."
@ -120,28 +117,26 @@ When prefix argument is negative
append next APPEND number of batches to the existing buffer." append next APPEND number of batches to the existing buffer."
(interactive "p") (interactive "p")
(let ((end (+ vlfi-end-pos (* vlfi-batch-size (let ((end (+ vlfi-end-pos (* vlfi-batch-size
(abs append))))) (abs append)))))
(when (< vlfi-file-size end) ; re-check file size (when (< vlfi-file-size end) ; re-check file size
(setq vlfi-file-size (nth 7 (file-attributes buffer-file-name))) (setq vlfi-file-size (nth 7 (file-attributes buffer-file-name)))
(cond ((= vlfi-end-pos vlfi-file-size) (cond ((= vlfi-end-pos vlfi-file-size)
(error "Already at EOF")) (error "Already at EOF"))
((< vlfi-file-size end) ((< vlfi-file-size end)
(setq end vlfi-file-size)))) (setq end vlfi-file-size))))
(let ((inhibit-read-only t) (let ((inhibit-read-only t)
(do-append (< append 0)) (do-append (< append 0))
(pos (point))) (pos (point)))
(if do-append (if do-append
(goto-char (point-max)) (goto-char (point-max))
(setq vlfi-start-pos (- end vlfi-batch-size)) (setq vlfi-start-pos (- end vlfi-batch-size))
(erase-buffer)) (erase-buffer))
(insert-file-contents buffer-file-name nil (insert-file-contents buffer-file-name nil (if do-append
(if do-append vlfi-end-pos
vlfi-end-pos vlfi-start-pos)
vlfi-start-pos) end)
end)
(goto-char pos)) (goto-char pos))
(setq vlfi-end-pos end (setq vlfi-end-pos end))
vlfi-buffer-size (buffer-size)))
(set-visited-file-modtime) (set-visited-file-modtime)
(set-buffer-modified-p nil) (set-buffer-modified-p nil)
(vlfi-update-buffer-name)) (vlfi-update-buffer-name))
@ -156,21 +151,20 @@ When prefix argument is negative
(if (zerop vlfi-start-pos) (if (zerop vlfi-start-pos)
(error "Already at BOF")) (error "Already at BOF"))
(let ((inhibit-read-only t) (let ((inhibit-read-only t)
(start (max 0 (- vlfi-start-pos (* vlfi-batch-size (start (max 0 (- vlfi-start-pos (* vlfi-batch-size
(abs prepend))))) (abs prepend)))))
(do-prepend (< prepend 0)) (do-prepend (< prepend 0))
(pos (- (point-max) (point)))) (pos (- (point-max) (point))))
(if do-prepend (if do-prepend
(goto-char (point-min)) (goto-char (point-min))
(setq vlfi-end-pos (+ start vlfi-batch-size)) (setq vlfi-end-pos (+ start vlfi-batch-size))
(erase-buffer)) (erase-buffer))
(insert-file-contents buffer-file-name nil start (insert-file-contents buffer-file-name nil start
(if do-prepend (if do-prepend
vlfi-start-pos vlfi-start-pos
vlfi-end-pos)) vlfi-end-pos))
(goto-char (- (point-max) pos)) (goto-char (- (point-max) pos))
(setq vlfi-start-pos start (setq vlfi-start-pos start))
vlfi-buffer-size (buffer-size)))
(set-visited-file-modtime) (set-visited-file-modtime)
(set-buffer-modified-p nil) (set-buffer-modified-p nil)
(vlfi-update-buffer-name)) (vlfi-update-buffer-name))
@ -179,19 +173,18 @@ When prefix argument is negative
"Move to batch determined by START. "Move to batch determined by START.
Adjust according to file start/end and show `vlfi-batch-size' bytes." Adjust according to file start/end and show `vlfi-batch-size' bytes."
(setq vlfi-start-pos (max 0 start) (setq vlfi-start-pos (max 0 start)
vlfi-end-pos (+ vlfi-start-pos vlfi-batch-size)) vlfi-end-pos (+ vlfi-start-pos vlfi-batch-size))
(if (< vlfi-file-size vlfi-end-pos) ; re-check file size (if (< vlfi-file-size vlfi-end-pos) ; re-check file size
(setq vlfi-file-size (setq vlfi-file-size
(nth 7 (file-attributes buffer-file-name)) (nth 7 (file-attributes buffer-file-name))
vlfi-end-pos (min vlfi-end-pos vlfi-file-size) vlfi-end-pos (min vlfi-end-pos vlfi-file-size)
vlfi-start-pos (max 0 (- vlfi-end-pos vlfi-batch-size)))) vlfi-start-pos (max 0 (- vlfi-end-pos vlfi-batch-size))))
(let ((inhibit-read-only t) (let ((inhibit-read-only t)
(pos (point))) (pos (point)))
(erase-buffer) (erase-buffer)
(insert-file-contents buffer-file-name nil (insert-file-contents buffer-file-name nil
vlfi-start-pos vlfi-end-pos) vlfi-start-pos vlfi-end-pos)
(goto-char pos)) (goto-char pos))
(setq vlfi-buffer-size (buffer-size))
(set-visited-file-modtime) (set-visited-file-modtime)
(set-buffer-modified-p nil) (set-buffer-modified-p nil)
(vlfi-update-buffer-name)) (vlfi-update-buffer-name))
@ -200,16 +193,15 @@ Adjust according to file start/end and show `vlfi-batch-size' bytes."
"Move to chunk determined by START END." "Move to chunk determined by START END."
(if (< vlfi-file-size end) ; re-check file size (if (< vlfi-file-size end) ; re-check file size
(setq vlfi-file-size (nth 7 (setq vlfi-file-size (nth 7
(file-attributes buffer-file-name)))) (file-attributes buffer-file-name))))
(setq vlfi-start-pos (max 0 start) (setq vlfi-start-pos (max 0 start)
vlfi-end-pos (min end vlfi-file-size)) vlfi-end-pos (min end vlfi-file-size))
(let ((inhibit-read-only t) (let ((inhibit-read-only t)
(pos (point))) (pos (point)))
(erase-buffer) (erase-buffer)
(insert-file-contents buffer-file-name nil (insert-file-contents buffer-file-name nil
vlfi-start-pos vlfi-end-pos) vlfi-start-pos vlfi-end-pos)
(goto-char pos)) (goto-char pos))
(setq vlfi-buffer-size (buffer-size))
(set-visited-file-modtime) (set-visited-file-modtime)
(set-buffer-modified-p nil) (set-buffer-modified-p nil)
(vlfi-update-buffer-name)) (vlfi-update-buffer-name))
@ -219,9 +211,9 @@ Adjust according to file start/end and show `vlfi-batch-size' bytes."
With FROM-END prefix, start from the back." With FROM-END prefix, start from the back."
(if from-end (if from-end
(setq vlfi-start-pos (max 0 (- vlfi-file-size vlfi-batch-size)) (setq vlfi-start-pos (max 0 (- vlfi-file-size vlfi-batch-size))
vlfi-end-pos vlfi-file-size) vlfi-end-pos vlfi-file-size)
(setq vlfi-start-pos 0 (setq vlfi-start-pos 0
vlfi-end-pos (min vlfi-batch-size vlfi-file-size))) vlfi-end-pos (min vlfi-batch-size vlfi-file-size)))
(vlfi-move-to-chunk vlfi-start-pos vlfi-end-pos)) (vlfi-move-to-chunk vlfi-start-pos vlfi-end-pos))
(defun vlfi-beginning-of-file () (defun vlfi-beginning-of-file ()
@ -243,7 +235,7 @@ buffer. You can customize number of bytes displayed by customizing
(interactive "fFile to open: \nP") (interactive "fFile to open: \nP")
(with-current-buffer (generate-new-buffer "*vlfi*") (with-current-buffer (generate-new-buffer "*vlfi*")
(setq buffer-file-name file (setq buffer-file-name file
vlfi-file-size (nth 7 (file-attributes file))) vlfi-file-size (nth 7 (file-attributes file)))
(vlfi-insert-file from-end) (vlfi-insert-file from-end)
(vlfi-mode) (vlfi-mode)
(switch-to-buffer (current-buffer)))) (switch-to-buffer (current-buffer))))
@ -272,25 +264,25 @@ OP-TYPE specifies the file operation being performed over FILENAME."
(and large-file-warning-threshold size (and large-file-warning-threshold size
(> size large-file-warning-threshold) (> size large-file-warning-threshold)
(let ((char nil)) (let ((char nil))
(while (not (memq (setq char (while (not (memq (setq char
(read-event (read-event
(propertize (propertize
(format (format
"File %s is large (%s): \ "File %s is large (%s): \
%s normally (o), %s with vlfi (v) or abort (a)" %s normally (o), %s with vlfi (v) or abort (a)"
(if filename (if filename
(file-name-nondirectory filename) (file-name-nondirectory filename)
"") "")
(file-size-human-readable size) (file-size-human-readable size)
op-type op-type) op-type op-type)
'face 'minibuffer-prompt))) 'face 'minibuffer-prompt)))
'(?o ?O ?v ?V ?a ?A)))) '(?o ?O ?v ?V ?a ?A))))
(cond ((memq char '(?o ?O))) (cond ((memq char '(?o ?O)))
((memq char '(?v ?V)) ((memq char '(?v ?V))
(vlfi filename nil) (vlfi filename nil)
(error "")) (error ""))
((memq char '(?a ?A)) ((memq char '(?a ?A))
(error "Aborted")))))) (error "Aborted"))))))
;;; hijack `abort-if-file-too-large' ;;; hijack `abort-if-file-too-large'
;;;###autoload ;;;###autoload
@ -300,66 +292,66 @@ OP-TYPE specifies the file operation being performed over FILENAME."
(defun vlfi-re-search (regexp count backward) (defun vlfi-re-search (regexp count backward)
"Search for REGEXP COUNT number of times forward or BACKWARD." "Search for REGEXP COUNT number of times forward or BACKWARD."
(let* ((match-start-pos (+ vlfi-start-pos (point))) (let* ((match-start-pos (+ vlfi-start-pos (point)))
(match-end-pos match-start-pos) (match-end-pos match-start-pos)
(to-find count) (to-find count)
(search-reporter (make-progress-reporter (search-reporter (make-progress-reporter
(concat "Searching for " regexp) (concat "Searching for " regexp)
(if backward (if backward
(- vlfi-file-size vlfi-end-pos) (- vlfi-file-size vlfi-end-pos)
vlfi-start-pos) vlfi-start-pos)
vlfi-file-size)) vlfi-file-size))
(batch-step (/ vlfi-batch-size 8))) ; amount of chunk overlap (batch-step (/ vlfi-batch-size 8))) ; amount of chunk overlap
(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-start-pos (+ vlfi-start-pos match-start-pos (+ vlfi-start-pos
(match-beginning 0)) (match-beginning 0))
match-end-pos (+ vlfi-start-pos match-end-pos (+ vlfi-start-pos
(match-end 0)))) (match-end 0))))
((zerop vlfi-start-pos) ((zerop vlfi-start-pos)
(throw 'end-of-file nil)) (throw 'end-of-file nil))
(t (let ((batch-move (- vlfi-start-pos (t (let ((batch-move (- vlfi-start-pos
(- vlfi-batch-size (- vlfi-batch-size
batch-step)))) batch-step))))
(vlfi-move-to-batch (vlfi-move-to-batch
(if (< match-start-pos batch-move) (if (< match-start-pos batch-move)
(- match-start-pos vlfi-batch-size) (- match-start-pos vlfi-batch-size)
batch-move))) batch-move)))
(goto-char (if (< match-start-pos (goto-char (if (< match-start-pos
vlfi-end-pos) vlfi-end-pos)
(- match-start-pos (- match-start-pos
vlfi-start-pos) vlfi-start-pos)
(point-max))) (point-max)))
(progress-reporter-update search-reporter (progress-reporter-update search-reporter
vlfi-start-pos)))) vlfi-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-start-pos (+ vlfi-start-pos match-start-pos (+ vlfi-start-pos
(match-beginning 0)) (match-beginning 0))
match-end-pos (+ vlfi-start-pos match-end-pos (+ vlfi-start-pos
(match-end 0)))) (match-end 0))))
((= vlfi-end-pos vlfi-file-size) ((= vlfi-end-pos vlfi-file-size)
(throw 'end-of-file nil)) (throw 'end-of-file nil))
(t (let ((batch-move (- vlfi-end-pos batch-step))) (t (let ((batch-move (- vlfi-end-pos batch-step)))
(vlfi-move-to-batch (vlfi-move-to-batch
(if (< batch-move match-end-pos) (if (< batch-move match-end-pos)
match-end-pos match-end-pos
batch-move))) batch-move)))
(goto-char (if (< vlfi-start-pos match-end-pos) (goto-char (if (< vlfi-start-pos match-end-pos)
(- match-end-pos vlfi-start-pos) (- match-end-pos vlfi-start-pos)
(point-min))) (point-min)))
(progress-reporter-update search-reporter (progress-reporter-update search-reporter
vlfi-end-pos))))) vlfi-end-pos)))))
(progress-reporter-done search-reporter)) (progress-reporter-done search-reporter))
(if backward (if backward
(vlfi-goto-match match-end-pos match-start-pos (vlfi-goto-match match-end-pos match-start-pos
count to-find) count to-find)
(vlfi-goto-match match-start-pos match-end-pos (vlfi-goto-match match-start-pos match-end-pos
count to-find))))) count to-find)))))
(defun vlfi-goto-match (match-pos-start match-pos-end 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. "Move to chunk surrounding MATCH-POS-START and MATCH-POS-END.
@ -367,41 +359,41 @@ According to COUNT and left TO-FIND, show if search has been
successful. Return nil if nothing found." successful. Return nil if nothing found."
(let ((success (zerop to-find))) (let ((success (zerop to-find)))
(or success (or success
(vlfi-move-to-batch (- match-pos-start (vlfi-move-to-batch (- match-pos-start
(/ vlfi-batch-size 2)))) (/ vlfi-batch-size 2))))
(let* ((match-end (- match-pos-end vlfi-start-pos)) (let* ((match-end (- match-pos-end vlfi-start-pos))
(overlay (make-overlay (- match-pos-start vlfi-start-pos) (overlay (make-overlay (- match-pos-start vlfi-start-pos)
match-end))) match-end)))
(overlay-put overlay 'face 'region) (overlay-put overlay 'face 'region)
(or success (goto-char match-end)) (or success (goto-char match-end))
(prog1 (cond (success t) (prog1 (cond (success t)
((< to-find count) ((< to-find count)
(message "Moved to the %d match which is last" (message "Moved to the %d match which is last"
(- count to-find)) (- count to-find))
t) t)
(t (message "Not found") (t (message "Not found")
nil)) nil))
(sit-for 0.1) (sit-for 0.1)
(delete-overlay overlay))))) (delete-overlay overlay)))))
(defun vlfi-re-search-forward (regexp count) (defun vlfi-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 `vlfi-batch-size' memory." Search is performed chunk by chunk in `vlfi-batch-size' memory."
(interactive (list (read-regexp "Search whole file" (interactive (list (read-regexp "Search whole file"
(if regexp-history (if regexp-history
(car regexp-history)) (car regexp-history))
'regexp-history) 'regexp-history)
(or current-prefix-arg 1))) (or current-prefix-arg 1)))
(vlfi-re-search regexp count nil)) (vlfi-re-search regexp count nil))
(defun vlfi-re-search-backward (regexp count) (defun vlfi-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 `vlfi-batch-size' memory." Search is performed chunk by chunk in `vlfi-batch-size' memory."
(interactive (list (read-regexp "Search whole file backward" (interactive (list (read-regexp "Search whole file backward"
(if regexp-history (if regexp-history
(car regexp-history)) (car regexp-history))
'regexp-history) 'regexp-history)
(or current-prefix-arg 1))) (or current-prefix-arg 1)))
(vlfi-re-search regexp count t)) (vlfi-re-search regexp count t))
;;; editing ;;; editing
@ -418,7 +410,7 @@ Search is performed chunk by chunk in `vlfi-batch-size' memory."
(setq buffer-read-only nil) (setq buffer-read-only nil)
(buffer-enable-undo) (buffer-enable-undo)
(message (substitute-command-keys (message (substitute-command-keys
"Editing: Type \\[vlfi-write] to write chunk \ "Editing: Type \\[vlfi-write] to write chunk \
or \\[vlfi-discard-edit] to discard changes."))) or \\[vlfi-discard-edit] to discard changes.")))
(defun vlfi-write-1 () (defun vlfi-write-1 ()
@ -433,31 +425,35 @@ Reopen last viewed chunk."
If changing size of chunk, may load the remaining part of file first." If changing size of chunk, may load the remaining part of file first."
(interactive) (interactive)
(when (and (derived-mode-p 'vlfi-mode) (when (and (derived-mode-p 'vlfi-mode)
(buffer-modified-p) (buffer-modified-p)
(or (verify-visited-file-modtime) (or (verify-visited-file-modtime)
(y-or-n-p "File has changed since visited or \ (y-or-n-p "File has changed since visited or \
saved. Save anyway? "))) saved. Save anyway? ")))
(let ((size-change (- vlfi-buffer-size (buffer-size)))) (let ((size-change (- vlfi-end-pos vlfi-start-pos
(length
(encode-coding-region
(point-min) (point-max)
buffer-file-coding-system t)))))
(if (zerop size-change) (if (zerop size-change)
(vlfi-write-1) (vlfi-write-1)
(setq vlfi-file-size (nth 7 (setq vlfi-file-size (nth 7
(file-attributes buffer-file-name))) (file-attributes buffer-file-name)))
(cond ((= vlfi-file-size vlfi-end-pos) (cond ((= vlfi-file-size vlfi-end-pos)
(vlfi-write-1)) (vlfi-write-1))
((y-or-n-p (concat "Changed size of original chunk. \ ((y-or-n-p (concat "Changed size of original chunk. \
Remaining part of the file [" Remaining part of the file ["
(file-size-human-readable (file-size-human-readable
(- vlfi-file-size vlfi-end-pos)) (- vlfi-file-size vlfi-end-pos))
"] has to be loaded. Continue? ")) "] has to be loaded. Continue? "))
(let ((pos (point))) (let ((pos (point)))
(goto-char (point-max)) (goto-char (point-max))
(insert-file-contents buffer-file-name nil (insert-file-contents buffer-file-name nil
vlfi-end-pos vlfi-file-size) vlfi-end-pos vlfi-file-size)
(when (< 0 size-change) ; pad with empty characters (when (< 0 size-change) ; pad with empty characters
(goto-char (point-max)) (goto-char (point-max))
(insert-char 32 size-change)) (insert-char 32 size-change))
(vlfi-write-1) (vlfi-write-1)
(goto-char pos)))))) (goto-char pos))))))
t)) t))
(defun vlfi-discard-edit () (defun vlfi-discard-edit ()