Mercurial > hg > xemacs-beta
diff lisp/hyperbole/hact.el @ 0:376386a54a3c r19-14
Import from CVS: tag r19-14
author | cvs |
---|---|
date | Mon, 13 Aug 2007 08:45:50 +0200 |
parents | |
children | 929b76928fce |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lisp/hyperbole/hact.el Mon Aug 13 08:45:50 2007 +0200 @@ -0,0 +1,218 @@ +;;!emacs +;; +;; FILE: hact.el +;; SUMMARY: Hyperbole button action handling. +;; USAGE: GNU Emacs Lisp Library +;; KEYWORDS: hypermedia +;; +;; AUTHOR: Bob Weiner +;; ORG: Brown U. +;; +;; ORIG-DATE: 18-Sep-91 at 02:57:09 +;; LAST-MOD: 14-Apr-95 at 15:57:11 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 'hhist) + +;;; ************************************************************************ +;;; Public variables +;;; ************************************************************************ + +(defvar hrule:action 'actype:act + "Value is a function of any number of arguments that executes actions. +Variable is used to vary actual effect of evaluating a Hyperbole action, +e.g. to inhibit actions.") + +;;; ************************************************************************ +;;; Public functions +;;; ************************************************************************ + +;;; ======================================================================== +;;; action class +;;; ======================================================================== + +(defun action:commandp (function) + "Return interactive calling form if FUNCTION has one, else nil." + (let ((action + (cond ((null function) nil) + ((symbolp function) + (and (fboundp function) + (hypb:indirect-function function))) + ((and (listp function) + (eq (car function) 'autoload)) + (error "(action:commandp): Autoload not supported: %s" function)) + (t function)))) + (if (hypb:v19-byte-code-p action) + (if (commandp action) + (list 'interactive (aref action 5))) + (commandp action)))) + +(defun action:create (param-list body) + "Create an action defined by PARAM-LIST and BODY, a list of Lisp forms." + (if (symbolp body) + body + (list 'function (cons 'lambda (cons param-list body))))) + +(defun action:kbd-macro (macro &optional repeat-count) + "Returns Hyperbole action that executes a keyboard MACRO REPEAT-COUNT times." + (list 'execute-kbd-macro macro repeat-count)) + +(defun action:params (action) + "Returns unmodified ACTION parameter list." + (cond ((null action) nil) + ((symbolp action) + (car (cdr + (and (fboundp action) (hypb:indirect-function action))))) + ((listp action) + (if (eq (car action) 'autoload) + (error "(action:params): Autoload not supported: %s" action) + (car (cdr action)))) + ((hypb:v19-byte-code-p action) + ;; Turn into a list for extraction + (car (cdr (cons nil (append action nil))))))) + +(defun action:param-list (action) + "Returns list of actual ACTION parameters (removes '&' special forms)." + (delq nil (mapcar + (function + (lambda (param) + (if (= (aref (symbol-name param) + 0) ?&) + nil param))) + (action:params action)))) + +(defun action:path-args-abs (args-list &optional default-dirs) + "Return any paths in ARGS-LIST made absolute. +Uses optional DEFAULT-DIRS or 'default-directory'. +Other arguments are returned unchanged." + (mapcar (function (lambda (arg) (hpath:absolute-to arg default-dirs))) + args-list)) + +(defun action:path-args-rel (args-list) + "Return any paths in ARGS-LIST below current directory made relative. +Other paths are simply expanded. Non-path arguments are returned unchanged." + (let ((dir (hattr:get 'hbut:current 'dir))) + (mapcar (function (lambda (arg) (hpath:relative-to arg dir))) + args-list))) + + +;;; ======================================================================== +;;; actype class +;;; ======================================================================== + +(defmacro hact (&rest args) + "Performs action formed from rest of ARGS. +First arg may be a symbol or symbol name for either an action type or a +function. Runs 'action:act-hook' before performing action." + (eval (` (cons 'funcall (cons 'hrule:action (quote (, args))))))) + +(defun actype:act (actype &rest args) + "Performs action formed from ACTYPE and rest of ARGS and returns value. +If value is nil, however, t is returned instead, to ensure that implicit button +types register the performance of the action. ACTYPE may be a symbol or symbol +name for either an action type or a function. Runs 'action:act-hook' before +performing ACTION." + ;; Needed so relative paths are expanded properly. + (setq args (action:path-args-abs args)) + (let ((prefix-arg current-prefix-arg) + (action (actype:action actype)) + (act '(apply action args))) + (if (null action) + (error "(actype:act): Null action for: '%s'" actype) + (let ((hist-elt (hhist:element))) + (run-hooks 'action:act-hook) + (prog1 (or (cond ((or (symbolp action) (listp action) + (hypb:v19-byte-code-p action)) + (eval act)) + ((and (stringp action) + (let ((func (key-binding action))) + (if (not (integerp action)) + (setq action func)))) + (eval act)) + (t (eval action))) + t) + (hhist:add hist-elt)) + )))) + +(defun actype:action (actype) + "Returns action part of ACTYPE (a symbol or symbol name). +ACTYPE may be a Hyperbole actype or Emacs Lisp function." + (let (actname) + (if (stringp actype) + (setq actname actype + actype (intern actype)) + (setq actname (symbol-name actype))) + (cond ((htype:body (if (string-match "^actypes::" actname) + actype + (intern-soft (concat "actypes::" actname))))) + ((fboundp actype) actype) + ))) + +(defmacro actype:create (type params doc &rest default-action) + "Creates an action TYPE (an unquoted symbol) with PARAMS, described by DOC. +The type uses PARAMS to perform DEFAULT-ACTION (list of the rest of the +arguments). A call to this function is syntactically the same as for +'defun', but a doc string is required. +Returns symbol created when successful, else nil." + (list 'htype:create type 'actypes doc params default-action nil)) + +(fset 'defact 'actype:create) +(put 'actype:create 'lisp-indent-function 'defun) + +(defun actype:delete (type) + "Deletes an action TYPE (a symbol). Returns TYPE's symbol if it existed." + (htype:delete type 'actypes)) + +(defun actype:doc (hbut &optional full) + "Returns first line of act doc for HBUT (a Hyperbole button symbol). +With optional FULL, returns full documentation string. +Returns nil when no documentation." + (let* ((act (and (hbut:is-p hbut) (or (hattr:get hbut 'action) + (hattr:get hbut 'actype)))) + (but-type (hattr:get hbut 'categ)) + (sym-p (and act (symbolp act))) + (end-line) (doc)) + (cond ((and but-type (fboundp but-type) + (setq doc (htype:doc but-type))) + ;; Is an implicit button, so use its doc string if any. + ) + (sym-p + (setq doc (htype:doc act)))) + (if (null doc) + nil + (setq doc (substitute-command-keys doc)) + (or full (setq end-line (string-match "[\n]" doc) + doc (substring doc 0 end-line)))) + doc)) + +(defun actype:identity (&rest args) + "Returns list of ARGS unchanged or if no ARGS, returns t. +Used as the setting of 'hrule:action' to inhibit action evaluation." + (or args t)) + +(defun actype:interact (actype) + "Interactively calls default action for ACTYPE. +ACTYPE is a symbol that was previously defined with 'defact'. +Returns nil only when no action is found or the action has no interactive +calling form." + (let ((action (htype:body + (intern-soft (concat "actypes::" (symbol-name actype)))))) + (and action (action:commandp action) (or (call-interactively action) t)))) + +(defun actype:params (actype) + "Returns list of ACTYPE's parameters." + (action:params (actype:action actype))) + +(provide 'hact)