mirror of
https://github.com/m00natic/vlfi.git
synced 2025-01-18 12:05:31 +00:00
Merge branch 'master' into chunk-opt2
This commit is contained in:
parent
3c2fb6b93e
commit
02a37c4192
20
README.org
20
README.org
@ -1,13 +1,12 @@
|
||||
* View Large Files Improved
|
||||
* View Large Files
|
||||
|
||||
An Emacs mode that allows viewing, editing and searching in large
|
||||
files in chunks. Batch size can be adjusted on the fly and bounds the
|
||||
memory that is to be used for operations on the file.
|
||||
|
||||
This mode builds on the bare bones GNU ELPA vlf.el. It adds the
|
||||
following improvements:
|
||||
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:
|
||||
|
||||
- proper dealing with Unicode
|
||||
- regular expression search on whole file (in constant memory
|
||||
determined by current batch size)
|
||||
- chunk editing (if size has changed, saving is done in constant
|
||||
@ -18,8 +17,7 @@ following improvements:
|
||||
- newly added content is acknowledged if file has changed size
|
||||
meanwhile
|
||||
- automatic scrolling of batches
|
||||
- VLFI is added as an option when opening large files and given dired
|
||||
key-binding
|
||||
- VLFI is added as an option when opening large files
|
||||
|
||||
GNU Emacs 23 and 24 are supported.
|
||||
|
||||
@ -48,15 +46,15 @@ integer value), VLFI will probably not quite work.
|
||||
VLFI is derived from special-mode and keeps all its properties. For
|
||||
example you can directly press digits to enter prefix arguments.
|
||||
|
||||
** Changing major mode
|
||||
** Change major mode
|
||||
|
||||
You can (temporarily) change major mode to whatever you like (for
|
||||
example hexl-mode). Saving will insert contents as intended. You can
|
||||
return to *vlfi-mode* too.
|
||||
You can change major mode to whatever you like (for example
|
||||
hexl-mode). Saving will insert contents as intended. You can return
|
||||
to *vlfi-mode* too.
|
||||
|
||||
* Detail usage
|
||||
|
||||
** Controlling batch size
|
||||
** Control batch size
|
||||
|
||||
*+* and *-* control current batch size by factors of 2.
|
||||
|
||||
|
104
vlfi.el
104
vlfi.el
@ -1,12 +1,14 @@
|
||||
;;; vlfi.el --- View Large Files Improved -*- lexical-binding: t -*-
|
||||
;;; vlfi.el --- View Large Files -*- lexical-binding: t -*-
|
||||
|
||||
;; Copyright (C) 2006, 2012, 2013 Free Software Foundation, Inc.
|
||||
|
||||
;; Version: 0.8
|
||||
;; Version: 0.9.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
|
||||
@ -30,7 +32,9 @@
|
||||
;; The buffer uses VLFI mode, which defines several commands for
|
||||
;; moving around, searching and editing selected part of file.
|
||||
|
||||
;; This package is upgraded version of the vlf.el package.
|
||||
;; This package was inspired by a snippet posted by Kevin Rodgers,
|
||||
;; showing how to use `insert-file-contents' to extract part of a
|
||||
;; file.
|
||||
|
||||
;;; Code:
|
||||
|
||||
@ -49,6 +53,7 @@
|
||||
"Absolute position of the visible chunk start.")
|
||||
(defvar vlfi-end-pos 0 "Absolute position of the visible chunk end.")
|
||||
(defvar vlfi-file-size 0 "Total size of presented file.")
|
||||
(defvar vlfi-encode-size 0 "Size in bytes of current batch decoded.")
|
||||
|
||||
(defvar vlfi-mode-map
|
||||
(let ((map (make-sparse-keymap)))
|
||||
@ -70,23 +75,25 @@
|
||||
map)
|
||||
"Keymap for `vlfi-mode'.")
|
||||
|
||||
(put 'vlfi-batch-size 'permanent-local t)
|
||||
(put 'vlfi-start-pos 'permanent-local t)
|
||||
(put 'vlfi-end-pos 'permanent-local t)
|
||||
(put 'vlfi-file-size 'permanent-local t)
|
||||
(put 'vlfi-encode-size 'permanent-local t)
|
||||
|
||||
(define-derived-mode vlfi-mode special-mode "VLFI"
|
||||
"Mode to browse large files in."
|
||||
(setq buffer-read-only t)
|
||||
(set-buffer-modified-p nil)
|
||||
(buffer-disable-undo)
|
||||
(make-local-variable 'write-file-functions)
|
||||
(add-hook 'write-file-functions 'vlfi-write)
|
||||
(add-hook 'write-file-functions 'vlfi-write nil t)
|
||||
(make-local-variable 'revert-buffer-function)
|
||||
(setq revert-buffer-function 'vlfi-revert)
|
||||
(make-local-variable 'vlfi-batch-size)
|
||||
(put 'vlfi-batch-size 'permanent-local t)
|
||||
(make-local-variable 'vlfi-start-pos)
|
||||
(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))
|
||||
(make-local-variable 'vlfi-encode-size))
|
||||
|
||||
;;;###autoload
|
||||
(defun vlfi (file)
|
||||
@ -96,9 +103,9 @@ buffer. You can customize number of bytes displayed by customizing
|
||||
`vlfi-batch-size'."
|
||||
(interactive "fFile to open: ")
|
||||
(with-current-buffer (generate-new-buffer "*vlfi*")
|
||||
(set-visited-file-name file)
|
||||
(vlfi-mode)
|
||||
(setq buffer-file-name file
|
||||
vlfi-file-size (vlfi-get-file-size file))
|
||||
(setq vlfi-file-size (vlfi-get-file-size buffer-file-name))
|
||||
(vlfi-insert-file)
|
||||
(switch-to-buffer (current-buffer))))
|
||||
|
||||
@ -116,9 +123,12 @@ buffer. You can customize number of bytes displayed by customizing
|
||||
'(define-key dired-mode-map "V" 'dired-vlfi))
|
||||
|
||||
;;;###autoload
|
||||
(defun vlfi-if-file-too-large (size op-type &optional filename)
|
||||
(defadvice abort-if-file-too-large (around vlfi-if-file-too-large
|
||||
(size op-type
|
||||
&optional filename)
|
||||
compile activate)
|
||||
"If file SIZE larger than `large-file-warning-threshold', \
|
||||
allow user to view file with `vlfi', open it normally or abort.
|
||||
allow user to view file with `vlfi', open it normally, or abort.
|
||||
OP-TYPE specifies the file operation being performed over FILENAME."
|
||||
(and large-file-warning-threshold size
|
||||
(> size large-file-warning-threshold)
|
||||
@ -143,15 +153,12 @@ OP-TYPE specifies the file operation being performed over FILENAME."
|
||||
((memq char '(?a ?A))
|
||||
(error "Aborted"))))))
|
||||
|
||||
;; hijack `abort-if-file-too-large'
|
||||
;;;###autoload
|
||||
(fset 'abort-if-file-too-large 'vlfi-if-file-too-large)
|
||||
|
||||
;; scroll auto batching
|
||||
(defadvice scroll-up (around vlfi-scroll-up
|
||||
activate compile)
|
||||
"Slide to next batch if at end of buffer in `vlfi-mode'."
|
||||
(if (and (eq major-mode 'vlfi-mode)
|
||||
(if (and (derived-mode-p 'vlfi-mode)
|
||||
(eobp))
|
||||
(progn (vlfi-next-batch 1)
|
||||
(goto-char (point-min)))
|
||||
@ -160,7 +167,7 @@ OP-TYPE specifies the file operation being performed over FILENAME."
|
||||
(defadvice scroll-down (around vlfi-scroll-down
|
||||
activate compile)
|
||||
"Slide to previous batch if at beginning of buffer in `vlfi-mode'."
|
||||
(if (and (eq major-mode 'vlfi-mode)
|
||||
(if (and (derived-mode-p 'vlfi-mode)
|
||||
(bobp))
|
||||
(progn (vlfi-prev-batch 1)
|
||||
(goto-char (point-max)))
|
||||
@ -180,8 +187,6 @@ OP-TYPE specifies the file operation being performed over FILENAME."
|
||||
Normally, the value is doubled;
|
||||
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)))
|
||||
@ -204,6 +209,12 @@ with the prefix argument DECREASE it is halved."
|
||||
"Get size in bytes of FILE."
|
||||
(nth 7 (file-attributes file)))
|
||||
|
||||
(defun vlfi-verify-size ()
|
||||
"Update file size information if necessary and visited file time."
|
||||
(unless (verify-visited-file-modtime (current-buffer))
|
||||
(setq vlfi-file-size (vlfi-get-file-size buffer-file-name))
|
||||
(set-visited-file-modtime)))
|
||||
|
||||
(defun vlfi-insert-file (&optional from-end)
|
||||
"Insert first chunk of current file contents in current buffer.
|
||||
With FROM-END prefix, start from the back."
|
||||
@ -225,13 +236,12 @@ With FROM-END prefix, start from the back."
|
||||
(interactive)
|
||||
(vlfi-insert-file t))
|
||||
|
||||
(defun vlfi-revert (&optional ignore-auto noconfirm)
|
||||
"Revert current chunk. Ignore IGNORE-AUTO.
|
||||
(defun vlfi-revert (&optional _ignore-auto noconfirm)
|
||||
"Revert current chunk. Ignore _IGNORE-AUTO.
|
||||
Ask for confirmation if NOCONFIRM is nil."
|
||||
(ignore ignore-auto)
|
||||
(or noconfirm
|
||||
(yes-or-no-p (format "Revert buffer from file %s? "
|
||||
buffer-file-name))
|
||||
(if (or noconfirm
|
||||
(yes-or-no-p (format "Revert buffer from file %s? "
|
||||
buffer-file-name)))
|
||||
(vlfi-move-to-chunk vlfi-start-pos vlfi-end-pos)))
|
||||
|
||||
(defun vlfi-jump-to-chunk (n)
|
||||
@ -249,8 +259,7 @@ When prefix argument is supplied and positive
|
||||
When prefix argument is negative
|
||||
append next APPEND number of batches to the existing buffer."
|
||||
(interactive "p")
|
||||
(or (verify-visited-file-modtime (current-buffer))
|
||||
(setq vlfi-file-size (vlfi-get-file-size buffer-file-name)))
|
||||
(vlfi-verify-size)
|
||||
(let* ((end (min (+ vlfi-end-pos (* vlfi-batch-size
|
||||
(abs append)))
|
||||
vlfi-file-size))
|
||||
@ -279,8 +288,7 @@ When prefix argument is negative
|
||||
"Move to batch determined by START.
|
||||
Adjust according to file start/end and show `vlfi-batch-size' bytes.
|
||||
When given MINIMAL flag, skip non important operations."
|
||||
(or (verify-visited-file-modtime (current-buffer))
|
||||
(setq vlfi-file-size (vlfi-get-file-size buffer-file-name)))
|
||||
(vlfi-verify-size)
|
||||
(let ((start (max 0 start))
|
||||
(end (min (+ vlfi-start-pos vlfi-batch-size)
|
||||
vlfi-file-size)))
|
||||
@ -417,10 +425,13 @@ Return cons \(success-status . number-of-bytes-moved-back\)."
|
||||
|
||||
(defun vlfi-decode-status (size)
|
||||
"Check if decoding followed by encoding results in SIZE bytes."
|
||||
(= size (length (encode-coding-string
|
||||
(decode-coding-region (point-min) (point-max)
|
||||
buffer-file-coding-system t)
|
||||
buffer-file-coding-system t))))
|
||||
(< (abs (- size (setq vlfi-encode-size
|
||||
(length (encode-coding-string
|
||||
(decode-coding-region
|
||||
(point-min) (point-max)
|
||||
buffer-file-coding-system t)
|
||||
buffer-file-coding-system t)))))
|
||||
4))
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;;; search
|
||||
@ -666,9 +677,9 @@ Prematurely ending indexing will still show what's found so far."
|
||||
(pos (point)))
|
||||
(vlfi-beginning-of-file)
|
||||
(goto-char (point-min))
|
||||
(vlfi-build-occur regexp)
|
||||
(vlfi-move-to-chunk start-pos end-pos)
|
||||
(goto-char pos)))
|
||||
(unwind-protect (vlfi-build-occur regexp)
|
||||
(vlfi-move-to-chunk start-pos end-pos)
|
||||
(goto-char pos))))
|
||||
|
||||
(defun vlfi-build-occur (regexp)
|
||||
"Build occur style index for REGEXP."
|
||||
@ -804,17 +815,19 @@ or \\[vlfi-discard-edit] to discard changes.")))
|
||||
|
||||
(defun vlfi-write ()
|
||||
"Write current chunk to file. Always return true to disable save.
|
||||
If changing size of chunk shift remaining file content."
|
||||
If changing size of chunk, shift remaining file content."
|
||||
(interactive)
|
||||
(when (and (buffer-modified-p)
|
||||
(or (verify-visited-file-modtime (current-buffer))
|
||||
(y-or-n-p "File has changed since visited or saved. \
|
||||
Save anyway? ")))
|
||||
(let ((pos (point))
|
||||
(size-change (- vlfi-end-pos vlfi-start-pos
|
||||
(length (encode-coding-region
|
||||
(point-min) (point-max)
|
||||
buffer-file-coding-system t)))))
|
||||
(size-change (- vlfi-encode-size
|
||||
(setq vlfi-encode-size
|
||||
(length (encode-coding-region
|
||||
(point-min) (point-max)
|
||||
buffer-file-coding-system
|
||||
t))))))
|
||||
(cond ((zerop size-change)
|
||||
(write-region nil nil buffer-file-name vlfi-start-pos t))
|
||||
((< 0 size-change)
|
||||
@ -840,6 +853,7 @@ Save anyway? ")))
|
||||
(progress-reporter-update reporter read-start-pos))
|
||||
;; pad end with space
|
||||
(erase-buffer)
|
||||
(vlfi-verify-size)
|
||||
(insert-char 32 size-change)
|
||||
(write-region nil nil buffer-file-name (- vlfi-file-size
|
||||
size-change) t)
|
||||
@ -849,8 +863,7 @@ Save anyway? ")))
|
||||
"Read `vlfi-batch-size' bytes from READ-POS and write them \
|
||||
back at WRITE-POS. Return nil if EOF is reached, t otherwise."
|
||||
(erase-buffer)
|
||||
(or (verify-visited-file-modtime (current-buffer))
|
||||
(setq vlfi-file-size (vlfi-get-file-size buffer-file-name)))
|
||||
(vlfi-verify-size)
|
||||
(let ((read-end (+ read-pos vlfi-batch-size)))
|
||||
(insert-file-contents-literally buffer-file-name nil
|
||||
read-pos
|
||||
@ -884,8 +897,7 @@ Done by saving content up front and then writing previous batch."
|
||||
Then write initial buffer content to file at WRITE-POS.
|
||||
If HIDE-READ is non nil, temporarily hide literal read content.
|
||||
Return nil if EOF is reached, t otherwise."
|
||||
(or (verify-visited-file-modtime (current-buffer))
|
||||
(setq vlfi-file-size (vlfi-get-file-size buffer-file-name)))
|
||||
(vlfi-verify-size)
|
||||
(let ((read-more (< read-pos vlfi-file-size))
|
||||
(start-write-pos (point-min))
|
||||
(end-write-pos (point-max)))
|
||||
|
Loading…
x
Reference in New Issue
Block a user