home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / gnu / lucid / lemacs-19.6 / lisp / energize / energize-mode.el < prev    next >
Encoding:
Text File  |  1993-03-18  |  30.5 KB  |  860 lines

  1. ;;; -*- Mode:Emacs-Lisp -*-
  2. ;;; Copyright ⌐ 1991-1993 by Lucid, Inc.  All Rights Reserved.
  3.  
  4. (require 'gdb)
  5. (require 'compile)
  6. (or (and (fboundp 'ask-user-about-lock)
  7.      (not (eq 'autoload
  8.           (car-safe (symbol-function 'ask-user-about-lock)))))
  9.     (load-library "userlock"))
  10.  
  11. ;;; Energize advised functions
  12.  
  13. (defun energize-next-error (&optional arg)
  14.   "If the current buffer is an Energize buffer, the server is consulted.
  15. In this case, a prefix argument means ``previous error''.  Otherwise,
  16. use the original definition of next-error."
  17.   (interactive "P")
  18.   (cond ((and (boundp 'compilation-error-list)
  19.           (boundp 'compilation-error-buffer)
  20.           compilation-error-list
  21.           compilation-error-buffer
  22.           (bufferp compilation-error-buffer)
  23.           (buffer-name compilation-error-buffer))
  24.      (energize-orig-next-error arg))
  25.     (t
  26.      (energize-execute-command (if arg "previouserror" "nexterror"))))
  27. ;  (if (energize-buffer-p (current-buffer))
  28. ;      (energize-execute-command (if arg "previouserror" "nexterror"))
  29. ;    (energize-orig-next-error arg))
  30.   )
  31.  
  32. ;(defun energize-previous-error (&optional arg)
  33. ;  "If the current buffer is an Energize buffer, the server is consulted.
  34. ;In this case, a prefix argument means ``next error''.  Otherwise,
  35. ;use the original definition of previous-error."
  36. ;  (interactive "P")
  37. ;  (if (energize-buffer-p (current-buffer))
  38. ;      (energize-execute-command (if arg "nexterror" "previouserror"))
  39. ;    (energize-orig-previous-error arg)))
  40.  
  41. (defun energize-set-visited-file-name (filename)
  42.   "This is illegal for Energize buffers."
  43.   (interactive "FSet visited file name: ")
  44.   (if (and (energize-write-file-buffer-p)
  45.        (not (equal filename buffer-file-name)))
  46.       (error "Can't change the name associated with an Energize buffer.")
  47.     (energize-orig-set-visited-file-name filename)
  48.     (if (energize-buffer-p (current-buffer))
  49.     (energize-mode-internal))))
  50.  
  51.  
  52. (defun energize-find-file-noselect (filename &optional nowarn)
  53.   "When connected to Energize, if the visited file is one that
  54. Energize knows about, it will be correctly annotated."
  55.   (if (and (connected-to-energize-p)
  56.        (not (file-directory-p filename))
  57.        (energize-query-buffer filename t))
  58.       ;; after-find-file and abbreviate-file-name are called from
  59.       ;; energize-buffer-creation-hook-function, which is run from
  60.       ;; editorside.c (way down under energize-query-buffer).
  61.       ;; This is a mess...
  62.       (energize-query-buffer filename)
  63.     (energize-orig-find-file-noselect filename nowarn)))
  64.  
  65.  
  66. (defun energize-ask-user-about-lock (fn opponent)
  67.   "Energize buffers do this by asking the server."
  68.   (if (energize-buffer-p (current-buffer))
  69.       t
  70.     (energize-orig-ask-user-about-lock fn opponent)))
  71.  
  72. (defun energize-init ()
  73.   (if (= 0 (energize-bits 1024))
  74.       (energize-announce (get 'energize 'energize))))
  75.  
  76. ;; true if current-buffer is an energize buffer that does not support
  77. ;; the real write-file and so has to do the special energize way of doing
  78. ;; write-file that loses the annotations.
  79. (defun energize-write-file-buffer-p ()
  80. ;;  (and (energize-buffer-p (current-buffer)
  81. ;;       (not (eq major-mode 'energize-project-mode)))
  82.   (energize-buffer-p (current-buffer)))
  83.  
  84. (defun energize-write-file (filename)
  85.   "When executed on an Energize buffer, this will cause all 
  86. annotations to be lost (that is, the buffer will become a normal
  87. buffer, not one that the Energize server knows about.)"
  88.   (interactive
  89.    (list (let ((prompt (if (energize-write-file-buffer-p)
  90.                "Write Energize buffer to file: "
  91.              "Write file: ")))
  92.        (if buffer-file-name
  93.            (read-file-name prompt nil nil nil nil)
  94.          (read-file-name prompt (cdr (assq 'default-directory
  95.                            (buffer-local-variables)))
  96.                  nil nil (buffer-name))))))
  97.   (if (not (energize-write-file-buffer-p))
  98.       (energize-orig-write-file filename)
  99.     ;; else...
  100.     (if (and (file-exists-p filename)
  101.          (not
  102.           (yes-or-no-p (format "File %s already exists.  Overwrite it? "
  103.                    filename))))
  104.     (error "Aborted"))
  105.     (write-region (point-min) (point-max) filename nil nil)
  106.     (if buffer-file-name
  107.     (revert-buffer t t)) ; revert this buffer from the Energize server
  108.     (kill-buffer nil) ; kill the current buffer, to lose Energize properties
  109.     (set-window-buffer ; and now visit the "new" file, and all that entails
  110.      (selected-window)
  111.      (find-file-noselect filename))))
  112.  
  113.  
  114. (defun energize-gdb-break (arg)
  115.   "If the current buffer is an Energize buffer, then this works by talking 
  116. to the server."
  117.   (interactive "P")
  118.   (if (not (energize-buffer-p (current-buffer)))
  119.       (energize-orig-gdb-break arg)
  120.     (energize-execute-command "setbreakpoint")))
  121.  
  122. (defun energize-gdb-step (arg)
  123.   "If the current buffer is an Energize buffer, then this works by talking to
  124. the server."
  125.   (interactive "p")
  126.   (if (not (energize-buffer-p (current-buffer)))
  127.       (energize-orig-gdb-step arg)
  128.     (while (> arg 0)
  129.       (energize-execute-command "steponce")
  130.       (setq arg (1- arg)))))
  131.  
  132. (defun energize-gdb-stepi (arg)
  133.   "If the current buffer is an Energize buffer, then this works by talking to
  134. the server."
  135.   (interactive "p")
  136.   (if (not (energize-buffer-p (current-buffer)))
  137.       (energize-orig-gdb-step arg)
  138.     ;; there's no energize command for this, so do it this way...
  139.     (save-excursion
  140.       (set-buffer "*Debugger*")
  141.       (goto-char (point-max))
  142.       (insert (format "stepi %d" arg))
  143.       (comint-send-input))))
  144.  
  145. (defun energize-beginning-of-defun (&optional arg)
  146.   "Move point to the beginning of the current top-level form.
  147. With a numeric argument, move back that many forms."
  148.   (interactive "p")
  149.   (or arg (setq arg 1))
  150.   (if (not (energize-buffer-p (current-buffer)))
  151.       ;;(energize-orig-beginning-of-defun arg)
  152.       (error "Not an Energize buffer")
  153.     (if (< arg 0)
  154.     (energize-end-of-defun (- arg))
  155.       (while (> arg 0)
  156.         (or (bobp) (forward-char -1))
  157.         (while (and (not (bobp)) (null (extent-at (point))))
  158.           (forward-char -1))
  159.         (let ((pos (point)))
  160.           (map-extents 
  161.            (function
  162.             (lambda (extent dummy)
  163.           (if (< (setq pos (extent-start-position extent)) (point))
  164.           (goto-char pos))))
  165.            (current-buffer) (point) (point) nil t))
  166.         (setq arg (1- arg))))))
  167.  
  168. (defun energize-end-of-defun (&optional arg)
  169.   "Move point to the end of the current top-level form.
  170. With a numeric argument, move forward over that many forms."
  171.   (interactive "p")
  172.   (or arg (setq arg 1))
  173.   (if (not (energize-buffer-p (current-buffer)))
  174.       ;;(energize-orig-end-of-defun arg)
  175.       (error "Not an Energize buffer")
  176.     (if (< arg 0)
  177.     (energize-beginning-of-defun (- arg))
  178.       (while (> arg 0)
  179.         (or (eobp) (forward-char 1))
  180.         (while (and (not (eobp)) (null (extent-at (point))))
  181.           (forward-char 1))
  182.         (let ((pos (point)))
  183.           (map-extents 
  184.            (function
  185.             (lambda (extent dummy)
  186.           (if (> (setq pos (extent-end-position extent)) (point))
  187.           (goto-char pos))))
  188.            (current-buffer) (point) (point) nil t))
  189.         (setq arg (1- arg))))))
  190.  
  191. (defun energize-normal-mode (&optional find-file)
  192. "If this is an Energize buffer, then the Energize modes are turned on as well."
  193.   (interactive)
  194.   (energize-orig-normal-mode find-file)
  195.   (if (and (energize-buffer-p (current-buffer))
  196.        (not inside-energize-buffer-creation-hook-function))
  197.       (funcall energize-create-buffer-hook (current-buffer))))
  198.  
  199.  
  200.  
  201. ;;; Patching Energize into file I/O via the standard hooks.
  202.  
  203. (defun energize-write-data-hook (name)
  204.   ;; for use as the last element of write-file-data-hooks
  205.   ;; in energize buffers.
  206.   (if (energize-buffer-p (current-buffer))
  207.       (progn
  208.     (message "saving %s to Energize..." name)
  209.     (energize-execute-command "save")
  210.     (energize-update-menubar)
  211.     (message "saved %s to Energize." name)
  212.     t)
  213.     nil))
  214.  
  215. (defun energize-revert-buffer-insert-file-contents-hook (file noconfirm)
  216.   ;; for use as the value of revert-buffer-insert-file-contents-function
  217.   ;; in energize buffers.
  218.   (if (not (energize-buffer-p (current-buffer)))
  219.       (error "energize-revert-buffer-hook called for a non-energize buffer"))
  220.   (widen)
  221.   (cond ((equal file buffer-file-name)        ; reverting from energize
  222.      (energize-execute-command "revert"))
  223.     (t                    ; reverting from autosave
  224.      (if (not (file-exists-p file))
  225.          (error "File %s no longer exists!" file))
  226.      (erase-buffer)
  227.      (insert-file-contents file)))
  228.   t)
  229.  
  230.  
  231. (defun energize-kill-buffer-hook ()
  232.   ;; for use as the value of kill-buffer-hook in energize buffers.
  233.   (if (energize-buffer-p (current-buffer))
  234.       (energize-request-kill-buffer (current-buffer))
  235.       (error "energize-kill-buffer-hook called on a non-energize buffer"))
  236.   t)
  237.  
  238.  
  239. ; ;;; An importing version of find-file.
  240. ; (fset 'find-file-in-energize 'energize-find-file)
  241. ; (defun energize-find-file (name)
  242. ;   "When connected to energize, energize will know about this file."
  243. ;   (interactive (list (read-file-name 
  244. ;               (if (connected-to-energize-p)
  245. ;               "Energize find file: "
  246. ;             "Find file: "))))
  247. ;   (if (and (connected-to-energize-p)
  248. ;        (not (file-directory-p name))
  249. ;        (or (energize-query-buffer name t)
  250. ;            (y-or-n-p (format "Import \"%s\" into Energize? " name))))
  251. ;       (let ((buffer (energize-query-buffer name))) ; create if necessary
  252. ;     (or (bufferp buffer) (error "couldn't import %s" name))
  253. ;     ;; change name, as energize might have trunamed it.
  254. ;     (setq name (or (buffer-file-name buffer) (error "no name?")))
  255. ;     ;; if it was in a buffer already, give it the energize keybindings.
  256. ;     (save-excursion
  257. ;       (set-buffer buffer)
  258. ;       (if (not energize-source-mode)
  259. ;           (energize-source-minor-mode)))
  260. ;     ))
  261. ;   ;; find-file will switch to the buffer if we created it above.
  262. ;   (find-file name))
  263.  
  264.  
  265. ;;; 
  266.  
  267. (defun energize-edit-definition-default ()
  268.   (save-excursion
  269.     (if (not (memq (char-syntax (preceding-char)) '(?w ?_)))
  270.     (while (not (looking-at "\\sw\\|\\s_\\|\\'"))
  271.       (forward-char 1)))
  272.     (while (looking-at "\\sw\\|\\s_")
  273.       (forward-char 1))
  274.     (if (re-search-backward "\\sw\\|\\s_" nil t)
  275.     (progn (forward-char 1)
  276.            (buffer-substring (point)
  277.                  (progn (forward-sexp -1)
  278.                     (while (looking-at "\\s'")
  279.                       (forward-char 1))
  280.                     (point))))
  281.       nil)))
  282.  
  283. ;;; This prompts in the minibuffer, ##### with no completion.
  284. (defun energize-edit-definition (def)
  285.   "If connected to Energize, the Energize database is used.  
  286. Otherwise, `find-tag' is invoked.
  287. The X selection is used as a default, if it exists and contains no 
  288. newlines.  Otherwise, the preceeding token is used as a default.  
  289. If invoked from a mouse command, prompting happens with a dialog box; 
  290. otherwise, the minibuffer is used."
  291.   (interactive
  292.    (if (and (connected-to-energize-p)
  293.         (or (menu-event-p last-command-event)
  294.         (button-press-event-p last-command-event)
  295.         (button-release-event-p last-command-event)))
  296.        '(nil)
  297.      (list
  298.       (let (default
  299.         def)
  300.     (cond ((x-selection-owner-p)
  301.            (setq default (x-get-selection))
  302.            (while (string-match "\\`[ \t\n]+" default)
  303.          (setq default (substring default (match-end 0))))
  304.            (while (string-match "[ \t\n]+\\'" default)
  305.          (setq default (substring default 0 (match-beginning 0))))
  306.            (if (string-match "[ \t\n]" default)
  307.            (setq default nil))))
  308.     (or default (setq default (energize-edit-definition-default)))
  309.     (setq def
  310.           (if (connected-to-energize-p)
  311.           (completing-read
  312.            (if default
  313.                (format "Edit definition [%s]: " default)
  314.              "Edit definition: ")
  315.            nil nil; 'energize-edit-def-predicate
  316.            nil nil)
  317.         (or (and (fboundp 'find-tag-tag) (fboundp 'find-tag-default))
  318.             (require 'tags "etags"))
  319.         (find-tag-tag "Edit definition: ")))
  320.     (if (consp def) (setq def (car def)))
  321.     (if (equal "" def) (setq def default))
  322.     def))))
  323.   (if (connected-to-energize-p)
  324.       (energize-execute-command "editdef" () def t)
  325.     (find-tag def)))
  326.  
  327. (define-key global-map "\M-." 'energize-edit-definition)
  328. (define-key global-map "\M-B" 'energize-build-a-target)   ; M-Sh-B
  329.  
  330. (defun disconnect-from-energize-query ()
  331.   "Disconnect this emacs from the Energize server, after confirming."
  332.   (interactive)
  333.   (or (y-or-n-p "Disconnect from Energize? ") (error "not confirmed"))
  334.   (disconnect-from-energize))
  335.  
  336.  
  337. ;;; Functions to add commands to the project buffers
  338. (defun energize-insert-slots (got-to-top-p l)
  339.   (if (not (eq major-mode 'energize-project-mode))
  340.       (error "Command available only in project buffers"))
  341.   ;; move to a suitable place
  342.   (if got-to-top-p
  343.       (beginning-of-buffer)
  344.     (beginning-of-line))
  345.   ;; go before "Associated Projects" and "Related Files"
  346.   (if (or (search-backward "Related Projects:" () t)
  347.       (search-backward "Associated Files:" () t)
  348.       (looking-at "Related Projects:")
  349.       (looking-at "Associated Files:"))
  350.       (previous-line 2))
  351.   ;; find empty space
  352.   (while (and (not (looking-at "$"))
  353.           (not (eq (point) (point-max))))
  354.     (next-line 1))
  355.   (newline)
  356.   (save-excursion
  357.     (mapcar '(lambda (i) (insert i) (newline)) l))
  358.   ;; this is magic
  359.   (forward-char 18))
  360.  
  361. (defun energize-insert-rule ()
  362.   (interactive)
  363.   (energize-insert-slots
  364.    t
  365.    '("           Rules:"
  366.      "          <rule>: lcc -Xez -c -g -Xa -o $object $source")))
  367.  
  368. (defun energize-insert-object-file-target ()
  369.   (interactive)
  370.   (energize-insert-slots
  371.    ()
  372.    '("     Object File: <object-file>"
  373.      "     Source File: <source-file>"
  374.      "      Build Rule: <rule>")))
  375.  
  376. (defun energize-insert-executable-target ()
  377.   (interactive)
  378.   (energize-insert-slots
  379.    ()
  380.    '("      Executable: <executable>"
  381.      "   Build Command: lcc -Xf -Xez -o $object <object-file> ...")))
  382.  
  383. (defun energize-insert-library-target ()
  384.   (interactive)
  385.   (energize-insert-slots
  386.    ()
  387.    '("         Library: <library>"
  388.      "   Build Command: energize_ar -Xez -remove -ranlib clq $object \\"
  389.      "                    <object-file> ...")))
  390.  
  391. (defun energize-insert-collection-target ()
  392.   (interactive)
  393.   (energize-insert-slots
  394.    ()
  395.    '("      Collection: <collection>"
  396.      "   Build Command: energize_collect -Xez -o $object <object-file> ...")))
  397.  
  398. (defun energize-insert-file-target ()
  399.   (interactive)
  400.   (energize-insert-slots
  401.    ()
  402.    '("     File Target: <target>"
  403.      "    Dependencies: <target> ..."
  404.      "   Build Command: <shell-command>")))
  405.  
  406. (defun energize-insert-target-target ()
  407.   (interactive)
  408.   (energize-insert-slots
  409.    ()
  410.    '("          Target: <target>"
  411.      "    Dependencies: <target> ..."
  412.      "   Build Command: <shell-command>")))
  413.  
  414.  
  415.  
  416. ;;; Keymaps for Energize buffers.
  417.  
  418. (defvar energize-map nil "*Parent keymap for all Energize buffers")
  419. (defvar energize-top-level-map nil "*Keymap for the Energize top-level buffer")
  420. (defvar energize-user-input-map nil
  421.   "*Parent keymap for Energize input buffers")
  422. (defvar energize-debugger-map nil "*Keymap for Energize debugger buffers")
  423. (defvar energize-breakpoint-map nil "*Keymap for Energize breakpoint-lists")
  424. (defvar energize-browser-map nil "*Keymap for Energize browser buffers")
  425. (defvar energize-project-map nil "*Keymap for Energize project buffers")
  426. (defvar energize-no-file-project-map nil
  427.   "*Keymap for Energize project buffers not associated with a file")
  428. (defvar energize-source-map nil "*Keymap for Energize source buffers")
  429.  
  430. (defvar energize-mode-hook nil
  431.   "Hook called when each energize buffer is created.")
  432. (defvar energize-top-level-mode-hook nil
  433.   "Hook called when the energize top-level buffer is created.")
  434. (defvar energize-project-mode-hook nil
  435.   "Hook called when an Energize project buffer is created.")
  436. (defvar energize-no-file-project-mode-hook nil
  437.   "Hook called when an Energize project buffer with no file is created.")
  438. (defvar energize-breakpoint-mode-hook nil
  439.   "Hook called when an Energize breakpoint-list buffer is created.")
  440. (defvar energize-browser-mode-hook nil
  441.   "Hook called when an Energize browser buffer is created.")
  442. (defvar energize-log-mode-hook nil
  443.   "Hook called when an Energize log buffer is created.")
  444. (defvar energize-manual-mode-hook nil
  445.   "Hook called when an Energize manual buffer is created.")
  446. (defvar energize-source-mode-hook nil
  447.   "Hook called when any source buffer is placed in the Energize minor-mode.")
  448.  
  449.  
  450. (if energize-map
  451.     nil
  452.   (setq energize-map (make-sparse-keymap))
  453.   (set-keymap-name energize-map 'energize-map)
  454.   (define-key energize-map "\^C\^F"    'energize-find-project)
  455.   (define-key energize-map "\^C\^B\^E"    'energize-browse-error)
  456.   (define-key energize-map "\^C\^B\^L"    'energize-browse-language-elt)
  457.   (define-key energize-map "\^C\^B\^T"    'energize-browse-tree)
  458.   (define-key energize-map "\^C\^B\^C"    'energize-browse-class)
  459. ;;  now in global-map
  460. ;;  (define-key energize-map "\M-B" 'energize-build-a-target) ; M-Sh-B
  461.   (define-key energize-map "\M-C" 'energize-default-compile-file) ; M-Sh-C
  462.   (define-key energize-map 'button3 'energize-popup-menu)
  463.   )
  464.  
  465. (if energize-top-level-map
  466.     nil
  467.   (setq energize-top-level-map (make-sparse-keymap))
  468.   (set-keymap-name energize-top-level-map 'energize-top-level-map)
  469.   (set-keymap-parent energize-top-level-map energize-map)
  470.   (suppress-keymap energize-top-level-map)
  471.   (define-key energize-top-level-map "?" 'describe-mode)
  472.   (define-key energize-top-level-map " " 'energize-top-next-project)
  473.   (define-key energize-top-level-map "n" 'energize-top-next-project)
  474.   (define-key energize-top-level-map "p" 'energize-top-prev-project)
  475.   (define-key energize-top-level-map "N" 'energize-top-next-project)
  476.   (define-key energize-top-level-map "P" 'energize-top-prev-project)
  477.   (define-key energize-top-level-map "\t" 'energize-top-next-project)
  478.   (define-key energize-top-level-map '(shift tab) 'energize-top-prev-project)
  479.   (define-key energize-top-level-map '(control I) 'energize-top-prev-project)
  480.  
  481.   (define-key energize-top-level-map "Q" 'disconnect-from-energize-query)
  482.  
  483.   (define-key energize-top-level-map "d" 'energize-top-debug)
  484.   (define-key energize-top-level-map "\^D" 'energize-top-delete-project)
  485.   (define-key energize-top-level-map "e" 'energize-top-edit-project)
  486.   )
  487.  
  488. (if energize-project-map
  489.     nil
  490.   (setq energize-project-map (make-sparse-keymap))
  491.   (set-keymap-name energize-project-map 'energize-project-map)
  492.   (set-keymap-parent energize-project-map energize-map)
  493.   ;;(suppress-keymap energize-project-map)
  494.   ;;(define-key energize-project-map "\t" 'energize-project-next-field)
  495.   ;;(define-key energize-project-map '(shift tab) 'energize-project-prev-field)
  496.   ;;(define-key energize-project-map '(control I) 'energize-project-prev-field)
  497.  
  498.   (define-key energize-project-map "\^C\^I" 'energize-import-file)
  499.   (define-key energize-project-map "\^C\^E" 'energize-project-edit-file)
  500.   (define-key energize-project-map "\^C\^S\^A" 'energize-project-sort-alpha)
  501.   (define-key energize-project-map "\^C\^S\^L" 'energize-project-sort-link)
  502.   (define-key energize-project-map "\^C\^V\^N" 'energize-project-view-names)
  503. ;  (define-key energize-project-map "\^C\^V\^L" 'energize-project-view-long)
  504.   (define-key energize-project-map "\^C\^V\^C" 'energize-project-view-options)
  505.   )
  506.  
  507.  
  508. (if energize-no-file-project-map
  509.     nil
  510.   (setq energize-no-file-project-map (make-sparse-keymap))
  511.   (set-keymap-name energize-no-file-project-map 'energize-no-file-project-map)
  512.   (set-keymap-parent energize-no-file-project-map energize-map))
  513.  
  514. (if energize-breakpoint-map
  515.     nil
  516.   (setq energize-breakpoint-map (make-sparse-keymap))
  517.   (set-keymap-name energize-breakpoint-map 'energize-breakpoint-map)
  518.   (set-keymap-parent energize-breakpoint-map energize-map)
  519.   )
  520.  
  521. (if energize-browser-map
  522.     nil
  523.   (setq energize-browser-map (make-sparse-keymap))
  524.   (set-keymap-name energize-browser-map 'energize-browser-map)
  525.   (set-keymap-parent energize-browser-map energize-map)
  526.   )
  527.  
  528. (if energize-source-map
  529.     nil
  530.   (setq energize-source-map (make-sparse-keymap))
  531.   (set-keymap-name energize-source-map 'energize-source-map)
  532.   (set-keymap-parent energize-source-map energize-map)
  533. ;;  There are too many problems with using extents to determine where the
  534. ;;  top level forms are...
  535. ;;  (define-key energize-source-map "\M-\C-a" 'energize-beginning-of-defun)
  536. ;;  (define-key energize-source-map "\M-\C-e" 'energize-end-of-defun)
  537.  )
  538.  
  539. (if energize-user-input-map
  540.     nil
  541.   (setq energize-user-input-map (copy-keymap comint-mode-map))
  542.   (if (keymap-parent comint-mode-map) (error "comint-mode-map has a parent?"))
  543.   (set-keymap-parent energize-user-input-map energize-map)
  544.   (define-key energize-user-input-map "\M-\t" 'comint-dynamic-complete)
  545.   (define-key energize-user-input-map "\M-?" 'comint-dynamic-list-completions)
  546.   )
  547.  
  548.  
  549. (defvar energize-menu-state nil
  550.   "State of the energize menu items of the buffer.  
  551. Automatically updated by the kernel when the state changes")
  552.  
  553. (defvar energize-default-menu-state nil
  554.   "State of the energize default menu items.  
  555. Automatically updated by the kernel when the state changes")
  556.  
  557. (defun energize-mode-internal ()
  558.   ;; initialize stuff common to all energize buffers (hooks, etc).
  559.   (make-local-variable 'write-file-data-hooks)
  560.   (add-hook 'write-file-data-hooks 'energize-write-data-hook t)
  561.   ;;
  562.   (make-local-variable 'revert-buffer-insert-file-contents-function)
  563.   (setq revert-buffer-insert-file-contents-function
  564.     'energize-revert-buffer-insert-file-contents-hook)
  565.   ;;
  566.   (make-local-variable 'kill-buffer-hook)
  567.   (setq kill-buffer-hook 'energize-kill-buffer-hook)
  568.   ;;
  569.   (make-local-variable 'require-final-newline)
  570.   (setq require-final-newline t)
  571.   ;;
  572.   (make-local-variable 'energize-menu-state)
  573.   ;;
  574.   (run-hooks 'energize-mode-hook))
  575.  
  576. (defun energize-non-file-mode-internal ()
  577.   ;; do magic associated with energize-modes for buffers which are not
  578.   ;; and cannot be associated with files.
  579. ;  (or (null buffer-file-name)
  580. ;      (equal buffer-file-name mode-name)
  581. ;      (error
  582. ;       "This buffer is associated with a file, it can't be placed in %s mode"
  583. ;       mode-name))
  584.   ;; hack so that save-file doesn't prompt for a filename.
  585.   (or buffer-file-name
  586.       (setq buffer-file-name (buffer-name)))
  587.   (set (make-local-variable 'version-control) 'never)
  588.   nil)
  589.  
  590. ;; don't create random new buffers in these modes
  591. (put 'energize-top-level-mode        'mode-class 'special)
  592. (put 'energize-project-mode        'mode-class 'special)
  593. (put 'energize-no-file-project-mode    'mode-class 'special)
  594. (put 'energize-breakpoint-mode        'mode-class 'special)
  595. (put 'energize-browser-mode        'mode-class 'special)
  596. (put 'energize-log-mode            'mode-class 'special)
  597.  
  598. (defun energize-top-level-mode ()
  599.   "Major mode for the Energize top-level buffer.
  600. In addition to normal cursor-motion commands, the following keys are bound:
  601. \\{energize-top-level-map}"
  602.   (interactive)
  603.   (energize-mode-internal)
  604.   (use-local-map energize-top-level-map)
  605.   (setq major-mode 'energize-top-level-mode
  606.     mode-name "Energize")
  607.   (energize-non-file-mode-internal)
  608.   ;; the default of "energize: Energize" is not very attractive.
  609.   (if (equal screen-title-format "%S: %b")
  610.       (set (make-local-variable 'screen-title-format) "%S: Top-Level"))
  611.   (run-hooks 'energize-top-level-mode-hook))
  612.  
  613.  
  614. (defun energize-project-mode ()
  615.   "Major mode for the Energize Project buffers.
  616. In addition to the normal editing commands, the following keys are bound:
  617. \\{energize-project-map}"
  618.   (interactive)
  619.   (energize-mode-internal)
  620.   (use-local-map energize-project-map)
  621.   (setq major-mode 'energize-project-mode
  622.     mode-name "Project")
  623.   ;; in later revisions of the kernel the project is really a file.
  624.   (if (< (cdr (energize-protocol-level)) 8)
  625.       (energize-non-file-mode-internal))
  626.   (run-hooks 'energize-project-mode-hook))
  627.  
  628. (defun energize-no-file-project-mode ()
  629.   "Major mode for the Energize Project buffers not associated with a file.
  630. In addition to the normal editing commands, the following keys are bound:
  631. \\{energize-no-file-project-map}"
  632.   (interactive)
  633.   (energize-mode-internal)
  634.   (use-local-map energize-no-file-project-map)
  635.   (setq major-mode 'energize-no-file-project-mode
  636.     mode-name "NoFileProject")
  637.   (energize-non-file-mode-internal)
  638.   (run-hooks 'energize-no-file-project-mode-hook))
  639.  
  640. (defun energize-breakpoint-mode ()
  641.   "Major mode for the Energize Breakpoint-list buffers.
  642. In addition to the normal editing commands, the following keys are bound:
  643. \\{energize-breakpoint-map}"
  644.   (interactive)
  645.   (energize-mode-internal)
  646.   (use-local-map energize-breakpoint-map)
  647.   (setq major-mode 'energize-breakpoint-mode
  648.     mode-name "Breakpoint")
  649.   (energize-non-file-mode-internal)
  650.   (run-hooks 'energize-breakpoint-mode-hook))
  651.  
  652. (defun energize-browser-mode ()
  653.   "Major mode for the Energize Browser buffers.
  654. In addition to the normal editing commands, the following keys are bound:
  655. \\{energize-browser-map}"
  656.   (interactive)
  657.   (energize-mode-internal)
  658.   (use-local-map energize-browser-map)
  659.   (setq major-mode 'energize-browser-mode
  660.     mode-name "Browser")
  661.   (energize-non-file-mode-internal)
  662.   (run-hooks 'energize-browser-mode-hook))
  663.  
  664. (defun energize-log-mode ()
  665.   "Major mode for the Energize Error Log and System Log buffers.
  666. In addition to the normal editing commands, the following keys are bound:
  667. \\{energize-map}"
  668.   (interactive)
  669.   (energize-mode-internal)
  670.   (use-local-map energize-map)
  671.   (setq major-mode 'energize-log-mode
  672.     mode-name "Energize-Log")
  673.   (energize-non-file-mode-internal)
  674.   (run-hooks 'energize-log-mode-hook))
  675.  
  676. (defun energize-manual-mode ()
  677.   "Major mode for the Energize UNIX Manual buffers.
  678. In addition to the normal editing commands, the following keys are bound:
  679. \\{energize-map}"
  680.   (interactive)
  681.   (energize-mode-internal)
  682.   (use-local-map energize-map)
  683.   (setq major-mode 'energize-manual-mode
  684.     mode-name "Energize-Manual")
  685.   (energize-non-file-mode-internal)
  686.   (run-hooks 'energize-manual-mode-hook))
  687.  
  688. (defvar energize-source-mode nil)
  689. ;;(put 'energize-source-mode 'permanent-local t) ; persists beyond mode-change
  690.  
  691. ;;; Add energize-source-mode to minor-mode-alist so that it shows up in 
  692. ;;; the modeline when true.
  693. ;;;
  694. (or (assq 'energize-source-mode minor-mode-alist)
  695.     (setq minor-mode-alist
  696.       (append minor-mode-alist
  697.           '((energize-source-mode " Energize")))))
  698.  
  699. ;;; add a function to the find-file-hooks that turns on the energize minor
  700. ;;; mode if this is an Energize buffer.  This happens both with find-file and
  701. ;;; with revert-buffer.
  702. ;;;
  703. ;(add-hook 'find-file-hooks 'maybe-turn-on-energize-minor-mode t)
  704.  
  705. (fmakunbound 'maybe-turn-on-energize-minor-mode)
  706. ;(defun maybe-turn-on-energize-minor-mode ()
  707. ;  (if (and (energize-buffer-p (current-buffer))
  708. ;       (eq (energize-buffer-type (current-buffer))
  709. ;           'energize-source-buffer))
  710. ;      (energize-source-minor-mode)))
  711.  
  712. (defun energize-source-minor-mode ()
  713.   "Minor mode for adding additional keybindings to Energize source buffers.
  714. The following key bindings are added:
  715. \\{energize-source-map}
  716.  
  717. Since this minor mode defines keys, once it gets turned on you can't really
  718. turn it off."
  719.   (interactive)
  720.   (energize-mode-internal)
  721.   (make-local-variable 'energize-source-mode)
  722.   (setq energize-source-mode t)
  723.   (let ((source-map energize-source-map)
  724.     (dest-map (make-sparse-keymap)))
  725.     (set-keymap-parent dest-map (current-local-map))
  726.     (set-keymap-name dest-map 'energize-minor-mode-map)
  727.     (while source-map
  728.       (let (mapper prefixes)
  729.     (setq mapper (function (lambda (key val)
  730.                  (if (keymapp val)
  731.                      (let ((prefixes (append prefixes
  732.                                  (cons key nil))))
  733.                        (map-keymap val mapper))
  734.                    (define-key dest-map
  735.                      (apply 'vector
  736.                         (append prefixes (cons key nil)))
  737.                      val)
  738.                    ))))
  739.     (map-keymap source-map mapper))
  740.       (setq source-map (keymap-parent source-map)))
  741.     (use-local-map dest-map))
  742.   (run-hooks 'energize-source-mode-hook))
  743.  
  744.  
  745. ;;; Commands in source buffers
  746.  
  747. (defun recenter-definition ()
  748.   "Position the beginning of the current definition at the top of the screen."
  749.   (interactive)
  750.   (end-of-line)
  751.   (if (eq major-mode 'c++-mode)
  752.       (c++-beginning-of-defun 1)
  753.     (beginning-of-defun 1))
  754.   (recenter 1))
  755.  
  756. (define-key global-map "\M-\C-r" 'recenter-definition)
  757.  
  758. ;;; Dired-like commands
  759.  
  760. (defun energize-next-extent-for (command prev not-this-one)
  761.   (let ((last-e (if not-this-one 'none nil))
  762.     e result)
  763.     (save-excursion
  764.       (let ((p (point)))
  765.     (while (not (or result
  766.             (if prev (bobp) (eobp))))
  767.       (setq e (extent-at (point) (current-buffer)))
  768.       (if (and (not (eq e last-e))
  769.            (not (eq last-e 'none)))
  770.           (setq result
  771.             (energize-menu-item-for-name e command)))
  772.       (forward-char (if prev -1 1))
  773.       (setq last-e e))))
  774.     (if result e)))
  775.  
  776. (defun energize-next-extent-on-line-for (command not-this-one)
  777.   (save-excursion
  778.     (save-restriction
  779.       (narrow-to-region (point) (progn (end-of-line) (point)))
  780.       (goto-char (point-min))
  781.       (energize-next-extent-for command nil not-this-one))))
  782.  
  783.  
  784. ;;; commands in the top-level buffer
  785.  
  786. (defun energize-top-next-project ()
  787.   "Position the cursor at the beginning of the following project."
  788.   (interactive)
  789.   (let ((p (point)))
  790.     (let ((e (energize-next-extent-for "editproject" nil t)))
  791.       (if (and e (= p (extent-start-position e)))
  792.       (save-excursion
  793.         (forward-char (extent-length e))
  794.         (setq e (energize-next-extent-for "editproject" nil t))))
  795.       (if e
  796.       (goto-char (extent-start-position e))
  797.     (error "no next project")))))
  798.  
  799. (defun energize-top-prev-project ()
  800.   "Position the cursor at the beginning of the preceeding project."
  801.   (interactive)
  802.   (let ((p (point)))
  803.     (let ((e (energize-next-extent-for "editproject" t t)))
  804.       (if (and e (= p (extent-start-position e)))
  805.       (save-excursion
  806.         (forward-char -1)
  807.         (setq e (energize-next-extent-for "editproject" t t))))
  808.       (if e
  809.       (goto-char (extent-start-position e))
  810.     (error "no previous project")))))
  811.  
  812. (defun energize-top-execute-command (command)
  813.   (let ((e (or (energize-next-extent-on-line-for command nil)
  814.            (error
  815.         (concat "no following field on this line that handles the `"
  816.             command "' Energize command.")))))
  817.     (energize-execute-command command e)))
  818.  
  819. (defun energize-top-debug ()
  820.   "Execute the `Debug' command on the project at or following point."
  821.   (interactive)
  822.   (energize-top-execute-command "debugprogram"))
  823.  
  824. (defun energize-top-delete-project ()
  825.   "Delete the project at or following point."
  826.   (interactive)
  827.   (energize-top-execute-command "deleteproject"))
  828.  
  829. (defun energize-top-edit-project ()
  830.   "Edit the project at or following point."
  831.   (interactive)
  832.   (energize-top-execute-command "editproject"))
  833.  
  834. ;;; commands in the project buffer
  835.  
  836. (defun energize-project-next-field (&optional prev)
  837.   (interactive)
  838.   (let ((e (extent-at (point) (current-buffer))))
  839.     (if e
  840.     (if prev
  841.         (goto-char (1- (extent-start-position e)))
  842.       (goto-char (1+ (extent-end-position e)))))
  843.     (while (null (extent-at (point) (current-buffer)))
  844.       (forward-char (if prev -1 1)))
  845.     (while (extent-at (point) (current-buffer) 'write-protected)
  846.       (forward-char (if prev -1 1)))
  847.     (if prev
  848.     (if (setq e (extent-at (point) (current-buffer)))
  849.         (goto-char (extent-start-position e))
  850.       (while (not (extent-at (point) (current-buffer)))
  851.         (forward-char -1))))))
  852.  
  853. (defun energize-project-prev-field () (interactive)
  854.   (energize-project-next-field t))
  855.  
  856. (defun energize-project-edit-file () (interactive)
  857.   (energize-top-execute-command "editfile"))
  858.