1;;; wid-browse.el --- functions for browsing widgets 2;; 3;; Copyright (C) 1997, 2001, 2002, 2003, 2004, 2005, 4;; 2006, 2007 Free Software Foundation, Inc. 5;; 6;; Author: Per Abrahamsen <abraham@dina.kvl.dk> 7;; Keywords: extensions 8 9;; This file is part of GNU Emacs. 10 11;; GNU Emacs is free software; you can redistribute it and/or modify 12;; it under the terms of the GNU General Public License as published by 13;; the Free Software Foundation; either version 2, or (at your option) 14;; any later version. 15 16;; GNU Emacs is distributed in the hope that it will be useful, 17;; but WITHOUT ANY WARRANTY; without even the implied warranty of 18;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19;; GNU General Public License for more details. 20 21;; You should have received a copy of the GNU General Public License 22;; along with GNU Emacs; see the file COPYING. If not, write to the 23;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 24;; Boston, MA 02110-1301, USA. 25 26;;; Commentary: 27;; 28;; Widget browser. See `widget.el'. 29 30;;; Code: 31 32(require 'easymenu) 33(require 'custom) 34(require 'wid-edit) 35(eval-when-compile (require 'cl)) 36 37(defgroup widget-browse nil 38 "Customization support for browsing widgets." 39 :group 'widgets) 40 41;;; The Mode. 42 43(defvar widget-browse-mode-map nil 44 "Keymap for `widget-browse-mode'.") 45 46(unless widget-browse-mode-map 47 (setq widget-browse-mode-map (make-sparse-keymap)) 48 (set-keymap-parent widget-browse-mode-map widget-keymap) 49 (define-key widget-browse-mode-map "q" 'bury-buffer)) 50 51(easy-menu-define widget-browse-mode-customize-menu 52 widget-browse-mode-map 53 "Menu used in widget browser buffers." 54 (customize-menu-create 'widgets)) 55 56(easy-menu-define widget-browse-mode-menu 57 widget-browse-mode-map 58 "Menu used in widget browser buffers." 59 '("Widget" 60 ["Browse" widget-browse t] 61 ["Browse At" widget-browse-at t])) 62 63(defcustom widget-browse-mode-hook nil 64 "Hook called when entering widget-browse-mode." 65 :type 'hook 66 :group 'widget-browse) 67 68(defun widget-browse-mode () 69 "Major mode for widget browser buffers. 70 71The following commands are available: 72 73\\[widget-forward] Move to next button or editable field. 74\\[widget-backward] Move to previous button or editable field. 75\\[widget-button-click] Activate button under the mouse pointer. 76\\[widget-button-press] Activate button under point. 77 78Entry to this mode calls the value of `widget-browse-mode-hook' 79if that value is non-nil." 80 (kill-all-local-variables) 81 (setq major-mode 'widget-browse-mode 82 mode-name "Widget") 83 (use-local-map widget-browse-mode-map) 84 (easy-menu-add widget-browse-mode-customize-menu) 85 (easy-menu-add widget-browse-mode-menu) 86 (run-mode-hooks 'widget-browse-mode-hook)) 87 88(put 'widget-browse-mode 'mode-class 'special) 89 90;;; Commands. 91 92;;;###autoload 93(defun widget-browse-at (pos) 94 "Browse the widget under point." 95 (interactive "d") 96 (let* ((field (get-char-property pos 'field)) 97 (button (get-char-property pos 'button)) 98 (doc (get-char-property pos 'widget-doc)) 99 (text (cond (field "This is an editable text area.") 100 (button "This is an active area.") 101 (doc "This is documentation text.") 102 (t "This is unidentified text."))) 103 (widget (or field button doc))) 104 (when widget 105 (widget-browse widget)) 106 (message text))) 107 108(defvar widget-browse-history nil) 109 110;;;###autoload 111(defun widget-browse (widget) 112 "Create a widget browser for WIDGET." 113 (interactive (list (completing-read "Widget: " 114 obarray 115 (lambda (symbol) 116 (get symbol 'widget-type)) 117 t nil 'widget-browse-history))) 118 (if (stringp widget) 119 (setq widget (intern widget))) 120 (unless (if (symbolp widget) 121 (get widget 'widget-type) 122 (and (consp widget) 123 (get (widget-type widget) 'widget-type))) 124 (error "Not a widget")) 125 ;; Create the buffer. 126 (if (symbolp widget) 127 (let ((buffer (format "*Browse %s Widget*" widget))) 128 (kill-buffer (get-buffer-create buffer)) 129 (switch-to-buffer (get-buffer-create buffer))) 130 (kill-buffer (get-buffer-create "*Browse Widget*")) 131 (switch-to-buffer (get-buffer-create "*Browse Widget*"))) 132 (widget-browse-mode) 133 134 ;; Quick way to get out. 135;; (widget-create 'push-button 136;; :action (lambda (widget &optional event) 137;; (bury-buffer)) 138;; "Quit") 139;; (widget-insert "\n") 140 141 ;; Top text indicating whether it is a class or object browser. 142 (if (listp widget) 143 (widget-insert "Widget object browser.\n\nClass: ") 144 (widget-insert "Widget class browser.\n\n") 145 (widget-create 'widget-browse 146 :format "%[%v%]\n%d" 147 :doc (get widget 'widget-documentation) 148 widget) 149 (unless (eq (preceding-char) ?\n) 150 (widget-insert "\n")) 151 (widget-insert "\nSuper: ") 152 (setq widget (get widget 'widget-type))) 153 154 ;; Now show the attributes. 155 (let ((name (car widget)) 156 (items (cdr widget)) 157 key value printer) 158 (widget-create 'widget-browse 159 :format "%[%v%]" 160 name) 161 (widget-insert "\n") 162 (while items 163 (setq key (nth 0 items) 164 value (nth 1 items) 165 printer (or (get key 'widget-keyword-printer) 166 'widget-browse-sexp) 167 items (cdr (cdr items))) 168 (widget-insert "\n" (symbol-name key) "\n\t") 169 (funcall printer widget key value) 170 (widget-insert "\n"))) 171 (widget-setup) 172 (goto-char (point-min))) 173 174;;;###autoload 175(defun widget-browse-other-window (&optional widget) 176 "Show widget browser for WIDGET in other window." 177 (interactive) 178 (let ((window (selected-window))) 179 (switch-to-buffer-other-window "*Browse Widget*") 180 (if widget 181 (widget-browse widget) 182 (call-interactively 'widget-browse)) 183 (select-window window))) 184 185 186;;; The `widget-browse' Widget. 187 188(define-widget 'widget-browse 'push-button 189 "Button for creating a widget browser. 190The :value of the widget shuld be the widget to be browsed." 191 :format "%[[%v]%]" 192 :value-create 'widget-browse-value-create 193 :action 'widget-browse-action) 194 195(defun widget-browse-action (widget &optional event) 196 ;; Create widget browser for WIDGET's :value. 197 (widget-browse (widget-get widget :value))) 198 199(defun widget-browse-value-create (widget) 200 ;; Insert type name. 201 (let ((value (widget-get widget :value))) 202 (cond ((symbolp value) 203 (insert (symbol-name value))) 204 ((consp value) 205 (insert (symbol-name (widget-type value)))) 206 (t 207 (insert "strange"))))) 208 209;;; Keyword Printer Functions. 210 211(defun widget-browse-widget (widget key value) 212 "Insert description of WIDGET's KEY VALUE. 213VALUE is assumed to be a widget." 214 (widget-create 'widget-browse value)) 215 216(defun widget-browse-widgets (widget key value) 217 "Insert description of WIDGET's KEY VALUE. 218VALUE is assumed to be a list of widgets." 219 (while value 220 (widget-create 'widget-browse 221 (car value)) 222 (setq value (cdr value)) 223 (when value 224 (widget-insert " ")))) 225 226(defun widget-browse-sexp (widget key value) 227 "Insert description of WIDGET's KEY VALUE. 228Nothing is assumed about value." 229 (let ((pp (condition-case signal 230 (pp-to-string value) 231 (error (prin1-to-string signal))))) 232 (when (string-match "\n\\'" pp) 233 (setq pp (substring pp 0 (1- (length pp))))) 234 (if (cond ((string-match "\n" pp) 235 nil) 236 ((> (length pp) (- (window-width) (current-column))) 237 nil) 238 (t t)) 239 (widget-insert pp) 240 (widget-create 'push-button 241 :tag "show" 242 :action (lambda (widget &optional event) 243 (with-output-to-temp-buffer 244 "*Pp Eval Output*" 245 (princ (widget-get widget :value)))) 246 pp)))) 247 248(defun widget-browse-sexps (widget key value) 249 "Insert description of WIDGET's KEY VALUE. 250VALUE is assumed to be a list of widgets." 251 (let ((target (current-column))) 252 (while value 253 (widget-browse-sexp widget key (car value)) 254 (setq value (cdr value)) 255 (when value 256 (widget-insert "\n" (make-string target ?\ )))))) 257 258;;; Keyword Printers. 259 260(put :parent 'widget-keyword-printer 'widget-browse-widget) 261(put :children 'widget-keyword-printer 'widget-browse-widgets) 262(put :buttons 'widget-keyword-printer 'widget-browse-widgets) 263(put :button 'widget-keyword-printer 'widget-browse-widget) 264(put :args 'widget-keyword-printer 'widget-browse-sexps) 265 266;;; Widget Minor Mode. 267 268(defvar widget-minor-mode nil 269 "If non-nil, we are in Widget Minor Mode.") 270(make-variable-buffer-local 'widget-minor-mode) 271 272(defvar widget-minor-mode-map nil 273 "Keymap used in Widget Minor Mode.") 274 275(unless widget-minor-mode-map 276 (setq widget-minor-mode-map (make-sparse-keymap)) 277 (set-keymap-parent widget-minor-mode-map widget-keymap)) 278 279;;;###autoload 280(defun widget-minor-mode (&optional arg) 281 "Togle minor mode for traversing widgets. 282With arg, turn widget mode on if and only if arg is positive." 283 (interactive "P") 284 (cond ((null arg) 285 (setq widget-minor-mode (not widget-minor-mode))) 286 ((<= arg 0) 287 (setq widget-minor-mode nil)) 288 (t 289 (setq widget-minor-mode t))) 290 (force-mode-line-update)) 291 292(add-to-list 'minor-mode-alist '(widget-minor-mode " Widget")) 293 294(add-to-list 'minor-mode-map-alist 295 (cons 'widget-minor-mode widget-minor-mode-map)) 296 297;;; The End: 298 299(provide 'wid-browse) 300 301;;; arch-tag: d5ffb18f-8984-4735-8502-edf70456db21 302;;; wid-browse.el ends here 303