X-Git-Url: https://code.delx.au/gnu-emacs-elpa/blobdiff_plain/7d682e9777bb38860a5f73e380ae033b93ed44d9..6517ec8921438deae6547ab5eb38e004935d5618:/packages/vlf/vlf-base.el diff --git a/packages/vlf/vlf-base.el b/packages/vlf/vlf-base.el index 2a530f854..f56820231 100644 --- a/packages/vlf/vlf-base.el +++ b/packages/vlf/vlf-base.el @@ -27,16 +27,15 @@ ;;; Code: -(defgroup vlf nil - "View Large Files in Emacs." - :prefix "vlf-" - :group 'files) +(require 'vlf-tune) -(defcustom vlf-batch-size 1024 - "Defines how large each batch of file data is (in bytes)." - :group 'vlf - :type 'integer) -(put 'vlf-batch-size 'permanent-local t) +(defcustom vlf-before-chunk-update nil + "Hook that runs before chunk update." + :group 'vlf :type 'hook) + +(defcustom vlf-after-chunk-update nil + "Hook that runs after chunk update." + :group 'vlf :type 'hook) ;;; Keep track of file position. (defvar vlf-start-pos 0 @@ -48,10 +47,6 @@ (make-variable-buffer-local 'vlf-end-pos) (put 'vlf-end-pos 'permanent-local t) -(defvar vlf-file-size 0 "Total size of presented file.") -(make-variable-buffer-local 'vlf-file-size) -(put 'vlf-file-size 'permanent-local t) - (defconst vlf-sample-size 24 "Minimal number of bytes that can be properly decoded.") @@ -106,8 +101,7 @@ bytes added to the end." 0))) (setq vlf-start-pos place vlf-end-pos place) - (if (not minimal) - (vlf-update-buffer-name)) + (or minimal (vlf-update-buffer-name)) (cons (- start place) (- place end))))) ((or (/= start vlf-start-pos) (/= end vlf-end-pos)) @@ -124,88 +118,118 @@ bytes added to the end." (let* ((modified (buffer-modified-p)) (start (max 0 start)) (end (min end vlf-file-size)) + (hexl (derived-mode-p 'hexl-mode)) + restore-hexl hexl-undo-list (edit-end (if modified - (+ vlf-start-pos - (length (encode-coding-region - (point-min) (point-max) - buffer-file-coding-system t))) - vlf-end-pos))) - (cond - ((or (< edit-end start) (< end vlf-start-pos) - (not (verify-visited-file-modtime (current-buffer)))) - (when (or (not modified) - (y-or-n-p "Chunk modified, are you sure? ")) ;full chunk renewal - (set-buffer-modified-p nil) - (vlf-move-to-chunk-2 start end))) - ((and (= start vlf-start-pos) (= end edit-end)) - (or modified (vlf-move-to-chunk-2 start end))) - ((or (and (<= start vlf-start-pos) (<= edit-end end)) - (not modified) - (y-or-n-p "Chunk modified, are you sure? ")) - (let ((shift-start 0) - (shift-end 0)) - (let ((pos (+ (position-bytes (point)) vlf-start-pos)) - (inhibit-read-only t)) - (cond ((= end vlf-start-pos) - (or (eq buffer-undo-list t) - (setq buffer-undo-list nil)) - (vlf-with-undo-disabled (erase-buffer)) - (setq modified nil)) - ((< end edit-end) - (setq end (car (vlf-delete-region - (point-min) vlf-start-pos edit-end - end (min (or (byte-to-position - (- end vlf-start-pos)) - (point-min)) - (point-max)) - nil)))) - ((< edit-end end) - (vlf-with-undo-disabled - (setq shift-end (cdr (vlf-insert-file-contents - vlf-end-pos end nil t - (point-max))))))) - (setq vlf-end-pos (+ end shift-end)) - (cond ((= start edit-end) - (or (eq buffer-undo-list t) - (setq buffer-undo-list nil)) - (vlf-with-undo-disabled - (delete-region (point-min) (point))) - (setq modified nil)) - ((< vlf-start-pos start) - (let ((del-info (vlf-delete-region - (point-min) vlf-start-pos - vlf-end-pos start - (min (or (byte-to-position - (- start vlf-start-pos)) - (point)) - (point-max)) t))) - (setq start (car del-info)) - (vlf-shift-undo-list (- (point-min) - (cdr del-info))))) - ((< start vlf-start-pos) - (let ((edit-end-pos (point-max))) - (vlf-with-undo-disabled - (setq shift-start (car (vlf-insert-file-contents - start vlf-start-pos t nil - edit-end-pos))) - (goto-char (point-min)) - (insert (delete-and-extract-region - edit-end-pos (point-max)))) - (vlf-shift-undo-list (- (point-max) - edit-end-pos))))) - (setq start (- start shift-start)) - (goto-char (or (byte-to-position (- pos start)) - (byte-to-position (- pos vlf-start-pos)) - (point-max))) - (setq vlf-start-pos start)) - (set-buffer-modified-p modified) - (set-visited-file-modtime) - (cons shift-start shift-end)))))) + (progn + (when hexl + (setq restore-hexl t + hexl-undo-list buffer-undo-list + buffer-undo-list t) + (vlf-tune-dehexlify)) + (+ vlf-start-pos + (vlf-tune-encode-length (point-min) + (point-max)))) + vlf-end-pos)) + (shifts + (cond + ((or (< edit-end start) (< end vlf-start-pos) + (not (verify-visited-file-modtime (current-buffer)))) + (when (or (not modified) + (y-or-n-p "Chunk modified, are you sure? ")) ;full chunk renewal + (set-buffer-modified-p nil) + (if (consp hexl-undo-list) + (setq hexl-undo-list nil)) + (vlf-move-to-chunk-2 start end))) + ((and (= start vlf-start-pos) (= end edit-end)) + (unless modified + (if (consp hexl-undo-list) + (setq hexl-undo-list nil)) + (vlf-move-to-chunk-2 start end))) + ((or (and (<= start vlf-start-pos) (<= edit-end end)) + (not modified) + (y-or-n-p "Chunk modified, are you sure? ")) + (run-hooks 'vlf-before-chunk-update) + (when (and hexl (not restore-hexl)) + (if (consp buffer-undo-list) + (setq buffer-undo-list nil)) + (vlf-tune-dehexlify)) + (let ((shift-start 0) + (shift-end 0)) + (let ((pos (+ (position-bytes (point)) vlf-start-pos)) + (inhibit-read-only t)) + (cond ((= end vlf-start-pos) + (or (eq buffer-undo-list t) + (setq buffer-undo-list nil)) + (vlf-with-undo-disabled (erase-buffer)) + (setq modified nil)) + ((< end edit-end) + (setq end (car (vlf-delete-region + (point-min) vlf-start-pos + edit-end end + (min (or (byte-to-position + (- end vlf-start-pos)) + (point-min)) + (point-max)) + nil)))) + ((< edit-end end) + (vlf-with-undo-disabled + (setq shift-end (cdr (vlf-insert-file-contents + vlf-end-pos end nil t + (point-max))))))) + (setq vlf-end-pos (+ end shift-end)) + (cond ((= start edit-end) + (or (eq buffer-undo-list t) + (setq buffer-undo-list nil)) + (vlf-with-undo-disabled + (delete-region (point-min) (point))) + (setq modified nil)) + ((< vlf-start-pos start) + (let ((del-info (vlf-delete-region + (point-min) vlf-start-pos + vlf-end-pos start + (min (or + (byte-to-position + (- start vlf-start-pos)) + (point)) + (point-max)) t))) + (setq start (car del-info)) + (vlf-shift-undo-list (- (point-min) + (cdr del-info))))) + ((< start vlf-start-pos) + (let ((edit-end-pos (point-max))) + (vlf-with-undo-disabled + (setq shift-start (car + (vlf-insert-file-contents + start vlf-start-pos t nil + edit-end-pos))) + (goto-char (point-min)) + (insert (delete-and-extract-region + edit-end-pos (point-max)))) + (vlf-shift-undo-list (- (point-max) + edit-end-pos))))) + (setq start (- start shift-start)) + (goto-char (or (byte-to-position (- pos start)) + (byte-to-position (- pos vlf-start-pos)) + (point-max))) + (setq vlf-start-pos start)) + (set-buffer-modified-p modified) + (set-visited-file-modtime) + (when hexl + (vlf-tune-hexlify) + (setq restore-hexl nil)) + (run-hooks 'vlf-after-chunk-update) + (cons shift-start shift-end)))))) + (when restore-hexl + (vlf-tune-hexlify) + (setq buffer-undo-list hexl-undo-list)) + shifts)) (defun vlf-move-to-chunk-2 (start end) "Unconditionally move to chunk enclosed by START END bytes. Return number of bytes moved back for proper decoding and number of bytes added to the end." + (run-hooks 'vlf-before-chunk-update) (vlf-verify-size t) (setq vlf-start-pos (max 0 start) vlf-end-pos (min end vlf-file-size)) @@ -213,22 +237,27 @@ bytes added to the end." (let ((inhibit-read-only t) (pos (position-bytes (point)))) (vlf-with-undo-disabled - (erase-buffer) - (setq shifts (vlf-insert-file-contents vlf-start-pos - vlf-end-pos t t) - vlf-start-pos (- vlf-start-pos (car shifts)) - vlf-end-pos (+ vlf-end-pos (cdr shifts))) + (let ((hexl (derived-mode-p 'hexl-mode))) + (if hexl (hexl-mode-exit t)) + (erase-buffer) + (setq shifts (vlf-insert-file-contents vlf-start-pos + vlf-end-pos t t) + vlf-start-pos (- vlf-start-pos (car shifts)) + vlf-end-pos (+ vlf-end-pos (cdr shifts))) + (if hexl (vlf-tune-hexlify))) (goto-char (or (byte-to-position (+ pos (car shifts))) (point-max))))) (set-buffer-modified-p nil) - (setq buffer-undo-list nil) + (or (eq buffer-undo-list t) + (setq buffer-undo-list nil)) + (run-hooks 'vlf-after-chunk-update) shifts)) (defun vlf-insert-file-contents (start end adjust-start adjust-end &optional 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 - append to the end. +properly decoded. ADJUST-START determines if trying to prepend bytes +to the beginning, ADJUST-END - append to the end. Use buffer POSITION as start if given. Return number of bytes moved back for proper decoding and number of bytes added to the end." @@ -245,7 +274,7 @@ bytes added to the end." (setq shift-start (vlf-adjust-start start safe-end position adjust-end) start (- start shift-start)) - (vlf-insert-file-contents-1 start safe-end position)) + (vlf-insert-file-contents-1 start safe-end)) (if adjust-end (setq shift-end (- (car (vlf-delete-region position start safe-end end @@ -254,23 +283,9 @@ bytes added to the end." end))) (cons shift-start shift-end))) -(defun vlf-insert-file-contents-1 (start end position) - "Extract decoded file bytes START to END at POSITION." - (let ((coding buffer-file-coding-system)) - (insert-file-contents-literally buffer-file-name nil start end) - (let ((coding-system-for-read coding)) - (decode-coding-inserted-region position (point-max) - buffer-file-name nil start end))) - (when (eq (detect-coding-region position (min (+ position - vlf-sample-size) - (point-max)) t) - 'no-conversion) - (delete-region position (point-max)) - (insert-file-contents-literally buffer-file-name nil start end) - (let ((coding-system-for-read nil)) - (decode-coding-inserted-region position (point-max) - buffer-file-name nil start end))) - (setq buffer-file-coding-system last-coding-system-used)) +(defun vlf-insert-file-contents-1 (start end) + "Extract decoded file bytes START to END." + (vlf-tune-insert-file-contents start end)) (defun vlf-adjust-start (start end position adjust-end) "Adjust chunk beginning at absolute START to END till content can\ @@ -283,8 +298,8 @@ Return number of bytes moved back for proper decoding." (strict (or (= sample-end vlf-file-size) (and (not adjust-end) (= sample-end end)))) (shift 0)) - (while (and (progn (vlf-insert-file-contents-1 - safe-start sample-end position) + (while (and (progn (vlf-insert-file-contents-1 safe-start + sample-end) (not (zerop safe-start))) (< shift 3) (let ((diff (- chunk-size @@ -304,7 +319,7 @@ Return number of bytes moved back for proper decoding." position t 'start))) (unless (= sample-end end) (delete-region position (point-max)) - (vlf-insert-file-contents-1 safe-start end position)) + (vlf-insert-file-contents-1 safe-start end)) (- start safe-start))) (defun vlf-delete-region (position start end border cut-point from-start @@ -322,12 +337,10 @@ which deletion was performed." (eq encode-direction 'end) (< (- end border) (- border start)))) (dist (if encode-from-end - (- end (length (encode-coding-region - cut-point (point-max) - buffer-file-coding-system t))) - (+ start (length (encode-coding-region - position cut-point - buffer-file-coding-system t))))) + (- end (vlf-tune-encode-length cut-point + (point-max))) + (+ start (vlf-tune-encode-length position + cut-point)))) (len 0)) (if (< border dist) (while (< border dist) @@ -355,7 +368,7 @@ which deletion was performed." (defun vlf-shift-undo-list (n) "Shift undo list element regions by N." - (or (eq buffer-undo-list t) + (or (null buffer-undo-list) (eq buffer-undo-list t) (setq buffer-undo-list (nreverse (let ((min (point-min))