If a defmath
form contains an interactive
clause, it defines
a Calculator command. Actually such a defmath
results in two
function definitions: One, a `calcFunc-' function as was just described,
with the interactive
clause removed. Two, a `calc-' function
with a suitable interactive
clause and some sort of wrapper to make
the command work in the Calc environment.
In the simple case, the interactive
clause has the same form as
for normal Emacs Lisp commands:
(defmath increase-precision (delta) "Increase precision by DELTA." ; This is the "documentation string" (interactive "p") ; Register this as a M-x-able command (setq calc-internal-prec (+ calc-internal-prec delta)))
This expands to the pair of definitions,
(defun calc-increase-precision (delta) "Increase precision by DELTA." (interactive "p") (calc-wrapper (setq calc-internal-prec (math-add calc-internal-prec delta)))) (defun calcFunc-increase-precision (delta) "Increase precision by DELTA." (setq calc-internal-prec (math-add calc-internal-prec delta)))
where in this case the latter function would never really be used! Note
that since the Calculator stores small integers as plain Lisp integers,
the math-add
function will work just as well as the native
+
even when the intent is to operate on native Lisp integers.
The `calc-wrapper' call invokes a macro which surrounds the body of the function with code that looks roughly like this:
(let ((calc-command-flags nil)) (unwind-protect (save-excursion (calc-select-buffer) body of function renumber stack clear Working message) realign cursor and window clear Inverse, Hyperbolic, and Keep Args flags update Emacs mode line))
The calc-select-buffer
function selects the `*Calculator*'
buffer if necessary, say, because the command was invoked from inside
the `*Calc Trail*' window.
You can call, for example, (calc-set-command-flag 'no-align)
to set
the above-mentioned command flags. The following command flags are
recognized by Calc routines:
renum-stack
calc-push
.
clear-message
no-align
position-point
calc-position-point-line
and
calc-position-point-column
to position the cursor after
this command finishes.
keep-flags
calc-inverse-flag
, calc-hyperbolic-flag
,
and calc-keep-args-flag
at the end of this command.
do-edit
hold-trail
Calc reserves a special prefix key, shift-Y, for user-written
extensions to Calc. There are no built-in commands that work with
this prefix key; you must call define-key
from Lisp (probably
from inside a calc-define
property) to add to it. Initially only
Y ? is defined; it takes help messages from a list of strings
(initially nil
) in the variable calc-Y-help-msgs
. All
other undefined keys except for Y are reserved for use by
future versions of Calc.
If you are writing a Calc enhancement which you expect to give to others, it is best to minimize the number of Y-key sequences you use. In fact, if you have more than one key sequence you should consider defining three-key sequences with a Y, then a key that stands for your package, then a third key for the particular command within your package.
Users may wish to install several Calc enhancements, and it is possible
that several enhancements will choose to use the same key. In the
example below, a variable inc-prec-base-key
has been defined
to contain the key that identifies the inc-prec
package. Its
value is initially "P"
, but a user can change this variable
if necessary without having to modify the file.
Here is a complete file, `inc-prec.el', which makes a Y P I command that increases the precision, and a Y P D command that decreases the precision.
;;; Increase and decrease Calc precision. Dave Gillespie, 5/31/91. ;;; (Include copyright or copyleft stuff here.) (defvar inc-prec-base-key "P" "Base key for inc-prec.el commands.") (put 'calc-define 'inc-prec '(progn (define-key calc-mode-map (format "Y%sI" inc-prec-base-key) 'increase-precision) (define-key calc-mode-map (format "Y%sD" inc-prec-base-key) 'decrease-precision) (setq calc-Y-help-msgs (cons (format "%s + Inc-prec, Dec-prec" inc-prec-base-key) calc-Y-help-msgs)) (defmath increase-precision (delta) "Increase precision by DELTA." (interactive "p") (setq calc-internal-prec (+ calc-internal-prec delta))) (defmath decrease-precision (delta) "Decrease precision by DELTA." (interactive "p") (setq calc-internal-prec (- calc-internal-prec delta))) )) ; end of calc-define property (run-hooks 'calc-check-defines)