1 ;;; mumamo-regions.el --- user defined regions with mumamo
3 ;; Author: Lennart Borgman (lennart O borgman A gmail O com)
4 ;; Created: 2009-05-31 Sun
6 ;; Last-Updated: 2009-06-01 Mon
11 ;; Features that might be required by this library:
15 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
19 ;; Add temporary mumamo chunks (called mumamo regions). This are
20 ;; added interactively from a highlighted region.
22 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
27 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
29 ;; This program is free software; you can redistribute it and/or
30 ;; modify it under the terms of the GNU General Public License as
31 ;; published by the Free Software Foundation; either version 3, or
32 ;; (at your option) any later version.
34 ;; This program is distributed in the hope that it will be useful,
35 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
36 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
37 ;; General Public License for more details.
39 ;; You should have received a copy of the GNU General Public License
40 ;; along with this program; see the file COPYING. If not, write to
41 ;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth
42 ;; Floor, Boston, MA 02110-1301, USA.
44 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
48 (eval-when-compile (require 'cl))
49 (eval-when-compile (require 'mumamo))
50 (eval-when-compile (require 'ourcomments-widgets))
51 (require 'ps-print) ;; For ps-print-ensure-fontified
53 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
54 ;;; Internal side functions etc
56 (defvar mumamo-regions nil
57 "List of active mumamo regions. Internal use only.
58 The entries in this list should be like this
62 where OVL-DEF is an overlay containing the definitions, ie `major-mode'.
63 OVL-CHUNK is the definitions set up temporarily for mumamo chunks.
65 The fontification functions in mumamo looks in this list, but the
66 chunk dividing functions defined by
67 `define-mumamo-multi-major-mode' does not. The effect is that
68 the normal chunks exists regardless of what is in this list, but
69 fontification etc is overridden by what this list says.")
70 (make-variable-buffer-local 'mumamo-regions)
71 (put 'mumamo-regions 'permanent-local t)
73 (defun mumamo-add-region-1 (major start end buffer)
74 "Add a mumamo region with major mode MAJOR from START to END.
75 Return the region. The returned value can be used in
76 `mumamo-clear-region'.
78 START and END should be markers in the buffer BUFFER. They may
79 also be nil in which case they extend the region to the buffer
81 (unless mumamo-multi-major-mode
82 (mumamo-temporary-multi-major))
85 (eq (marker-buffer start) buffer)
86 (error "Bad arg start: %s" start))
89 (eq (marker-buffer end) buffer)
90 (error "Bad arg end: %s" end))
91 (let ((ovl (make-overlay start end)))
92 (overlay-put ovl 'mumamo-region 'defined)
93 (overlay-put ovl 'face 'mumamo-region)
94 (overlay-put ovl 'priority 2)
95 (mumamo-region-set-major ovl major)
96 (setq mumamo-regions (cons (list ovl nil) mumamo-regions))
97 (mumamo-mark-for-refontification (overlay-start ovl) (overlay-end ovl))
98 (message "Added mumamo region from %d to %d" (+ 0 start) (+ 0 end))
101 (defun mumamo-clear-region-1 (region-entry)
102 "Clear mumamo region REGION-ENTRY.
103 The entry must have been returned from `mumamo-add-region-1'."
104 (let ((buffer (overlay-buffer (car region-entry)))
105 (entry (cdr region-entry)))
106 (when (buffer-live-p buffer)
107 (with-current-buffer buffer
108 (let ((ovl1 (car region-entry))
109 (ovl2 (cadr region-entry)))
110 (delete-overlay ovl1)
112 (mumamo-mark-for-refontification (overlay-start ovl2) (overlay-end ovl2))
113 (delete-overlay ovl2))
114 (setq mumamo-regions (delete region-entry mumamo-regions)))))))
116 (defvar mumamo-region-priority 0)
117 (make-variable-buffer-local 'mumamo-region-priority)
118 (put 'mumamo-region-priority 'permanent-local t)
120 (defun mumamo-get-region-from-1 (point)
121 "Return mumamo region values for POINT.
122 The return value is either mumamo chunk or a cons with
123 information about where regions starts to hide normal chunks.
124 Such a cons has the format \(BELOW . OVER) where each of them is
135 (dolist (reg mumamo-regions)
136 (assert (eq (overlay-get (car reg) 'mumamo-region) 'defined) t)
137 (assert (or (not (cadr reg)) (overlayp (cadr reg))))
138 (let* ((this-ovl (car reg))
139 (this-start (overlay-start this-ovl))
140 (this-end (overlay-end this-ovl)))
141 (when (<= this-end point)
142 (setq start this-end))
143 (when (< point this-start)
144 (setq end this-start))
145 (when (and (<= this-start point)
147 (setq major (overlay-get this-ovl 'mumamo-major-mode))
148 (setq start (max this-start (or start this-start)))
149 (setq end (min this-end (or end this-end)))
151 (throw 'found-major nil)))))
154 (setq ret-val (nth 1 hit-reg))
155 (when ret-val (assert (eq (overlay-get ret-val 'mumamo-region) 'used) t))
157 (move-overlay ret-val start end)
158 (setq ret-val (make-overlay start end nil t nil)) ;; fix-me
159 (setcar (cdr hit-reg) ret-val)
160 (overlay-put ret-val 'mumamo-region 'used)
161 (overlay-put ret-val 'priority ;; above normal chunks + chunks on chunks
162 (setq mumamo-region-priority (1+ mumamo-region-priority)))
163 ;;(overlay-put ret-val 'face '(:background "chocolate")) ;; temporary
164 (overlay-put ret-val 'mumamo-major-mode
165 (overlay-get (car hit-reg) 'mumamo-major-mode))))
166 (setq ret-val (cons start end)))
167 ;;(message "mumamo-get-region-from-1, point=%s ret-val=%s" point ret-val)
170 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
171 ;;; User side functions
173 (defun mumamo-temporary-multi-major ()
174 "Turn on a temporary multi major mode from buffers current mode.
175 Define one if no one exists. It will have no chunk dividing
176 routines. It is meant mainly to be used with mumamo regions when
177 there is no mumamo multi major mode in the buffer and the user
178 wants to add a mumamo region \(which requires a multi major mode
180 (when mumamo-multi-major-mode
181 (error "Mumamo is already active in buffer"))
182 (let* ((temp-mode-name (concat "mumamo-1-"
183 (symbol-name major-mode)))
184 (temp-mode-sym (intern-soft temp-mode-name)))
185 (unless (and temp-mode-sym
186 (fboundp temp-mode-sym))
187 (setq temp-mode-sym (intern temp-mode-name))
189 `(define-mumamo-multi-major-mode ,temp-mode-sym
190 "Temporary multi major mode."
191 ("Temporary" ,major-mode nil))))
192 (put temp-mode-sym 'mumamo-temporary major-mode)
193 (funcall temp-mode-sym)))
195 (defface mumamo-region
196 '((t (:background "white")))
197 "Face for mumamo-region regions."
201 (defun mumamo-add-region ()
202 "Add a mumamo region from selection.
203 Mumamo regions are like another layer of chunks above the normal chunks.
204 They does not affect the normal chunks, but they overrides them.
206 To create a mumamo region first select a visible region and then
209 If the buffer is not in a multi major mode a temporary multi
210 major mode will be created applied to the buffer first.
211 To get out of this and get back to a single major mode just use
215 (if (not mark-active)
216 (message (propertize "Please select a visible region first" 'face 'secondary-selection))
217 (let ((beg (region-beginning))
219 (maj (mumamo-region-read-major)))
220 (mumamo-add-region-1 maj (copy-marker beg) (copy-marker end) (current-buffer))
221 (setq deactivate-mark t))))
224 (defun mumamo-add-region-from-string ()
225 "Add a mumamo region from string at point.
226 Works as `mumamo-add-region' but for string or comment at point.
228 Buffer must be fontified."
230 ;; assure font locked.
232 (ps-print-ensure-fontified (point-min) (point-max))
233 (let ((the-face (get-text-property (point) 'face)))
234 (if (not (memq the-face
236 font-lock-string-face
237 font-lock-comment-face)))
238 (message "No string or comment at point")
239 (let ((beg (previous-single-property-change (point) 'face))
240 (end (next-single-property-change (point) 'face))
241 (maj (mumamo-region-read-major)))
242 (setq beg (or (when beg (1+ beg))
244 (setq end (or (when end (1- end))
246 (mumamo-add-region-1 maj (copy-marker beg) (copy-marker end) (current-buffer))))))
247 ;; (dolist (o (overlays-in (point-min) (point-max))) (delete-overlay o))
248 (defun mumamo-clear-all-regions ()
249 "Clear all mumamo regions in buffer.
250 For information about mumamo regions see `mumamo-add-region'."
252 (unless mumamo-multi-major-mode
253 (error "There can be no mumamo regions to clear unless in multi major modes"))
254 (while mumamo-regions
255 (mumamo-clear-region-1 (car mumamo-regions))
256 (setq mumamo-regions (cdr mumamo-regions)))
257 (let ((old (get mumamo-multi-major-mode 'mumamo-temporary)))
258 (when old (funcall old)))
259 (message "Cleared all mumamo regions"))
261 (defun mumamo-region-read-major ()
262 "Prompt user for major mode.
263 Accept only single major mode, not mumamo multi major modes."
264 (let ((major (read-command "Major mode: ")))
265 (unless (major-modep major) (error "Not a major mode: %s" major))
266 (when (mumamo-multi-major-modep major) (error "Multi major modes not allowed: %s" major))
267 (when (let ((major-mode major))
268 (derived-mode-p 'nxml-mode))
269 (error "%s is based on nxml-mode and can't be used here" major))
272 (defun mumamo-region-at (point)
273 "Return mumamo region at POINT."
274 (let ((ovls (overlays-at (point))))
277 (when (overlay-get o 'mumamo-region)
281 (defun mumamo-region-set-major (ovl major)
282 "Change major mode for mumamo region at point.
283 For information about mumamo regions see `mumamo-add-region'.
285 If run non-interactively then OVL should be a mumamo region and
286 MAJOR the major mode to set for that region."
288 (list (or (mumamo-region-at (point))
289 (error "There is no mumamo region at point"))
290 (mumamo-region-read-major)))
291 (overlay-put ovl 'mumamo-major-mode `(,major))
292 (overlay-put ovl 'help-echo (format "Mumamo region, major mode `%s'" major)))
294 (defun mumamo-clear-region (ovl)
295 "Clear the mumamo region at point.
296 For information about mumamo regions see `mumamo-add-region'.
298 If run non-interactively then OVL should be the mumamo region to
301 (list (or (mumamo-region-at (point))
302 (error "There is no mumamo region at point"))))
303 (let ((region-entry (rassoc (list ovl) mumamo-regions)))
305 (error "No mumamo region found at point"))
306 (mumamo-clear-region-1 region-entry)))
309 (provide 'mumamo-regions)
310 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
311 ;;; mumamo-regions.el ends here