From 94d2fc1815a919734353c942f224db1de4b4fcb8 Mon Sep 17 00:00:00 2001 From: Tom Willemsen Date: Mon, 7 Mar 2011 09:04:49 +0100 Subject: Django, org * Added nxhtml, mostly for django support. * Changed some org settings. --- emacs.d/nxhtml/util/appmenu.el | 523 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 523 insertions(+) create mode 100644 emacs.d/nxhtml/util/appmenu.el (limited to 'emacs.d/nxhtml/util/appmenu.el') diff --git a/emacs.d/nxhtml/util/appmenu.el b/emacs.d/nxhtml/util/appmenu.el new file mode 100644 index 0000000..1f060ef --- /dev/null +++ b/emacs.d/nxhtml/util/appmenu.el @@ -0,0 +1,523 @@ +;;; appmenu.el --- A framework for [apps] popup menus. + +;; Copyright (C) 2008 by Lennart Borgman + +;; Author: Lennart Borgman +;; Created: Thu Jan 05 14:00:26 2006 +(defconst appmenu:version "0.63") ;; Version: +;; Last-Updated: 2010-01-04 Mon +;; Keywords: +;; Compatibility: +;; +;; Features that might be required by this library: +;; +;; None +;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;;; Commentary: +;; +;; appmenu.el is a framework for creating cooperative context +;; sensitive popup menus with commands from different major and minor +;; modes. For more information see `appmenu-mode'. +;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;;; Change log: +;; +;; Version 0.61: +;; - Remove support for minor and major menus. +;; - Add support for text and overlay keymaps. +;; - Add customization options. +;; +;; Version 0.62: +;; - Fix problem with keymap at point. +;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 2, or (at your option) +;; any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with this program; see the file COPYING. If not, write to the +;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, +;; Boston, MA 02111-1307, USA. +;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;;; Code: + +(eval-when-compile (require 'cl)) +(eval-when-compile (require 'flyspell)) +(eval-when-compile (require 'help-mode)) +(eval-when-compile (require 'ourcomments-util nil t)) +(eval-when-compile (require 'mumamo nil t)) +;;(eval-when-compile (require 'mlinks nil t)) + +;;;###autoload +(defgroup appmenu nil + "Customization group for `appmenu-mode'." + :group 'convenience) + +(defcustom appmenu-show-help nil + "Non-nil means show AppMenu help on AppMenu popup." + :type 'boolean + :group 'appmenu) + +(defcustom appmenu-show-point-menu t + "If non-nil show entries fetched from keymaps at point." + :type 'boolean + :group 'appmenu) + +(defvar appmenu-alist nil + "List of additional menu keymaps. +To change this list use `appmenu-add' and `appmenu-remove'. + +The entries in this list are lists: + + \(ID PRIORITY TEST TITLE DEFINITION) + +ID is a unique identity. + +PRIORITY is a number or a variable whose value is a number +telling where to put this entry when showing the menu. + +TEST should be a form to evaluate. The entry is used if \(eval +TEST) returns non-nil. + +DEFINITION should be either a keymap or a function that returns a +keymap. + +The function must take no argument and return a keymap. If the +function returns nil then the entry is not shown in the popup +menu. Using this you can make context sensitive popup menus. + +For an example of use see mlinks.el.") + +(defun appmenu-sort-by-priority () + "Sort `appmenu-alist' entries by priority." + (setq appmenu-alist + (sort appmenu-alist + (lambda (recA recB) + (let ((priA (nth 1 recA)) + (priB (nth 1 recB))) + (when (symbolp priA) (setq priA (symbol-value priA))) + (when (symbolp priB) (setq priB (symbol-value priB))) + (< priA priB)))))) + +;;;###autoload +(defun appmenu-add (id priority test title definition) + "Add entry to `appmenu-alist'. +Add an entry to this list with ID, PRIORITY, TEST, TITLE and +DEFINITION as explained there." + (assert (symbolp id)) + (unless priority (setq priority 100)) + (assert (numberp priority)) + (assert (stringp title)) + (let ((rec (list id priority test title definition))) + (appmenu-remove id) + (add-to-list 'appmenu-alist rec))) + +(defun appmenu-remove (id) + "Remove entry with id ID from `appmenu-alist'." + (setq appmenu-alist (assq-delete-all id appmenu-alist))) + +(defun appmenu-help () + "Show help for minor mode function `appmenu-mode'." + (interactive) + (describe-function 'appmenu-mode)) + +(defun appmenu-keymap-len (map) + "Return length of keymap MAP." + (let ((ml 0)) + (map-keymap (lambda (e f) (setq ml (1+ ml))) map) + ml)) + +(defvar appmenu-mouse-only + '((flyspell-correct-word appmenu-flyspell-correct-word-before-point))) + +(defun appmenu-flyspell-correct-word-before-point () + "Pop up a menu of possible corrections for misspelled word before point. +Special version for AppMenu." + (interactive) + (flyspell-correct-word-before-point)) + +(defcustom appmenu-at-any-point '(ispell-word) + "Commands that may work at any point in a buffer. +Some important but not too often used commands that may be useful +for most points in a buffer." + :group 'appmenu) + +(defvar appmenu-map-fun) ;; dyn var, silence compiler + +(defun appmenu-make-menu-for-point (this-point) + "Construct a menu based on point THIS-POINT. +This includes some known commands for point and keymap at +point." + (let ((point-map (get-char-property this-point 'keymap)) + (funs appmenu-at-any-point) + (map (make-sparse-keymap "At point")) + (num 0) + last-prefix + this-prefix) + ;; Known for any point + (when point-map + (let ((appmenu-map-fun + (lambda (key fun) + (if (keymapp fun) + (map-keymap appmenu-map-fun fun) + (when (and (symbolp fun) + (fboundp fun)) + (let ((mouse-only (assq fun appmenu-mouse-only))) + (when mouse-only + (setq fun (cadr mouse-only))) + (add-to-list 'funs fun))))))) + (map-keymap appmenu-map-fun point-map))) + (dolist (fun funs) + (let ((desc (when fun (documentation fun)))) + (when desc + (setq desc (car (split-string desc "[\n]"))) + ;;(lwarn t :warning "pk: %s, %s" fun desc) + (setq this-prefix + (car (split-string (symbol-name fun) "[-]"))) + (when (and last-prefix + (not (string= last-prefix this-prefix))) + (define-key map + (vector (intern (format "appmenu-point-div-%s" num))) + (list 'menu-item "--"))) + (setq last-prefix this-prefix) + (setq num (1+ num)) + (define-key map + (vector (intern (format "appmenu-point-%s" num))) + (list 'menu-item desc fun))))) + (when (> num 0) map))) + +(defvar appmenu-level) ;; dyn var +(defvar appmenu-funs) ;; dyn var +(defvar appmenu-events) ;; dyn var +(defvar appmenu-this-point) ;; dyn var + +(defun appmenu-keymap-map-fun (ev def) + (if (keymapp def) + (progn + (add-to-list 'appmenu-funs (list appmenu-level ev)) + (setq appmenu-events (cons ev appmenu-events)) + (setq appmenu-level (1+ appmenu-level)) + + (map-keymap 'appmenu-keymap-map-fun def) + + (setq appmenu-events (cdr appmenu-events)) + (setq appmenu-level (1- appmenu-level))) + (when (and (symbolp def) + (fboundp def)) + (let* ((mouse-only (assq def appmenu-mouse-only)) + (fun (if mouse-only (cadr mouse-only) def)) + (doc (when fun + (if (not (eq fun 'push-button)) + (documentation fun) + (concat + "Button: " + (with-current-buffer (marker-buffer appmenu-this-point) + (or (get-char-property appmenu-this-point 'help-echo) + (let ((action-fun (get-char-property appmenu-this-point 'action))) + (if action-fun + (documentation action-fun) + "No action, ignored")) + "No documentation available"))))))) + (add-to-list 'appmenu-funs (list appmenu-level (cons ev appmenu-events) def doc)))))) + +;;(appmenu-as-help (point)) +(defun appmenu-as-help (this-point) + "Show keybindings specific done current point in buffer. +This shows the binding in the help buffer. + +Tip: This may be helpful if you are using `css-color-mode'." + (interactive (list (copy-marker (point)))) + ;; Split this for debugging + (let ((menu-here + (with-current-buffer (or (and (markerp this-point) + (marker-buffer this-point)) + (current-buffer)) + (unless (markerp this-point) (setq this-point (copy-marker this-point))) + (get-char-property this-point 'keymap)))) + ;;(describe-variable 'menu-here) + (appmenu-as-help-1 menu-here this-point))) + +(defun appmenu-as-help-1 (menu-here this-point) + (let ((appmenu-level 0) + (appmenu-funs nil) + (appmenu-events nil) + (appmenu-this-point this-point)) + (when menu-here + (map-keymap 'appmenu-keymap-map-fun menu-here)) + ;;(describe-variable 'appmenu-funs) + ;; Fix-me: collect info first in case we are in help-buffer! + (with-output-to-temp-buffer (help-buffer) + (help-setup-xref (list #'appmenu-as-help this-point) (interactive-p)) + (with-current-buffer (help-buffer) + (let ((fmt " %s%15s %-30s\n")) + (insert (propertize + ;;"AppMenu: Keys found at point in buffer\n\n" + (format "Appmenu: Key bindings specific to point %s in buffer %S\n\n" + (+ 0 this-point) + (when (markerp this-point) + (buffer-name (marker-buffer this-point)))) + 'face 'font-lock-comment-face)) + (if (not menu-here) + (insert "\n\nThere are no point specific key bindings there now.") + (insert (propertize (format fmt "" "Key" "Function") 'face 'font-lock-function-name-face)) + (insert (propertize (format fmt "" "---" "--------") 'face 'font-lock-function-name-face)) + (dolist (rec appmenu-funs) + (let* ((lev (nth 0 rec)) + (ev (nth 1 rec)) + (fun (nth 2 rec)) + (doc (nth 3 rec)) + (d1 (when doc (car (split-string doc "[\n]"))))) + (if fun + (insert (format fmt + "" ;;(concat "*" (make-string (* 4 lev) ?\ )) + (key-description (reverse ev)) + d1) + (if nil (format "(%s)" fun) "")) + ;;(insert (format "something else=%S\n" rec)) + ))))))))) + + +(defun appmenu-map () + "Return menu keymap to use for popup menu." + (let* ((map (make-sparse-keymap + "AppMenu" + )) + (map-len (appmenu-keymap-len map)) + (map-init-len map-len) + (num-minor 0) + (id 0) + (point-menu (when appmenu-show-point-menu + (appmenu-make-menu-for-point (point))))) + ;; AppMenu itself + (when appmenu-show-help + (define-key map [appmenu-customize] + (list 'menu-item "Customize AppMenu" + (lambda () (interactive) (customize-group 'appmenu)) + :help "Customize AppMenu" + :visible 'appmenu-show-help)) + (define-key map [appmenu-help] + (list 'menu-item "Help for AppMenu" 'appmenu-help + :help "Help for how to use AppMenu" + :visible 'appmenu-show-help)) + (define-key map [appmenu-separator-1] + (list 'menu-item "--"))) + (setq map-len (appmenu-keymap-len map)) + (appmenu-sort-by-priority) + (dolist (rec appmenu-alist) + (let* ((test (nth 2 rec)) + (title (nth 3 rec)) + (mapdef (nth 4 rec)) + (usedef (if (symbolp mapdef) + (funcall mapdef) + mapdef))) + (when (and usedef + (eval test)) + (setq id (1+ id)) + (define-key map + (vector (intern (format "appmenu-%s" id))) + (list 'menu-item title usedef))) + )) + (when point-menu + (setq map-len (appmenu-keymap-len map)) + (when (> map-len map-init-len) + (define-key map [appmenu-at-point-div] + (list 'menu-item "--"))) + (define-key map [appmenu-at-point] + (list 'menu-item "Bound To Point" + point-menu))) + (setq map-len (appmenu-keymap-len map)) + (when (> map-len map-init-len) + map))) + +;; (defun appmenu-get-submenu (menu-command) +;; (let (subtitle submenumap) +;; (if (eq 'menu-item (car menu-command)) +;; (progn (setq subtitle (cadr menu-command)) +;; (setq submenumap (caddr menu-command))) +;; (setq subtitle (car menu-command)) +;; (setq submenumap (cdr menu-command))) +;; (unless (keymapp submenumap) (error "Submenu not a keymap=%s" submenumap)) +;; (cons subtitle submenumap))) + +(defun appmenu-popup () + "Pops up the AppMenu menu." + (interactive) + (let* ((mod (event-modifiers last-input-event)) + (is-mouse (or (memq 'click mod) + (memq 'down mod) + (memq 'drag mod)))) + (when is-mouse + (goto-char (posn-point (event-start last-input-event))) + (sit-for 0.01)) + (let ((menu (appmenu-map))) + (if menu + (popup-menu-at-point menu) + (message "Appmenu is empty"))))) + +(defvar appmenu-mode-map + (let ((map (make-sparse-keymap))) + (define-key map [apps] 'appmenu-popup) + (define-key map [mouse-3] 'appmenu-popup) + (define-key map [(control apps)] 'appmenu-as-help) + map)) + + +;;(setq appmenu-auto-help 4) +(defcustom appmenu-auto-help 2 + "Automatically show help on keymap at current point. +This shows up after the number of seconds in this variable. +If it it nil this feature is off. + +This feature is only on in `appmenu-mode'." + :type '(choice (number :tag "Number of seconds to wait") + (const :tag "Turned off" nil)) + :set (lambda (sym val) + (set-default sym val) + (if val + (add-hook 'post-command-hook 'appmenu-auto-help-post-command nil t) + (remove-hook 'post-command-hook 'appmenu-auto-help-post-command t))) + :group 'appmenu) + +(defcustom appmenu-auto-match-keymaps + '(css-color) + "Keymaps listed here can be avoided." + :type '(set (const unknown) + (const mlink) + (const css-color)) + :group 'appmenu) + +(defvar appmenu-auto-help-timer nil) + +(defun appmenu-dump-keymap (km) + (let ((fun (lambda (ev def) + (message "ev=%S def=%S" ev def) + (when (keymapp def) + (map-keymap fun def))))) + (map-keymap fun km))) + +(defun appmenu-on-keymap (where) + (setq where (or where (point))) + (let* ((rec (get-char-property-and-overlay where 'keymap)) + (kmp (car rec)) + (ovl (cdr rec))) + (when kmp + (or (memq 'unknown appmenu-auto-match-keymaps) + (and (memq 'css-color appmenu-auto-match-keymaps) + (get-text-property where 'css-color-type)) + (and (memq 'mlinks appmenu-auto-match-keymaps) + (boundp 'mlinks-point-hilighter-overlay) + (eq ovl mlinks-point-hilighter-overlay)) + )))) + +(defsubst appmenu-auto-help-add-wcfg (at-point wcfg) + (mumamo-with-buffer-prepared-for-jit-lock + (add-text-properties at-point (1+ at-point) + (list 'point-left 'appmenu-auto-help-maybe-remove + 'appmenu-auto-help-wcfg wcfg)))) + +(defsubst appmenu-auto-help-remove-wcfg (at-point) + (mumamo-with-buffer-prepared-for-jit-lock + (remove-list-of-text-properties at-point (1+ at-point) + '(appmenu-auto-help-wcfg point-left)))) + +(defun appmenu-auto-help-maybe-remove (at-point new-point) + "Run in 'point-left property. +Restores window configuration." + (let ((old-wcfg (get-text-property at-point 'appmenu-auto-help-wcfg))) + (appmenu-auto-help-remove-wcfg at-point) + (if (appmenu-on-keymap new-point) + (appmenu-auto-help-add-wcfg new-point old-wcfg) + (if old-wcfg + (set-window-configuration old-wcfg) + (help-xref-go-back (help-buffer)))))) + +(defun appmenu-as-help-in-timer (win buf) + (condition-case err + (when (and (eq (selected-window) win) + (eq (current-buffer) buf) + appmenu-auto-help + (appmenu-on-keymap (point))) + (let* ((old-help-win (get-buffer-window (help-buffer))) + (wcfg (unless old-help-win + (current-window-configuration)))) + (unless old-help-win + (display-buffer (help-buffer))) + (appmenu-auto-help-add-wcfg (point) wcfg) + (appmenu-as-help (copy-marker (point))))) + (error (message "appmenu-as-help-in-timer: %s" (error-message-string err))))) + +(defun appmenu-auto-help-cancel-timer () + (when (timerp appmenu-auto-help-timer) + (cancel-timer appmenu-auto-help-timer)) + (setq appmenu-auto-help-timer nil)) + +(defun appmenu-auto-help-post-command () + (when (fboundp 'appmenu-as-help) + (condition-case err + (appmenu-auto-help-post-command-1) + (error (message "css-color-post-command: %s" (error-message-string err)))))) + +;; #fff #c9ff33 +(defun appmenu-auto-help-post-command-1 () + (appmenu-auto-help-cancel-timer) + (and appmenu-auto-help + (appmenu-on-keymap (point)) + (not (get-text-property (point) 'appmenu-auto-help-wcfg)) + (setq appmenu-auto-help-timer + (run-with-idle-timer appmenu-auto-help nil 'appmenu-as-help-in-timer + (selected-window) + (current-buffer))))) + + +;;;###autoload +(define-minor-mode appmenu-mode + "Use a context sensitive popup menu. +AppMenu (appmenu.el) is a framework for creating cooperative +context sensitive popup menus with commands from different major +and minor modes. Using this different modes may cooperate about +the use of popup menus. + +There is also the command `appmenu-as-help' that shows the key +bindings at current point in the help buffer. + +The popup menu and the help buffer version are on these keys: + +\\{appmenu-mode-map} + +The variable `appmenu-alist' is where the popup menu entries +comes from. + +If there is a `keymap' property at point then relevant bindings +from this is also shown in the popup menu. + +You can write functions that use whatever information you want in +Emacs to construct these entries. Since this information is only +collected when the popup menu is shown you do not have to care as +much about computation time as for entries in the menu bar." + :global t + :keymap appmenu-mode-map + :group 'appmenu + (if appmenu-mode + (add-hook 'post-command-hook 'appmenu-auto-help-post-command) + (remove-hook 'post-command-hook 'appmenu-auto-help-post-command))) + +(when (and appmenu-mode + (not (boundp 'define-globa-minor-mode-bug))) + (appmenu-mode 1)) + +(provide 'appmenu) +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; appmenu.el ends here -- cgit v1.2.3-54-g00ecf