comparison lisp/energize/energize-init.el @ 0:376386a54a3c r19-14

Import from CVS: tag r19-14
author cvs
date Mon, 13 Aug 2007 08:45:50 +0200
parents
children 131b0175ea99
comparison
equal deleted inserted replaced
-1:000000000000 0:376386a54a3c
1 ;;; -*- Mode:Emacs-Lisp -*-
2 ;;; Copyright © 1990-1994 by Lucid, Inc. All Rights Reserved.
3
4 (defvar energize-auto-raise-screen t
5 "If T frames are automatically raised when Energize wants to show them.")
6
7 (defvar energize-connect-hook nil
8 "*Function or functions to run when the Energize connection is established.")
9
10 (defvar energize-disconnect-hook nil
11 "*Function or functions to run when the Emacs/Energize connection is closed.")
12
13
14 (defvar energize-screen-mode nil)
15 (defvar energize-split-screens-p t)
16
17 (defun energize-multi-screen-mode ()
18 "Call this function to put Energize into multi-frame mode.
19
20 A frame named \"debugger\" will be used for the *Debugger* buffer,
21 and its associated source files.
22 A frame named \"energize\" will be used for the Top-Level buffer.
23 A frame named \"browser\" will be created for each L.E. Browser buffer.
24 At most 5 of these will be created; then they will be reused.
25 A frame named \"project\" will be created for each Project buffer.
26 A frame named \"error-log\" will be created for the Error Log buffer
27 and its associated source files (as when the Next Error command
28 displays a source file.)
29 A frame named \"manual\" will be created for each UNIX Manual page.
30 At most 5 of these will be created; then they will be reused.
31
32 If an external editor is being used, then source files will be displayed
33 read-only in the \"debugger\" frame.
34
35 If an external editor is not being used, then frames named \"sources\"
36 will be created to edit source files. At most five of these will be
37 created; then they will be reused. Find-file will use the current frame,
38 whatever that happens to be, but find-file-other-window, and selecting
39 source files from the Buffers menu will use an existing frame displaying
40 the file in question, or create a new one if there isn't one.
41
42 Call `energize-single-screen-mode' to turn this off.
43
44 See the documentation for the function get-frame-for-buffer for
45 information on how to customize this."
46 (interactive)
47 (put 'project 'instance-limit 0)
48 (put 'sources 'instance-limit 5)
49 (put 'manual 'instance-limit 5)
50 (put 'browser 'instance-limit 5)
51 (put 'energize-debugger-mode 'frame-name 'debugger)
52 (put 'gdb-mode 'frame-name 'debugger)
53 (put 'energize-top-level-mode 'frame-name 'energize)
54 (put 'energize-browser-mode 'frame-name 'browser)
55 (put 'energize-breakpoint-mode 'frame-name 'browser)
56 (put 'energize-project-mode 'frame-name 'project)
57 (put 'energize-no-file-project-mode 'frame-name 'project)
58 (put 'energize-log-mode 'frame-name 'error-log)
59 (put 'energize-manual-entry-mode 'frame-name 'manual)
60 (if energize-external-editor
61 (setq get-frame-for-buffer-default-frame-name 'debugger)
62 ;; hmmmm...
63 (setq get-frame-for-buffer-default-frame-name 'sources))
64 (setq buffers-menu-switch-to-buffer-function 'pop-to-buffer)
65 (setq energize-screen-mode 'multi)
66 t)
67
68 (defun energize-several-screens-mode ()
69 "Call this function to put Energize into multi-frame mode,
70 but with only a few frames. See also `energize-multi-screen-mode'.
71
72 A frame named \"debugger\" will be used for the *Debugger* buffer,
73 and its associated source files.
74 A frame named \"energize\" will be used for the Top-Level buffer.
75 A single frame named \"browser\" will be created for L.E. Browser buffers.
76 A single frame named \"project\" will be created for Project buffers.
77 A frame named \"error-log\" will be created for the Error Log buffer
78 and its associated source files (as when the Next Error command
79 displays a source file.)
80 A single frame named \"manual\" will be created for UNIX Manual page buffers.
81
82 If an external editor is being used, then source files will be displayed
83 read-only in the \"debugger\" frame.
84
85 If an external editor is not being used, then a single frame named
86 \"sources\" will be created to edit source files. Find-file will use the
87 current frame, whatever that happens to be, but find-file-other-window,
88 and selecting source files from the Buffers menu will use an existing frame
89 displaying the file in question, or create a new one if there isn't one.
90
91 Call `energize-single-screen-mode' to turn this off.
92
93 See the documentation for the function get-frame-for-buffer for
94 information on how to customize this."
95 (interactive)
96 (energize-multi-screen-mode)
97 (remprop 'browser 'instance-limit)
98 (remprop 'project 'instance-limit)
99 (remprop 'manual 'instance-limit)
100 (remprop 'sources 'instance-limit)
101 (setq energize-screen-mode 'several)
102 t)
103
104 (defun energize-single-screen-mode ()
105 "Call this function to put Energize into single-frame mode.
106 All buffers will be displayed in the currently selected frame."
107 (interactive)
108 (remprop 'browser 'instance-limit)
109 (remprop 'project 'instance-limit)
110 (remprop 'manual 'instance-limit)
111 (remprop 'sources 'instance-limit)
112 (remprop 'energize-debugger-mode 'frame-name)
113 (remprop 'gdb-mode 'frame-name)
114 (remprop 'energize-top-level-mode 'frame-name)
115 (remprop 'energize-browser-mode 'frame-name)
116 (remprop 'energize-breakpoint-mode 'frame-name)
117 (remprop 'energize-project-mode 'frame-name)
118 (remprop 'energize-no-file-project-mode 'frame-name)
119 (remprop 'energize-log-mode 'frame-name)
120 (remprop 'energize-manual-entry-mode 'frame-name)
121 (setq get-frame-for-buffer-default-frame-name nil)
122 (setq buffers-menu-switch-to-buffer-function 'switch-to-buffer)
123 (setq energize-screen-mode 'single)
124 nil)
125
126 (energize-single-screen-mode)
127
128
129 ;;; Connecting and disconnecting
130
131 (or energize-attributes-mapping
132 (setq energize-attributes-mapping
133 (purecopy
134 '((0 . default)
135 (1 . bold)
136 (2 . italic)
137 (3 . bold-italic)
138 (4 . attributeSmall)
139 (50 . attributeGlyph)
140 (51 . attributeSectionHeader)
141 (52 . attributeToplevelFormGlyph)
142 (53 . attributeModifiedToplevelFormGlyph)
143 (54 . attributeBrowserHeader)
144 (68 . attributeWriteProtected)
145 (69 . attributeModifiedText)
146 ))))
147
148 ;; Make the faces before emacs is dumped - this should be ok, they will be
149 ;; initialized from the resource database when the first frame is created.
150 (let ((rest energize-attributes-mapping))
151 (while rest
152 (make-face (cdr (car rest)))
153 (setq rest (cdr rest))))
154
155
156 (defun any-energize-buffers-p ()
157 (let ((rest (buffer-list))
158 (result nil))
159 (while rest
160 (if (energize-buffer-p (car rest))
161 (setq result (car rest) rest nil)
162 (setq rest (cdr rest))))
163 result))
164
165 (defun connect-to-energize (server &optional enarg)
166 "Connect this emacs to a Energize server.
167 The SERVER argument should be the name of the host that the kernel is
168 running on (empty-string for localhost). It may also be of the form
169 ``hostname:user'' or ``:user'', meaning to use the server running with
170 userid USER."
171 (interactive (if (connected-to-energize-p)
172 (error "Already connected to the server.") ; you bogon.
173 (list (read-string "connect to energize server: "))))
174 (if (connected-to-energize-p)
175 (error "Already connected to the server.")) ; you bogon.
176 (if (or (null server) (equal server ""))
177 (setq server (or (getenv "ENERGIZE_PORT") (system-name))))
178 (setq default-frame-name "energize")
179 (energize-rename-things)
180 (energize-hack-external-editor-mode)
181
182 (let ((energize-disconnect-hook
183 ;; If we're being run interactively, don't exit emacs if connecting
184 ;; to Energize fails! That's damn annoying.
185 (if (and (interactive-p)
186 (consp energize-disconnect-hook)
187 (memq 'save-buffers-kill-emacs energize-disconnect-hook))
188 (delq 'save-buffers-kill-emacs
189 (copy-sequence energize-disconnect-hook))
190 energize-disconnect-hook)))
191
192 (connect-to-energize-internal server enarg)
193 ;; Wait for the Top-Level buffer to be created.
194 ;; This really should happen down in C, but...
195 (let ((p (or (get-process "energize")
196 (error "Could not connect to Energize.")))
197 b)
198 (while (progn
199 (or (connected-to-energize-p)
200 (error "Energize connection refused."))
201 (not (setq b (any-energize-buffers-p))))
202 (accept-process-output p))
203 ;; Make the displayed Energize buffer initially displayed.
204 (pop-to-buffer b)
205 (delete-other-windows)
206 (run-hooks 'energize-connect-hook))))
207
208 (defun disconnect-from-energize ()
209 (interactive)
210 "Close the connection to energize"
211 (close-connection-to-energize))
212
213 ;;; Energizing all buffers
214 ;; After being connected to energize this function energizes all the
215 ;; buffers that contain files that Energize knows about.
216
217 (defun energize-all-buffers ()
218 "Energize any buffer showing a file that the Energize server knows about.
219 Has to be called after Emacs has been connected to Energize"
220 (if (not (connected-to-energize-p))
221 (error "You have to connect to Energize first"))
222 (save-window-excursion
223 (save-excursion
224 (let ((buffers (buffer-list))
225 (buffers-to-avoid '())
226 (lock-directory nil)
227 buffer
228 filename)
229 (while buffers
230 (setq buffer (car buffers))
231 (setq buffers (cdr buffers))
232 (setq filename (buffer-file-name buffer))
233 (set-buffer buffer)
234 (cond
235 ((and filename
236 (not (energize-buffer-p buffer))
237 (energize-query-buffer filename t))
238 (cond ((buffer-modified-p)
239 (if (y-or-n-p
240 (format
241 "Buffer %s must be saved to be Energized; save it? "
242 (buffer-name buffer)))
243 (progn
244 (set-buffer buffer) ; oh, man...
245 (save-buffer))
246 ;; said "no"
247 (setq buffers-to-avoid (cons buffer buffers-to-avoid))))
248
249 ((and (null (verify-visited-file-modtime buffer))
250 (file-exists-p filename))
251 (set-buffer buffer)
252 (if (y-or-n-p
253 (format "Buffer %s has changed on disk, revert? "
254 (buffer-name buffer)))
255 (progn
256 (set-buffer buffer)
257 (revert-buffer nil t))
258 ;; said "no"
259 (setq buffers-to-avoid (cons buffer buffers-to-avoid))))
260
261 ;; It's wrong to check to also see if someone else is locking
262 ;; the file. The file is already in the buffer, and the user
263 ;; isn't really modifying it -- we're just rewriting it because
264 ;; energize likes to do that. That's why locking should be
265 ;; disabled here.
266 )
267 (if (not (memq buffer buffers-to-avoid))
268 (progn
269 (message "Energizing buffer %s..." (buffer-name buffer))
270 (find-file-noselect filename))
271 (message (format "Buffer %s not Energized." (buffer-name buffer)))
272 (sit-for 1)))))
273 (message nil)))))
274
275 (add-hook 'energize-connect-hook 'energize-all-buffers)
276
277
278 ;; This is called when the connection to Energize is lose (for whatever
279 ;; reason). We could just run the energize-disconnect-hook from C and
280 ;; put this function on it, but then the user could hurt themselves.
281 ;;
282 (defun de-energize-all-buffers ()
283 (save-excursion
284 (let ((buffers (buffer-list))
285 buffer)
286 (while buffers
287 (condition-case condition
288 (progn
289 (setq buffer (car buffers))
290 (set-buffer buffer)
291 (cond ((not (energize-buffer-p buffer))
292 nil)
293 ((eq (energize-buffer-type buffer) 'energize-source-buffer)
294 (map-extents
295 (function (lambda (extent ignore)
296 (if (extent-property extent 'energize)
297 (delete-extent extent))
298 nil))
299 buffer)
300 (remove-hook 'write-file-data-hooks
301 'energize-write-data-hook)
302 (setq revert-buffer-insert-file-contents-function nil)
303 (ad-Orig-normal-mode-after-energize) ; #### necessary?
304 )
305 (t ; non-source-file Energize buffers
306 (set-buffer-modified-p nil)
307 (if (eq (other-buffer buffer) buffer)
308 (set-buffer (get-buffer-create "*scratch*"))
309 (set-buffer (other-buffer buffer)))
310 (kill-buffer buffer))))
311 (error ;; condition-case clause
312 (beep)
313 (message "Error while de-Energizing: %s" condition)))
314 (setq buffers (cdr buffers)))))
315 ;; now clean the menubar
316 (deactivate-all-energize-menu-items)
317 (energize-rename-things 'back)
318 (run-hooks 'energize-disconnect-hook)
319 nil)
320
321
322 (defun energize-rename-things (&optional back)
323 ;; People who don't like emacs don't like seeing the word "Emacs" either
324 (let ((case-fold-search t))
325 (if (and (consp mode-line-buffer-identification)
326 (stringp (car mode-line-buffer-identification))
327 (string-match (if back "\\bEnergize\\b"
328 "\\bL?Emacs\\([- \t]*[-._0-9]+\\)?\\b")
329 (car mode-line-buffer-identification)))
330 (setq-default mode-line-buffer-identification
331 (cons
332 (concat (substring (car mode-line-buffer-identification)
333 0 (match-beginning 0))
334 (if back "Emacs" "Energize")
335 (substring (car mode-line-buffer-identification)
336 (match-end 0)))
337 (cdr mode-line-buffer-identification))))
338 ; (if (stringp frame-title-format)
339 ; (if back
340 ; (if (string-match "^Energize\\b ?" frame-title-format)
341 ; (setq-default frame-title-format "%S: %b"))
342 ; (or (string-match "Energize" frame-title-format)
343 ; (setq-default frame-title-format "Energize: %b"))))
344 )
345 nil)
346
347
348
349 ;;; The kernel is very random about the buffer-types it returns.
350 ;;; This is a temporary permanent fix...
351
352 (defun energize-buffer-type (buffer)
353 "Returns a symbol denoting the type of an Energize buffer, or nil."
354 (let ((type (energize-buffer-type-internal buffer)))
355 (cond ((eq type 'energize-top-level-buffer)
356 (cond ((equal "Error Log" (buffer-name buffer))
357 'energize-error-log-buffer)
358 ((equal "*includers*" (buffer-name buffer))
359 'energize-includers-buffer)
360 ((string-match "^Browser" (buffer-name buffer))
361 'energize-browser-buffer)
362 (t type)))
363 ((eq type 'energize-unspecified-buffer)
364 (signal 'error (list "buffer type unspecified" buffer)))
365 ((and (null type) (energize-buffer-p buffer))
366 (signal 'error
367 (list "null buffer type for energize buffer" buffer)))
368 (t type))))
369
370 (defun energize-extent-at (pos &optional buffer)
371 (extent-at pos buffer 'energize))
372
373 (defun non-energize-errors-exist-p ()
374 ;; Whether `next-error' executed right now should do the emacs thing.
375 ;; If we're in a *grep* or *compile* buffer, always do the emacs thing.
376 ;; If we're in the Error Log, always do the Energize thing.
377 ;; Otherwise, do the emacs thing if it would succeed; otherwise do the
378 ;; Energize thing.
379 (or (compilation-buffer-p (current-buffer)) ; in *grep*
380 (and (not (eq (energize-buffer-type (current-buffer)) ; in ErrLog
381 'energize-error-log-buffer))
382 ;; defined in compile.el (a XEmacs addition).
383 (compilation-errors-exist-p))))
384
385
386 ;;; Misc Energize hook functions
387
388 (defvar inside-energize-buffer-creation-hook-function nil)
389
390 (defun energize-buffer-creation-hook-function (buffer)
391 ;; This loser is called every time Energize wants to create a buffer,
392 ;; whether it is being spontaniously displayed (as by the debugger) or
393 ;; as a result of calling find-file -> energize-find-file-noselect ->
394 ;; energize-query-buffer.
395 (let ((inside-energize-buffer-creation-hook-function t))
396 ;; the above is so we can call this from normal-mode, except when
397 ;; we're calling normal-mode.
398 (save-excursion
399 (set-buffer buffer)
400
401 ;; Energize always hands us truenames, or something close to them
402 ;; (it chomps the /tmp_mnt/ automounter cruft off.) Let the user
403 ;; set up a pretty translation just like they can for normal files.
404 (if buffer-file-name
405 (setq buffer-file-name (abbreviate-file-name
406 (expand-file-name buffer-file-name))
407 default-directory (file-name-directory buffer-file-name))
408 (setq default-directory
409 (abbreviate-file-name (expand-file-name default-directory))))
410
411 (if buffer-file-name (set-buffer-modtime buffer))
412
413 (let ((type (energize-buffer-type buffer)))
414 (cond ((eq type 'energize-top-level-buffer)
415 (energize-top-level-mode))
416 ((eq type 'energize-browser-buffer)
417 (energize-browser-mode))
418 ((eq type 'energize-includers-buffer)
419 (energize-browser-mode))
420 ((or (eq type 'energize-error-log-buffer)
421 (eq type 'energize-log-file-buffer))
422 (energize-log-mode)
423 (setq buffer-read-only t))
424 ((eq type 'energize-project-buffer)
425 (if (buffer-file-name)
426 (energize-project-mode)
427 (energize-no-file-project-mode)))
428 ((eq type 'energize-debugger-buffer)
429 (energize-debugger-mode))
430 ((eq type 'energize-breakpoint-buffer)
431 (energize-breakpoint-mode))
432 ((eq type 'energize-unix-manual-buffer)
433 (energize-manual-mode))
434 ((or (eq type 'energize-source-buffer)
435 ;;(eq type 'energize-unspecified-buffer)
436 ;;(null type)
437 )
438 (compute-buffer-file-truename)
439 (if (buffer-file-name buffer)
440 (after-find-file nil t)
441 (funcall default-major-mode))
442 )
443 (t
444 (signal 'error (list "unknown energize buffer type" type)))))
445
446 (if (eq (energize-buffer-type (current-buffer)) 'energize-source-buffer)
447 (energize-source-minor-mode))
448
449 (energize-external-editor-set-mode buffer)
450 )))
451
452 (setq energize-create-buffer-hook 'energize-buffer-creation-hook-function)
453
454 ;;; Buffer modified hook
455
456 (defun energize-send-buffer-modified-1 (start end)
457 (if (not (energize-buffer-p (current-buffer)))
458 nil
459 (map-extents #'(lambda (ext ignore)
460 (and (extent-property ext 'energize)
461 (set-extent-face ext 'attributeModifiedText))
462 nil)
463 (current-buffer) start end)
464 (energize-send-buffer-modified t start end)))
465
466 (add-hook 'before-change-functions 'energize-send-buffer-modified-1)
467
468 ;;; Reverting buffers
469 ;;; This is called when Energize has informed us that a buffer has changed
470 ;;; on disk, and we need to revert.
471
472 (defun energize-auto-revert-buffer (buf)
473 (cond ((not (file-exists-p (buffer-file-name buf)))
474 ;; Signal an error here? Naah, let someone else deal with it.
475 nil)
476 ;; If it's not modified, just revert. If it is modified, ask.
477 ((or (not (buffer-modified-p buf))
478 (yes-or-no-p
479 (format "File %s changed on disk. Discard your edits? "
480 (file-name-nondirectory (buffer-file-name buf)))))
481 (save-excursion
482 (set-buffer buf)
483 (revert-buffer t t)))))
484
485 ;;; Energize kernel busy hook
486
487 (defun energize-message-if-not-in-minibuffer (reason)
488 (if (not (eq (selected-window) (minibuffer-window)))
489 (message reason)))
490
491 (setq energize-kernel-busy-hook 'energize-message-if-not-in-minibuffer)
492
493 ;;; set-buffer-modified-p hook
494
495 (defun energize-send-buffer-modified-2 (state start end)
496 (if (not (energize-buffer-p (current-buffer)))
497 nil
498 (if (not state)
499 ;; If we're unmodifying the buffer, un-highlight all Energize extents.
500 (let ((e (next-extent (current-buffer))))
501 (while e
502 (if (and (extent-property e 'energize)
503 (eq (extent-face e) 'attributeModifiedText))
504 (set-extent-face e nil))
505 (setq e (next-extent e)))))
506 (energize-send-buffer-modified state start end)))
507
508 (setq energize-buffer-modified-hook 'energize-send-buffer-modified-2)
509
510 ;;; hook in editorside.c
511
512 (setq energize-kernel-modification-hook nil)
513
514
515 ;; command line
516
517 (defconst energize-args '(("-energize" . command-line-process-energize)
518 ("-context" . command-line-process-energize-1)
519 ("-beam-me-up" . command-line-process-energize-1)))
520
521 (setq command-switch-alist (append command-switch-alist energize-args))
522
523 (fset 'command-line-process-energize 'command-line-process-energize-1)
524 (put 'command-line-process-energize-1 'undocumented t)
525 (defun command-line-process-energize-1 (arg)
526 "Connect to the Energize server at $ENERGIZE_PORT."
527 (let ((e-arg (car command-line-args-left))
528 (e-host (getenv "ENERGIZE_PORT"))) ; maybe nil
529 (if (and e-arg (string-match "\\`[0-9a-fA-F]+[,][0-9a-fA-F]+\\'" e-arg))
530 (setq command-line-args-left (cdr command-line-args-left))
531 (setq e-arg nil))
532 (message "Connecting to Energize...")
533 (sit-for 0)
534 (condition-case ()
535 (connect-to-energize e-host e-arg)
536 (error
537 (beep)
538 (if e-host
539 (message "Failed to connect to Energize at %s." e-host)
540 (message "Failed to connect to Energize."))
541 (sit-for 1)))))
542
543
544 ;;; Originally defined in frame.el
545 ;;; If we're being invoked with -energize, then set the default
546 ;;; frame name to "energize"
547 ;;; This is a total kludge; there ought to be a hook that gets
548 ;;; run before the first frame is created (either before or
549 ;;; after term/x-win.el is loaded.)
550
551 (or (fboundp 'energize-orig-frame-initialize)
552 (fset 'energize-orig-frame-initialize
553 (symbol-function 'frame-initialize)))
554
555 (defun frame-initialize ()
556 (if (let ((rest energize-args))
557 (catch 'done
558 (while rest
559 (if (member (car (car rest)) command-line-args)
560 (throw 'done t))
561 (setq rest (cdr rest)))
562 nil))
563 (setq default-frame-name "energize"))
564 (energize-orig-frame-initialize))
565
566 (defun energize-x-initializations ()
567 (cond ((not noninteractive)
568 (energize-define-function-keys)
569 (energize-configure-font-lock-mode t (not (x-color-display-p)) t)
570 ;; faces will be initialized from the resource database when the first
571 ;; frame is created.
572 (let ((rest energize-attributes-mapping))
573 (while rest
574 (make-face (cdr (car rest)))
575 (setq rest (cdr rest))))
576 )))
577
578 ;; Do these bindings after connecting to the X server, but before
579 ;;; loading any init files, so that init files can override them.
580 (add-hook 'before-init-hook 'energize-x-initializations)