1 ;;; hact.el --- Hyperbole button action handling.
3 ;; Copyright (C) 1991-1995, 2006 Free Software Foundation, Inc.
4 ;; Developed with support from Motorola Inc.
6 ;; Author: Bob Weiner, Brown U.
7 ;; Maintainer: Mats Lidell <matsl@contactor.se>
8 ;; Keywords: hypermedia
10 ;; This file is part of GNU Hyperbole.
12 ;; GNU Hyperbole is free software; you can redistribute it and/or
13 ;; modify it under the terms of the GNU General Public License as
14 ;; published by the Free Software Foundation; either version 3, or (at
15 ;; your option) any later version.
17 ;; GNU Hyperbole is distributed in the hope that it will be useful,
18 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
19 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 ;; General Public License for more details.
22 ;; You should have received a copy of the GNU General Public License
23 ;; along with GNU Emacs; see the file COPYING. If not, write to the
24 ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
25 ;; Boston, MA 02110-1301, USA.
32 ;;; Other required Elisp libraries
40 (defvar hrule:action 'actype:act
41 "Value is a function of any number of arguments that executes actions.
42 Variable is used to vary actual effect of evaluating a Hyperbole action,
43 e.g. to inhibit actions.")
53 (defun action:commandp (function)
54 "Return interactive calling form if FUNCTION has one, else nil."
56 (cond ((null function) nil)
58 (and (fboundp function)
59 (hypb:indirect-function function)))
60 ((and (listp function)
61 (eq (car function) 'autoload))
62 (error "(action:commandp): Autoload not supported: %s" function))
64 (if (hypb:v19-byte-code-p action)
66 (if (fboundp 'compiled-function-interactive)
67 (compiled-function-interactive action)
68 (list 'interactive (aref action 5))))
71 (defun action:create (param-list body)
72 "Create an action defined by PARAM-LIST and BODY, a list of Lisp forms."
75 (list 'function (cons 'lambda (cons param-list body)))))
77 (defun action:kbd-macro (macro &optional repeat-count)
78 "Returns Hyperbole action that executes a keyboard MACRO REPEAT-COUNT times."
79 (list 'execute-kbd-macro macro repeat-count))
81 (defun action:params (action)
82 "Returns unmodified ACTION parameter list."
83 (cond ((null action) nil)
86 (and (fboundp action) (hypb:indirect-function action)))))
88 (if (eq (car action) 'autoload)
89 (error "(action:params): Autoload not supported: %s" action)
91 ((hypb:v19-byte-code-p action)
92 (if (fboundp 'compiled-function-arglist)
93 (compiled-function-arglist action)
94 ;; Turn into a list for extraction
95 (car (cdr (cons nil (append action nil))))))))
97 (defun action:param-list (action)
98 "Returns list of actual ACTION parameters (removes '&' special forms)."
102 (if (= (aref (symbol-name param)
105 (action:params action))))
107 (defun action:path-args-abs (args-list &optional default-dirs)
108 "Return any paths in ARGS-LIST made absolute.
109 Uses optional DEFAULT-DIRS or 'default-directory'.
110 Other arguments are returned unchanged."
111 (mapcar (function (lambda (arg) (hpath:absolute-to arg default-dirs)))
114 (defun action:path-args-rel (args-list)
115 "Return any paths in ARGS-LIST below current directory made relative.
116 Other paths are simply expanded. Non-path arguments are returned unchanged."
117 (let ((dir (hattr:get 'hbut:current 'dir)))
118 (mapcar (function (lambda (arg) (hpath:relative-to arg dir)))
126 (defmacro hact (&rest args)
127 "Performs action formed from rest of ARGS.
128 First arg may be a symbol or symbol name for either an action type or a
129 function. Runs 'action:act-hook' before performing action."
130 (eval (` (cons 'funcall (cons 'hrule:action (quote (, args)))))))
132 (defun actype:act (actype &rest args)
133 "Performs action formed from ACTYPE and rest of ARGS and returns value.
134 If value is nil, however, t is returned instead, to ensure that implicit button
135 types register the performance of the action. ACTYPE may be a symbol or symbol
136 name for either an action type or a function. Runs 'action:act-hook' before
138 ;; Needed so relative paths are expanded properly.
139 (setq args (action:path-args-abs args))
140 (let ((prefix-arg current-prefix-arg)
141 (action (actype:action actype))
142 (act '(apply action args)))
144 (error "(actype:act): Null action for: '%s'" actype)
145 (let ((hist-elt (hhist:element)))
146 (run-hooks 'action:act-hook)
147 (prog1 (or (cond ((or (symbolp action) (listp action)
148 (hypb:v19-byte-code-p action))
150 ((and (stringp action)
151 (let ((func (key-binding action)))
152 (if (not (integerp action))
153 (setq action func))))
157 (hhist:add hist-elt))
160 (defun actype:action (actype)
161 "Returns action part of ACTYPE (a symbol or symbol name).
162 ACTYPE may be a Hyperbole actype or Emacs Lisp function."
166 actype (intern actype))
167 (setq actname (symbol-name actype)))
168 (cond ((htype:body (if (string-match "^actypes::" actname)
170 (intern-soft (concat "actypes::" actname)))))
171 ((fboundp actype) actype)
174 (defmacro actype:create (type params doc &rest default-action)
175 "Creates an action TYPE (an unquoted symbol) with PARAMS, described by DOC.
176 The type uses PARAMS to perform DEFAULT-ACTION (list of the rest of the
177 arguments). A call to this function is syntactically the same as for
178 'defun', but a doc string is required.
179 Returns symbol created when successful, else nil."
180 (list 'htype:create type 'actypes doc params default-action nil))
182 (fset 'defact 'actype:create)
183 (put 'actype:create 'lisp-indent-function 'defun)
185 (defun actype:delete (type)
186 "Deletes an action TYPE (a symbol). Returns TYPE's symbol if it existed."
187 (htype:delete type 'actypes))
189 (defun actype:doc (hbut &optional full)
190 "Returns first line of act doc for HBUT (a Hyperbole button symbol).
191 With optional FULL, returns full documentation string.
192 Returns nil when no documentation."
193 (let* ((act (and (hbut:is-p hbut) (or (hattr:get hbut 'action)
194 (hattr:get hbut 'actype))))
195 (but-type (hattr:get hbut 'categ))
196 (sym-p (and act (symbolp act)))
198 (cond ((and but-type (fboundp but-type)
199 (setq doc (htype:doc but-type)))
200 ;; Is an implicit button, so use its doc string if any.
203 (setq doc (htype:doc act))))
206 (setq doc (substitute-command-keys doc))
207 (or full (setq end-line (string-match "[\n]" doc)
208 doc (substring doc 0 end-line))))
211 (defun actype:identity (&rest args)
212 "Returns list of ARGS unchanged or if no ARGS, returns t.
213 Used as the setting of 'hrule:action' to inhibit action evaluation."
216 (defun actype:interact (actype)
217 "Interactively calls default action for ACTYPE.
218 ACTYPE is a symbol that was previously defined with 'defact'.
219 Returns nil only when no action is found or the action has no interactive
222 (let ((action (htype:body
223 (intern-soft (concat "actypes::" (symbol-name actype))))))
224 (and action (action:commandp action) (or (call-interactively action) t))))
226 (defun actype:params (actype)
227 "Returns list of ACTYPE's parameters."
228 (action:params (actype:action actype)))
232 ;;; hact.el ends here