Mercurial > hg > xemacs-beta
diff lisp/hyperbole/hui-mini.el @ 0:376386a54a3c r19-14
Import from CVS: tag r19-14
author | cvs |
---|---|
date | Mon, 13 Aug 2007 08:45:50 +0200 |
parents | |
children | 4103f0995bd7 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lisp/hyperbole/hui-mini.el Mon Aug 13 08:45:50 2007 +0200 @@ -0,0 +1,507 @@ +;;!emacs +;; +;; FILE: hui-mini.el +;; SUMMARY: One line command menus for Hyperbole +;; USAGE: GNU Emacs Lisp Library +;; KEYWORDS: hypermedia, mouse +;; +;; AUTHOR: Bob Weiner +;; ORG: Brown U. +;; +;; ORIG-DATE: 15-Oct-91 at 20:13:17 +;; LAST-MOD: 3-Nov-95 at 04:02:02 by Bob Weiner +;; +;; This file is part of Hyperbole. +;; Available for use and distribution under the same terms as GNU Emacs. +;; +;; Copyright (C) 1991-1995, Free Software Foundation, Inc. +;; Developed with support from Motorola Inc. +;; +;; DESCRIPTION: +;; DESCRIP-END. + +;;; ************************************************************************ +;;; Other required Elisp libraries +;;; ************************************************************************ + +(require 'hypb) + +;;; ************************************************************************ +;;; Public variables +;;; ************************************************************************ + +(defvar hui:menu-select "\C-m" + "*Upper case char-string which selects the Hyperbole menu item at point.") +(defvar hui:menu-quit "Q" + "*Upper case char-string which quits selecting from a Hyperbole menu item.") +(defvar hui:menu-abort "\C-g" + "*Same function as 'hui:menu-quit'.") +(defvar hui:menu-top "\C-t" + "*Character which returns to top Hyperbole menu.") + +(defvar hui:menu-p nil + "Non-nil iff a current Hyperbole menu activation exists.") + +(defvar hui:menus nil + "Command menus for use with the default Hyperbole user interface.") +(setq + hui:menus + (delq nil + (list (cons + 'hyperbole + (append + (let ((version (if (= (aref hyperb:version 0) ?0) + (substring hyperb:version 1) + hyperb:version))) + (list (list (concat "Hy" version ">")))) + (delq nil + (list + '("Act" hui:hbut-act + "Activates button at point or prompts for explicit button.") + '("Butfile/" (menu . butfile) + "Quick access button files menus.") + '("Doc/" (menu . doc) + "Quick access to Hyperbole documentation.") + '("Ebut/" (menu . ebut) + "Explicit button commands.") + '("Gbut/" (menu . gbut) + "Global button commands.") + '("Hist" (hhist:remove current-prefix-arg) + "Jumps back to location prior to last Hyperbole button follow.") + '("Ibut/" (menu . ibut) + "Implicit button and button type commands.") + '("Msg/" (menu . msg) + "Mail and News messaging facilities.") + (if hyperb:kotl-p + '("Otl/" (menu . otl) + "Autonumbered outlining and hyper-node facilities.")) + '("Rolo/" (menu . rolo) + "Hierarchical, multi-file rolodex lookup and edit commands.") + '("Win/" (menu . win) + "Window configuration management command.") + )))) + '(butfile . + (("Butfile>") + ("DirFile" (find-file hbmap:filename) + "Edits directory-specific button file.") + ("Info" + (id-info "(hyperbole.info)Button Files") + "Displays manual section on button files.") + ("PersonalFile" (find-file + (expand-file-name hbmap:filename hbmap:dir-user)) + "Edits user-specific button file.") + )) + '(doc . + (("Doc>") + ("Demo" (find-file-read-only + (expand-file-name "DEMO" hyperb:dir)) + "Demonstrates Hyperbole features.") + ("Files" (find-file-read-only + (expand-file-name "MANIFEST" hyperb:dir)) + "Summarizes Hyperbole system files. Click on an entry to view it.") + ("Glossary" + (id-info "(hyperbole.info)Glossary") + "Glossary of Hyperbole terms.") + ("HypbCopy" (id-info "(hyperbole.info)Top") + "Displays general Hyperbole copyright and license details.") + ("Info" (id-info "(hyperbole.info)Top") + "Online Info version of Hyperbole manual.") + ("MailLists" (id-info "(hyperbole.info)Mail Lists") + "Details on Hyperbole mail list subscriptions.") + ("New" (progn + (hact 'link-to-regexp-match + "\\*[ \t]+What's New" 2 + (expand-file-name "README" hyperb:dir)) + (setq buffer-read-only nil) + (toggle-read-only)) + "Recent changes to Hyperbole.") + ("SmartKy" (find-file-read-only (hypb:mouse-help-file)) + "Summarizes Smart Key mouse or keyboard handling.") + ("Types/" (menu . types) + "Provides documentation on Hyperbole types.") + )) + '(ebut . + (("EButton>") + ("Act" hui:hbut-act + "Activates button at point or prompts for explicit button.") + ("Create" hui:ebut-create) + ("Delete" hui:ebut-delete) + ("Edit" hui:ebut-modify "Modifies any desired button attributes.") + ("Help/" (menu . ebut-help) "Summarizes button attributes.") + ("Info" + (id-info "(hyperbole.info)Explicit Buttons") + "Displays manual section on explicit buttons.") + ("Modify" hui:ebut-modify "Modifies any desired button attributes.") + ("Rename" hui:ebut-rename "Relabels an explicit button.") + ("Search" hui:ebut-search + "Locates and displays personally created buttons in context.") + )) + '(ebut-help . + (("Help on>") + ("BufferButs" (hui:hbut-report -1) + "Summarizes all explicit buttons in buffer.") + ("CurrentBut" (hui:hbut-report) + "Summarizes only current button in buffer.") + ("OrderedButs" (hui:hbut-report 1) + "Summarizes explicit buttons in lexicographically order.") + )) + '(gbut . + (("GButton>") + ("Act" gbut:act "Activates global button by name.") + ("Create" hui:gbut-create "Adds a global button to gbut:file.") + ("Edit" hui:gbut-modify "Modifies global button attributes.") + ("Help" gbut:help "Reports on a global button by name.") + ("Info" (id-info "(hyperbole.info)Global Buttons") + "Displays manual section on global buttons.") + ("Modify" hui:gbut-modify "Modifies global button attributes.") + )) + '(ibut . + (("IButton>") + ("Act" hui:hbut-act "Activates implicit button at point.") + ("DeleteIButType" (hui:htype-delete 'ibtypes) + "Deletes specified button type.") + ("Help" hui:hbut-help "Reports on button's attributes.") + ("Info" (id-info "(hyperbole.info)Implicit Buttons") + "Displays manual section on implicit buttons.") + ("Types" (hui:htype-help 'ibtypes 'no-sort) + "Displays documentation for one or all implicit button types.") + )) + '(msg . + (("Msg>") + ("Compose-Hypb-Mail" + (hmail:compose "hyperbole@hub.ucsb.edu" '(hact 'hyp-config)) + "Send a message to the Hyperbole discussion list.") + ("Edit-Hypb-List-Entry" + (hmail:compose "hyperbole-request@hub.ucsb.edu" + '(hact 'hyp-request)) + "Add, remove or change your entry on a the Hyperbole mail list.") + ("Modify-Hypb-Announce-Entry" + (hmail:compose "hyperbole-announce-request@hub.ucsb.edu" + '(hact 'hyp-request)) + "Add, remove or change your entry on the Hyperbole Announce mail list.") + )) + (if hyperb:kotl-p + '(otl + . (("Otl>") + ("All" kotl-mode:show-all "Expand all collapsed cells.") + ("Blanks" kvspec:toggle-blank-lines + "Toggle blank lines between cells on or off.") + ("Create" kfile:find "Create or edit an outline file.") + ("Downto" kotl-mode:hide-sublevels + "Hide all cells in outline deeper than a particular level.") + ("Examp" (find-file-read-only + (expand-file-name + "EXAMPLE.kotl" (concat hyperb:dir "kotl/"))) + "Display a self-descriptive example outline file.") + ("Hide" (progn (kotl-mode:is-p) + (kotl-mode:hide-tree (kcell-view:label))) + "Collapse tree rooted at point.") + ("Info" + (id-info "(hyperbole.info)Outliner") + "Display manual section on Hyperbole outliner.") + ("Kill" kotl-mode:kill-tree + "Kill ARG following trees starting from point.") + ("Link" klink:create + "Create and insert an implicit link at point.") + ("Overvw" kotl-mode:overview + "Show first line of each cell.") + ("Show" (progn (kotl-mode:is-p) + (kotl-mode:show-tree (kcell-view:label))) + "Expand tree rooted at point.") + ("Top" kotl-mode:top-cells + "Hide all but top-level cells.") + ("Vspec" kvspec:activate + "Prompt for and activate a view specifiction.") + ))) + '(rolo . + (("Rolo>") + ("Add" rolo-add "Add a new rolo entry.") + ("Display" rolo-display-matches + "Display last found rolodex matches again.") + ("Edit" rolo-edit "Edit an existing rolo entry.") + ("Info" (id-info "(hyperbole.info)Rolodex") + "Displays manual section on Hyperbole rolodex.") + ("Kill" rolo-kill "Kill an existing rolo entry.") + ("Mail" rolo-mail-to "Mail to address following point.") + ("Order" rolo-sort "Order rolo entries in a file.") + ("RegexFind" rolo-grep "Find entries containing a regexp.") + ("StringFind" rolo-fgrep "Find entries containing a string.") + ("WordFind" rolo-word "Find entries containing words.") + ("Yank" rolo-yank + "Find an entry containing a string and insert it at point.") + )) + '(types . + (("Types>") + ("ActionTypes" (hui:htype-help 'actypes) + "Displays documentation for one or all action types.") + ("IButTypes" (hui:htype-help 'ibtypes 'no-sort) + "Displays documentation for one or all implicit button types.") + )) + '(win . + (("WinConfig>") + ("AddName" wconfig-add-by-name + "Name current window configuration.") + ("DeleteName" wconfig-delete-by-name + "Delete named window configuration.") + ("RestoreName" wconfig-restore-by-name + "Restore frame to window configuration given by name.") + ("PopRing" (progn (wconfig-delete-pop) + (hyperbole 'win)) + "Restores window configuration from ring and removes it from ring.") + ("SaveRing" (wconfig-ring-save) + "Saves current window configuration to ring.") + ("YankRing" (progn (call-interactively 'wconfig-yank-pop) + (hyperbole 'win)) + "Restores next window configuration from ring.") + )) + ))) + +;;; ************************************************************************ +;;; Public functions +;;; ************************************************************************ + +;;; Old name +(fset 'hui:menu 'hyperbole) + +;;; Used as autoloaded main entry point to Hyperbole (but hsite.el) is the +;;; file that is autoloaded when this is invoked. +;;; It brings up a menu of commands. +(defun hyperbole (&optional menu menu-list) + "Invokes default Hyperbole menu user interface when not already active. +Suitable for binding to a key, e.g. {C-h h}. +Non-interactively, returns t if menu is actually invoked by call, else nil. + +Two optional arguments may be given to invoke alternative menus. +MENU (a symbol) specifies the menu to invoke from MENU-LIST, (a +Hyperbole menu list structure). MENU defaults to 'hyperbole and MENU-LIST +to `hui:menus'. See `hui:menus' definition for the format of the menu list +structure." + + (interactive) + (if (and hui:menu-p (> (minibuffer-depth) 0)) + (progn (beep) nil) + (unwind-protect + (progn + (require 'hsite) ;; Since "hui-mini" may be loaded without loading + ;; all of Hyperbole. + (hyperb:init-menubar) + (setq hui:menu-p t) + (hui:menu-act (or menu 'hyperbole) menu-list) + t) + (setq hui:menu-p nil)))) + +(defun hui:menu-act (menu &optional menu-list) + "Prompts user with Hyperbole MENU (a symbol) and performs selected item. +Optional second argument MENU-LIST is a Hyperbole menu list structure from +which to extract MENU. It defaults to `hui:menus'. See its definition for +the menu list structure." + (let ((set-menu '(or (and menu (symbolp menu) + (setq menu-alist + (cdr (assq menu (or menu-list hui:menus))))) + (hypb:error "(menu-act): Invalid menu symbol arg: %s" + menu))) + (show-menu t) + (rtn) + menu-alist act-form) + (while (and show-menu (eval set-menu)) + (cond ((and (consp (setq act-form (hui:menu-select menu-alist))) + (cdr act-form) + (symbolp (cdr act-form))) + ;; Display another menu + (setq menu (cdr act-form))) + (act-form + (let ((prefix-arg current-prefix-arg)) + (cond ((symbolp act-form) + (if (eq act-form t) + nil + (setq show-menu nil + rtn (call-interactively act-form)))) + ((stringp act-form) + (hui:menu-help act-form) + ;; Loop and show menu again. + ) + (t (setq show-menu nil + rtn (eval act-form)))))) + (t (setq show-menu nil)))) + rtn)) + +(defun hui:menu-enter (&optional char-str) + "Uses CHAR-STR or last input character as minibuffer argument." + (interactive) + (let ((input (or char-str (aref (recent-keys) (1- (length (recent-keys))))))) + (cond (hyperb:emacs19-p + (and (not (integerp input)) + (eventp input) + (setq input (event-basic-type input)))) + (hyperb:lemacs-p + (if (eventp input) + (setq input (event-to-character input))))) + (if (or (symbolp input) + (and (integerp input) + (= input ?\r))) + (setq input (hargs:at-p))) + (erase-buffer) + (or (symbolp input) (insert input))) + (exit-minibuffer)) + +(defun hui:menu-help (help-str) + "Displays HELP-STR in a small window. HELP-STR must be a string." + (let* ((window-min-height 2) + (owind (selected-window)) + (buf-name (hypb:help-buf-name "Menu"))) + (unwind-protect + (progn + (save-window-excursion + (hkey-help-show buf-name)) ;; Needed to save wconfig. + (if (eq (selected-window) (minibuffer-window)) + (other-window 1)) + (if (= (length (hypb:window-list 'no-mini)) 1) + (split-window-vertically nil)) + (select-window (hui:bottom-window)) + (switch-to-buffer (get-buffer-create buf-name)) + (setq buffer-read-only nil) + (erase-buffer) + (insert "\n" help-str) + (set-buffer-modified-p nil) + (shrink-window + (- (window-height) + (+ 3 (length + (delq nil + (mapcar (function + (lambda (chr) (= chr ?\n))) + help-str))))))) + (select-window owind)))) + +(defun hui:menu-xemacs (&optional menu menu-list) + "Returns an XEmacs menu built from Hyperbole type menus. +Optional MENU (a symbol) specifies a specific submenu of optional MENU-LIST. +a Hyperbole menu list structure. Otherwise, all menus are used. +MENU defaults to 'hyperbole and MENU-LIST to `hui:menus'. See `hui:menus' +definition for the format of the menu list structure." + (mapcar + (function + (lambda (entry) + (or (consp entry) + (error "(hui:menu-xemacs): Invalid menu entry: %s" entry)) + (let ((label (car entry)) + (content (car (cdr entry)))) + (cond ((null content) (hypb:replace-match-string ">$" label "" t)) + ((and (consp content) (eq (car content) 'menu)) + (hui:menu-xemacs (cdr content))) + (t (vector label content 't)))))) + (cdr (assq (or menu 'hyperbole) (or menu-list hui:menus))))) + +(defun hui:menu-select (menu-alist) + "Prompts user to choose the first character of any item from MENU-ALIST. +Case is not significant. If chosen by direct selection with the Assist Key, +returns any help string for item, else returns the action form for the item." + (let* ((menu-line (hui:menu-line menu-alist)) + (set:equal-op 'eq) + (select-char (string-to-char hui:menu-select)) + (quit-char (string-to-char hui:menu-quit)) + (abort-char (string-to-char hui:menu-abort)) + (top-char (string-to-char hui:menu-top)) + (item-keys (mapcar (function + (lambda (item) (aref item 0))) + (mapcar 'car (cdr menu-alist)))) + (keys (apply 'list select-char quit-char abort-char + top-char item-keys)) + (key 0) + (hargs:reading-p 'hmenu) + sublist) + (while (not (memq (setq key (upcase + (string-to-char + (read-from-minibuffer + "" menu-line hui:menu-mode-map)))) + keys)) + (beep) + (setq hargs:reading-p 'hmenu) + (discard-input)) + (cond ((eq key quit-char) nil) + ((eq key abort-char) (beep) nil) + ((eq key top-char) '(menu . hyperbole)) + ((and (eq key select-char) + (save-excursion + (if (search-backward " " nil t) + (progn (skip-chars-forward " ") + (setq key (following-char)) + nil) ;; Drop through. + t)))) + (t (if (setq sublist (memq key item-keys)) + (let* ((label-act-help-list + (nth (- (1+ (length item-keys)) (length sublist)) + menu-alist)) + (act-form (car (cdr label-act-help-list)))) + (if (eq hargs:reading-p 'hmenu-help) + (let ((help-str + (or (car (cdr (cdr label-act-help-list))) + "No help documentation for this item."))) + (concat (car label-act-help-list) "\n " + help-str "\n Action: " + (prin1-to-string act-form))) + act-form))))))) + +;;; ************************************************************************ +;;; Private functions +;;; ************************************************************************ + +(if (fboundp 'window-lowest-p) + (defun hui:bottom-window () + "Return a window that is at the bottom of the selected frame." + (let ((winds (hypb:window-list 'no-mini)) + (window)) + (while (and (not window) winds) + (if (window-lowest-p (car winds)) + (setq window (car winds)) + (setq winds (cdr winds)))) + window)) + (defun hui:bottom-window () + "Return a window that is at the bottom of the selected frame." + (let* ((winds (hypb:window-list 'no-mini)) + (bot-list (mapcar + (function + (lambda (wind) + (nth 3 (window-edges wind)))) + winds)) + (bot (apply 'max bot-list))) + (nth (- (length winds) (length (memq bot bot-list))) winds)))) + +(defun hui:menu-line (menu-alist) + "Returns a menu line string built from MENU-ALIST." + (let ((menu-prompt (concat (car (car menu-alist)) " ")) + (menu-items (mapconcat 'car (cdr menu-alist) " ")) + menu-line) + (setq menu-line (concat menu-prompt menu-items)) + ;; Narrow menu by changing 2 spaces to 1 if too wide for current frame. + (if (>= (length menu-line) (1- (frame-width))) + (concat menu-prompt (mapconcat 'car (cdr menu-alist) " ")) + menu-line))) + +;;; ************************************************************************ +;;; Private variables +;;; ************************************************************************ + +;; Hyperbole menu mode is suitable only for specially formatted data. +(put 'hui:menu-mode 'mode-class 'special) + +(defvar hui:menu-mode-map nil + "Keymap containing hui:menu commands.") +(if hui:menu-mode-map + nil + (setq hui:menu-mode-map (make-keymap)) + (suppress-keymap hui:menu-mode-map) + (define-key hui:menu-mode-map hui:menu-quit 'hui:menu-enter) + (define-key hui:menu-mode-map hui:menu-abort 'hui:menu-enter) + (define-key hui:menu-mode-map hui:menu-top 'hui:menu-enter) + (define-key hui:menu-mode-map hui:menu-select 'hui:menu-enter) + ;; + ;; This next binding is necessary since the default button1 binding under + ;; XEmacs, mouse-track, is broken under XEmacs V19.8. + (and hyperb:lemacs-p window-system + (define-key hui:menu-mode-map 'button1 'mouse-set-point)) + (let ((i 32)) + (while (<= i 126) + (define-key hui:menu-mode-map (char-to-string i) 'hui:menu-enter) + (setq i (1+ i))))) + +(provide 'hui-mini)