Commit | Line | Data |
---|---|---|
854f487a DL |
1 | ;;; delim-col.el --- Prettify all columns in a region or rectangle. |
2 | ||
3 | ;; Copyright (C) 1999 Vinicius Jose Latorre <vinicius@cpqd.com.br> | |
4 | ||
5 | ;; Author: Vinicius Jose Latorre <vinicius@cpqd.com.br> | |
6 | ;; Time-stamp: <99/08/21 19:51:13 vinicius> | |
7 | ;; Version: 1.3 | |
8 | ;; Keywords: internal | |
9 | ||
10 | ;; This file is part of GNU Emacs. | |
11 | ||
12 | ;; This GNU Emacs is free software; you can redistribute it and/or modify it | |
13 | ;; under the terms of the GNU General Public License as published by the | |
14 | ;; Free Software Foundation; either version 2, or (at your option) any | |
15 | ;; later version. | |
16 | ||
17 | ;; This program is distributed in the hope that it will be useful, but | |
18 | ;; WITHOUT ANY WARRANTY; without even the implied warranty of | |
19 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
20 | ;; General Public License for more details. | |
21 | ||
22 | ;; You should have received a copy of the GNU General Public License along | |
23 | ;; with GNU Emacs; see the file COPYING. If not, write to the Free | |
24 | ;; Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA | |
25 | ;; 02111-1307, USA. | |
26 | ||
27 | ;;; Commentary: | |
28 | ||
29 | ;; delim-col helps to prettify columns in a text region or rectangle. | |
30 | ;; | |
31 | ;; To use it, make sure that this file is in load-path and insert in your | |
32 | ;; .emacs: | |
33 | ;; | |
34 | ;; (require 'delim-col) | |
35 | ;; | |
36 | ;; If you have, for example, the following columns: | |
37 | ;; | |
38 | ;; a b c d | |
39 | ;; aaaa bb ccc ddddd | |
40 | ;; aaa bbb cccc dddd | |
41 | ;; aa bb ccccccc ddd | |
42 | ;; | |
43 | ;; And the following settings: | |
44 | ;; | |
45 | ;; (setq delimit-columns-str-before "[ ") | |
46 | ;; (setq delimit-columns-str-after " ]") | |
47 | ;; (setq delimit-columns-str-separator ", ") | |
48 | ;; (setq delimit-columns-separator "\t") | |
49 | ;; | |
50 | ;; If you select the lines above and type: | |
51 | ;; | |
52 | ;; M-x delimit-columns-region RET | |
53 | ;; | |
54 | ;; You obtain the following result: | |
55 | ;; | |
56 | ;; [ a , b , c , d ] | |
57 | ;; [ aaaa, bb , ccc , ddddd ] | |
58 | ;; [ aaa , bbb, cccc , dddd ] | |
59 | ;; [ aa , bb , ccccccc, ddd ] | |
60 | ;; | |
61 | ;; But if you select start from the very first b and the very last c and type: | |
62 | ;; | |
63 | ;; M-x delimit-columns-rectangle RET | |
64 | ;; | |
65 | ;; You obtain the following result: | |
66 | ;; | |
67 | ;; a [ b , c ] d | |
68 | ;; aaaa [ bb , ccc ] ddddd | |
69 | ;; aaa [ bbb, cccc ] dddd | |
70 | ;; aa [ bb , ccccccc ] ddd | |
71 | ;; | |
72 | ;; Note that `delimit-columns-region' operates over all text region | |
73 | ;; selected, extending the region start to the beginning of line and the | |
74 | ;; region end to the end of line. While `delimit-columns-rectangle' | |
75 | ;; operates over the text rectangle selected which rectangle diagonal is | |
76 | ;; given by the region start and end. | |
77 | ;; | |
78 | ;; `delimit-columns-region' is useful when you have columns of text that | |
79 | ;; are not well aligned, like: | |
80 | ;; | |
81 | ;; horse apple bus | |
82 | ;; dog pineapple car | |
83 | ;; porcupine strawberry airplane | |
84 | ;; | |
85 | ;; `delimit-columns-region' and `delimit-columns-rectangle' handle lines | |
86 | ;; with different number of columns, like: | |
87 | ;; | |
88 | ;; horse apple bus | |
89 | ;; dog pineapple car EXTRA | |
90 | ;; porcupine strawberry airplane | |
91 | ||
92 | ;;; Code: | |
93 | ||
94 | ||
95 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
96 | ;; User Options: | |
97 | ||
98 | (defvar delimit-columns-str-before "" | |
99 | "*Specify a string to be inserted before all columns.") | |
100 | ||
101 | (defvar delimit-columns-str-separator ", " | |
102 | "*Specify a string to be inserted between each column.") | |
103 | ||
104 | (defvar delimit-columns-str-after "" | |
105 | "*Specify a string to be inserted after all columns.") | |
106 | ||
107 | (defvar delimit-columns-separator "\t" | |
108 | "*Specify a regexp which separates each column.") | |
109 | ||
110 | \f | |
111 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
112 | ;; User Commands: | |
113 | ||
114 | ||
115 | ;;;###autoload | |
116 | (defun delimit-columns-region (start end) | |
117 | "Prettify all columns in a text region. | |
118 | ||
119 | START and END delimits the text region." | |
120 | (interactive "*r") | |
121 | (let ((delimit-columns-str-before | |
122 | (if (stringp delimit-columns-str-before) | |
123 | delimit-columns-str-before | |
124 | "")) | |
125 | (delimit-columns-str-separator | |
126 | (if (stringp delimit-columns-str-separator) | |
127 | delimit-columns-str-separator | |
128 | " ")) | |
129 | (delimit-columns-str-after | |
130 | (if (stringp delimit-columns-str-after) | |
131 | delimit-columns-str-after | |
132 | "")) | |
133 | (delimit-columns-limit (make-marker)) | |
134 | (the-end (copy-marker end)) | |
135 | delimit-columns-max) | |
136 | (save-excursion | |
137 | (goto-char start) | |
138 | (beginning-of-line) | |
139 | ;; get maximum length for each column | |
140 | (save-excursion | |
141 | (while (< (point) the-end) | |
142 | (delimit-columns-rectangle-max | |
143 | (prog1 | |
144 | (point) | |
145 | (end-of-line))) | |
146 | (forward-char 1))) | |
147 | ;; prettify columns | |
148 | (while (< (point) the-end) | |
149 | (delimit-columns-rectangle-line | |
150 | (prog1 | |
151 | (point) | |
152 | (end-of-line))) | |
153 | (forward-char 1)) | |
154 | ;; nullify markers | |
155 | (set-marker delimit-columns-limit nil) | |
156 | (set-marker the-end nil)))) | |
157 | ||
158 | ||
159 | (require 'rect) | |
160 | ||
161 | ||
162 | ;;;###autoload | |
163 | (defun delimit-columns-rectangle (start end) | |
164 | "Prettify all columns in a text rectangle. | |
165 | ||
166 | START and END delimits the corners of text rectangle." | |
167 | (interactive "*r") | |
168 | (let ((delimit-columns-str-before | |
169 | (if (stringp delimit-columns-str-before) | |
170 | delimit-columns-str-before | |
171 | "")) | |
172 | (delimit-columns-str-separator | |
173 | (if (stringp delimit-columns-str-separator) | |
174 | delimit-columns-str-separator | |
175 | " ")) | |
176 | (delimit-columns-str-after | |
177 | (if (stringp delimit-columns-str-after) | |
178 | delimit-columns-str-after | |
179 | "")) | |
180 | (delimit-columns-limit (make-marker)) | |
181 | (the-end (copy-marker end)) | |
182 | delimit-columns-max) | |
183 | ;; get maximum length for each column | |
184 | (save-excursion | |
185 | (operate-on-rectangle 'delimit-columns-rectangle-max | |
186 | start the-end t)) | |
187 | ;; prettify columns | |
188 | (save-excursion | |
189 | (operate-on-rectangle 'delimit-columns-rectangle-line | |
190 | start the-end t)) | |
191 | ;; nullify markers | |
192 | (set-marker delimit-columns-limit nil) | |
193 | (set-marker the-end nil))) | |
194 | ||
195 | \f | |
196 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
197 | ;; Internal Variables and Functions: | |
198 | ||
199 | ||
200 | ;; to avoid compilation gripes | |
201 | (defvar delimit-columns-max nil) | |
202 | (defvar delimit-columns-limit nil) | |
203 | ||
204 | ||
205 | (defun delimit-columns-rectangle-max (startpos &optional ignore ignore) | |
206 | (set-marker delimit-columns-limit (point)) | |
207 | (goto-char startpos) | |
208 | (let ((ncol 1) | |
209 | origin values) | |
210 | ;; get current column length | |
211 | (while (progn | |
212 | (setq origin (current-column)) | |
213 | (re-search-forward delimit-columns-separator | |
214 | delimit-columns-limit 'move)) | |
215 | (save-excursion | |
216 | (goto-char (match-beginning 0)) | |
217 | (setq values (cons (- (current-column) origin) | |
218 | values))) | |
219 | (setq ncol (1+ ncol))) | |
220 | (setq values (cons (- (current-column) origin) | |
221 | values)) | |
222 | ;; extend delimit-columns-max, if needed | |
223 | (let ((index (length delimit-columns-max))) | |
224 | (and (> ncol index) | |
225 | (let ((extend (make-vector ncol 0))) | |
226 | (while (> index 0) | |
227 | (setq index (1- index)) | |
228 | (aset extend index (aref delimit-columns-max index))) | |
229 | (setq delimit-columns-max extend)))) | |
230 | ;; get maximum column length | |
231 | (while values | |
232 | (setq ncol (1- ncol)) | |
233 | (aset delimit-columns-max ncol (max (aref delimit-columns-max ncol) | |
234 | (car values))) | |
235 | (setq values (cdr values))))) | |
236 | ||
237 | ||
238 | (defun delimit-columns-rectangle-line (startpos &optional ignore ignore) | |
239 | (let ((ncol 0) | |
240 | (len (length delimit-columns-max)) | |
241 | origin) | |
242 | (set-marker delimit-columns-limit (point)) | |
243 | (goto-char startpos) | |
244 | (insert delimit-columns-str-before) | |
245 | ;; Adjust all columns but last one | |
246 | (while (progn | |
247 | (setq origin (current-column)) | |
248 | (and (< (point) delimit-columns-limit) | |
249 | (re-search-forward delimit-columns-separator | |
250 | delimit-columns-limit 'move))) | |
251 | (delete-region (match-beginning 0) (point)) | |
252 | (insert (make-string (- (aref delimit-columns-max ncol) | |
253 | (- (current-column) origin)) | |
254 | ?\ ) | |
255 | delimit-columns-str-separator) | |
256 | (setq ncol (1+ ncol))) | |
257 | ;; Adjust last column | |
258 | (insert (make-string (- (aref delimit-columns-max ncol) | |
259 | (- (current-column) origin)) | |
260 | ?\ )) | |
261 | ;; Adjust extra columns, if needed | |
262 | (while (< (setq ncol (1+ ncol)) len) | |
263 | (insert delimit-columns-str-separator | |
264 | (make-string (aref delimit-columns-max ncol) ?\ ))) | |
265 | (insert delimit-columns-str-after))) | |
266 | ||
267 | \f | |
268 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
269 | ||
270 | ||
271 | (provide 'delim-col) | |
272 | ||
273 | ||
274 | ;;; delim-col.el ends here |