1 ;;; efc.el -- Emacs Foundation Classes
2 ;; $Revision: 1.1 $ $Date: 2007-11-26 15:16:44 $
4 ;; Author: Paul Kinnucan <paulk@mathworks.com>
5 ;; Maintainer: Paul Kinnucan
6 ;; Keywords: lisp, tools, classes
8 ;; Copyright (C) 2001, 2002, 2003, 2004, 2005 Paul Kinnucan.
10 ;; GNU Emacs is free software; you can redistribute it and/or modify
11 ;; it under the terms of the GNU General Public License as published by
12 ;; the Free Software Foundation; either version 2, or (at your option)
15 ;; GNU Emacs is distributed in the hope that it will be useful,
16 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
17 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 ;; GNU General Public License for more details.
20 ;; You should have received a copy of the GNU General Public License
21 ;; along with GNU Emacs; see the file COPYING. If not, write to the
22 ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
23 ;; Boston, MA 02111-1307, US
26 ;; This package contains a set of eieio-based foundation classes
29 ;; Please send bug reports and enhancement suggestions
30 ;; to Paul Kinnucan at <paulk@mathworks.com>
32 ;; See end of this file for change history.
39 (defvar efc-query-options-function nil
40 "If non-nil the function to use for interactively querying options.
41 If nil then the default efc custom-based dialogs will be used.")
43 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
47 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
49 (defclass efc-dialog ()
50 ((title :initarg :title
59 (initbuf :initarg :initbuf
62 "Buffer from which dialog was called.")
64 "Super class of EFC dialogs."
67 (defmethod initialize-instance ((this efc-dialog) &rest fields)
68 "Constructor for dialog."
69 ;; Call parent initializer.
73 (defmethod efc-dialog-create ((this efc-dialog)))
75 (defmethod efc-dialog-ok ((this efc-dialog))
76 "Invoked when the user clicks the dialog's okay button. The
77 default method kills the dialog buffer."
78 (kill-buffer (current-buffer)))
80 (defmethod efc-dialog-cancel ((this efc-dialog))
81 "Invoked when the user clicks the dialog's Cancel button. The
82 default method kills the dialog buffer."
84 (set-buffer (oref this initbuf))
85 (pop-to-buffer (oref this initbuf))
86 (kill-buffer (oref this buf)))
88 (defmethod efc-dialog-show ((this efc-dialog))
89 (oset this initbuf (current-buffer))
91 (oset this buf (get-buffer-create (oref this title)))
92 (set-buffer (oref this buf))
94 (efc-dialog-create this)
100 (lambda (button &rest ignore) (efc-dialog-ok (widget-get button :dialog)))
109 :notify (lambda (button &rest ignore) (efc-dialog-cancel (widget-get button :dialog)))
113 (use-local-map widget-keymap)
116 ;; Position cursor over OK button.
119 (goto-char (point-min))
121 (pop-to-buffer (oref this buf)))
124 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
128 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
130 (defclass efc-option-dialog (efc-dialog)
131 ((options :initarg :options
133 "Options from from which to choose.")
134 (radio-buttons :initarg :radio-buttons
136 "Buttons for selecting options.")
139 :initform "Select option."
141 "Text to be inserted at top of dialog.")
142 (selection :initarg :selection
144 "Option chosen by the user."))
145 "This dialog allows a user to choose one of a set of OPTIONS by clicking
146 a radio button next to the option. The dialog sets SELECTION to the option
147 chosen by the user when the user selects the OK button on the dialog. This
148 dialog uses recursive edit to emulate a modal dialog.")
150 (defmethod initialize-instance ((this efc-option-dialog) &rest fields)
151 "Dialog constructor."
154 (defmethod efc-dialog-create ((this efc-option-dialog))
155 (widget-insert (oref this text))
156 (widget-insert "\n\n")
157 (oset this radio-buttons
161 :value (car (oref this options))
165 (oref this options)))))
166 (widget-insert "\n"))
168 (defmethod efc-dialog-show ((this efc-option-dialog))
169 "Shows the options dialog buffer. After showing the dialog buffer,
170 this method invokes recursive-edit to emulate the behavior of a modal
171 dialog. This suspends the current command until the user has selected
172 an option or canceled the dialog. See `efc-dialog-ok' and
173 `efc-dialog-cancel' for more information."
174 (save-window-excursion
179 (defmethod efc-dialog-ok ((this efc-option-dialog))
180 "Invoked when the user selects the OK button on the options
181 dialog. Sets the :selection field of THIS to the option chosen by the
182 user, kills the dialog buffer, and exits recursive-edit mode."
185 (widget-value (oref this radio-buttons)))
187 (set-buffer (oref this initbuf))
188 (pop-to-buffer (oref this initbuf))
189 (kill-buffer (oref this buf))
190 (exit-recursive-edit))
192 (defmethod efc-dialog-cancel ((this efc-option-dialog))
193 "Invoked when the user clicks the dialog's Cancel button. Invokes
194 the default cancel method, sets the :selection field of THIS to nil,
195 and then exits recursive edit mode."
197 (oset this selection nil)
198 (exit-recursive-edit))
200 (defun efc-query-options (options &optional prompt title)
201 "Ask user to choose among a set of options."
202 (if efc-query-options-function
203 (funcall efc-query-options-function options prompt title)
206 (or title "option dialog")
207 :text (or prompt "Select option:")
209 (efc-dialog-show dialog)
210 (oref dialog selection))))
212 ;; The following code is a patch that implements Richard Stallman's fix
213 ;; for the following error that occurs only in Emacs 21.1.1.
215 ;; Debugger entered--Lisp error: (wrong-type-argument window-live-p #<window 66>)
216 ;; select-window(#<window 66>)
217 ;; exit-recursive-edit()
218 ;; This replacement macro fixes the problem with exit-recursive-edit on Emacs 21.
219 ;; You'll have to recompile wid-edit.el with it.
220 ;; (defmacro save-selected-window (&rest body)
221 ;; "Execute BODY, then select the window that was selected before BODY.
222 ;; However, if that window has become dead, don't get an error,
223 ;; just refrain from switching to it."
224 ;; `(let ((save-selected-window-window (selected-window)))
227 ;; (if (window-live-p save-selected-window-window)
228 ;; (select-window save-selected-window-window)))))
231 (if (and (not (featurep 'xemacs))
233 (string-match "21\\.1" (emacs-version))
234 (string-match "21\\.2" (emacs-version))))
236 ;; Need to load wid-edit first to ensure that
237 ;; it does not get loaded after this patch and
238 ;; hence override the patch.
241 ;; Patched version of save-selected-window.
242 (defmacro save-selected-window (&rest body)
243 "Execute BODY, then select the window that was selected before BODY.
244 However, if that window has become dead, don't get an error,
245 just refrain from switching to it."
246 `(let ((save-selected-window-window (selected-window)))
249 (if (window-live-p save-selected-window-window)
250 (select-window save-selected-window-window)))))
252 ;; Redefine widget-button-click to use the patched
253 ;; version of save-selected-window
254 (defun widget-button-click (event)
255 "Invoke the button that the mouse is pointing at."
257 (if (widget-event-point event)
258 (let* ((pos (widget-event-point event))
259 (button (get-char-property pos 'button)))
261 ;; Mouse click on a widget button. Do the following
262 ;; in a save-excursion so that the click on the button
263 ;; doesn't change point.
264 (save-selected-window
266 (mouse-set-point event)
267 (let* ((overlay (widget-get button :button-overlay))
268 (face (overlay-get overlay 'face))
269 (mouse-face (overlay-get overlay 'mouse-face)))
271 ;; Read events, including mouse-movement events
272 ;; until we receive a release event. Highlight/
273 ;; unhighlight the button the mouse was initially
274 ;; on when we move over it.
275 (let ((track-mouse t))
277 (when face ; avoid changing around image
279 'face widget-button-pressed-face)
281 'mouse-face widget-button-pressed-face))
282 (unless (widget-apply button :mouse-down-action event)
283 (while (not (widget-button-release-event-p event))
284 (setq event (read-event)
285 pos (widget-event-point event))
287 (eq (get-char-property pos 'button)
292 widget-button-pressed-face)
295 widget-button-pressed-face))
296 (overlay-put overlay 'face face)
297 (overlay-put overlay 'mouse-face mouse-face))))
299 ;; When mouse is released over the button, run
300 ;; its action function.
302 (eq (get-char-property pos 'button) button))
303 (widget-apply-action button event))))
304 (overlay-put overlay 'face face)
305 (overlay-put overlay 'mouse-face mouse-face))))
307 (unless (pos-visible-in-window-p (widget-event-point event))
308 (mouse-set-point event)
312 (let ((up t) command)
313 ;; Mouse click not on a widget button. Find the global
314 ;; command to run, and check whether it is bound to an
316 (mouse-set-point event)
317 (if (memq (event-basic-type event) '(mouse-1 down-mouse-1))
318 (cond ((setq command ;down event
319 (lookup-key widget-global-map [down-mouse-1]))
321 ((setq command ;up event
322 (lookup-key widget-global-map [mouse-1]))))
323 (cond ((setq command ;down event
324 (lookup-key widget-global-map [down-mouse-2]))
326 ((setq command ;up event
327 (lookup-key widget-global-map [mouse-2])))))
329 ;; Don't execute up events twice.
330 (while (not (widget-button-release-event-p event))
331 (setq event (read-event))))
333 (call-interactively command)))))
334 (message "You clicked somewhere weird.")))
338 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
340 ;; Multiple Option Dialog ;;
342 ;; Contributed by Philip Lord. ;;
344 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
345 (defclass efc-multi-option-dialog (efc-option-dialog)
346 ((build-message :initarg :text
348 :initform "Building Dialog"
350 "Warning message while building dialog, as this can be slow"))
351 "Provides a dialog with several sets of OPTIONS.
352 The dialog sets SELECTION to the options selected by the user.")
354 (defmethod initialize-instance ((this efc-multi-option-dialog) &rest fields)
355 "Dialog constructor."
358 (defmethod efc-dialog-create ((this efc-multi-option-dialog))
359 (message "%s..." (oref this build-message))
360 (widget-insert (oref this text))
361 (widget-insert "\n\n")
362 ;; use radio buttons slot as list of radio buttons rather than.
363 (oset this radio-buttons
371 (efc-multi-option-dialog-default this list)
376 (widget-insert "\n")))
377 (efc-multi-option-dialog-sort this
378 (oref this options))))
380 (message "%s...done" (oref this text)))
382 (defmethod efc-dialog-ok((this efc-multi-option-dialog))
383 ;; set the selection up as a list rather a simple result
387 (widget-value widget))
388 (oref this radio-buttons)))
390 (set-buffer (oref this initbuf))
391 (pop-to-buffer (oref this initbuf))
392 (kill-buffer (oref this buf))
393 (exit-recursive-edit))
396 (defmethod efc-multi-option-dialog-default ((this efc-multi-option-dialog) list)
397 "Pick the default from a collection of options."
398 (if (= 1 (length list))
401 (defmethod efc-multi-option-dialog-sort ((this efc-multi-option-dialog) list)
403 ;; sort the ones with the most options first...
410 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
414 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
416 (defclass efc-compiler ()
417 ((name :initarg :name
419 :documentation "Compiler name.")
420 (buffer :initarg :buffer
423 "Compilation buffer")
424 (window :initarg :window
427 "Window that displays the compilation buffer.")
428 (exec-path :initarg :exec-path
430 :documentation "Path of compiler executable.")
431 (comp-finish-fcn :initarg :comp-finish-fcn
433 :documentation "Function to invoke at end of compilation."))
434 "Class of compiler-like applications.")
436 (defmethod create-buffer ((this efc-compiler))
437 "Create a buffer to display the output of a compiler process."
439 (let ((buf (get-buffer-create (format "*%s*" (oref this name))))
440 (error-regexp-alist compilation-error-regexp-alist)
441 (enter-regexp-alist (if (boundp 'compilation-enter-directory-regexp-alist)
442 compilation-enter-directory-regexp-alist))
443 (leave-regexp-alist (if (boundp 'compilation-leave-directory-regexp-alist)
444 compilation-leave-directory-regexp-alist))
445 (file-regexp-alist (if (boundp 'compilation-file-regexp-alist)
446 compilation-file-regexp-alist))
447 (nomessage-regexp-alist (if (not jde-xemacsp) compilation-nomessage-regexp-alist))
448 (parser compilation-parse-errors-function)
449 (error-message "No further errors")
450 (thisdir default-directory))
452 (oset this :buffer buf)
456 ;; Make sure a compiler process is not
458 (let ((compiler-proc (get-buffer-process (current-buffer))))
460 (if (or (not (eq (process-status compiler-proc) 'run))
462 (format "A %s process is running; kill it?" (oref this name))))
465 (interrupt-process compiler-proc)
467 (delete-process compiler-proc))
469 (error "Cannot have two processes in `%s' at once"
472 ;; In case the compiler buffer is current, make sure we get the global
473 ;; values of compilation-error-regexp-alist, etc.
474 (kill-all-local-variables)
476 ;; Clear out the compilation buffer and make it writable.
477 (setq buffer-read-only nil)
478 (buffer-disable-undo (current-buffer))
480 (buffer-enable-undo (current-buffer))
482 (compilation-mode (oref this name))
484 (set (make-local-variable 'compilation-parse-errors-function) parser)
485 (set (make-local-variable 'compilation-error-message) error-message)
486 (set (make-local-variable 'compilation-error-regexp-alist)
488 (if (not jde-xemacsp)
490 (set (make-local-variable 'compilation-enter-directory-regexp-alist)
492 (set (make-local-variable 'compilation-leave-directory-regexp-alist)
494 (set (make-local-variable 'compilation-file-regexp-alist)
496 (set (make-local-variable 'compilation-nomessage-regexp-alist)
497 nomessage-regexp-alist)))
499 (if (slot-boundp this 'comp-finish-fcn)
500 (set (make-local-variable 'compilation-finish-function)
501 (oref this comp-finish-fcn)))
503 (setq default-directory thisdir
504 compilation-directory-stack (list default-directory)))))
506 (defmethod get-args ((this efc-compiler))
507 "Get a list of command-line arguments to pass to the
511 (defmethod exec ((this efc-compiler))
512 "Start the compiler process."
516 ;; Pop to checker buffer.
517 (let ((outwin (display-buffer (oref this :buffer))))
518 (compilation-set-window-height outwin)
519 (oset this :window outwin))
521 (if (not (featurep 'xemacs))
522 (if compilation-process-setup-function
523 (funcall compilation-process-setup-function)))
525 (let* ((outbuf (oref this :buffer))
526 (executable-path (oref this exec-path))
527 (args (get-args this)))
532 (insert (format "cd %s\n" default-directory))
537 (mapconcat 'identity args " ")
540 (let* ((process-environment (cons "EMACS=t" process-environment))
541 (w32-quote-process-args ?\")
542 (win32-quote-process-args ?\") ;; XEmacs
543 (proc (apply 'start-process
548 (set-process-sentinel proc 'compilation-sentinel)
549 (set-process-filter proc 'compilation-filter)
550 (set-marker (process-mark proc) (point) outbuf)
551 (setq compilation-in-progress
552 (cons proc compilation-in-progress)))
554 (set-buffer-modified-p nil)
555 (setq compilation-last-buffer (oref this :buffer)))))
558 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
560 ;; Collection Class ;;
562 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
564 (defclass efc-collection ()
565 ((elem-type :initarg :elem-type
566 :type (or null symbol)
568 :documentation "Type of element that this collection contains."))
569 "A collection of objects. The collection can be either homogeneous, i.e.,
570 composed of elements of one type, or heterogeneous. The ELEM-TYPE property of
571 a heterogeneous collection is nil.")
573 (defmethod efc-coll-type-compatible-p ((this efc-collection) item)
574 "Returns t if ITEM is type-compatible with this collection. An item is
575 type-compatible with a collection if the collection is heterogeneous or
576 the item's type is the same as the collection's element type."
577 (let ((element-type (oref this elem-type)))
578 (or (eq element-type nil)
579 (typep item element-type))))
581 (defmethod efc-coll-iterator ((this efc-collection))
582 "Returns an iterator for this collection."
583 (error "Abstract method."))
585 (defmethod efc-coll-visit ((this efc-collection) visitor)
586 "Maps VISITOR to each element of the collection. VISITOR
587 is an object of efc-visitor class."
588 (let ((iter (efc-coll-iterator this)))
589 (while (efc-iter-has-next iter)
590 (efc-visitor-visit visitor (efc-iter-next iter)))))
592 (defmethod efc-coll-memberp ((this efc-collection) member)
593 "Returns nonil if this contains item."
594 (error "Abstract method."))
596 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
600 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
602 (defclass efc-iterator ()
604 "Iterates over a collection.")
606 (defmethod efc-iter-has-next ((this efc-iterator))
607 "Returns nonnil if the iterator has not returned all of the collection's elements."
608 (error "Abstract method."))
610 (defmethod efc-iter-next ((this efc-iterator))
611 "Return the next element of the collection."
612 (error "Abstract method."))
615 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
619 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
620 (defclass efc-visitor ()
622 "Visits each member of a collection.")
624 (defmethod efc-visitor-visit ((this efc-visitor) member)
625 "Visits MEMBER, a member of a collection."
626 (error "Abstract method."))
629 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
633 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
635 (defclass efc-list (efc-collection)
636 ((items :initarg :items
639 :documentation "List of items."))
642 (defmethod initialize-instance ((this efc-list) &rest fields)
643 "Iterator constructor."
646 (defmethod efc-coll-add ((this efc-list) item)
647 "Adds an item to the list."
648 (if (efc-coll-type-compatible-p this item)
649 (oset this items (append (oref this items) (list item)))
650 (error "Tried to add an item of type %s to a list of items of type %s"
651 (typep item) (oref this elem-type))))
653 (defmethod efc-coll-iterator ((this efc-list))
654 "Return an iterator for this list."
655 (efc-list-iterator "list iterator" :list-obj this))
658 (defmethod efc-coll-memberp ((this efc-list) item)
659 "Returns nonil if this list contains item."
660 (member item (oref this items)))
662 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
664 ;; List Iterator Class ;;
666 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
668 (defclass efc-list-iterator (efc-iterator)
669 ((list-obj :initarg :list-obj
671 :documentation "List that this iterator iterates.")
673 :documentation "Lisp list."))
674 "Iterates over a list.")
676 (defmethod initialize-instance ((this efc-list-iterator) &rest fields)
677 "Iterator constructor."
679 (assert (oref this list-obj))
680 (assert (typep (oref this list-obj) efc-list))
681 (oset this list (oref (oref this list-obj) items)))
683 (defmethod efc-iter-has-next ((this efc-list-iterator))
684 "Returns true if this iterator has another list item to return."
687 (defmethod efc-iter-next ((this efc-list-iterator))
688 "Get next item in the list."
689 (let* ((list (oref this list))
691 (oset this list (cdr list))
695 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
699 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
700 (defclass efc-list-set (efc-list)
702 "List that contains no duplicates.")
705 (defmethod efc-coll-add ((this efc-list-set) item)
706 "Adds an item to a set only if the set does not
707 already contain the item."
708 (if (efc-coll-memberp this item)
709 (error "This set already contains %s" item)
714 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
716 ;; Association Class ;;
718 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
719 (defclass efc-assoc (efc-list)
723 (defmethod efc-coll-put ((this efc-assoc) key value)
724 "Put an item into the association list."
725 (oset this items (append (oref this items) (list (cons key value)))))
727 (defmethod efc-coll-get ((this efc-assoc) key)
728 "Get an item from the association list."
729 (cdr (assq key (oref this items))))
732 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
734 ;; Association Set Class ;;
736 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
737 (defclass efc-assoc-set (efc-assoc)
739 "Association that contains no duplicate keys.")
741 (defmethod efc-coll-put ((this efc-assoc-set) key value)
742 "Adds an item to a set only if the set does not
743 already contain the item."
744 (if (efc-coll-get this key)
745 (error "This set already contains %s" key)
749 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
751 ;; Hash Table Class ;;
753 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
754 (defclass efc-hash-table (efc-collection)
755 ((table :type hash-table
756 :documentation "Lisp table object."))
760 (defmethod initialize-instance ((this efc-hash-table) &rest fields)
761 "Hash table constructor."
763 (oset table (make-hash-table)))
765 (defmethod efc-coll-put ((this efc-hash-table) key value)
766 "Put an item into the table."
767 (if (efc-coll-type-compatible-p this value)
768 (puthash key value (oref this table))
769 (error "Tried to add an item of type %s to a hash table of items of type %s"
770 (typep value) (oref this elem-type))))
772 (defmethod efc-coll-get ((this efc-hash-table) key)
773 "Get an item from the table."
774 (gethash key (oref this table)))
776 (defmethod efc-coll-visit ((this efc-hash-table) visitor)
777 "Visit each item in the hash table. VISITOR is an instance
778 of efc-visitor class."
781 (efc-visitor-visit visitor value))
784 (defmethod efc-coll-iterator ((this efc-hash-table))
785 "Return an iterator for this hash table."
787 "hash table iterator"
788 :list-obj (let (values)
791 (setq values (append values (list value))))
801 ;; $Log: efc.el.upstream,v $
802 ;; Revision 1.1 2007-11-26 15:16:44 michaels
803 ;; Update jde to author version 2.3.5.1.
805 ;; Revision 1.18 2005/03/19 03:50:31 paulk
806 ;; Define an association set.
808 ;; Revision 1.17 2005/03/18 04:53:14 paulk
809 ;; Define a set of collection classes.
811 ;; Revision 1.16 2004/12/10 03:38:04 paulk
812 ;; Fix efc-compiler to make and set a buffer-local version of compilation-finish-function.
813 ;; Thanks To David Evers.
815 ;; Revision 1.15 2004/07/01 14:04:39 jslopez
816 ;; Compatibility fix for emacs in CVS. Replaces jde-xemacsp check for boundp for
817 ;; the following variables: compilation-nomessage-regexp-alist,
818 ;; compilation-file-regexp-alist, compilation-leave-directory-regexp-alist,
819 ;; compilation-enter-directory-regexp-alist. Uses the compilation-mode without a
820 ;; parameter. The emacs in CVS does not contain the variables, or the parameter
821 ;; for compilation mode.
823 ;; Revision 1.14 2004/03/16 07:42:09 paulk
824 ;; Define new efc-multi-option-dialog. Thanks to Philip Lord.
826 ;; Revision 1.13 2003/11/29 05:50:18 paulk
827 ;; The efc-dialog-show method ofr efc-option-dialog now uses save-window-excursion
828 ;; to restore the user's original window conversion after showing the selection
831 ;; Revision 1.12 2003/08/25 04:57:30 paulk
832 ;; Adds efc-compiler class. This class implements an Emacs interface to an external process
833 ;; that generates compiler-like output.
835 ;; Revision 1.11 2003/06/07 04:04:10 paulk
836 ;; Fix regexp for matching Emacs versions. Thanks to David Ponce.
838 ;; Revision 1.10 2003/03/28 05:33:29 andyp
839 ;; XEmacs optimizations for JDEbug and efc.
841 ;; Revision 1.9 2002/03/29 12:40:27 paulk
842 ;; Adds efc-query-option function.
844 ;; Revision 1.8 2002/03/19 12:24:47 paulk
845 ;; Updated live-window error patch to work for Emacs 21.2.
847 ;; Revision 1.7 2002/02/21 05:35:39 paulk
848 ;; efc-dialog class now creates the dialog buffer in
849 ;; the efc-dialog-show method instead of in the
850 ;; intialize-instance method. This permits reuse
851 ;; of the dialog buffer object and hence persistance
852 ;; of user settings in the dialog.
854 ;; Revision 1.6 2002/01/25 10:41:55 paulk
855 ;; Fixes Lisp error: (wrong-type-argument window-live-p #<window 66>) that
856 ;; occurs in Emacs 21.1.1 when the user clicks an efc dialog box button.
858 ;; Revision 1.5 2002/01/06 06:54:06 paulk
859 ;; Finally found a fix for the efc dialog class that works around
860 ;; the delete-other-windows bug in Emacs 21.
862 ;; Revision 1.4 2001/12/04 14:45:55 jslopez
863 ;; Change jde-xemacs for (featurep 'xemacs).
865 ;; Revision 1.3 2001/12/04 12:32:34 jslopez
866 ;; Fixes typo (efc-xemacsp to jde-xemacsp).
868 ;; Revision 1.2 2001/12/04 06:06:34 paulk
869 ;; Remove carriage returns.
871 ;; Revision 1.1 2001/12/04 05:23:20 paulk