1 ;;; vlf.el --- View Large Files
3 ;; Copyright (C) 2006, 2012 Free Software Foundation, Inc.
6 ;; Keywords: large files, utilities
7 ;; Authors: 2006 Mathias Dahl <mathias.dahl@gmail.com>
8 ;; 2012 Sam Steingold <sds@gnu.org>
10 ;; This file is free software; you can redistribute it and/or modify
11 ;; it under the terms of the GNU General Public License as published by
12 ;; the Free Software Foundation; either version 2, or (at your option)
15 ;; This file is distributed in the hope that it will be useful,
16 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
17 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 ;; GNU General Public License for more details.
20 ;; You should have received a copy of the GNU General Public License
21 ;; along with GNU Emacs; see the file COPYING. If not, write to
22 ;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
23 ;; Boston, MA 02111-1307, USA.
27 ;; This package provides the M-x vlf command, which visits part of a
28 ;; large file in a read-only buffer without visiting the entire file.
29 ;; The buffer uses VLF mode, which defines the commands M-<next>
30 ;; (vlf-next-batch) and M-<prior> (vlf-prev-batch) to visit other
31 ;; parts of the file. The option `vlf-batch-size' specifies the size
32 ;; of each batch, in bytes.
34 ;; This package was inspired by a snippet posted by Kevin Rodgers,
35 ;; showing how to use `insert-file-contents' to extract part of a
41 "View Large Files in Emacs."
45 (defcustom vlf-batch-size 1024
46 "Defines how large each batch of file data is (in bytes)."
50 ;; Keep track of file position.
51 (defvar vlf-start-pos)
53 (defvar vlf-file-size)
56 (let ((map (make-sparse-keymap)))
57 (define-key map [M-next] 'vlf-next-batch)
58 (define-key map [M-prior] 'vlf-prev-batch)
59 (define-key map (kbd "C-+") 'vlf-change-batch-size)
61 "Keymap for `vlf-mode'.")
63 (define-derived-mode vlf-mode special-mode "VLF"
64 "Mode to browse large files in."
65 (setq buffer-read-only t)
66 (set-buffer-modified-p nil)
67 (make-local-variable 'vlf-batch-size)
68 (make-local-variable 'vlf-start-pos)
69 (make-local-variable 'vlf-file-size))
71 (defun vlf-change-batch-size (decrease)
72 "Change the buffer-local value of `vlf-batch-size'.
73 Normally, the value is doubled;
74 with the prefix argument it is halved."
76 (or (assq 'vlf-batch-size (buffer-local-variables))
77 (error "%s is not local in this buffer" 'vlf-batch-size))
81 (* vlf-batch-size 2)))
82 (vlf-update-buffer-name))
84 (defun vlf-format-buffer-name ()
85 "Return format for vlf buffer name."
86 (format "%s(%s)[%d,%d](%d)"
87 (file-name-nondirectory buffer-file-name)
88 (file-size-human-readable vlf-file-size)
89 vlf-start-pos vlf-end-pos vlf-batch-size))
91 (defun vlf-update-buffer-name ()
92 "Update the current buffer name."
93 (rename-buffer (vlf-format-buffer-name) t))
95 (defun vlf-next-batch (append)
96 "Display the next batch of file data.
97 Append to the existing buffer when the prefix argument is supplied."
99 (when (= vlf-end-pos vlf-file-size)
100 (error "Already at EOF"))
101 (let ((inhibit-read-only t)
102 (end (min vlf-file-size (+ vlf-end-pos vlf-batch-size))))
103 (goto-char (point-max))
104 ;; replacing `erase-buffer' with replace arg to `insert-file-contents'
106 (unless append (erase-buffer))
107 (insert-file-contents buffer-file-name nil vlf-end-pos end)
109 (setq vlf-start-pos vlf-end-pos))
110 (setq vlf-end-pos end)
111 (set-buffer-modified-p nil)
112 (vlf-update-buffer-name)))
114 (defun vlf-prev-batch (prepend)
115 "Display the previous batch of file data.
116 Prepend to the existing buffer when the prefix argument is supplied."
118 (when (= vlf-start-pos 0)
119 (error "Already at BOF"))
120 (let ((inhibit-read-only t)
121 (start (max 0 (- vlf-start-pos vlf-batch-size))))
122 (goto-char (point-min))
123 (unless prepend (erase-buffer))
124 (insert-file-contents buffer-file-name nil start vlf-start-pos)
126 (setq vlf-end-pos vlf-start-pos))
127 (setq vlf-start-pos start)
128 (set-buffer-modified-p nil)
129 (vlf-update-buffer-name)))
132 "View a Large File in Emacs.
133 FILE is the file to open.
134 Batches of the file data from FILE will be displayed in a
136 You can customize the number of bytes to
137 display by customizing `vlf-batch-size'."
138 (interactive "fFile to open: ")
139 (with-current-buffer (generate-new-buffer "*vlf*")
140 (setq buffer-file-name file
142 vlf-end-pos vlf-batch-size
143 vlf-file-size (nth 7 (file-attributes file)))
144 (vlf-update-buffer-name)
145 (insert-file-contents buffer-file-name nil
146 vlf-start-pos vlf-end-pos nil)
148 (display-buffer (current-buffer))))