aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDave Love2000-11-14 18:52:08 +0000
committerDave Love2000-11-14 18:52:08 +0000
commit25c269ef6e910382e8a1e9b97cc0c87480ae5653 (patch)
tree93d67a640c233cc15f3a02b206478b0709dfa667
parent0894e696763f4faef3023e7445480b35a2a11860 (diff)
downloademacs-25c269ef6e910382e8a1e9b97cc0c87480ae5653.tar.gz
emacs-25c269ef6e910382e8a1e9b97cc0c87480ae5653.zip
New maintainer version.
-rw-r--r--lisp/ChangeLog5
-rw-r--r--lisp/calculator.el626
2 files changed, 444 insertions, 187 deletions
diff --git a/lisp/ChangeLog b/lisp/ChangeLog
index 7c636855205..920e609444e 100644
--- a/lisp/ChangeLog
+++ b/lisp/ChangeLog
@@ -4,6 +4,11 @@
4 4
52000-11-14 Dave Love <fx@gnu.org> 52000-11-14 Dave Love <fx@gnu.org>
6 6
7 * calculator.el: New maintainer version.
8
9 * diff-mode.el (diff-imenu-generic-expression): Modify unidiff
10 pattern.
11
7 * cmuscheme.el: Doc fixes. 12 * cmuscheme.el: Doc fixes.
8 (cmuscheme) <defgroup>: Use `scheme' as parent. 13 (cmuscheme) <defgroup>: Use `scheme' as parent.
9 (cmuscheme-program-name): Remove. Change uses to 14 (cmuscheme-program-name): Remove. Change uses to
diff --git a/lisp/calculator.el b/lisp/calculator.el
index ad385a9de4d..ab84d088e6b 100644
--- a/lisp/calculator.el
+++ b/lisp/calculator.el
@@ -1,10 +1,10 @@
1;;; calculator.el --- A simple pocket calculator. 1;;; calculator.el --- A [not so] simple calculator for Emacs.
2 2
3;; Copyright (C) 1998 by Free Software Foundation, Inc. 3;; Copyright (C) 1998, 2000 by Free Software Foundation, Inc.
4 4
5;; Author: Eli Barzilay <eli@lambda.cs.cornell.edu> 5;; Author: Eli Barzilay <eli@www.barzilay.org>
6;; Keywords: tools, convenience 6;; Keywords: tools, convenience
7;; Time-stamp: <2000-02-16 21:07:54 eli> 7;; Time-stamp: <2000-11-07 15:04:06 eli>
8 8
9;; This file is part of GNU Emacs. 9;; This file is part of GNU Emacs.
10 10
@@ -23,33 +23,35 @@
23;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, 23;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
24;; MA 02111-1307, USA. 24;; MA 02111-1307, USA.
25 25
26;;;============================================================================
26;;; Commentary: 27;;; Commentary:
27;; 28;;
28;; A simple pocket calculator for Emacs. 29;; A calculator for Emacs.
29;; Why touch your mouse to get xcalc (or calc.exe), when you have Emacs? 30;; Why should you each for your mouse to get xcalc (calc.exe, gcalc or
31;; whatever), when you have Emacs running already?
30;; 32;;
31;; If this is not part of your Emacs distribution, then simply bind 33;; If this is not part of your Emacs distribution, then simply bind
32;; `calculator' to a key and make it an autoloaded function, e.g.: 34;; `calculator' to a key and make it an autoloaded function, e.g.:
33;; (autoload 'calculator "calculator" 35;; (autoload 'calculator "calculator"
34;; "Run the pocket calculator." t) 36;; "Run the Emacs calculator." t)
35;; (global-set-key [(control return)] 'calculator) 37;; (global-set-key [(control return)] 'calculator)
36;; 38;;
37;; Written by Eli Barzilay: Maze is Life! eli@cs.cornell.edu 39;; Written by Eli Barzilay: Maze is Life! eli@barzilay.org
38;; http://www.cs.cornell.edu/eli 40;; http://www.barzilay.org/
39;; 41;;
40;; For latest version, check 42;; For latest version, check
41;; http://www.cs.cornell.edu/eli/misc/calculator.el 43;; http://www.barzilay.org/misc/calculator.el
42
43 44
44(eval-and-compile 45(eval-and-compile
45 (if (fboundp 'defgroup) nil 46 (if (fboundp 'defgroup) nil
46 (defmacro defgroup (&rest forms) nil) 47 (defmacro defgroup (&rest forms) nil)
47 (defmacro defcustom (s v d &rest r) (list 'defvar s v d)))) 48 (defmacro defcustom (s v d &rest r) (list 'defvar s v d))))
48 49
50;;;============================================================================
49;;; Customization: 51;;; Customization:
50 52
51(defgroup calculator nil 53(defgroup calculator nil
52 "Simple pocket calculator." 54 "Simple Emacs calculator."
53 :prefix "calculator" 55 :prefix "calculator"
54 :version "21.1" 56 :version "21.1"
55 :group 'tools 57 :group 'tools
@@ -57,8 +59,8 @@
57 59
58(defcustom calculator-electric-mode nil 60(defcustom calculator-electric-mode nil
59 "*Run `calculator' electrically, in the echo area. 61 "*Run `calculator' electrically, in the echo area.
60Note that if you use electric-mode, you wouldn't be able to use 62Electric mode saves some place but changes the way you interact with the
61conventional help keys." 63calculator."
62 :type 'boolean 64 :type 'boolean
63 :group 'calculator) 65 :group 'calculator)
64 66
@@ -79,43 +81,69 @@ This determines the default behavior of unary operators."
79 :type '(choice (const prefix) (const postfix)) 81 :type '(choice (const prefix) (const postfix))
80 :group 'calculator) 82 :group 'calculator)
81 83
82(defcustom calculator-prompt "Calculator=%s> " 84(defcustom calculator-prompt "Calc=%s> "
83 "*The prompt used by the pocket calculator. 85 "*The prompt used by the Emacs calculator.
84It should contain a \"%s\" somewhere that will indicate the i/o radixes, 86It should contain a \"%s\" somewhere that will indicate the i/o radixes,
85this string will be a two-character string as described in the 87this string will be a two-character string as described in the
86documentation for `calculator-mode'." 88documentation for `calculator-mode'."
87 :type 'string 89 :type 'string
88 :group 'calculator) 90 :group 'calculator)
89 91
90(defcustom calculator-epsilon 1e-15 92(defcustom calculator-number-digits 3
91 "*A threshold for results. 93 "*The calculator's number of digits used for standard display.
92If any result computed in `calculator-funcall' is smaller than this in 94Used by the `calculator-standard-display' function - it will use the
93its absolute value, then zero will be returned." 95format string \"%.NC\" where this number is N and C is a character given
94 :type 'number 96at runtime."
95 :group 'calculator)
96
97(defcustom calculator-number-format "%1.3f"
98 "*The calculator's string used to display normal numbers."
99 :type 'string 97 :type 'string
100 :group 'calculator) 98 :group 'calculator)
101 99
102(defcustom calculator-number-exp-ulimit 1e16 100(defcustom calculator-remove-zeros t
103 "*The calculator's upper limit for normal numbers." 101 "*Non-nil value means delete all redundant zero decimal digits.
104 :type 'number 102If this value is not t, and not nil, redundant zeros are removed except
103for one and if it is nil, nothing is removed.
104Used by the `calculator-remove-zeros' function."
105 :type '(choice (const t) (const leave-decimal) (const nil))
105 :group 'calculator) 106 :group 'calculator)
106 107
107(defcustom calculator-number-exp-llimit 0.001 108(defcustom calculator-displayer '(std ?n)
108 "*The calculator's lower limit for normal numbers." 109 "*A displayer specification for numerical values.
109 :type 'number 110This is the displayer used to show all numbers in an expression. Result
111values will be displayed according to the first element of
112`calculator-displayers'.
113
114The displayer is a symbol, a string or an expression. A symbol should
115be the name of a one-argument function, a string is used with a single
116argument and an expression will be evaluated with the variable `num'
117bound to whatever should be displayed. If it is a function symbol, it
118should be able to handle special symbol arguments, currently 'left and
119'right which will be sent by special keys to modify display parameters
120associated with the displayer function (for example to change the number
121of digits displayed).
122
123An exception to the above is the case of the list (std C) where C is a
124character, in this case the `calculator-standard-displayer' function
125will be used with this character for a format string.")
126
127(defcustom calculator-displayers
128 '(((std ?n) "Standard dislpay, decimal point or scientific")
129 (calculator-eng-display "Eng display")
130 ((std ?f) "Standard display, decimal point")
131 ((std ?e) "Standard dislpay, scientific")
132 ("%S" "Emacs printer"))
133 "*A list of displayers.
134Each element is a list of a displayer and a description string. The
135first element is the one which is curently used, this is for the display
136of result values not values in expressions. A displayer specification
137is the same as the values that can be stored in `calculator-displayer'.
138
139`calculator-rotate-displayer' rotates this list."
140 :type 'sexp
110 :group 'calculator) 141 :group 'calculator)
111 142
112(defcustom calculator-number-exp-format "%g" 143(defcustom calculator-paste-decimals t
113 "*The calculator's string used to display exponential numbers." 144 "*If non-nil, convert pasted integers so they have a decimal point.
114 :type 'string 145This makes it possible to paste big integers since they will be read as
115 :group 'calculator) 146floats, otherwise the Emacs reader will fail on them."
116
117(defcustom calculator-show-integers t
118 "*Non-nil value means delete all zero digits after the decimal point."
119 :type 'boolean 147 :type 'boolean
120 :group 'calculator) 148 :group 'calculator)
121 149
@@ -126,18 +154,18 @@ Otherwise show as a negative number."
126 :group 'calculator) 154 :group 'calculator)
127 155
128(defcustom calculator-mode-hook nil 156(defcustom calculator-mode-hook nil
129 "*List of hook functions run by `calculator-mode'." 157 "*List of hook functions for `calculator-mode' to run."
130 :type 'hook 158 :type 'hook
131 :group 'calculator) 159 :group 'calculator)
132 160
133(defcustom calculator-user-registers nil 161(defcustom calculator-user-registers nil
134 "*An association list of user-defined register bindings. 162 "*An association list of user-defined register bindings.
135
136Each element in this list is a list of a character and a number that 163Each element in this list is a list of a character and a number that
137will be stored in that character's register. 164will be stored in that character's register.
138 165
139For example, use this to define the golden ratio number: 166For example, use this to define the golden ratio number:
140 (setq calculator-user-registers '((?g . 1.61803398875)))" 167 (setq calculator-user-registers '((?g . 1.61803398875)))
168before you load calculator."
141 :type '(repeat (cons character number)) 169 :type '(repeat (cons character number))
142 :set '(lambda (_ val) 170 :set '(lambda (_ val)
143 (and (boundp 'calculator-registers) 171 (and (boundp 'calculator-registers)
@@ -148,7 +176,6 @@ For example, use this to define the golden ratio number:
148 176
149(defcustom calculator-user-operators nil 177(defcustom calculator-user-operators nil
150 "*A list of additional operators. 178 "*A list of additional operators.
151
152This is a list in the same format as specified in the documentation for 179This is a list in the same format as specified in the documentation for
153`calculator-operators', that you can use to bind additional calculator 180`calculator-operators', that you can use to bind additional calculator
154operators. It is probably not a good idea to modify this value with 181operators. It is probably not a good idea to modify this value with
@@ -174,23 +201,27 @@ Examples:
174 201
175 (add-to-list 'calculator-user-operators 202 (add-to-list 'calculator-user-operators
176 '(\"F\" fib (if (<= TX 1) 203 '(\"F\" fib (if (<= TX 1)
177 1 204 1
178 (+ (F (- TX 1)) (F (- TX 2)))) 0)) 205 (+ (F (- TX 1)) (F (- TX 2)))) 0))
179 206
180 Note that this will be either postfix or prefix, according to 207 Note that this will be either postfix or prefix, according to
181 `calculator-unary-style'." 208 `calculator-unary-style'."
182 :type '(repeat (list string symbol sexp integer integer)) 209 :type '(repeat (list string symbol sexp integer integer))
183 :group 'calculator) 210 :group 'calculator)
184 211
212;;;============================================================================
185;;; Code: 213;;; Code:
186 214
215;;;----------------------------------------------------------------------------
216;;; Variables
217
187(defvar calculator-initial-operators 218(defvar calculator-initial-operators
188 '(;; "+"/"-" have keybindings of themselves, not calculator-ops 219 '(;; "+"/"-" have keybindings of themselves, not calculator-ops
189 ("=" = identity 1 -1) 220 ("=" = identity 1 -1)
190 (nobind "+" + + 2 4) 221 (nobind "+" + + 2 4)
191 (nobind "-" - - 2 4) 222 (nobind "-" - - 2 4)
192 (nobind "+" + + -1 9) 223 (nobind "+" + + -1 9)
193 (nobind "-" - - -1 9) 224 (nobind "-" - - -1 9)
194 ("(" \( identity -1 -1) 225 ("(" \( identity -1 -1)
195 (")" \) identity +1 10) 226 (")" \) identity +1 10)
196 ;; normal keys 227 ;; normal keys
@@ -220,7 +251,6 @@ Examples:
220 ("l" tot (apply '+ L) 0 8) 251 ("l" tot (apply '+ L) 0 8)
221 ) 252 )
222 "A list of initial operators. 253 "A list of initial operators.
223
224This is a list in the same format as `calculator-operators'. Whenever 254This is a list in the same format as `calculator-operators'. Whenever
225`calculator' starts, it looks at the value of this variable, and if it 255`calculator' starts, it looks at the value of this variable, and if it
226is not empty, its contents is prepended to `calculator-operators' and 256is not empty, its contents is prepended to `calculator-operators' and
@@ -243,12 +273,13 @@ user-defined operators, use `calculator-user-operators' instead.")
243 (list of saved values), `F' (function for recursive iteration calls) 273 (list of saved values), `F' (function for recursive iteration calls)
244 and evaluates to the function value - these variables are capital; 274 and evaluates to the function value - these variables are capital;
245 275
2464. The function's arity, optional, one of: 2=binary, -1=prefix unary, 2764. The function's arity, optional, one of: 2 => binary, -1 => prefix
247 +1=postfix unary, 0=a 0-arg operator func, non-number=postfix/prefix 277 unary, +1 => postfix unary, 0 => a 0-arg operator func, non-number =>
248 as determined by `calculator-unary-style' (the default); 278 postfix/prefix as determined by `calculator-unary-style' (the
279 default);
249 280
2505. The function's precedence - should be in the range of 1=lowest to 2815. The function's precedence - should be in the range of 1 (lowest) to
251 9=highest (optional, defaults to 1); 282 9 (highest) (optional, defaults to 1);
252 283
253It it possible have a unary prefix version of a binary operator if it 284It it possible have a unary prefix version of a binary operator if it
254comes later in this list. If the list begins with the symbol 'nobind, 285comes later in this list. If the list begins with the symbol 'nobind,
@@ -295,6 +326,12 @@ documentation for an example.")
295(defvar calculator-buffer nil 326(defvar calculator-buffer nil
296 "The current calculator buffer.") 327 "The current calculator buffer.")
297 328
329(defvar calculator-eng-extra nil
330 "Internal value used by `calculator-eng-display'.")
331
332(defvar calculator-eng-tmp-show nil
333 "Internal value used by `calculator-eng-display'.")
334
298(defvar calculator-last-opXY nil 335(defvar calculator-last-opXY nil
299 "The last binary operation and its arguments. 336 "The last binary operation and its arguments.
300Used for repeating operations in calculator-repR/L.") 337Used for repeating operations in calculator-repR/L.")
@@ -307,7 +344,10 @@ Used for repeating operations in calculator-repR/L.")
307 "Saved global key map.") 344 "Saved global key map.")
308 345
309(defvar calculator-restart-other-mode nil 346(defvar calculator-restart-other-mode nil
310 "Used to hack restarting with the mode electric mode changed.") 347 "Used to hack restarting with the electric mode changed.")
348
349;;;----------------------------------------------------------------------------
350;;; Key bindings
311 351
312(defvar calculator-mode-map nil 352(defvar calculator-mode-map nil
313 "The calculator key map.") 353 "The calculator key map.")
@@ -318,16 +358,16 @@ Used for repeating operations in calculator-repR/L.")
318 (define-key map "i" nil) 358 (define-key map "i" nil)
319 (define-key map "o" nil) 359 (define-key map "o" nil)
320 (let ((p 360 (let ((p
321 '(("(" "[" "{") 361 '((calculator-open-paren "[")
322 (")" "]" "}") 362 (calculator-close-paren "]")
323 (calculator-op-or-exp "+" "-" [kp-add] [kp-subtract]) 363 (calculator-op-or-exp "+" "-" [kp-add] [kp-subtract])
324 (calculator-digit "0" "1" "2" "3" "4" "5" "6" "7" "8" 364 (calculator-digit "0" "1" "2" "3" "4" "5" "6" "7" "8"
325 "9" "a" "b" "c" "d" "f" 365 "9" "a" "b" "c" "d" "f"
326 [kp-0] [kp-1] [kp-2] [kp-3] [kp-4] 366 [kp-0] [kp-1] [kp-2] [kp-3] [kp-4]
327 [kp-5] [kp-6] [kp-7] [kp-8] [kp-9]) 367 [kp-5] [kp-6] [kp-7] [kp-8] [kp-9])
328 (calculator-op [kp-divide] [kp-multiply]) 368 (calculator-op [kp-divide] [kp-multiply])
329 (calculator-decimal "." [kp-decimal]) 369 (calculator-decimal "." [kp-decimal])
330 (calculator-exp "e") 370 (calculator-exp "e")
331 (calculator-dec/deg-mode "D") 371 (calculator-dec/deg-mode "D")
332 (calculator-set-register "s") 372 (calculator-set-register "s")
333 (calculator-get-register "g") 373 (calculator-get-register "g")
@@ -336,16 +376,20 @@ Used for repeating operations in calculator-repR/L.")
336 "iD" "iH" "iX" "iO" "iB") 376 "iD" "iH" "iX" "iO" "iB")
337 (calculator-radix-output-mode "od" "oh" "ox" "oo" "ob" 377 (calculator-radix-output-mode "od" "oh" "ox" "oo" "ob"
338 "oD" "oH" "oX" "oO" "oB") 378 "oD" "oH" "oX" "oO" "oB")
379 (calculator-rotate-displayer "'")
380 (calculator-rotate-displayer-back "\"")
381 (calculator-displayer-left "{")
382 (calculator-displayer-right "}")
339 (calculator-saved-up [up] [?\C-p]) 383 (calculator-saved-up [up] [?\C-p])
340 (calculator-saved-down [down] [?\C-n]) 384 (calculator-saved-down [down] [?\C-n])
341 (calculator-quit "q" [?\C-g]) 385 (calculator-quit "q" [?\C-g])
342 ("=" [enter] [linefeed] [kp-enter] 386 (calculator-enter [enter] [linefeed] [kp-enter]
343 [?\r] [?\n]) 387 [return] [?\r] [?\n])
344 (calculator-save-on-list " " [space]) 388 (calculator-save-on-list " " [space])
345 (calculator-clear-saved [?\C-c] [(control delete)]) 389 (calculator-clear-saved [?\C-c] [(control delete)])
346 (calculator-save-and-quit [(control return)] 390 (calculator-save-and-quit [(control return)]
347 [(control kp-enter)]) 391 [(control kp-enter)])
348 (calculator-paste [insert] [(shift insert)]) 392 (calculator-paste [insert] [(shift insert)] [mouse-2])
349 (calculator-clear [delete] [?\C-?] [?\C-d]) 393 (calculator-clear [delete] [?\C-?] [?\C-d])
350 (calculator-help [?h] [??] [f1] [help]) 394 (calculator-help [?h] [??] [f1] [help])
351 (calculator-copy [(control insert)]) 395 (calculator-copy [(control insert)])
@@ -482,13 +526,26 @@ Used for repeating operations in calculator-repR/L.")
482 ,@(mapcar (lambda (x) (nth 1 x)) radix-selectors) 526 ,@(mapcar (lambda (x) (nth 1 x)) radix-selectors)
483 "---" 527 "---"
484 ,@(mapcar (lambda (x) (nth 2 x)) radix-selectors))) 528 ,@(mapcar (lambda (x) (nth 2 x)) radix-selectors)))
529 ("Decimal Dislpay"
530 ,@(mapcar (lambda (d)
531 (vector (cadr d)
532 ;; Note: inserts actual object here
533 `(calculator-rotate-displayer ',d)))
534 calculator-displayers)
535 "---"
536 ["Change Display Left" calculator-displayer-left]
537 ["Change Display Right" calculator-displayer-right])
485 "---" 538 "---"
486 ["Copy+Quit" calculator-save-and-quit] 539 ["Copy+Quit" calculator-save-and-quit]
487 ["Quit" calculator-quit])))) 540 ["Quit" calculator-quit]))))
488 (setq calculator-mode-map map))) 541 (setq calculator-mode-map map)))
489 542
543;;;----------------------------------------------------------------------------
544;;; Startup and mode stuff
545
490(defun calculator-mode () 546(defun calculator-mode ()
491 "A simple pocket calculator in Emacs. 547 ;; this help is also used as the major help screen
548 "A [not so] simple calculator for Emacs.
492 549
493This calculator is used in the same way as other popular calculators 550This calculator is used in the same way as other popular calculators
494like xcalc or calc.exe - but using an Emacs interface. 551like xcalc or calc.exe - but using an Emacs interface.
@@ -544,6 +601,11 @@ The prompt indicates the current modes:
544* \"=?\": (? is B/O/H) the display radix (when input is decimal); 601* \"=?\": (? is B/O/H) the display radix (when input is decimal);
545* \"??\": (? is D/B/O/H) 1st char for input radix, 2nd for display. 602* \"??\": (? is D/B/O/H) 1st char for input radix, 2nd for display.
546 603
604Also, the quote character can be used to switch display modes for
605decimal numbers (double-quote rotates back), and the two brace
606characters (\"{\" and \"}\" change display parameters that these
607displayers use (if they handle such).
608
547Values can be saved for future reference in either a list of saved 609Values can be saved for future reference in either a list of saved
548values, or in registers. 610values, or in registers.
549 611
@@ -581,9 +643,11 @@ more information.
581 (use-local-map calculator-mode-map) 643 (use-local-map calculator-mode-map)
582 (run-hooks 'calculator-mode-hook)) 644 (run-hooks 'calculator-mode-hook))
583 645
646(eval-when-compile (require 'electric) (require 'ehelp))
647
584;;;###autoload 648;;;###autoload
585(defun calculator () 649(defun calculator ()
586 "Run the pocket calculator. 650 "Run the Emacs calculator.
587See the documentation for `calculator-mode' for more information." 651See the documentation for `calculator-mode' for more information."
588 (interactive) 652 (interactive)
589 (if calculator-restart-other-mode 653 (if calculator-restart-other-mode
@@ -592,7 +656,7 @@ See the documentation for `calculator-mode' for more information."
592 (progn (calculator-add-operators calculator-initial-operators) 656 (progn (calculator-add-operators calculator-initial-operators)
593 (setq calculator-initial-operators nil) 657 (setq calculator-initial-operators nil)
594 ;; don't change this since it is a customization variable, 658 ;; don't change this since it is a customization variable,
595 ;; its set function will add any new operators. 659 ;; its set function will add any new operators
596 (calculator-add-operators calculator-user-operators))) 660 (calculator-add-operators calculator-user-operators)))
597 (if calculator-electric-mode 661 (if calculator-electric-mode
598 (save-window-excursion 662 (save-window-excursion
@@ -632,14 +696,16 @@ See the documentation for `calculator-mode' for more information."
632 (let ((split-window-keep-point nil) 696 (let ((split-window-keep-point nil)
633 (window-min-height 2)) 697 (window-min-height 2))
634 (select-window 698 (select-window
635 ;; Maybe leave two lines for our window because 699 ;; maybe leave two lines for our window because
636 ;; of the normal `raised' modeline in Emacs 21. 700 ;; of the normal `raised' modeline in Emacs 21
637 (split-window-vertically 701 (split-window-vertically
638 (- (window-height) 702 (- (window-height)
639 (if (plist-get (face-attr-construct 'modeline) 703 (if (and
640 :box) 704 (fboundp 'face-attr-construct)
641 3 705 (plist-get (face-attr-construct 'modeline)
642 2)))) 706 :box))
707 3
708 2))))
643 (switch-to-buffer 709 (switch-to-buffer
644 (get-buffer-create "*calculator*")))))) 710 (get-buffer-create "*calculator*"))))))
645 (set-buffer calculator-buffer) 711 (set-buffer calculator-buffer)
@@ -650,6 +716,9 @@ See the documentation for `calculator-mode' for more information."
650 (if (and calculator-restart-other-mode calculator-electric-mode) 716 (if (and calculator-restart-other-mode calculator-electric-mode)
651 (calculator))) 717 (calculator)))
652 718
719;;;----------------------------------------------------------------------------
720;;; Operatos
721
653(defun calculator-op-arity (op) 722(defun calculator-op-arity (op)
654 "Return OP's arity, 2, +1 or -1." 723 "Return OP's arity, 2, +1 or -1."
655 (let ((arity (or (nth 3 op) 'x))) 724 (let ((arity (or (nth 3 op) 'x)))
@@ -690,6 +759,9 @@ Adds MORE-OPS to `calculator-operator', called initially to handle
690 (setq calculator-operators 759 (setq calculator-operators
691 (append (nreverse added-ops) calculator-operators)))) 760 (append (nreverse added-ops) calculator-operators))))
692 761
762;;;----------------------------------------------------------------------------
763;;; Display stuff
764
693(defun calculator-reset () 765(defun calculator-reset ()
694 "Reset calculator variables." 766 "Reset calculator variables."
695 (or calculator-restart-other-mode 767 (or calculator-restart-other-mode
@@ -769,12 +841,155 @@ The string is set not to exceed the screen width."
769 ((string-match "\\.[0-9]\\|[eE]" calculator-curnum) 841 ((string-match "\\.[0-9]\\|[eE]" calculator-curnum)
770 calculator-curnum) 842 calculator-curnum)
771 ((string-match "\\." calculator-curnum) 843 ((string-match "\\." calculator-curnum)
772 ;; do this because Emacs reads "23." as an integer. 844 ;; do this because Emacs reads "23." as an integer
773 (concat calculator-curnum "0")) 845 (concat calculator-curnum "0"))
774 ((stringp calculator-curnum) 846 ((stringp calculator-curnum)
775 (concat calculator-curnum ".0")) 847 (concat calculator-curnum ".0"))
776 (t "0.0")))))) 848 (t "0.0"))))))
777 849
850(defun calculator-rotate-displayer (&optional new-disp)
851 "Switch to the next displayer on the `calculator-displayers' list.
852Can be called with an optional argument NEW-DISP to force rotation to
853that argument."
854 (interactive)
855 (setq calculator-displayers
856 (if (and new-disp (memq new-disp calculator-displayers))
857 (let ((tmp nil))
858 (while (not (eq (car calculator-displayers) new-disp))
859 (setq tmp (cons (car calculator-displayers) tmp))
860 (setq calculator-displayers (cdr calculator-displayers)))
861 (setq calculator-displayers
862 (nconc calculator-displayers (nreverse tmp))))
863 (nconc (cdr calculator-displayers)
864 (list (car calculator-displayers)))))
865 (message "Using %s." (cadr (car calculator-displayers)))
866 (if calculator-electric-mode
867 (progn (sit-for 1) (message nil)))
868 (calculator-enter))
869
870(defun calculator-rotate-displayer-back ()
871 "Like `calculator-rotate-displayer', but rotates modes back."
872 (interactive)
873 (calculator-rotate-displayer (car (last calculator-displayers))))
874
875(defun calculator-displayer-left ()
876 "Send the current displayer function a 'left argument.
877This is used to modify display arguments (if the current displayer
878function supports this)."
879 (interactive)
880 (and (car calculator-displayers)
881 (let ((disp (caar calculator-displayers)))
882 (cond ((symbolp disp) (funcall disp 'left))
883 ((and (consp disp) (eq 'std (car disp)))
884 (calculator-standard-displayer 'left (cadr disp)))))))
885
886(defun calculator-displayer-right ()
887 "Send the current displayer function a 'right argument.
888This is used to modify display arguments (if the current displayer
889function supports this)."
890 (interactive)
891 (and (car calculator-displayers)
892 (let ((disp (caar calculator-displayers)))
893 (cond ((symbolp disp) (funcall disp 'right))
894 ((and (consp disp) (eq 'std (car disp)))
895 (calculator-standard-displayer 'right (cadr disp)))))))
896
897(defun calculator-remove-zeros (numstr)
898 "Get a number string NUMSTR and remove unnecessary zeroes.
899the behavior of this function is controlled by
900`calculator-remove-zeros'."
901 (cond ((and (eq calculator-remove-zeros t)
902 (string-match "\\.0+\\([eE][+-]?[0-9]*\\)?$" numstr))
903 ;; remove all redundant zeros leaving an integer
904 (if (match-beginning 1)
905 (concat (substring numstr 0 (match-beginning 0))
906 (match-string 1 numstr))
907 (substring numstr 0 (match-beginning 0))))
908 ((and calculator-remove-zeros
909 (string-match
910 "\\..\\([0-9]*[1-9]\\)?\\(0+\\)\\([eE][+-]?[0-9]*\\)?$"
911 numstr))
912 ;; remove zeros, except for first after the "."
913 (if (match-beginning 3)
914 (concat (substring numstr 0 (match-beginning 2))
915 (match-string 3 numstr))
916 (substring numstr 0 (match-beginning 2))))
917 (t numstr)))
918
919(defun calculator-standard-displayer (num char)
920 "Standard display function, used to display NUM.
921Its behavior is determined by `calculator-number-digits' and the given
922CHAR argument (both will be used to compose a format string). If the
923char is \"n\" then this function will choose one between %f or %e, this
924is a work around %g jumping to exponential notation too fast.
925
926The special 'left and 'right symbols will make it change the current
927number of digits displayed (`calculator-number-digits').
928
929It will also remove redundant zeros from the result."
930 (if (symbolp num)
931 (cond ((eq num 'left)
932 (and (> calculator-number-digits 0)
933 (setq calculator-number-digits
934 (1- calculator-number-digits))
935 (calculator-enter)))
936 ((eq num 'right)
937 (setq calculator-number-digits
938 (1+ calculator-number-digits))
939 (calculator-enter)))
940 (let ((str (format
941 (concat "%."
942 (number-to-string calculator-number-digits)
943 (if (eq char ?n)
944 (let ((n (abs num)))
945 (if (or (< n 0.001) (> n 1e8)) "e" "f"))
946 (string char)))
947 num)))
948 (calculator-remove-zeros str))))
949
950(defun calculator-eng-display (num)
951 "Display NUM in engineering notation.
952The number of decimal digits used is controlled by
953`calculator-number-digits', so to change it at runtime you have to use
954the 'left or 'right when one of the standard modes is used."
955 (if (symbolp num)
956 (cond ((eq num 'left)
957 (setq calculator-eng-extra
958 (if calculator-eng-extra
959 (1+ calculator-eng-extra)
960 1))
961 (let ((calculator-eng-tmp-show t)) (calculator-enter)))
962 ((eq num 'right)
963 (setq calculator-eng-extra
964 (if calculator-eng-extra
965 (1- calculator-eng-extra)
966 -1))
967 (let ((calculator-eng-tmp-show t)) (calculator-enter))))
968 (let ((exp 0))
969 (and (not (= 0 num))
970 (progn
971 (while (< (abs num) 1.0)
972 (setq num (* num 1000.0)) (setq exp (- exp 3)))
973 (while (> (abs num) 999.0)
974 (setq num (/ num 1000.0)) (setq exp (+ exp 3)))
975 (and calculator-eng-tmp-show
976 (not (= 0 calculator-eng-extra))
977 (let ((i calculator-eng-extra))
978 (while (> i 0)
979 (setq num (* num 1000.0)) (setq exp (- exp 3))
980 (setq i (1- i)))
981 (while (< i 0)
982 (setq num (/ num 1000.0)) (setq exp (+ exp 3))
983 (setq i (1+ i)))))))
984 (or calculator-eng-tmp-show (setq calculator-eng-extra nil))
985 (let ((str (format (concat "%." calculator-number-digits "f")
986 num)))
987 (concat (let ((calculator-remove-zeros
988 ;; make sure we don't leave integers
989 (and calculator-remove-zeros 'x)))
990 (calculator-remove-zeros str))
991 "e" (number-to-string exp))))))
992
778(defun calculator-num-to-string (num) 993(defun calculator-num-to-string (num)
779 "Convert NUM to a displayable string." 994 "Convert NUM to a displayable string."
780 (cond 995 (cond
@@ -799,21 +1014,20 @@ The string is set not to exceed the screen width."
799 (if (and (not calculator-2s-complement) (< num 0)) 1014 (if (and (not calculator-2s-complement) (< num 0))
800 (concat "-" str) 1015 (concat "-" str)
801 str)))) 1016 str))))
802 ((and (numberp num) 1017 ((and (numberp num) (car calculator-displayers))
803 ;; is this a normal-range number? 1018 (let ((disp (if (= 1 (length calculator-stack))
804 (>= (abs num) calculator-number-exp-llimit) 1019 ;; customizable display for a single value
805 (< (abs num) calculator-number-exp-ulimit)) 1020 (caar calculator-displayers)
806 (let ((str (format calculator-number-format num))) 1021 calculator-displayer)))
807 (cond 1022 (cond ((stringp disp) (format disp num))
808 ((and calculator-show-integers (string-match "\\.?0+$" str)) 1023 ((symbolp disp) (funcall disp num))
809 ;; remove all redundant zeros 1024 ((and (consp disp)
810 (substring str 0 (match-beginning 0))) 1025 (eq 'std (car disp)))
811 ((and (not calculator-show-integers) 1026 (calculator-standard-displayer
812 (string-match "\\..\\(.*[^0]\\)?\\(0+\\)$" str)) 1027 num (cadr disp)))
813 ;; remove zeros, except for first after the "." 1028 ((listp disp) (eval disp))
814 (substring str 0 (match-beginning 2))) 1029 (t (prin1-to-string num t)))))
815 (t str)))) 1030 ;; operators are printed here
816 ((numberp num) (format calculator-number-exp-format num))
817 (t (prin1-to-string (nth 1 num) t)))) 1031 (t (prin1-to-string (nth 1 num) t))))
818 1032
819(defun calculator-update-display (&optional force) 1033(defun calculator-update-display (&optional force)
@@ -851,6 +1065,9 @@ If optional argument FORCE is non-nil, don't use the cached string."
851 (goto-char (1+ (length calculator-prompt))) 1065 (goto-char (1+ (length calculator-prompt)))
852 (goto-char (1- (point))))) 1066 (goto-char (1- (point)))))
853 1067
1068;;;----------------------------------------------------------------------------
1069;;; Stack computations
1070
854(defun calculator-reduce-stack (prec) 1071(defun calculator-reduce-stack (prec)
855 "Reduce the stack using top operator. 1072 "Reduce the stack using top operator.
856PREC is a precedence - reduce everything with higher precedence." 1073PREC is a precedence - reduce everything with higher precedence."
@@ -936,12 +1153,51 @@ PREC is a precedence - reduce everything with higher precedence."
936 (t ;; no more iterations 1153 (t ;; no more iterations
937 nil)))) 1154 nil))))
938 1155
1156(defun calculator-funcall (f &optional X Y)
1157 "If F is a symbol, evaluate (F X Y).
1158Otherwise, it should be a list, evaluate it with X, Y bound to the
1159arguments."
1160 ;; remember binary ops for calculator-repR/L
1161 (if Y (setq calculator-last-opXY (list f X Y)))
1162 (condition-case nil
1163 ;; there used to be code here that returns 0 if the result was
1164 ;; smaller than calculator-epsilon (1e-15). I don't think this is
1165 ;; necessary now.
1166 (if (symbolp f)
1167 (cond ((and X Y) (funcall f X Y))
1168 (X (funcall f X))
1169 (t (funcall f)))
1170 ;; f is an expression
1171 (let* ((__f__ f) ; so we can get this value below...
1172 (TX (calculator-truncate X))
1173 (TY (and Y (calculator-truncate Y)))
1174 (DX (if calculator-deg (/ (* X pi) 180) X))
1175 (L calculator-saved-list)
1176 (Fbound (fboundp 'F))
1177 (Fsave (and Fbound (symbol-function 'F)))
1178 (Dbound (fboundp 'D))
1179 (Dsave (and Dbound (symbol-function 'D))))
1180 ;; a shortened version of flet
1181 (fset 'F (function
1182 (lambda (&optional x y)
1183 (calculator-funcall __f__ x y))))
1184 (fset 'D (function
1185 (lambda (x)
1186 (if calculator-deg (/ (* x 180) pi) x))))
1187 (unwind-protect (eval f)
1188 (if Fbound (fset 'F Fsave) (fmakunbound 'F))
1189 (if Dbound (fset 'D Dsave) (fmakunbound 'D)))))
1190 (error 0)))
1191
939(eval-when-compile ; silence the compiler 1192(eval-when-compile ; silence the compiler
940 (or (fboundp 'event-key) 1193 (or (fboundp 'event-key)
941 (defun event-key (&rest _) nil)) 1194 (defun event-key (&rest _) nil))
942 (or (fboundp 'key-press-event-p) 1195 (or (fboundp 'key-press-event-p)
943 (defun key-press-event-p (&rest _) nil))) 1196 (defun key-press-event-p (&rest _) nil)))
944 1197
1198;;;----------------------------------------------------------------------------
1199;;; Input interaction
1200
945(defun calculator-last-input (&optional keys) 1201(defun calculator-last-input (&optional keys)
946 "Last char (or event or event sequence) that was read. 1202 "Last char (or event or event sequence) that was read.
947Optional string argument KEYS will force using it as the keys entered." 1203Optional string argument KEYS will force using it as the keys entered."
@@ -958,7 +1214,7 @@ Optional string argument KEYS will force using it as the keys entered."
958 ;; if Emacs will someday have a event-key, then this would 1214 ;; if Emacs will someday have a event-key, then this would
959 ;; probably be modified anyway 1215 ;; probably be modified anyway
960 (and (fboundp 'event-key) (key-press-event-p k) 1216 (and (fboundp 'event-key) (key-press-event-p k)
961 (setq k (event-key k))) 1217 (event-key k) (setq k (event-key k)))
962 ;; assume all symbols are translatable with an ascii-character 1218 ;; assume all symbols are translatable with an ascii-character
963 (and (symbolp k) 1219 (and (symbolp k)
964 (setq k (or (get k 'ascii-character) ? ))) 1220 (setq k (or (get k 'ascii-character) ? )))
@@ -973,7 +1229,7 @@ OP is the operator (if any) that caused this call."
973 (= -1 (calculator-op-arity op)) 1229 (= -1 (calculator-op-arity op))
974 (= 0 (calculator-op-arity op)))) 1230 (= 0 (calculator-op-arity op))))
975 ;; reset if last calc finished, and now get a num or prefix or 0-ary 1231 ;; reset if last calc finished, and now get a num or prefix or 0-ary
976 ;; op. 1232 ;; op
977 (calculator-reset)) 1233 (calculator-reset))
978 (setq calculator-display-fragile nil)) 1234 (setq calculator-display-fragile nil))
979 1235
@@ -989,7 +1245,7 @@ OP is the operator (if any) that caused this call."
989 ((eq calculator-input-radix 'oct) (<= inp ?7)) 1245 ((eq calculator-input-radix 'oct) (<= inp ?7))
990 (t t))) 1246 (t t)))
991 ;; enter digit if starting a new computation or have an op on the 1247 ;; enter digit if starting a new computation or have an op on the
992 ;; stack. 1248 ;; stack
993 (progn 1249 (progn
994 (calculator-clear-fragile) 1250 (calculator-clear-fragile)
995 (let ((digit (upcase (char-to-string inp)))) 1251 (let ((digit (upcase (char-to-string inp))))
@@ -1008,7 +1264,7 @@ OP is the operator (if any) that caused this call."
1008 (not (and calculator-curnum 1264 (not (and calculator-curnum
1009 (string-match "[.eE]" calculator-curnum)))) 1265 (string-match "[.eE]" calculator-curnum))))
1010 ;; enter the period on the same condition as a digit, only if no 1266 ;; enter the period on the same condition as a digit, only if no
1011 ;; period or exponent entered yet. 1267 ;; period or exponent entered yet
1012 (progn 1268 (progn
1013 (calculator-clear-fragile) 1269 (calculator-clear-fragile)
1014 (setq calculator-curnum (concat (or calculator-curnum "0") ".")) 1270 (setq calculator-curnum (concat (or calculator-curnum "0") "."))
@@ -1023,7 +1279,7 @@ OP is the operator (if any) that caused this call."
1023 (not (numberp (car calculator-stack)))) 1279 (not (numberp (car calculator-stack))))
1024 (not (and calculator-curnum 1280 (not (and calculator-curnum
1025 (string-match "[eE]" calculator-curnum)))) 1281 (string-match "[eE]" calculator-curnum))))
1026 ;; same condition as above, also no E so far. 1282 ;; same condition as above, also no E so far
1027 (progn 1283 (progn
1028 (calculator-clear-fragile) 1284 (calculator-clear-fragile)
1029 (setq calculator-curnum (concat (or calculator-curnum "1") "e")) 1285 (setq calculator-curnum (concat (or calculator-curnum "1") "e"))
@@ -1033,53 +1289,66 @@ OP is the operator (if any) that caused this call."
1033 "Enter an operator on the stack, doing all necessary reductions. 1289 "Enter an operator on the stack, doing all necessary reductions.
1034Optional string argument KEYS will force using it as the keys entered." 1290Optional string argument KEYS will force using it as the keys entered."
1035 (interactive) 1291 (interactive)
1036 (let* ((last-inp (calculator-last-input keys)) 1292 (catch 'op-error
1037 (op (assoc last-inp calculator-operators))) 1293 (let* ((last-inp (calculator-last-input keys))
1038 (calculator-clear-fragile op) 1294 (op (assoc last-inp calculator-operators)))
1039 (if (and calculator-curnum (/= (calculator-op-arity op) 0)) 1295 (calculator-clear-fragile op)
1040 (setq calculator-stack 1296 (if (and calculator-curnum (/= (calculator-op-arity op) 0))
1041 (cons (calculator-curnum-value) calculator-stack))) 1297 (setq calculator-stack
1042 (setq calculator-curnum nil) 1298 (cons (calculator-curnum-value) calculator-stack)))
1043 (if (and (= 2 (calculator-op-arity op)) 1299 (setq calculator-curnum nil)
1044 (not (and calculator-stack 1300 (if (and (= 2 (calculator-op-arity op))
1045 (numberp (nth 0 calculator-stack))))) 1301 (not (and calculator-stack
1046 ;; we have a binary operator but no number - search for a prefix 1302 (numberp (nth 0 calculator-stack)))))
1047 ;; version 1303 ;; we have a binary operator but no number - search for a prefix
1048 (let ((rest-ops calculator-operators)) 1304 ;; version
1049 (while (not (equal last-inp (car (car rest-ops)))) 1305 (let ((rest-ops calculator-operators))
1050 (setq rest-ops (cdr rest-ops))) 1306 (while (not (equal last-inp (car (car rest-ops))))
1051 (setq op (assoc last-inp (cdr rest-ops))) 1307 (setq rest-ops (cdr rest-ops)))
1052 (if (not (and op (= -1 (calculator-op-arity op)))) 1308 (setq op (assoc last-inp (cdr rest-ops)))
1053 (error "Binary operator without a first operand")))) 1309 (if (not (and op (= -1 (calculator-op-arity op))))
1054 (calculator-reduce-stack 1310 ;;(error "Binary operator without a first operand")
1055 (cond ((eq (nth 1 op) '\() 10) 1311 (progn
1056 ((eq (nth 1 op) '\)) 0) 1312 (message "Binary operator without a first operand")
1057 (t (calculator-op-prec op)))) 1313 (if calculator-electric-mode
1058 (if (or (and (= -1 (calculator-op-arity op)) 1314 (progn (sit-for 1) (message nil)))
1059 (numberp (car calculator-stack))) 1315 (throw 'op-error nil)))))
1060 (and (/= (calculator-op-arity op) -1) 1316 (calculator-reduce-stack
1061 (/= (calculator-op-arity op) 0) 1317 (cond ((eq (nth 1 op) '\() 10)
1062 (not (numberp (car calculator-stack))))) 1318 ((eq (nth 1 op) '\)) 0)
1063 (error "Unterminated expression")) 1319 (t (calculator-op-prec op))))
1064 (setq calculator-stack (cons op calculator-stack)) 1320 (if (or (and (= -1 (calculator-op-arity op))
1065 (calculator-reduce-stack (calculator-op-prec op)) 1321 (numberp (car calculator-stack)))
1066 (and (= (length calculator-stack) 1) 1322 (and (/= (calculator-op-arity op) -1)
1067 (numberp (nth 0 calculator-stack)) 1323 (/= (calculator-op-arity op) 0)
1068 ;; the display is fragile if it contains only one number 1324 (not (numberp (car calculator-stack)))))
1069 (setq calculator-display-fragile t) 1325 ;;(error "Unterminated expression")
1070 ;; add number to the saved-list 1326 (progn
1071 calculator-add-saved 1327 (message "Unterminated expression")
1072 (if (= 0 calculator-saved-ptr) 1328 (if calculator-electric-mode
1073 (setq calculator-saved-list 1329 (progn (sit-for 1) (message nil)))
1074 (cons (car calculator-stack) calculator-saved-list)) 1330 (throw 'op-error nil)))
1075 (let ((p (nthcdr (1- calculator-saved-ptr) 1331 (setq calculator-stack (cons op calculator-stack))
1076 calculator-saved-list))) 1332 (calculator-reduce-stack (calculator-op-prec op))
1077 (setcdr p (cons (car calculator-stack) (cdr p)))))) 1333 (and (= (length calculator-stack) 1)
1078 (calculator-update-display))) 1334 (numberp (nth 0 calculator-stack))
1335 ;; the display is fragile if it contains only one number
1336 (setq calculator-display-fragile t)
1337 ;; add number to the saved-list
1338 calculator-add-saved
1339 (if (= 0 calculator-saved-ptr)
1340 (setq calculator-saved-list
1341 (cons (car calculator-stack) calculator-saved-list))
1342 (let ((p (nthcdr (1- calculator-saved-ptr)
1343 calculator-saved-list)))
1344 (setcdr p (cons (car calculator-stack) (cdr p))))))
1345 (calculator-update-display))))
1079 1346
1080(defun calculator-op-or-exp () 1347(defun calculator-op-or-exp ()
1081 "Either enter an operator or a digit. 1348 "Either enter an operator or a digit.
1082Used with +/- for entering them as digits in numbers like 1e-3." 1349Used with +/- for entering them as digits in numbers like 1e-3 (there is
1350no need for negative numbers since these are handled by unary
1351operators)."
1083 (interactive) 1352 (interactive)
1084 (if (and (not calculator-display-fragile) 1353 (if (and (not calculator-display-fragile)
1085 calculator-curnum 1354 calculator-curnum
@@ -1087,6 +1356,9 @@ Used with +/- for entering them as digits in numbers like 1e-3."
1087 (calculator-digit) 1356 (calculator-digit)
1088 (calculator-op))) 1357 (calculator-op)))
1089 1358
1359;;;----------------------------------------------------------------------------
1360;;; Input/output modes (not display)
1361
1090(defun calculator-dec/deg-mode () 1362(defun calculator-dec/deg-mode ()
1091 "Set decimal mode for display & input, if decimal, toggle deg mode." 1363 "Set decimal mode for display & input, if decimal, toggle deg mode."
1092 (interactive) 1364 (interactive)
@@ -1136,6 +1408,9 @@ Optional string argument KEYS will force using it as the keys entered."
1136 calculator-char-radix)))) 1408 calculator-char-radix))))
1137 (calculator-update-display t)) 1409 (calculator-update-display t))
1138 1410
1411;;;----------------------------------------------------------------------------
1412;;; Saved values list
1413
1139(defun calculator-save-on-list () 1414(defun calculator-save-on-list ()
1140 "Evaluate current expression, put result on the saved values list." 1415 "Evaluate current expression, put result on the saved values list."
1141 (interactive) 1416 (interactive)
@@ -1146,6 +1421,7 @@ Optional string argument KEYS will force using it as the keys entered."
1146 "Clear the list of saved values in `calculator-saved-list'." 1421 "Clear the list of saved values in `calculator-saved-list'."
1147 (interactive) 1422 (interactive)
1148 (setq calculator-saved-list nil) 1423 (setq calculator-saved-list nil)
1424 (setq calculator-saved-ptr 0)
1149 (calculator-update-display t)) 1425 (calculator-update-display t))
1150 1426
1151(defun calculator-saved-move (n) 1427(defun calculator-saved-move (n)
@@ -1175,6 +1451,9 @@ Optional string argument KEYS will force using it as the keys entered."
1175 (interactive) 1451 (interactive)
1176 (calculator-saved-move -1)) 1452 (calculator-saved-move -1))
1177 1453
1454;;;----------------------------------------------------------------------------
1455;;; Misc functions
1456
1178(defun calculator-open-paren () 1457(defun calculator-open-paren ()
1179 "Equivalents of `(' use this." 1458 "Equivalents of `(' use this."
1180 (interactive) 1459 (interactive)
@@ -1231,9 +1510,9 @@ Optional string argument KEYS will force using it as the keys entered."
1231 "Copy current number to the `kill-ring'." 1510 "Copy current number to the `kill-ring'."
1232 (interactive) 1511 (interactive)
1233 (calculator-enter) 1512 (calculator-enter)
1234 ;; remove trailing .0 and spaces .0 1513 ;; remove trailing spaces and and an index
1235 (let ((s (cdr calculator-stack-display))) 1514 (let ((s (cdr calculator-stack-display)))
1236 (if (string-match "^\\(.*[^ ]\\) *$" s) 1515 (if (string-match "^\\([^ ]+\\) *\\(\\[[0-9/]+\\]\\)? *$" s)
1237 (setq s (match-string 1 s))) 1516 (setq s (match-string 1 s)))
1238 (kill-new s))) 1517 (kill-new s)))
1239 1518
@@ -1264,8 +1543,18 @@ Used by `calculator-paste' and `get-register'."
1264 "Paste a value from the `kill-ring'." 1543 "Paste a value from the `kill-ring'."
1265 (interactive) 1544 (interactive)
1266 (calculator-put-value 1545 (calculator-put-value
1267 (condition-case nil (car (read-from-string (current-kill 0))) 1546 (let ((str (current-kill 0)))
1268 (error nil)))) 1547 (if calculator-paste-decimals
1548 (progn
1549 (string-match "\\([0-9]+\\)\\(\\.[0-9]+\\)?\\(e[0-9]+\\)?" str)
1550 (if (or (match-string 1 str)
1551 (match-string 2 str)
1552 (match-string 3 str))
1553 (setq str (concat (match-string 1 str)
1554 (or (match-string 2 str) ".0")
1555 (match-string 3 str))))))
1556 (condition-case nil (car (read-from-string str))
1557 (error nil)))))
1269 1558
1270(defun calculator-get-register (reg) 1559(defun calculator-get-register (reg)
1271 "Get a value from a register REG." 1560 "Get a value from a register REG."
@@ -1279,8 +1568,8 @@ Used by `calculator-paste' and `get-register'."
1279 + - * / \\(div) %(rem) _(-X,postfix) ;(1/X,postfix) ^(exp) L(og) 1568 + - * / \\(div) %(rem) _(-X,postfix) ;(1/X,postfix) ^(exp) L(og)
1280 Q(sqrt) !(fact) S(in) C(os) T(an) |(or) #(xor) &(and) ~(not) 1569 Q(sqrt) !(fact) S(in) C(os) T(an) |(or) #(xor) &(and) ~(not)
1281* >/< repeats last binary operation with its 2nd (1st) arg as postfix op 1570* >/< repeats last binary operation with its 2nd (1st) arg as postfix op
1282* I inverses next trig function 1571* I inverses next trig function * '/\"/{} - display/display args
1283* D - switch to all-decimal mode, or toggles deg/rad mode 1572* D - switch to all-decimal, or toggle deg/rad mode
1284* B/O/H/X - binary/octal/hex mode for i/o (X is a shortcut for H) 1573* B/O/H/X - binary/octal/hex mode for i/o (X is a shortcut for H)
1285* i/o - prefix for d/b/o/x - set only input/output modes 1574* i/o - prefix for d/b/o/x - set only input/output modes
1286* enter/= - evaluate current expr. * s/g - set/get a register 1575* enter/= - evaluate current expr. * s/g - set/get a register
@@ -1343,43 +1632,6 @@ Used by `calculator-paste' and `get-register'."
1343 (calculator-copy) 1632 (calculator-copy)
1344 (calculator-quit)) 1633 (calculator-quit))
1345 1634
1346(defun calculator-funcall (f &optional X Y)
1347 "If F is a symbol, evaluate (F X Y).
1348Otherwise, it should be a list, evaluate it with X, Y bound to the
1349arguments."
1350 ;; remember binary ops for calculator-repR/L
1351 (if Y (setq calculator-last-opXY (list f X Y)))
1352 (condition-case nil
1353 (let ((result
1354 (if (symbolp f)
1355 (cond ((and X Y) (funcall f X Y))
1356 (X (funcall f X))
1357 (t (funcall f)))
1358 ;; f is an expression
1359 (let* ((__f__ f) ; so we can get this value below...
1360 (TX (calculator-truncate X))
1361 (TY (and Y (calculator-truncate Y)))
1362 (DX (if calculator-deg (/ (* X pi) 180) X))
1363 (L calculator-saved-list)
1364 (Fbound (fboundp 'F))
1365 (Fsave (and Fbound (symbol-function 'F)))
1366 (Dbound (fboundp 'D))
1367 (Dsave (and Dbound (symbol-function 'D))))
1368 ;; a shortened version of flet
1369 (fset 'F (function
1370 (lambda (&optional x y)
1371 (calculator-funcall __f__ x y))))
1372 (fset 'D (function
1373 (lambda (x)
1374 (if calculator-deg (/ (* x 180) pi) x))))
1375 (unwind-protect (eval f)
1376 (if Fbound (fset 'F Fsave) (fmakunbound 'F))
1377 (if Dbound (fset 'D Dsave) (fmakunbound 'D)))))))
1378 (if (< (abs result) calculator-epsilon)
1379 0
1380 result))
1381 (error 0)))
1382
1383(defun calculator-repR (x) 1635(defun calculator-repR (x)
1384 "Repeats the last binary operation with its second argument and X. 1636 "Repeats the last binary operation with its second argument and X.
1385To use this, apply a binary operator (evaluate it), then call this." 1637To use this, apply a binary operator (evaluate it), then call this."