comparison lisp/hyperbole/kotl/kvspec.el @ 0:376386a54a3c r19-14

Import from CVS: tag r19-14
author cvs
date Mon, 13 Aug 2007 08:45:50 +0200
parents
children 4103f0995bd7
comparison
equal deleted inserted replaced
-1:000000000000 0:376386a54a3c
1 ;;!emacs
2 ;;
3 ;; FILE: kvspec.el
4 ;; SUMMARY: Koutline view specification.
5 ;; USAGE: GNU Emacs Lisp Library
6 ;; KEYWORDS: outlines, wp
7 ;;
8 ;; AUTHOR: Bob Weiner
9 ;;
10 ;; ORIG-DATE: 21-Oct-95 at 15:17:07
11 ;; LAST-MOD: 3-Nov-95 at 19:44:10 by Bob Weiner
12 ;;
13 ;; This file is part of Hyperbole.
14 ;; Available for use and distribution under the same terms as GNU Emacs.
15 ;;
16 ;; Copyright (C) 1995, Free Software Foundation, Inc.
17 ;; Developed with support from Motorola Inc.
18 ;;
19 ;; DESCRIPTION:
20 ;;
21 ;;; Koutliner view specs
22 ;; + means support code has been written already.
23 ;;
24 ;; + all: Show all lines of cells and all cells in the outline.
25 ;; + blank: Blank lines are on.
26 ;; b - on
27 ;; + cutoff: Show only NUM lines per cell, 0 = all
28 ;; c - set default cutoff lines
29 ;; cNUM - set cutoff lines to NUM
30 ;; descend: Only entries below this entry
31 ;; + elide: Ellipses are on.
32 ;; e - ellipses on
33 ;; filter: Regexp or filter program to select entries for view,
34 ;; off=select non-matching entries
35 ;; glue: Freeze any group of entries selected to stay at top of
36 ;; window, off=freeze those not-in-group.
37 ;; include: Include an entry referenced by a link.
38 ;; + level: Some levels are hidden.
39 ;; l - set default level clipping
40 ;; lNUM - set level clipping to NUM
41 ;; name: Display leading names within cells.
42 ;; m - show names
43 ;; + number: Cell numbers are on
44 ;; n - set default labels
45 ;; n0 - display idstamp labels
46 ;; n1 - display alpha labels
47 ;; n2 - display partial alpha labels
48 ;; n. - display legal labels
49 ;; n* - display star labels
50 ;; n~ - turn off labels
51 ;; rest: Only following cells.
52 ;; synthesize: Use a named generator function to generate entries for
53 ;; view.
54 ;; view: Turn koutliner view mode on. Standard insertion keys then
55 ;; can be used for browsing and view setting.
56 ;;
57 ;; DESCRIP-END.
58
59 ;;; ************************************************************************
60 ;;; Other required Elisp libraries
61 ;;; ************************************************************************
62
63 (require 'kview)
64
65 ;;; ************************************************************************
66 ;;; Public variables
67 ;;; ************************************************************************
68
69 (defvar kvspec:current nil
70 "String that represents the current view spec.
71 It is local to each koutline. Nil value means it has not been set yet.")
72
73 ;;; ************************************************************************
74 ;;; Public functions
75 ;;; ************************************************************************
76
77 (defun kvspec:activate (&optional view-spec)
78 "Activate optional VIEW-SPEC or existing view spec in the current koutline.
79 VIEW-SPEC is a string or t, which means recompute the current view spec. See
80 <${hyperb:dir}/kotl/EXAMPLE.kotl, 2b17=048> for details on valid view specs."
81 (interactive (list (read-string "Set view spec: " kvspec:current)))
82 (kotl-mode:is-p)
83 (if (or (equal view-spec "") (equal view-spec kvspec:current))
84 (setq view-spec nil))
85 (kvspec:initialize)
86 (kvspec:update view-spec)
87 (kvspec:update-view))
88
89 (defun kvspec:initialize ()
90 "Ensure that view spec settings will be local to the current buffer."
91 (if (and (fboundp 'local-variable-p)
92 (local-variable-p 'kvspec:current (current-buffer)))
93 nil
94 (make-local-variable 'kvspec:current)
95 (make-local-variable 'kvspec:string)))
96
97 (defun kvspec:levels-to-show (levels-to-keep)
98 "Hide all cells in outline at levels deeper than LEVELS-TO-KEEP (a number).
99 Shows any hidden cells within LEVELS-TO-KEEP. 1 is the first level. 0 means
100 display all levels of cells."
101 (if (null levels-to-keep)
102 (setq levels-to-keep
103 (read-from-minibuffer "Show cells down to level (0 = show all levels): "
104 nil nil t)))
105 (setq levels-to-keep (prefix-numeric-value levels-to-keep))
106 (if (< levels-to-keep 0)
107 (error "(kvspec:levels-to-show): Must display at least one level."))
108 (kview:map-tree
109 (function (lambda (kview)
110 (if (/= (kcell-view:level) levels-to-keep)
111 (kotl-mode:show-tree)
112 (kotl-mode:hide-subtree)
113 ;; Move to last cell in hidden subtree, to skip further
114 ;; processing of these cells.
115 (if (kcell-view:next t)
116 (kcell-view:previous)
117 (goto-char (point-max))))))
118 kview t)
119 (kview:set-attr kview 'levels-to-show levels-to-keep))
120
121 (defun kvspec:show-lines-per-cell (num)
122 "Show NUM lines per cell."
123 (if (and (integerp num) (>= num 0))
124 nil
125 (error "(kvspec:show-lines-per-cell): Invalid lines per cell, '%d'" num))
126 (kview:set-attr kview 'lines-to-show num)
127 (let (start end count)
128 (if (zerop num)
129 ;; Show all lines in cells.
130 (kview:map-tree
131 (function
132 (lambda (kview)
133 ;; Use free variable label-sep-len bound in kview:map-tree for
134 ;; speed.
135 (setq start (goto-char (kcell-view:start nil label-sep-len))
136 end (kcell-view:end-contents))
137 ;; Show all lines in cell.
138 (subst-char-in-region start end ?\r ?\n t)))
139 kview t t)
140 ;; Show NUM lines in cells.
141 (kview:map-tree
142 (function
143 (lambda (kview)
144 ;; Use free variable label-sep-len bound in kview:map-tree for speed.
145 (setq start (goto-char (kcell-view:start nil label-sep-len))
146 end (kcell-view:end-contents)
147 count (1- num))
148 ;; Hide all lines in cell.
149 (subst-char-in-region start end ?\n ?\r t)
150 ;; Expand num - 1 newlines to show num lines.
151 (while (and (> count 0) (search-forward "\r" end t))
152 (replace-match "\n") (setq count (1- count)))))
153 kview t t))))
154
155 (defun kvspec:toggle-blank-lines ()
156 "Toggle blank lines between cells on or off."
157 (interactive)
158 (setq kvspec:current
159 (if (string-match "b" kvspec:current)
160 (hypb:replace-match-string "b" kvspec:current "" t)
161 (concat "b" kvspec:current)))
162 (kvspec:blank-lines)
163 (kvspec:update-modeline))
164
165 (defun kvspec:update (view-spec)
166 "Update current view spec according to VIEW-SPEC but don't change the view.
167 VIEW-SPEC is a string or t, which means recompute the current view spec. See
168 <${hyperb:dir}/kotl/EXAMPLE.kotl, 2b17=048> for details on valid view specs."
169 (cond ((stringp view-spec)
170 ;; Use given view-spec after removing extraneous characters.
171 (setq kvspec:current
172 (hypb:replace-match-string
173 "[^.*~0-9abcdefgilnrsv]+" view-spec "" t)))
174 ((or (eq view-spec t) (null kvspec:current))
175 (setq kvspec:current (kvspec:compute))))
176 ;; Update display using current specs.
177 (kvspec:update-modeline))
178
179 ;;; ************************************************************************
180 ;;; Private functions
181 ;;; ************************************************************************
182
183 (defun kvspec:blank-lines ()
184 "Turn blank lines on or off according to 'kvspec:current'."
185 (let ((modified-p (buffer-modified-p))
186 (buffer-read-only))
187 (if (string-match "b" kvspec:current)
188 ;; On
189 (progn (kview:set-attr kview 'blank-lines t)
190 (kproperty:remove (point-min) (point-max) '(invisible t)))
191 ;; Off
192 (kview:set-attr kview 'blank-lines nil)
193 (save-excursion
194 (goto-char (point-max))
195 (while (re-search-backward "[\n\r][\n\r]" nil t)
196 ;; Make blank lines invisible.
197 (kproperty:put (1+ (point)) (min (+ (point) 2) (point-max))
198 '(invisible t)))))
199 (set-buffer-modified-p modified-p)))
200
201 (defun kvspec:compute ()
202 "Compute and return current view spec string."
203 (concat
204
205 ;; a - Show all cells and cell lines.
206 ;; Never compute this setting (use it only within links) since it will
207 ;; expose all carefully hidden outline items if the user forgets to turn
208 ;; it off when he resets the view specs.
209
210 ;; b - blank separator lines
211 (if (kview:get-attr kview 'blank-lines) "b")
212
213 ;; c - cutoff lines per cell
214 (let ((lines (kview:get-attr kview 'lines-to-show)))
215 (if (zerop lines)
216 nil
217 (concat "c" (int-to-string lines))))
218
219 ;; e - ellipses on
220 (if selective-display-ellipses "e")
221
222 ;; l - hide some levels
223 (let ((levels (kview:get-attr kview 'levels-to-show)))
224 (if (zerop levels)
225 nil
226 (concat "l" (int-to-string levels))))
227
228 ;; n - numbering type
229 (let ((type (kview:label-type kview)))
230 (cond ((eq type 'no) nil)
231 ((eq type kview:default-label-type) "n")
232 (t (concat "n" (char-to-string
233 (car (rassq (kview:label-type kview)
234 kvspec:label-type-alist)))))))))
235
236 (defun kvspec:elide ()
237 "Turn ellipses display following clipped cells on or off according to 'kvspec:current'."
238 (setq selective-display-ellipses
239 (if (string-match "e" kvspec:current) t)))
240
241 (defun kvspec:hide-levels ()
242 "Show a set number of cell levels according to 'kvspec:current'."
243 ;; "l" means use value of kview:default-levels-to-show.
244 ;; "l0" means show all levels.
245 (let (levels)
246 (if (not (string-match "l\\([0-9]+\\)?" kvspec:current))
247 ;; Don't change the view if no view spec is given but note that
248 ;; all levels should be shown in the future.
249 (kview:set-attr kview 'levels-to-show 0)
250 (if (match-beginning 1)
251 (setq levels (string-to-int
252 (substring kvspec:current (match-beginning 1)
253 (match-end 1))))
254 (setq levels kview:default-levels-to-show))
255 (kview:set-attr kview 'levels-to-show levels)
256 (kvspec:levels-to-show levels))))
257
258 (defun kvspec:lines-to-show ()
259 "Show a set number of lines per cell according to 'kvspec:current'."
260 ;; "c" means use value of kview:default-lines-to-show.
261 ;; "c0" means show all lines.
262 (cond ((not (string-match "c\\([0-9]+\\)?" kvspec:current))
263 ;; Don't change the view if no view spec is given but note that all
264 ;; lines should be shown in the future.
265 (kview:set-attr kview 'lines-to-show 0))
266 ((match-beginning 1)
267 (kvspec:show-lines-per-cell
268 (string-to-int (substring kvspec:current (match-beginning 1)
269 (match-end 1)))))
270 (t (kvspec:show-lines-per-cell kview:default-lines-to-show))))
271
272 (defun kvspec:numbering ()
273 "Set the type of numbering (label) display according to 'kvspec:current'."
274 (if (not (string-match "n\\([.*~0-2]\\)?" kvspec:current))
275 nil
276 ;; "n" means use value of kview:default-label-type.
277 ;; "n0" means display idstamps.
278 ;; "n1" means display alpha labels.
279 ;; "n2" means display partial alpha labels.
280 ;; "n." means display legal labels.
281 ;; "n*" means star labels.
282 ;; "n~" means no labels.
283 (let (spec type)
284 (if (match-beginning 1)
285 (setq spec (string-to-char
286 (substring kvspec:current
287 (match-beginning 1) (match-end 1)))
288 type (cdr (assq spec kvspec:label-type-alist)))
289 (setq type kview:default-label-type))
290 (kview:set-label-type kview type))))
291
292 (defun kvspec:update-modeline ()
293 "Setup or update display of the current kview spec in the modeline."
294 (if (stringp kvspec:current)
295 (setq kvspec:string (format kvspec:string-format kvspec:current)))
296 (if (memq 'kvspec:string mode-line-format)
297 nil
298 (setq mode-line-format (copy-sequence mode-line-format))
299 (let ((elt (or (memq 'mode-line-buffer-identification mode-line-format)
300 (memq 'modeline-buffer-identification mode-line-format))))
301 (setcdr elt (cons 'kvspec:string (cdr elt))))))
302
303 (defun kvspec:update-view ()
304 "Update view according to current setting of local 'kvspec:current' variable."
305 (let ((modified-p (buffer-modified-p))
306 (buffer-read-only))
307 (save-excursion
308
309 (if (string-match "a" kvspec:current)
310 (kotl-mode:show-all))
311
312 (kvspec:blank-lines) ;; b
313
314 ;; This must come before kvspec:lines-to-show or else it could show
315 ;; lines that should be hidden.
316 (kvspec:hide-levels) ;; l
317
318 (kvspec:lines-to-show) ;; c
319
320 (if (string-match "d" kvspec:current)
321 nil)
322
323 (kvspec:elide) ;; e
324
325 (if (string-match "f" kvspec:current)
326 nil)
327
328 (if (string-match "g" kvspec:current)
329 nil)
330
331 (if (string-match "i" kvspec:current)
332 nil)
333
334 (if (string-match "r" kvspec:current)
335 nil)
336
337 (if (string-match "s" kvspec:current)
338 nil)
339
340 ;; Do this last since it can trigger an error if partial alpha is
341 ;; selected.
342 (kvspec:numbering) ;; n
343
344 )
345 (set-buffer-modified-p modified-p)))
346
347 ;;; ************************************************************************
348 ;;; Private variables
349 ;;; ************************************************************************
350
351 (defvar kvspec:label-type-alist
352 '((?0 . idstamp) (?1 . alpha) (?2 . partial-alpha)
353 (?. . legal) (?* . star) (?~ . no))
354 "Alist of (view-spec-character . label-type) pairs.")
355
356 (defvar kvspec:string ""
357 "String displayed in koutline modelines to reflect the current view spec.
358 It is local to each koutline. Set this to nil to disable modeline display of
359 the view spec settings.")
360
361 (defvar kvspec:string-format " <|%s>"
362 "Format of the kview spec modeline display.
363 It must contain a '%s' which is replaced with the current set of view spec
364 characters at run-time.")
365
366 (provide 'kvspec)