]> code.delx.au - gnu-emacs-elpa/blob - packages/vlf/vlf.el
Add smart-operator.
[gnu-emacs-elpa] / packages / vlf / vlf.el
1 ;;; vlf.el --- View Large Files
2
3 ;; Copyright (C) 2006, 2012 Free Software Foundation, Inc.
4
5 ;; Version: 0.2
6 ;; Keywords: large files, utilities
7 ;; Authors: 2006 Mathias Dahl <mathias.dahl@gmail.com>
8 ;; 2012 Sam Steingold <sds@gnu.org>
9
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)
13 ;; any later version.
14
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.
19
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.
24
25 ;;; Commentary:
26
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.
33
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
36 ;; file.
37
38 ;;; Code:
39
40 (defgroup vlf nil
41 "View Large Files in Emacs."
42 :prefix "vlf-"
43 :group 'files)
44
45 (defcustom vlf-batch-size 1024
46 "Defines how large each batch of file data is (in bytes)."
47 :type 'integer
48 :group 'vlf)
49
50 ;; Keep track of file position.
51 (defvar vlf-start-pos)
52 (defvar vlf-end-pos)
53 (defvar vlf-file-size)
54
55 (defvar vlf-mode-map
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)
60 map)
61 "Keymap for `vlf-mode'.")
62
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))
70
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."
75 (interactive "P")
76 (or (assq 'vlf-batch-size (buffer-local-variables))
77 (error "%s is not local in this buffer" 'vlf-batch-size))
78 (setq vlf-batch-size
79 (if decrease
80 (/ vlf-batch-size 2)
81 (* vlf-batch-size 2)))
82 (vlf-update-buffer-name))
83
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))
90
91 (defun vlf-update-buffer-name ()
92 "Update the current buffer name."
93 (rename-buffer (vlf-format-buffer-name) t))
94
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."
98 (interactive "P")
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'
105 ;; hangs emacs
106 (unless append (erase-buffer))
107 (insert-file-contents buffer-file-name nil vlf-end-pos end)
108 (unless append
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)))
113
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."
117 (interactive "P")
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)
125 (unless prepend
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)))
130
131 (defun vlf (file)
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
135 read-only buffer.
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
141 vlf-start-pos 0
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)
147 (vlf-mode)
148 (display-buffer (current-buffer))))
149
150 (provide 'vlf)
151
152 ;;; vlf.el ends here