1
0
mirror of https://github.com/m00natic/vlfi.git synced 2025-01-18 20:10:47 +00:00

Manually decode and use several bytes buffer when loading chunk.

This commit is contained in:
Andrey Kotlarski 2014-01-07 01:55:27 +02:00
parent df8c9ea5dd
commit dd43af51ff
2 changed files with 89 additions and 103 deletions

View File

@ -27,15 +27,9 @@
;;; Code: ;;; Code:
(defconst vlf-min-chunk-size 16 (defconst vlf-sample-size 24
"Minimal number of bytes that can be properly decoded.") "Minimal number of bytes that can be properly decoded.")
(defconst vlf-partial-decode-shown
(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")))
"Indicates whether partial decode codes are displayed.")
(defun vlf-get-file-size (file) (defun vlf-get-file-size (file)
"Get size in bytes of FILE." "Get size in bytes of FILE."
(or (nth 7 (file-attributes file)) 0)) (or (nth 7 (file-attributes file)) 0))
@ -70,7 +64,7 @@ If non-nil, UPDATE-VISITED-TIME."
(setq buffer-undo-list undo-list)))) (setq buffer-undo-list undo-list))))
(defun vlf-move-to-chunk (start end &optional minimal) (defun vlf-move-to-chunk (start end &optional minimal)
"Move to chunk determined by START END. "Move to chunk enclosed by START END bytes.
When given MINIMAL flag, skip non important operations. When given MINIMAL flag, skip non important operations.
If same as current chunk is requested, do nothing. If same as current chunk is requested, do nothing.
Return number of bytes moved back for proper decoding and number of Return number of bytes moved back for proper decoding and number of
@ -84,7 +78,7 @@ bytes added to the end."
shifts))) shifts)))
(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 enclosed by START END keeping as much edits if any.
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* ((modified (buffer-modified-p)) (let* ((modified (buffer-modified-p))
@ -113,8 +107,9 @@ bytes added to the end."
(let ((pos (+ (position-bytes (point)) vlf-start-pos)) (let ((pos (+ (position-bytes (point)) vlf-start-pos))
(inhibit-read-only t)) (inhibit-read-only t))
(cond ((< end edit-end) (cond ((< end edit-end)
(let* ((del-pos (1+ (byte-to-position (let* ((del-pos (1+ (or (byte-to-position
(- end vlf-start-pos)))) (- end vlf-start-pos))
0)))
(del-len (length (encode-coding-region (del-len (length (encode-coding-region
del-pos (point-max) del-pos (point-max)
buffer-file-coding-system buffer-file-coding-system
@ -126,13 +121,11 @@ bytes added to the end."
(vlf-with-undo-disabled (vlf-with-undo-disabled
(delete-region del-pos (point-max))))) (delete-region del-pos (point-max)))))
((< edit-end end) ((< edit-end end)
(if (and (not vlf-partial-decode-shown) (vlf-with-undo-disabled
(< (- end vlf-end-pos) 4)) (setq shift-end (cdr (vlf-insert-file-contents
(setq end vlf-end-pos) vlf-end-pos end
(vlf-with-undo-disabled (/= start vlf-end-pos) t
(setq shift-end (cdr (vlf-insert-file-contents (point-max)))))))
vlf-end-pos end nil t
(point-max))))))))
(cond ((< vlf-start-pos start) (cond ((< vlf-start-pos start)
(let* ((del-pos (1+ (byte-to-position (let* ((del-pos (1+ (byte-to-position
(- start vlf-start-pos)))) (- start vlf-start-pos))))
@ -143,20 +136,18 @@ bytes added to the end."
(setq start (+ vlf-start-pos del-len)) (setq start (+ vlf-start-pos del-len))
(vlf-with-undo-disabled (vlf-with-undo-disabled
(delete-region (point-min) del-pos)) (delete-region (point-min) del-pos))
(vlf-shift-undo-list (- 1 del-pos)))) (vlf-shift-undo-list (- (point-min) del-pos))))
((< start vlf-start-pos) ((< start vlf-start-pos)
(if (and (not vlf-partial-decode-shown) (let ((edit-end-pos (point-max)))
(< (- vlf-start-pos start) 4)) (vlf-with-undo-disabled
(setq start vlf-start-pos) (setq shift-start (car (vlf-insert-file-contents
(let ((edit-end-pos (point-max))) start vlf-start-pos t
(vlf-with-undo-disabled (/= end vlf-start-pos)
(setq shift-start (car (vlf-insert-file-contents edit-end-pos)))
start vlf-start-pos (goto-char (point-min))
t nil edit-end-pos))) (insert (delete-and-extract-region
(goto-char (point-min)) edit-end-pos (point-max))))
(insert (delete-and-extract-region (vlf-shift-undo-list (- (point-max) edit-end-pos)))))
edit-end-pos (point-max))))
(vlf-shift-undo-list (- (point-max) edit-end-pos))))))
(setq start (- start shift-start)) (setq start (- start shift-start))
(goto-char (or (byte-to-position (- pos start)) (goto-char (or (byte-to-position (- pos start))
(byte-to-position (- pos vlf-start-pos)) (byte-to-position (- pos vlf-start-pos))
@ -200,17 +191,19 @@ bytes added to the end."
(setq adjust-start (and adjust-start (not (zerop start))) (setq adjust-start (and adjust-start (not (zerop start)))
adjust-end (and adjust-end (< end vlf-file-size)) adjust-end (and adjust-end (< end vlf-file-size))
position (or position (point-min))) position (or position (point-min)))
(goto-char position)
(let ((shift-start 0) (let ((shift-start 0)
(shift-end 0)) (shift-end 0)
(safe-end (if adjust-end
(min vlf-file-size (+ end 4))
end)))
(if adjust-start (if adjust-start
(setq shift-start (vlf-adjust-start start end position (setq shift-start (vlf-adjust-start start safe-end position
adjust-end) adjust-end)
start (- start shift-start)) start (- start shift-start))
(setq shift-end (vlf-insert-content-safe start end position) (vlf-insert-file-contents-safe start safe-end position))
end (+ end shift-end)))
(if adjust-end (if adjust-end
(setq shift-end (+ shift-end (setq shift-end (vlf-adjust-end start end position)))
(vlf-adjust-end start end position))))
(cons shift-start shift-end))) (cons shift-start shift-end)))
(defun vlf-adjust-start (start end position adjust-end) (defun vlf-adjust-start (start end position adjust-end)
@ -218,83 +211,75 @@ bytes added to the end."
be properly decoded. Use buffer POSITION as start. be properly decoded. Use buffer POSITION as start.
ADJUST-END is non-nil if end would be adjusted later. ADJUST-END is non-nil if end would be adjusted later.
Return number of bytes moved back for proper decoding." Return number of bytes moved back for proper decoding."
(let* ((min-end (min end (+ start vlf-min-chunk-size))) (let* ((safe-start (max 0 (- start 4)))
(chunk-size (- min-end start)) (sample-end (min end (+ safe-start vlf-sample-size)))
(strict (and (not adjust-end) (= min-end end))) (chunk-size (- sample-end safe-start))
(shift (vlf-insert-content-safe start min-end position t))) (strict (or (= sample-end vlf-file-size)
(setq start (- start shift)) (and (not adjust-end) (= sample-end end))))
(while (and (not (zerop start)) (shift 0))
(while (and (progn (vlf-insert-file-contents-safe
safe-start sample-end position)
(not (zerop safe-start)))
(< shift 3) (< shift 3)
(let ((diff (- chunk-size (let ((diff (- chunk-size
(length (length
(encode-coding-region (encode-coding-region
position (point-max) position (point-max)
buffer-file-coding-system t))))) buffer-file-coding-system t)))))
(cond (strict (not (zerop diff))) (if strict
(vlf-partial-decode-shown (not (zerop diff))
(or (< diff -3) (< 0 diff))) (or (< diff 0) (< 3 diff)))))
(t (or (< diff 0) (< 3 diff))))))
(setq shift (1+ shift) (setq shift (1+ shift)
start (1- start) safe-start (1- safe-start)
chunk-size (1+ chunk-size)) chunk-size (1+ chunk-size))
(delete-region position (point-max)) (delete-region position (point-max)))
(insert-file-contents buffer-file-name nil start min-end)) (let ((cut-pos position)
(unless (= min-end end) (cut-len 0))
(delete-region position (point-max)) (while (< safe-start start)
(insert-file-contents buffer-file-name nil start end)) (setq cut-len (length (encode-coding-region
shift)) cut-pos (1+ cut-pos)
buffer-file-coding-system t))
cut-pos (1+ cut-pos)
safe-start (+ safe-start cut-len)))
(if (< start safe-start)
(setq safe-start (- safe-start cut-len)
cut-pos (1- cut-pos)))
(if (= sample-end end)
(delete-region position cut-pos)
(delete-region position (point-max))
(vlf-insert-file-contents-safe safe-start end position)))
(- start safe-start)))
(defun vlf-adjust-end (start end position) (defun vlf-adjust-end (start end position)
"Adjust chunk end at absolute START to END till content can be\ "Adjust chunk end at absolute START to END starting at POSITION.
properly decoded starting at POSITION. Remove characters from the end until length is closest to expected.
Return number of bytes added for proper decoding." Return number of bytes added over expected."
(let ((shift 0)) (let ((expected-size (- end start))
(if vlf-partial-decode-shown (current-size (length (encode-coding-region
(let ((new-pos (max position position (point-max)
(- (point-max) vlf-min-chunk-size)))) buffer-file-coding-system t)))
(if (< position new-pos) (cut-point (point-max))
(setq start (+ start (length (encode-coding-region (cut-len 0))
position new-pos (while (< expected-size current-size)
buffer-file-coding-system (setq cut-len (length (encode-coding-region
t))) (1- cut-point) cut-point
position new-pos)))) buffer-file-coding-system t))
(let ((chunk-size (- end start))) cut-point (1- cut-point)
(goto-char (point-max)) current-size (- current-size cut-len)))
(while (and (< shift 3) (if (< current-size expected-size)
(< end vlf-file-size) (setq cut-point (1+ cut-point)
(or (eq (char-charset (preceding-char)) 'eight-bit) current-size (+ current-size cut-len)))
(/= chunk-size (delete-region cut-point (point-max))
(length (encode-coding-region (- current-size expected-size)))
position (point-max)
buffer-file-coding-system t)))))
(setq shift (1+ shift)
end (1+ end)
chunk-size (1+ chunk-size))
(delete-region position (point-max))
(insert-file-contents buffer-file-name nil start end)
(goto-char (point-max))))
shift))
(defun vlf-insert-content-safe (start end position &optional shift-start) (defun vlf-insert-file-contents-safe (start end position)
"Insert file content from absolute START to END of file at\ "Extract decoded file bytes START to END at POSITION."
POSITION. Adjust start if SHIFT-START is non nil, end otherwise. (let ((coding buffer-file-coding-system))
Clean up if no characters are inserted." (insert-file-contents-literally buffer-file-name nil start end)
(goto-char position) (let ((coding-system-for-read coding))
(let ((shift 0)) (decode-coding-inserted-region position (point-max)
(while (and (< shift 3) buffer-file-name nil start end))
(zerop (cadr (insert-file-contents buffer-file-name (setq buffer-file-coding-system last-coding-system-used)))
nil start end)))
(if shift-start
(not (zerop start))
(< end vlf-file-size)))
;; TODO: this seems like regression after Emacs 24.3
(message "Buffer content may be broken")
(setq shift (1+ shift))
(if shift-start
(setq start (1- start))
(setq end (1+ end)))
(delete-region position (point-max)))
shift))
(defun vlf-shift-undo-list (n) (defun vlf-shift-undo-list (n)
"Shift undo list element regions by N." "Shift undo list element regions by N."

1
vlf.el
View File

@ -149,6 +149,7 @@ You can customize number of bytes displayed by customizing
(with-current-buffer (generate-new-buffer "*vlf*") (with-current-buffer (generate-new-buffer "*vlf*")
(set-visited-file-name file) (set-visited-file-name file)
(set-buffer-modified-p nil) (set-buffer-modified-p nil)
(setq buffer-file-coding-system nil)
(vlf-mode 1) (vlf-mode 1)
(switch-to-buffer (current-buffer)))) (switch-to-buffer (current-buffer))))