Mercurial > emacs
annotate lisp/calculator.el @ 56811:694cd033cd0d
Make "GNU GENERAL PUBLIC LICENSE" an appendix.
Rearrange order of nodes and sections such that both "GNU GENERAL
PUBLIC LICENSE" and "GNU Free Documentation License" appear at the
end, as appropriate for appendices.
(Acknowledgments): Use `@unnumberedsec'.
author | Luc Teirlinck <teirllm@auburn.edu> |
---|---|
date | Fri, 27 Aug 2004 23:36:38 +0000 |
parents | 695cf19ef79e |
children | 956483cc3659 375f2633d815 |
rev | line source |
---|---|
38436
b174db545cfd
Some fixes to follow coding conventions.
Pavel Janík <Pavel@Janik.cz>
parents:
35314
diff
changeset
|
1 ;;; calculator.el --- a [not so] simple calculator for Emacs |
27587 | 2 |
39430
48633cf4ce7c
(calculator-copy-displayer): New user-option.
Gerd Moellmann <gerd@gnu.org>
parents:
38436
diff
changeset
|
3 ;; Copyright (C) 1998, 2000, 2001 by Free Software Foundation, Inc. |
27587 | 4 |
35314 | 5 ;; Author: Eli Barzilay <eli@barzilay.org> |
27587 | 6 ;; Keywords: tools, convenience |
7 | |
8 ;; This file is part of GNU Emacs. | |
9 | |
10 ;; GNU Emacs is free software; you can redistribute it and/or modify it | |
11 ;; under the terms of the GNU General Public License as published by the | |
12 ;; Free Software Foundation; either version 2, or (at your option) any | |
13 ;; later version. | |
14 | |
15 ;; GNU Emacs is distributed in the hope that it will be useful, but | |
16 ;; WITHOUT ANY WARRANTY; without even the implied warranty of | |
17 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
18 ;; General Public License for more details. | |
19 | |
20 ;; You should have received a copy of the GNU General Public License | |
21 ;; along with GNU Emacs; see the file COPYING. If not, write to the | |
22 ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, | |
23 ;; MA 02111-1307, USA. | |
24 | |
33631 | 25 ;;;===================================================================== |
27587 | 26 ;;; Commentary: |
27 ;; | |
33491 | 28 ;; A calculator for Emacs. |
33551 | 29 ;; Why should you reach for your mouse to get xcalc (calc.exe, gcalc or |
33491 | 30 ;; whatever), when you have Emacs running already? |
27587 | 31 ;; |
32 ;; If this is not part of your Emacs distribution, then simply bind | |
33 ;; `calculator' to a key and make it an autoloaded function, e.g.: | |
34 ;; (autoload 'calculator "calculator" | |
33491 | 35 ;; "Run the Emacs calculator." t) |
27587 | 36 ;; (global-set-key [(control return)] 'calculator) |
37 ;; | |
33491 | 38 ;; Written by Eli Barzilay: Maze is Life! eli@barzilay.org |
39 ;; http://www.barzilay.org/ | |
27587 | 40 ;; |
41 ;; For latest version, check | |
33491 | 42 ;; http://www.barzilay.org/misc/calculator.el |
39430
48633cf4ce7c
(calculator-copy-displayer): New user-option.
Gerd Moellmann <gerd@gnu.org>
parents:
38436
diff
changeset
|
43 ;; |
48633cf4ce7c
(calculator-copy-displayer): New user-option.
Gerd Moellmann <gerd@gnu.org>
parents:
38436
diff
changeset
|
44 |
48633cf4ce7c
(calculator-copy-displayer): New user-option.
Gerd Moellmann <gerd@gnu.org>
parents:
38436
diff
changeset
|
45 ;;; History: |
48633cf4ce7c
(calculator-copy-displayer): New user-option.
Gerd Moellmann <gerd@gnu.org>
parents:
38436
diff
changeset
|
46 ;; I hate history. |
27587 | 47 |
48 (eval-and-compile | |
49 (if (fboundp 'defgroup) nil | |
50 (defmacro defgroup (&rest forms) nil) | |
51 (defmacro defcustom (s v d &rest r) (list 'defvar s v d)))) | |
52 | |
33631 | 53 ;;;===================================================================== |
27587 | 54 ;;; Customization: |
55 | |
56 (defgroup calculator nil | |
33491 | 57 "Simple Emacs calculator." |
27587 | 58 :prefix "calculator" |
30889 | 59 :version "21.1" |
27587 | 60 :group 'tools |
61 :group 'convenience) | |
62 | |
63 (defcustom calculator-electric-mode nil | |
64 "*Run `calculator' electrically, in the echo area. | |
33491 | 65 Electric mode saves some place but changes the way you interact with the |
66 calculator." | |
27587 | 67 :type 'boolean |
68 :group 'calculator) | |
69 | |
27904
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
70 (defcustom calculator-use-menu t |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
71 "*Make `calculator' create a menu. |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
72 Note that this requires easymenu. Must be set before loading." |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
73 :type 'boolean |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
74 :group 'calculator) |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
75 |
27587 | 76 (defcustom calculator-bind-escape nil |
77 "*If non-nil, set escape to exit the calculator." | |
78 :type 'boolean | |
79 :group 'calculator) | |
80 | |
81 (defcustom calculator-unary-style 'postfix | |
82 "*Value is either 'prefix or 'postfix. | |
83 This determines the default behavior of unary operators." | |
84 :type '(choice (const prefix) (const postfix)) | |
85 :group 'calculator) | |
86 | |
33491 | 87 (defcustom calculator-prompt "Calc=%s> " |
88 "*The prompt used by the Emacs calculator. | |
27587 | 89 It should contain a \"%s\" somewhere that will indicate the i/o radixes, |
90 this string will be a two-character string as described in the | |
91 documentation for `calculator-mode'." | |
92 :type 'string | |
93 :group 'calculator) | |
94 | |
33491 | 95 (defcustom calculator-number-digits 3 |
96 "*The calculator's number of digits used for standard display. | |
97 Used by the `calculator-standard-display' function - it will use the | |
98 format string \"%.NC\" where this number is N and C is a character given | |
99 at runtime." | |
35214
668b2bcf528a
(calculator-number-digits): Fix :type.
Dave Love <fx@gnu.org>
parents:
33631
diff
changeset
|
100 :type 'integer |
27587 | 101 :group 'calculator) |
102 | |
33491 | 103 (defcustom calculator-remove-zeros t |
104 "*Non-nil value means delete all redundant zero decimal digits. | |
105 If this value is not t, and not nil, redundant zeros are removed except | |
106 for one and if it is nil, nothing is removed. | |
107 Used by the `calculator-remove-zeros' function." | |
108 :type '(choice (const t) (const leave-decimal) (const nil)) | |
27587 | 109 :group 'calculator) |
110 | |
33491 | 111 (defcustom calculator-displayer '(std ?n) |
112 "*A displayer specification for numerical values. | |
113 This is the displayer used to show all numbers in an expression. Result | |
114 values will be displayed according to the first element of | |
115 `calculator-displayers'. | |
116 | |
117 The displayer is a symbol, a string or an expression. A symbol should | |
118 be the name of a one-argument function, a string is used with a single | |
119 argument and an expression will be evaluated with the variable `num' | |
120 bound to whatever should be displayed. If it is a function symbol, it | |
121 should be able to handle special symbol arguments, currently 'left and | |
122 'right which will be sent by special keys to modify display parameters | |
123 associated with the displayer function (for example to change the number | |
124 of digits displayed). | |
125 | |
126 An exception to the above is the case of the list (std C) where C is a | |
127 character, in this case the `calculator-standard-displayer' function | |
128 will be used with this character for a format string.") | |
129 | |
130 (defcustom calculator-displayers | |
43091
f18f05d77411
(calculator-displayers): Doc fixes.
Pavel Janík <Pavel@Janik.cz>
parents:
39818
diff
changeset
|
131 '(((std ?n) "Standard display, decimal point or scientific") |
33491 | 132 (calculator-eng-display "Eng display") |
133 ((std ?f) "Standard display, decimal point") | |
43091
f18f05d77411
(calculator-displayers): Doc fixes.
Pavel Janík <Pavel@Janik.cz>
parents:
39818
diff
changeset
|
134 ((std ?e) "Standard display, scientific") |
33491 | 135 ("%S" "Emacs printer")) |
136 "*A list of displayers. | |
137 Each element is a list of a displayer and a description string. The | |
43091
f18f05d77411
(calculator-displayers): Doc fixes.
Pavel Janík <Pavel@Janik.cz>
parents:
39818
diff
changeset
|
138 first element is the one which is currently used, this is for the display |
33491 | 139 of result values not values in expressions. A displayer specification |
140 is the same as the values that can be stored in `calculator-displayer'. | |
141 | |
142 `calculator-rotate-displayer' rotates this list." | |
143 :type 'sexp | |
27587 | 144 :group 'calculator) |
145 | |
33491 | 146 (defcustom calculator-paste-decimals t |
147 "*If non-nil, convert pasted integers so they have a decimal point. | |
148 This makes it possible to paste big integers since they will be read as | |
149 floats, otherwise the Emacs reader will fail on them." | |
27587 | 150 :type 'boolean |
151 :group 'calculator) | |
152 | |
39430
48633cf4ce7c
(calculator-copy-displayer): New user-option.
Gerd Moellmann <gerd@gnu.org>
parents:
38436
diff
changeset
|
153 (defcustom calculator-copy-displayer nil |
48633cf4ce7c
(calculator-copy-displayer): New user-option.
Gerd Moellmann <gerd@gnu.org>
parents:
38436
diff
changeset
|
154 "*If non-nil, this is any value that can be used for |
48633cf4ce7c
(calculator-copy-displayer): New user-option.
Gerd Moellmann <gerd@gnu.org>
parents:
38436
diff
changeset
|
155 `calculator-displayer', to format a string before copying it with |
48633cf4ce7c
(calculator-copy-displayer): New user-option.
Gerd Moellmann <gerd@gnu.org>
parents:
38436
diff
changeset
|
156 `calculator-copy'. If nil, then `calculator-displayer's normal value is |
48633cf4ce7c
(calculator-copy-displayer): New user-option.
Gerd Moellmann <gerd@gnu.org>
parents:
38436
diff
changeset
|
157 used.") |
48633cf4ce7c
(calculator-copy-displayer): New user-option.
Gerd Moellmann <gerd@gnu.org>
parents:
38436
diff
changeset
|
158 |
27587 | 159 (defcustom calculator-2s-complement nil |
160 "*If non-nil, show negative numbers in 2s complement in radix modes. | |
161 Otherwise show as a negative number." | |
162 :type 'boolean | |
163 :group 'calculator) | |
164 | |
165 (defcustom calculator-mode-hook nil | |
33491 | 166 "*List of hook functions for `calculator-mode' to run." |
27587 | 167 :type 'hook |
168 :group 'calculator) | |
169 | |
170 (defcustom calculator-user-registers nil | |
171 "*An association list of user-defined register bindings. | |
172 Each element in this list is a list of a character and a number that | |
173 will be stored in that character's register. | |
174 | |
175 For example, use this to define the golden ratio number: | |
33491 | 176 (setq calculator-user-registers '((?g . 1.61803398875))) |
177 before you load calculator." | |
27587 | 178 :type '(repeat (cons character number)) |
179 :set '(lambda (_ val) | |
180 (and (boundp 'calculator-registers) | |
181 (setq calculator-registers | |
182 (append val calculator-registers))) | |
183 (setq calculator-user-registers val)) | |
184 :group 'calculator) | |
185 | |
186 (defcustom calculator-user-operators nil | |
187 "*A list of additional operators. | |
188 This is a list in the same format as specified in the documentation for | |
189 `calculator-operators', that you can use to bind additional calculator | |
190 operators. It is probably not a good idea to modify this value with | |
191 `customize' since it is too complex... | |
192 | |
193 Examples: | |
194 | |
30889 | 195 * A very simple one, adding a postfix \"x-to-y\" conversion keys, using |
196 t as a prefix key: | |
27587 | 197 |
198 (setq calculator-user-operators | |
199 '((\"tf\" cl-to-fr (+ 32 (/ (* X 9) 5)) 1) | |
200 (\"tc\" fr-to-cl (/ (* (- X 32) 5) 9) 1) | |
201 (\"tp\" kg-to-lb (/ X 0.453592) 1) | |
202 (\"tk\" lb-to-kg (* X 0.453592) 1) | |
203 (\"tF\" mt-to-ft (/ X 0.3048) 1) | |
204 (\"tM\" ft-to-mt (* X 0.3048) 1))) | |
205 | |
206 * Using a function-like form is very simple, X for an argument (Y the | |
207 second in case of a binary operator), TX is a truncated version of X | |
208 and F does a recursive call, Here is a [very inefficient] Fibonacci | |
209 number calculation: | |
210 | |
211 (add-to-list 'calculator-user-operators | |
212 '(\"F\" fib (if (<= TX 1) | |
33491 | 213 1 |
214 (+ (F (- TX 1)) (F (- TX 2)))) 0)) | |
27587 | 215 |
216 Note that this will be either postfix or prefix, according to | |
217 `calculator-unary-style'." | |
218 :type '(repeat (list string symbol sexp integer integer)) | |
219 :group 'calculator) | |
220 | |
33631 | 221 ;;;===================================================================== |
27587 | 222 ;;; Code: |
223 | |
33631 | 224 ;;;--------------------------------------------------------------------- |
33491 | 225 ;;; Variables |
226 | |
27587 | 227 (defvar calculator-initial-operators |
27904
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
228 '(;; "+"/"-" have keybindings of themselves, not calculator-ops |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
229 ("=" = identity 1 -1) |
33491 | 230 (nobind "+" + + 2 4) |
231 (nobind "-" - - 2 4) | |
232 (nobind "+" + + -1 9) | |
233 (nobind "-" - - -1 9) | |
27904
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
234 ("(" \( identity -1 -1) |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
235 (")" \) identity +1 10) |
27587 | 236 ;; normal keys |
237 ("|" or (logior TX TY) 2 2) | |
238 ("#" xor (logxor TX TY) 2 2) | |
239 ("&" and (logand TX TY) 2 3) | |
240 ("*" * * 2 5) | |
241 ("/" / / 2 5) | |
242 ("\\" div (/ TX TY) 2 5) | |
243 ("%" rem (% TX TY) 2 5) | |
244 ("L" log log 2 6) | |
245 ("S" sin (sin DX) x 6) | |
246 ("C" cos (cos DX) x 6) | |
247 ("T" tan (tan DX) x 6) | |
248 ("IS" asin (D (asin X)) x 6) | |
249 ("IC" acos (D (acos X)) x 6) | |
250 ("IT" atan (D (atan X)) x 6) | |
251 ("Q" sqrt sqrt x 7) | |
252 ("^" ^ expt 2 7) | |
253 ("!" ! calculator-fact x 7) | |
254 (";" 1/ (/ 1 X) 1 7) | |
255 ("_" - - 1 8) | |
256 ("~" ~ (lognot TX) x 8) | |
257 (">" repR calculator-repR 1 8) | |
258 ("<" repL calculator-repL 1 8) | |
259 ("v" avg (/ (apply '+ L) (length L)) 0 8) | |
260 ("l" tot (apply '+ L) 0 8) | |
261 ) | |
262 "A list of initial operators. | |
263 This is a list in the same format as `calculator-operators'. Whenever | |
264 `calculator' starts, it looks at the value of this variable, and if it | |
265 is not empty, its contents is prepended to `calculator-operators' and | |
266 the appropriate key bindings are made. | |
267 | |
268 This variable is then reset to nil. Don't use this if you want to add | |
269 user-defined operators, use `calculator-user-operators' instead.") | |
270 | |
271 (defvar calculator-operators nil | |
272 "The calculator operators, each a list with: | |
273 | |
274 1. The key that is bound to for this operation (usually a string); | |
275 | |
276 2. The displayed symbol for this function; | |
277 | |
278 3. The function symbol, or a form that uses the variables `X' and `Y', | |
279 (if it is a binary operator), `TX' and `TY' (truncated integer | |
280 versions), `DX' (converted to radians if degrees mode is on), `D' | |
281 (function for converting radians to degrees if deg mode is on), `L' | |
282 (list of saved values), `F' (function for recursive iteration calls) | |
283 and evaluates to the function value - these variables are capital; | |
284 | |
33491 | 285 4. The function's arity, optional, one of: 2 => binary, -1 => prefix |
286 unary, +1 => postfix unary, 0 => a 0-arg operator func, non-number => | |
287 postfix/prefix as determined by `calculator-unary-style' (the | |
288 default); | |
27587 | 289 |
33491 | 290 5. The function's precedence - should be in the range of 1 (lowest) to |
291 9 (highest) (optional, defaults to 1); | |
27587 | 292 |
293 It it possible have a unary prefix version of a binary operator if it | |
294 comes later in this list. If the list begins with the symbol 'nobind, | |
295 then no key binding will take place - this is only useful for predefined | |
296 keys. | |
297 | |
298 Use `calculator-user-operators' to add operators to this list, see its | |
299 documentation for an example.") | |
300 | |
301 (defvar calculator-stack nil | |
302 "Stack contents - operations and operands.") | |
303 | |
304 (defvar calculator-curnum nil | |
305 "Current number being entered (as a string).") | |
306 | |
307 (defvar calculator-stack-display nil | |
308 "Cons of the stack and its string representation.") | |
309 | |
310 (defvar calculator-char-radix | |
311 '((?D . nil) (?B . bin) (?O . oct) (?H . hex) (?X . hex)) | |
312 "A table to convert input characters to corresponding radix symbols.") | |
313 | |
314 (defvar calculator-output-radix nil | |
315 "The mode for display, one of: nil (decimal), 'bin, 'oct or 'hex.") | |
316 | |
317 (defvar calculator-input-radix nil | |
318 "The mode for input, one of: nil (decimal), 'bin, 'oct or 'hex.") | |
319 | |
320 (defvar calculator-deg nil | |
321 "Non-nil if trig functions operate on degrees instead of radians.") | |
322 | |
323 (defvar calculator-saved-list nil | |
324 "A list of saved values collected.") | |
325 | |
326 (defvar calculator-saved-ptr 0 | |
327 "The pointer to the current saved number.") | |
328 | |
329 (defvar calculator-add-saved nil | |
330 "Bound to t when a value should be added to the saved-list.") | |
331 | |
332 (defvar calculator-display-fragile nil | |
333 "When non-nil, we see something that the next digit should replace.") | |
334 | |
335 (defvar calculator-buffer nil | |
336 "The current calculator buffer.") | |
337 | |
33491 | 338 (defvar calculator-eng-extra nil |
339 "Internal value used by `calculator-eng-display'.") | |
340 | |
341 (defvar calculator-eng-tmp-show nil | |
342 "Internal value used by `calculator-eng-display'.") | |
343 | |
27587 | 344 (defvar calculator-last-opXY nil |
345 "The last binary operation and its arguments. | |
346 Used for repeating operations in calculator-repR/L.") | |
347 | |
348 (defvar calculator-registers ; use user-bindings first | |
349 (append calculator-user-registers (list (cons ?e e) (cons ?p pi))) | |
350 "The association list of calculator register values.") | |
351 | |
352 (defvar calculator-saved-global-map nil | |
353 "Saved global key map.") | |
354 | |
27904
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
355 (defvar calculator-restart-other-mode nil |
33491 | 356 "Used to hack restarting with the electric mode changed.") |
357 | |
33631 | 358 ;;;--------------------------------------------------------------------- |
33491 | 359 ;;; Key bindings |
27904
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
360 |
27587 | 361 (defvar calculator-mode-map nil |
362 "The calculator key map.") | |
363 | |
364 (or calculator-mode-map | |
27904
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
365 (let ((map (make-sparse-keymap))) |
27587 | 366 (suppress-keymap map t) |
367 (define-key map "i" nil) | |
368 (define-key map "o" nil) | |
27904
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
369 (let ((p |
33491 | 370 '((calculator-open-paren "[") |
371 (calculator-close-paren "]") | |
372 (calculator-op-or-exp "+" "-" [kp-add] [kp-subtract]) | |
373 (calculator-digit "0" "1" "2" "3" "4" "5" "6" "7" "8" | |
374 "9" "a" "b" "c" "d" "f" | |
375 [kp-0] [kp-1] [kp-2] [kp-3] [kp-4] | |
376 [kp-5] [kp-6] [kp-7] [kp-8] [kp-9]) | |
377 (calculator-op [kp-divide] [kp-multiply]) | |
378 (calculator-decimal "." [kp-decimal]) | |
379 (calculator-exp "e") | |
27904
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
380 (calculator-dec/deg-mode "D") |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
381 (calculator-set-register "s") |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
382 (calculator-get-register "g") |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
383 (calculator-radix-mode "H" "X" "O" "B") |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
384 (calculator-radix-input-mode "id" "ih" "ix" "io" "ib" |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
385 "iD" "iH" "iX" "iO" "iB") |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
386 (calculator-radix-output-mode "od" "oh" "ox" "oo" "ob" |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
387 "oD" "oH" "oX" "oO" "oB") |
33491 | 388 (calculator-rotate-displayer "'") |
389 (calculator-rotate-displayer-back "\"") | |
39430
48633cf4ce7c
(calculator-copy-displayer): New user-option.
Gerd Moellmann <gerd@gnu.org>
parents:
38436
diff
changeset
|
390 (calculator-displayer-pref "{") |
48633cf4ce7c
(calculator-copy-displayer): New user-option.
Gerd Moellmann <gerd@gnu.org>
parents:
38436
diff
changeset
|
391 (calculator-displayer-next "}") |
27904
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
392 (calculator-saved-up [up] [?\C-p]) |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
393 (calculator-saved-down [down] [?\C-n]) |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
394 (calculator-quit "q" [?\C-g]) |
33491 | 395 (calculator-enter [enter] [linefeed] [kp-enter] |
396 [return] [?\r] [?\n]) | |
27904
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
397 (calculator-save-on-list " " [space]) |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
398 (calculator-clear-saved [?\C-c] [(control delete)]) |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
399 (calculator-save-and-quit [(control return)] |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
400 [(control kp-enter)]) |
33631 | 401 (calculator-paste [insert] [(shift insert)] |
402 [mouse-2]) | |
27904
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
403 (calculator-clear [delete] [?\C-?] [?\C-d]) |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
404 (calculator-help [?h] [??] [f1] [help]) |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
405 (calculator-copy [(control insert)]) |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
406 (calculator-backspace [backspace]) |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
407 ))) |
27587 | 408 (while p |
27904
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
409 ;; reverse the keys so first defs come last - makes the more |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
410 ;; sensible bindings visible in the menu |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
411 (let ((func (car (car p))) (keys (reverse (cdr (car p))))) |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
412 (while keys |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
413 (define-key map (car keys) func) |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
414 (setq keys (cdr keys)))) |
27587 | 415 (setq p (cdr p)))) |
416 (if calculator-bind-escape | |
417 (progn (define-key map [?\e] 'calculator-quit) | |
418 (define-key map [escape] 'calculator-quit)) | |
419 (define-key map [?\e ?\e ?\e] 'calculator-quit)) | |
420 ;; make C-h work in text-mode | |
421 (or window-system (define-key map [?\C-h] 'calculator-backspace)) | |
27904
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
422 ;; set up a menu |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
423 (if (and calculator-use-menu (not (boundp 'calculator-menu))) |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
424 (let ((radix-selectors |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
425 (mapcar (lambda (x) |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
426 `([,(nth 0 x) |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
427 (calculator-radix-mode ,(nth 2 x)) |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
428 :style radio |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
429 :keys ,(nth 2 x) |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
430 :selected |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
431 (and |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
432 (eq calculator-input-radix ',(nth 1 x)) |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
433 (eq calculator-output-radix ',(nth 1 x)))] |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
434 [,(concat (nth 0 x) " Input") |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
435 (calculator-radix-input-mode ,(nth 2 x)) |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
436 :keys ,(concat "i" (downcase (nth 2 x))) |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
437 :style radio |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
438 :selected |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
439 (eq calculator-input-radix ',(nth 1 x))] |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
440 [,(concat (nth 0 x) " Output") |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
441 (calculator-radix-output-mode ,(nth 2 x)) |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
442 :keys ,(concat "o" (downcase (nth 2 x))) |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
443 :style radio |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
444 :selected |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
445 (eq calculator-output-radix ',(nth 1 x))])) |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
446 '(("Decimal" nil "D") |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
447 ("Binary" bin "B") |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
448 ("Octal" oct "O") |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
449 ("Hexadecimal" hex "H")))) |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
450 (op '(lambda (name key) |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
451 `[,name (calculator-op ,key) :keys ,key]))) |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
452 (easy-menu-define |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
453 calculator-menu map "Calculator menu." |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
454 `("Calculator" |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
455 ["Help" |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
456 (let ((last-command 'calculator-help)) (calculator-help)) |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
457 :keys "?"] |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
458 "---" |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
459 ["Copy" calculator-copy] |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
460 ["Paste" calculator-paste] |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
461 "---" |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
462 ["Electric mode" |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
463 (progn (calculator-quit) |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
464 (setq calculator-restart-other-mode t) |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
465 (run-with-timer 0.1 nil '(lambda () (message nil))) |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
466 ;; the message from the menu will be visible, |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
467 ;; couldn't make it go away... |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
468 (calculator)) |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
469 :active (not calculator-electric-mode)] |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
470 ["Normal mode" |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
471 (progn (setq calculator-restart-other-mode t) |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
472 (calculator-quit)) |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
473 :active calculator-electric-mode] |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
474 "---" |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
475 ("Functions" |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
476 ,(funcall op "Repeat-right" ">") |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
477 ,(funcall op "Repeat-left" "<") |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
478 "------General------" |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
479 ,(funcall op "Reciprocal" ";") |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
480 ,(funcall op "Log" "L") |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
481 ,(funcall op "Square-root" "Q") |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
482 ,(funcall op "Factorial" "!") |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
483 "------Trigonometric------" |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
484 ,(funcall op "Sinus" "S") |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
485 ,(funcall op "Cosine" "C") |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
486 ,(funcall op "Tangent" "T") |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
487 ,(funcall op "Inv-Sinus" "IS") |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
488 ,(funcall op "Inv-Cosine" "IC") |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
489 ,(funcall op "Inv-Tangent" "IT") |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
490 "------Bitwise------" |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
491 ,(funcall op "Or" "|") |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
492 ,(funcall op "Xor" "#") |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
493 ,(funcall op "And" "&") |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
494 ,(funcall op "Not" "~")) |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
495 ("Saved List" |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
496 ["Eval+Save" calculator-save-on-list] |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
497 ["Prev number" calculator-saved-up] |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
498 ["Next number" calculator-saved-down] |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
499 ["Delete current" calculator-clear |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
500 :active (and calculator-display-fragile |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
501 calculator-saved-list |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
502 (= (car calculator-stack) |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
503 (nth calculator-saved-ptr |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
504 calculator-saved-list)))] |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
505 ["Delete all" calculator-clear-saved] |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
506 "---" |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
507 ,(funcall op "List-total" "l") |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
508 ,(funcall op "List-average" "v")) |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
509 ("Registers" |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
510 ["Get register" calculator-get-register] |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
511 ["Set register" calculator-set-register]) |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
512 ("Modes" |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
513 ["Radians" |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
514 (progn |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
515 (and (or calculator-input-radix calculator-output-radix) |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
516 (calculator-radix-mode "D")) |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
517 (and calculator-deg (calculator-dec/deg-mode))) |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
518 :keys "D" |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
519 :style radio |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
520 :selected (not (or calculator-input-radix |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
521 calculator-output-radix |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
522 calculator-deg))] |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
523 ["Degrees" |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
524 (progn |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
525 (and (or calculator-input-radix calculator-output-radix) |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
526 (calculator-radix-mode "D")) |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
527 (or calculator-deg (calculator-dec/deg-mode))) |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
528 :keys "D" |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
529 :style radio |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
530 :selected (and calculator-deg |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
531 (not (or calculator-input-radix |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
532 calculator-output-radix)))] |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
533 "---" |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
534 ,@(mapcar 'car radix-selectors) |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
535 ("Seperate I/O" |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
536 ,@(mapcar (lambda (x) (nth 1 x)) radix-selectors) |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
537 "---" |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
538 ,@(mapcar (lambda (x) (nth 2 x)) radix-selectors))) |
33491 | 539 ("Decimal Dislpay" |
540 ,@(mapcar (lambda (d) | |
541 (vector (cadr d) | |
542 ;; Note: inserts actual object here | |
543 `(calculator-rotate-displayer ',d))) | |
544 calculator-displayers) | |
545 "---" | |
39430
48633cf4ce7c
(calculator-copy-displayer): New user-option.
Gerd Moellmann <gerd@gnu.org>
parents:
38436
diff
changeset
|
546 ["Change Prev Display" calculator-displayer-prev] |
48633cf4ce7c
(calculator-copy-displayer): New user-option.
Gerd Moellmann <gerd@gnu.org>
parents:
38436
diff
changeset
|
547 ["Change Next Display" calculator-displayer-next]) |
27904
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
548 "---" |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
549 ["Copy+Quit" calculator-save-and-quit] |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
550 ["Quit" calculator-quit])))) |
27587 | 551 (setq calculator-mode-map map))) |
552 | |
33631 | 553 ;;;--------------------------------------------------------------------- |
33491 | 554 ;;; Startup and mode stuff |
555 | |
27587 | 556 (defun calculator-mode () |
33491 | 557 ;; this help is also used as the major help screen |
558 "A [not so] simple calculator for Emacs. | |
27587 | 559 |
560 This calculator is used in the same way as other popular calculators | |
561 like xcalc or calc.exe - but using an Emacs interface. | |
562 | |
563 Expressions are entered using normal infix notation, parens are used as | |
564 normal. Unary functions are usually postfix, but some depends on the | |
565 value of `calculator-unary-style' (if the style for an operator below is | |
566 specified, then it is fixed, otherwise it depends on this variable). | |
567 `+' and `-' can be used as either binary operators or prefix unary | |
568 operators. Numbers can be entered with exponential notation using `e', | |
569 except when using a non-decimal radix mode for input (in this case `e' | |
570 will be the hexadecimal digit). | |
571 | |
572 Here are the editing keys: | |
573 * `RET' `=' evaluate the current expression | |
574 * `C-insert' copy the whole current expression to the `kill-ring' | |
27904
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
575 * `C-return' evaluate, save result the `kill-ring' and exit |
27587 | 576 * `insert' paste a number if the one was copied (normally) |
577 * `delete' `C-d' clear last argument or whole expression (hit twice) | |
578 * `backspace' delete a digit or a previous expression element | |
579 * `h' `?' pop-up a quick reference help | |
580 * `ESC' `q' exit (`ESC' can be used if `calculator-bind-escape' is | |
581 non-nil, otherwise use three consecutive `ESC's) | |
582 | |
583 These operators are pre-defined: | |
584 * `+' `-' `*' `/' the common binary operators | |
585 * `\\' `%' integer division and reminder | |
586 * `_' `;' postfix unary negation and reciprocal | |
587 * `^' `L' binary operators for x^y and log(x) in base y | |
588 * `Q' `!' unary square root and factorial | |
589 * `S' `C' `T' unary trigonometric operators - sin, cos and tan | |
590 * `|' `#' `&' `~' bitwise operators - or, xor, and, not | |
591 | |
592 The trigonometric functions can be inverted if prefixed with an `I', see | |
593 below for the way to use degrees instead of the default radians. | |
594 | |
595 Two special postfix unary operators are `>' and `<': whenever a binary | |
596 operator is performed, it is remembered along with its arguments; then | |
597 `>' (`<') will apply the same operator with the same right (left) | |
598 argument. | |
599 | |
600 hex/oct/bin modes can be set for input and for display separately. | |
601 Another toggle-able mode is for using degrees instead of radians for | |
602 trigonometric functions. | |
603 The keys to switch modes are (`X' is shortcut for `H'): | |
604 * `D' switch to all-decimal mode, or toggle degrees/radians | |
605 * `B' `O' `H' `X' binary/octal/hexadecimal modes for input & display | |
606 * `i' `o' followed by one of `D' `B' `O' `H' `X' (case | |
607 insensitive) sets only the input or display radix mode | |
608 The prompt indicates the current modes: | |
609 * \"D=\": degrees mode; | |
610 * \"?=\": (? is B/O/H) this is the radix for both input and output; | |
611 * \"=?\": (? is B/O/H) the display radix (when input is decimal); | |
612 * \"??\": (? is D/B/O/H) 1st char for input radix, 2nd for display. | |
613 | |
33491 | 614 Also, the quote character can be used to switch display modes for |
615 decimal numbers (double-quote rotates back), and the two brace | |
616 characters (\"{\" and \"}\" change display parameters that these | |
617 displayers use (if they handle such). | |
618 | |
27587 | 619 Values can be saved for future reference in either a list of saved |
620 values, or in registers. | |
621 | |
622 The list of saved values is useful for statistics operations on some | |
623 collected data. It is possible to navigate in this list, and if the | |
624 value shown is the current one on the list, an indication is displayed | |
625 as \"[N]\" if this is the last number and there are N numbers, or | |
626 \"[M/N]\" if the M-th value is shown. | |
627 * `SPC' evaluate the current value as usual, but also adds | |
628 the result to the list of saved values | |
629 * `l' `v' computes total / average of saved values | |
630 * `up' `C-p' browse to the previous value in the list | |
631 * `down' `C-n' browse to the next value in the list | |
632 * `delete' `C-d' remove current value from the list (if it is on it) | |
633 * `C-delete' `C-c' delete the whole list | |
634 | |
635 Registers are variable-like place-holders for values: | |
636 * `s' followed by a character attach the current value to that character | |
637 * `g' followed by a character fetches the attached value | |
638 | |
639 There are many variables that can be used to customize the calculator. | |
640 Some interesting customization variables are: | |
641 * `calculator-electric-mode' use only the echo-area electrically. | |
642 * `calculator-unary-style' set most unary ops to pre/postfix style. | |
643 * `calculator-user-registers' to define user-preset registers. | |
644 * `calculator-user-operators' to add user-defined operators. | |
645 See the documentation for these variables, and \"calculator.el\" for | |
646 more information. | |
647 | |
648 \\{calculator-mode-map}" | |
649 (interactive) | |
650 (kill-all-local-variables) | |
651 (setq major-mode 'calculator-mode) | |
652 (setq mode-name "Calculator") | |
653 (use-local-map calculator-mode-map) | |
654 (run-hooks 'calculator-mode-hook)) | |
655 | |
33491 | 656 (eval-when-compile (require 'electric) (require 'ehelp)) |
657 | |
27587 | 658 ;;;###autoload |
659 (defun calculator () | |
33491 | 660 "Run the Emacs calculator. |
27587 | 661 See the documentation for `calculator-mode' for more information." |
662 (interactive) | |
27904
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
663 (if calculator-restart-other-mode |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
664 (setq calculator-electric-mode (not calculator-electric-mode))) |
27587 | 665 (if calculator-initial-operators |
666 (progn (calculator-add-operators calculator-initial-operators) | |
667 (setq calculator-initial-operators nil) | |
668 ;; don't change this since it is a customization variable, | |
33491 | 669 ;; its set function will add any new operators |
27587 | 670 (calculator-add-operators calculator-user-operators))) |
49575
336c18b62203
(calculator): Don't use the minibuffer even in electric mode; use a private
Juanma Barranquero <lekktu@gmail.com>
parents:
43091
diff
changeset
|
671 (setq calculator-buffer (get-buffer-create "*calculator*")) |
27587 | 672 (if calculator-electric-mode |
673 (save-window-excursion | |
27904
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
674 (progn (require 'electric) (message nil)) ; hide load message |
27587 | 675 (let (old-g-map old-l-map (echo-keystrokes 0) |
676 (garbage-collection-messages nil)) ; no gc msg when electric | |
49575
336c18b62203
(calculator): Don't use the minibuffer even in electric mode; use a private
Juanma Barranquero <lekktu@gmail.com>
parents:
43091
diff
changeset
|
677 (set-window-buffer (minibuffer-window) calculator-buffer) |
27587 | 678 (select-window (minibuffer-window)) |
679 (calculator-reset) | |
680 (calculator-update-display) | |
681 (setq old-l-map (current-local-map)) | |
682 (setq old-g-map (current-global-map)) | |
683 (setq calculator-saved-global-map (current-global-map)) | |
27904
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
684 (use-local-map nil) |
27587 | 685 (use-global-map calculator-mode-map) |
686 (unwind-protect | |
687 (catch 'calculator-done | |
688 (Electric-command-loop | |
689 'calculator-done | |
690 ;; can't use 'noprompt, bug in electric.el | |
691 '(lambda () 'noprompt) | |
692 nil | |
27904
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
693 (lambda (x y) (calculator-update-display)))) |
27587 | 694 (and calculator-buffer |
695 (catch 'calculator-done (calculator-quit))) | |
696 (use-local-map old-l-map) | |
697 (use-global-map old-g-map)))) | |
27904
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
698 (progn |
39430
48633cf4ce7c
(calculator-copy-displayer): New user-option.
Gerd Moellmann <gerd@gnu.org>
parents:
38436
diff
changeset
|
699 (cond |
48633cf4ce7c
(calculator-copy-displayer): New user-option.
Gerd Moellmann <gerd@gnu.org>
parents:
38436
diff
changeset
|
700 ((not (get-buffer-window calculator-buffer)) |
48633cf4ce7c
(calculator-copy-displayer): New user-option.
Gerd Moellmann <gerd@gnu.org>
parents:
38436
diff
changeset
|
701 (let ((split-window-keep-point nil) |
48633cf4ce7c
(calculator-copy-displayer): New user-option.
Gerd Moellmann <gerd@gnu.org>
parents:
38436
diff
changeset
|
702 (window-min-height 2)) |
48633cf4ce7c
(calculator-copy-displayer): New user-option.
Gerd Moellmann <gerd@gnu.org>
parents:
38436
diff
changeset
|
703 ;; maybe leave two lines for our window because of the normal |
48633cf4ce7c
(calculator-copy-displayer): New user-option.
Gerd Moellmann <gerd@gnu.org>
parents:
38436
diff
changeset
|
704 ;; `raised' modeline in Emacs 21 |
48633cf4ce7c
(calculator-copy-displayer): New user-option.
Gerd Moellmann <gerd@gnu.org>
parents:
38436
diff
changeset
|
705 (select-window |
48633cf4ce7c
(calculator-copy-displayer): New user-option.
Gerd Moellmann <gerd@gnu.org>
parents:
38436
diff
changeset
|
706 (split-window-vertically |
48633cf4ce7c
(calculator-copy-displayer): New user-option.
Gerd Moellmann <gerd@gnu.org>
parents:
38436
diff
changeset
|
707 (if (and (fboundp 'face-attr-construct) |
48633cf4ce7c
(calculator-copy-displayer): New user-option.
Gerd Moellmann <gerd@gnu.org>
parents:
38436
diff
changeset
|
708 (plist-get (face-attr-construct 'modeline) :box)) |
48633cf4ce7c
(calculator-copy-displayer): New user-option.
Gerd Moellmann <gerd@gnu.org>
parents:
38436
diff
changeset
|
709 -3 -2))) |
48633cf4ce7c
(calculator-copy-displayer): New user-option.
Gerd Moellmann <gerd@gnu.org>
parents:
38436
diff
changeset
|
710 (switch-to-buffer calculator-buffer))) |
48633cf4ce7c
(calculator-copy-displayer): New user-option.
Gerd Moellmann <gerd@gnu.org>
parents:
38436
diff
changeset
|
711 ((not (eq (current-buffer) calculator-buffer)) |
48633cf4ce7c
(calculator-copy-displayer): New user-option.
Gerd Moellmann <gerd@gnu.org>
parents:
38436
diff
changeset
|
712 (select-window (get-buffer-window calculator-buffer)))) |
27904
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
713 (calculator-mode) |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
714 (setq buffer-read-only t) |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
715 (calculator-reset) |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
716 (message "Hit `?' For a quick help screen."))) |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
717 (if (and calculator-restart-other-mode calculator-electric-mode) |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
718 (calculator))) |
27587 | 719 |
33631 | 720 ;;;--------------------------------------------------------------------- |
43091
f18f05d77411
(calculator-displayers): Doc fixes.
Pavel Janík <Pavel@Janik.cz>
parents:
39818
diff
changeset
|
721 ;;; Operators |
33491 | 722 |
27587 | 723 (defun calculator-op-arity (op) |
724 "Return OP's arity, 2, +1 or -1." | |
725 (let ((arity (or (nth 3 op) 'x))) | |
726 (if (numberp arity) | |
727 arity | |
728 (if (eq calculator-unary-style 'postfix) +1 -1)))) | |
729 | |
730 (defun calculator-op-prec (op) | |
731 "Return OP's precedence for reducing when inserting into the stack. | |
732 Defaults to 1." | |
733 (or (nth 4 op) 1)) | |
734 | |
735 (defun calculator-add-operators (more-ops) | |
736 "This function handles operator addition. | |
737 Adds MORE-OPS to `calculator-operator', called initially to handle | |
738 `calculator-initial-operators' and `calculator-user-operators'." | |
739 (let ((added-ops nil)) | |
740 (while more-ops | |
741 (or (eq (car (car more-ops)) 'nobind) | |
742 (let ((i -1) (key (car (car more-ops)))) | |
743 ;; make sure the key is undefined, so it's easy to define | |
744 ;; prefix keys | |
745 (while (< (setq i (1+ i)) (length key)) | |
746 (or (keymapp | |
747 (lookup-key calculator-mode-map | |
748 (substring key 0 (1+ i)))) | |
749 (progn | |
750 (define-key | |
751 calculator-mode-map (substring key 0 (1+ i)) nil) | |
752 (setq i (length key))))) | |
753 (define-key calculator-mode-map key 'calculator-op))) | |
754 (setq added-ops (cons (if (eq (car (car more-ops)) 'nobind) | |
755 (cdr (car more-ops)) | |
756 (car more-ops)) | |
757 added-ops)) | |
758 (setq more-ops (cdr more-ops))) | |
759 ;; added-ops come first, but in correct order | |
760 (setq calculator-operators | |
761 (append (nreverse added-ops) calculator-operators)))) | |
762 | |
33631 | 763 ;;;--------------------------------------------------------------------- |
33491 | 764 ;;; Display stuff |
765 | |
27587 | 766 (defun calculator-reset () |
767 "Reset calculator variables." | |
27904
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
768 (or calculator-restart-other-mode |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
769 (setq calculator-stack nil |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
770 calculator-curnum nil |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
771 calculator-stack-display nil |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
772 calculator-display-fragile nil)) |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
773 (setq calculator-restart-other-mode nil) |
27587 | 774 (calculator-update-display)) |
775 | |
776 (defun calculator-get-prompt () | |
777 "Return a string to display. | |
778 The string is set not to exceed the screen width." | |
779 (let* ((calculator-prompt | |
780 (format calculator-prompt | |
781 (cond | |
782 ((or calculator-output-radix calculator-input-radix) | |
783 (if (eq calculator-output-radix | |
784 calculator-input-radix) | |
785 (concat | |
786 (char-to-string | |
787 (car (rassq calculator-output-radix | |
788 calculator-char-radix))) | |
789 "=") | |
790 (concat | |
791 (if calculator-input-radix | |
792 (char-to-string | |
793 (car (rassq calculator-input-radix | |
794 calculator-char-radix))) | |
795 "=") | |
796 (char-to-string | |
797 (car (rassq calculator-output-radix | |
798 calculator-char-radix)))))) | |
799 (calculator-deg "D=") | |
800 (t "==")))) | |
801 (prompt | |
802 (concat calculator-prompt | |
803 (cdr calculator-stack-display) | |
804 (cond (calculator-curnum | |
805 ;; number being typed | |
806 (concat calculator-curnum "_")) | |
807 ((and (= 1 (length calculator-stack)) | |
808 calculator-display-fragile) | |
809 ;; only the result is shown, next number will | |
810 ;; restart | |
811 nil) | |
812 (t | |
813 ;; waiting for a number or an operator | |
814 "?")))) | |
815 (trim (- (length prompt) (1- (window-width))))) | |
816 (if (<= trim 0) | |
817 prompt | |
818 (concat calculator-prompt | |
819 (substring prompt (+ trim (length calculator-prompt))))))) | |
820 | |
821 (defun calculator-curnum-value () | |
822 "Get the numeric value of the displayed number string as a float." | |
823 (if calculator-input-radix | |
824 (let ((radix | |
825 (cdr (assq calculator-input-radix | |
826 '((bin . 2) (oct . 8) (hex . 16))))) | |
827 (i -1) (value 0)) | |
828 ;; assume valid input (upcased & characters in range) | |
829 (while (< (setq i (1+ i)) (length calculator-curnum)) | |
830 (setq value | |
831 (+ (let ((ch (aref calculator-curnum i))) | |
832 (- ch (if (<= ch ?9) ?0 (- ?A 10)))) | |
833 (* radix value)))) | |
834 value) | |
835 (car | |
836 (read-from-string | |
837 (cond | |
838 ((equal "." calculator-curnum) | |
839 "0.0") | |
840 ((string-match "[eE][+-]?$" calculator-curnum) | |
841 (concat calculator-curnum "0")) | |
842 ((string-match "\\.[0-9]\\|[eE]" calculator-curnum) | |
843 calculator-curnum) | |
844 ((string-match "\\." calculator-curnum) | |
33491 | 845 ;; do this because Emacs reads "23." as an integer |
27587 | 846 (concat calculator-curnum "0")) |
847 ((stringp calculator-curnum) | |
848 (concat calculator-curnum ".0")) | |
849 (t "0.0")))))) | |
850 | |
33491 | 851 (defun calculator-rotate-displayer (&optional new-disp) |
852 "Switch to the next displayer on the `calculator-displayers' list. | |
853 Can be called with an optional argument NEW-DISP to force rotation to | |
854 that argument." | |
855 (interactive) | |
856 (setq calculator-displayers | |
857 (if (and new-disp (memq new-disp calculator-displayers)) | |
858 (let ((tmp nil)) | |
859 (while (not (eq (car calculator-displayers) new-disp)) | |
860 (setq tmp (cons (car calculator-displayers) tmp)) | |
861 (setq calculator-displayers (cdr calculator-displayers))) | |
862 (setq calculator-displayers | |
863 (nconc calculator-displayers (nreverse tmp)))) | |
864 (nconc (cdr calculator-displayers) | |
865 (list (car calculator-displayers))))) | |
866 (message "Using %s." (cadr (car calculator-displayers))) | |
867 (if calculator-electric-mode | |
868 (progn (sit-for 1) (message nil))) | |
869 (calculator-enter)) | |
870 | |
871 (defun calculator-rotate-displayer-back () | |
872 "Like `calculator-rotate-displayer', but rotates modes back." | |
873 (interactive) | |
874 (calculator-rotate-displayer (car (last calculator-displayers)))) | |
875 | |
39430
48633cf4ce7c
(calculator-copy-displayer): New user-option.
Gerd Moellmann <gerd@gnu.org>
parents:
38436
diff
changeset
|
876 (defun calculator-displayer-prev () |
33491 | 877 "Send the current displayer function a 'left argument. |
878 This is used to modify display arguments (if the current displayer | |
879 function supports this)." | |
880 (interactive) | |
881 (and (car calculator-displayers) | |
882 (let ((disp (caar calculator-displayers))) | |
883 (cond ((symbolp disp) (funcall disp 'left)) | |
884 ((and (consp disp) (eq 'std (car disp))) | |
885 (calculator-standard-displayer 'left (cadr disp))))))) | |
886 | |
39430
48633cf4ce7c
(calculator-copy-displayer): New user-option.
Gerd Moellmann <gerd@gnu.org>
parents:
38436
diff
changeset
|
887 (defun calculator-displayer-next () |
33491 | 888 "Send the current displayer function a 'right argument. |
889 This is used to modify display arguments (if the current displayer | |
890 function supports this)." | |
891 (interactive) | |
892 (and (car calculator-displayers) | |
893 (let ((disp (caar calculator-displayers))) | |
894 (cond ((symbolp disp) (funcall disp 'right)) | |
895 ((and (consp disp) (eq 'std (car disp))) | |
896 (calculator-standard-displayer 'right (cadr disp))))))) | |
897 | |
898 (defun calculator-remove-zeros (numstr) | |
899 "Get a number string NUMSTR and remove unnecessary zeroes. | |
900 the behavior of this function is controlled by | |
901 `calculator-remove-zeros'." | |
902 (cond ((and (eq calculator-remove-zeros t) | |
903 (string-match "\\.0+\\([eE][+-]?[0-9]*\\)?$" numstr)) | |
904 ;; remove all redundant zeros leaving an integer | |
905 (if (match-beginning 1) | |
906 (concat (substring numstr 0 (match-beginning 0)) | |
907 (match-string 1 numstr)) | |
908 (substring numstr 0 (match-beginning 0)))) | |
909 ((and calculator-remove-zeros | |
910 (string-match | |
911 "\\..\\([0-9]*[1-9]\\)?\\(0+\\)\\([eE][+-]?[0-9]*\\)?$" | |
912 numstr)) | |
913 ;; remove zeros, except for first after the "." | |
914 (if (match-beginning 3) | |
915 (concat (substring numstr 0 (match-beginning 2)) | |
916 (match-string 3 numstr)) | |
917 (substring numstr 0 (match-beginning 2)))) | |
918 (t numstr))) | |
919 | |
920 (defun calculator-standard-displayer (num char) | |
921 "Standard display function, used to display NUM. | |
922 Its behavior is determined by `calculator-number-digits' and the given | |
923 CHAR argument (both will be used to compose a format string). If the | |
924 char is \"n\" then this function will choose one between %f or %e, this | |
925 is a work around %g jumping to exponential notation too fast. | |
926 | |
927 The special 'left and 'right symbols will make it change the current | |
928 number of digits displayed (`calculator-number-digits'). | |
929 | |
930 It will also remove redundant zeros from the result." | |
931 (if (symbolp num) | |
932 (cond ((eq num 'left) | |
933 (and (> calculator-number-digits 0) | |
934 (setq calculator-number-digits | |
935 (1- calculator-number-digits)) | |
936 (calculator-enter))) | |
937 ((eq num 'right) | |
938 (setq calculator-number-digits | |
939 (1+ calculator-number-digits)) | |
940 (calculator-enter))) | |
39430
48633cf4ce7c
(calculator-copy-displayer): New user-option.
Gerd Moellmann <gerd@gnu.org>
parents:
38436
diff
changeset
|
941 (let ((str (if (zerop num) |
48633cf4ce7c
(calculator-copy-displayer): New user-option.
Gerd Moellmann <gerd@gnu.org>
parents:
38436
diff
changeset
|
942 "0" |
48633cf4ce7c
(calculator-copy-displayer): New user-option.
Gerd Moellmann <gerd@gnu.org>
parents:
38436
diff
changeset
|
943 (format |
48633cf4ce7c
(calculator-copy-displayer): New user-option.
Gerd Moellmann <gerd@gnu.org>
parents:
38436
diff
changeset
|
944 (concat "%." |
48633cf4ce7c
(calculator-copy-displayer): New user-option.
Gerd Moellmann <gerd@gnu.org>
parents:
38436
diff
changeset
|
945 (number-to-string calculator-number-digits) |
48633cf4ce7c
(calculator-copy-displayer): New user-option.
Gerd Moellmann <gerd@gnu.org>
parents:
38436
diff
changeset
|
946 (if (eq char ?n) |
48633cf4ce7c
(calculator-copy-displayer): New user-option.
Gerd Moellmann <gerd@gnu.org>
parents:
38436
diff
changeset
|
947 (let ((n (abs num))) |
48633cf4ce7c
(calculator-copy-displayer): New user-option.
Gerd Moellmann <gerd@gnu.org>
parents:
38436
diff
changeset
|
948 (if (or (< n 0.001) (> n 1e8)) "e" "f")) |
48633cf4ce7c
(calculator-copy-displayer): New user-option.
Gerd Moellmann <gerd@gnu.org>
parents:
38436
diff
changeset
|
949 (string char))) |
48633cf4ce7c
(calculator-copy-displayer): New user-option.
Gerd Moellmann <gerd@gnu.org>
parents:
38436
diff
changeset
|
950 num)))) |
33491 | 951 (calculator-remove-zeros str)))) |
952 | |
953 (defun calculator-eng-display (num) | |
954 "Display NUM in engineering notation. | |
955 The number of decimal digits used is controlled by | |
956 `calculator-number-digits', so to change it at runtime you have to use | |
957 the 'left or 'right when one of the standard modes is used." | |
958 (if (symbolp num) | |
959 (cond ((eq num 'left) | |
960 (setq calculator-eng-extra | |
961 (if calculator-eng-extra | |
962 (1+ calculator-eng-extra) | |
963 1)) | |
964 (let ((calculator-eng-tmp-show t)) (calculator-enter))) | |
965 ((eq num 'right) | |
966 (setq calculator-eng-extra | |
967 (if calculator-eng-extra | |
968 (1- calculator-eng-extra) | |
969 -1)) | |
970 (let ((calculator-eng-tmp-show t)) (calculator-enter)))) | |
971 (let ((exp 0)) | |
972 (and (not (= 0 num)) | |
973 (progn | |
974 (while (< (abs num) 1.0) | |
975 (setq num (* num 1000.0)) (setq exp (- exp 3))) | |
976 (while (> (abs num) 999.0) | |
977 (setq num (/ num 1000.0)) (setq exp (+ exp 3))) | |
978 (and calculator-eng-tmp-show | |
979 (not (= 0 calculator-eng-extra)) | |
980 (let ((i calculator-eng-extra)) | |
981 (while (> i 0) | |
982 (setq num (* num 1000.0)) (setq exp (- exp 3)) | |
983 (setq i (1- i))) | |
984 (while (< i 0) | |
985 (setq num (/ num 1000.0)) (setq exp (+ exp 3)) | |
986 (setq i (1+ i))))))) | |
987 (or calculator-eng-tmp-show (setq calculator-eng-extra nil)) | |
39818
6564021e098e
(calculator-eng-display): Don't call concat
Gerd Moellmann <gerd@gnu.org>
parents:
39430
diff
changeset
|
988 (let ((str (format (concat "%." (number-to-string |
6564021e098e
(calculator-eng-display): Don't call concat
Gerd Moellmann <gerd@gnu.org>
parents:
39430
diff
changeset
|
989 calculator-number-digits) |
6564021e098e
(calculator-eng-display): Don't call concat
Gerd Moellmann <gerd@gnu.org>
parents:
39430
diff
changeset
|
990 "f") |
33491 | 991 num))) |
992 (concat (let ((calculator-remove-zeros | |
993 ;; make sure we don't leave integers | |
994 (and calculator-remove-zeros 'x))) | |
995 (calculator-remove-zeros str)) | |
996 "e" (number-to-string exp)))))) | |
997 | |
27587 | 998 (defun calculator-num-to-string (num) |
999 "Convert NUM to a displayable string." | |
1000 (cond | |
1001 ((and (numberp num) calculator-output-radix) | |
1002 ;; print with radix - for binary I convert the octal number | |
1003 (let ((str (format (if (eq calculator-output-radix 'hex) "%x" "%o") | |
1004 (calculator-truncate | |
1005 (if calculator-2s-complement num (abs num)))))) | |
1006 (if (eq calculator-output-radix 'bin) | |
1007 (let ((i -1) (s "")) | |
1008 (while (< (setq i (1+ i)) (length str)) | |
1009 (setq s | |
1010 (concat s | |
1011 (cdr (assq (aref str i) | |
1012 '((?0 . "000") (?1 . "001") | |
1013 (?2 . "010") (?3 . "011") | |
1014 (?4 . "100") (?5 . "101") | |
1015 (?6 . "110") (?7 . "111"))))))) | |
1016 (string-match "^0*\\(.+\\)" s) | |
1017 (setq str (match-string 1 s)))) | |
1018 (upcase | |
1019 (if (and (not calculator-2s-complement) (< num 0)) | |
1020 (concat "-" str) | |
1021 str)))) | |
39430
48633cf4ce7c
(calculator-copy-displayer): New user-option.
Gerd Moellmann <gerd@gnu.org>
parents:
38436
diff
changeset
|
1022 ((and (numberp num) calculator-displayer) |
48633cf4ce7c
(calculator-copy-displayer): New user-option.
Gerd Moellmann <gerd@gnu.org>
parents:
38436
diff
changeset
|
1023 (cond |
48633cf4ce7c
(calculator-copy-displayer): New user-option.
Gerd Moellmann <gerd@gnu.org>
parents:
38436
diff
changeset
|
1024 ((stringp calculator-displayer) |
48633cf4ce7c
(calculator-copy-displayer): New user-option.
Gerd Moellmann <gerd@gnu.org>
parents:
38436
diff
changeset
|
1025 (format calculator-displayer num)) |
48633cf4ce7c
(calculator-copy-displayer): New user-option.
Gerd Moellmann <gerd@gnu.org>
parents:
38436
diff
changeset
|
1026 ((symbolp calculator-displayer) |
48633cf4ce7c
(calculator-copy-displayer): New user-option.
Gerd Moellmann <gerd@gnu.org>
parents:
38436
diff
changeset
|
1027 (funcall calculator-displayer num)) |
48633cf4ce7c
(calculator-copy-displayer): New user-option.
Gerd Moellmann <gerd@gnu.org>
parents:
38436
diff
changeset
|
1028 ((and (consp calculator-displayer) |
48633cf4ce7c
(calculator-copy-displayer): New user-option.
Gerd Moellmann <gerd@gnu.org>
parents:
38436
diff
changeset
|
1029 (eq 'std (car calculator-displayer))) |
48633cf4ce7c
(calculator-copy-displayer): New user-option.
Gerd Moellmann <gerd@gnu.org>
parents:
38436
diff
changeset
|
1030 (calculator-standard-displayer num (cadr calculator-displayer))) |
48633cf4ce7c
(calculator-copy-displayer): New user-option.
Gerd Moellmann <gerd@gnu.org>
parents:
38436
diff
changeset
|
1031 ((listp calculator-displayer) |
48633cf4ce7c
(calculator-copy-displayer): New user-option.
Gerd Moellmann <gerd@gnu.org>
parents:
38436
diff
changeset
|
1032 (eval calculator-displayer)) |
48633cf4ce7c
(calculator-copy-displayer): New user-option.
Gerd Moellmann <gerd@gnu.org>
parents:
38436
diff
changeset
|
1033 (t (prin1-to-string num t)))) |
33491 | 1034 ;; operators are printed here |
27587 | 1035 (t (prin1-to-string (nth 1 num) t)))) |
1036 | |
1037 (defun calculator-update-display (&optional force) | |
1038 "Update the display. | |
1039 If optional argument FORCE is non-nil, don't use the cached string." | |
1040 (set-buffer calculator-buffer) | |
1041 ;; update calculator-stack-display | |
1042 (if (or force | |
1043 (not (eq (car calculator-stack-display) calculator-stack))) | |
1044 (setq calculator-stack-display | |
1045 (cons calculator-stack | |
1046 (if calculator-stack | |
1047 (concat | |
39430
48633cf4ce7c
(calculator-copy-displayer): New user-option.
Gerd Moellmann <gerd@gnu.org>
parents:
38436
diff
changeset
|
1048 (let ((calculator-displayer |
48633cf4ce7c
(calculator-copy-displayer): New user-option.
Gerd Moellmann <gerd@gnu.org>
parents:
38436
diff
changeset
|
1049 (if (and calculator-displayers |
48633cf4ce7c
(calculator-copy-displayer): New user-option.
Gerd Moellmann <gerd@gnu.org>
parents:
38436
diff
changeset
|
1050 (= 1 (length calculator-stack))) |
48633cf4ce7c
(calculator-copy-displayer): New user-option.
Gerd Moellmann <gerd@gnu.org>
parents:
38436
diff
changeset
|
1051 ;; customizable display for a single value |
48633cf4ce7c
(calculator-copy-displayer): New user-option.
Gerd Moellmann <gerd@gnu.org>
parents:
38436
diff
changeset
|
1052 (caar calculator-displayers) |
48633cf4ce7c
(calculator-copy-displayer): New user-option.
Gerd Moellmann <gerd@gnu.org>
parents:
38436
diff
changeset
|
1053 calculator-displayer))) |
48633cf4ce7c
(calculator-copy-displayer): New user-option.
Gerd Moellmann <gerd@gnu.org>
parents:
38436
diff
changeset
|
1054 (mapconcat 'calculator-num-to-string |
48633cf4ce7c
(calculator-copy-displayer): New user-option.
Gerd Moellmann <gerd@gnu.org>
parents:
38436
diff
changeset
|
1055 (reverse calculator-stack) |
48633cf4ce7c
(calculator-copy-displayer): New user-option.
Gerd Moellmann <gerd@gnu.org>
parents:
38436
diff
changeset
|
1056 " ")) |
27587 | 1057 " " |
1058 (and calculator-display-fragile | |
1059 calculator-saved-list | |
1060 (= (car calculator-stack) | |
1061 (nth calculator-saved-ptr | |
1062 calculator-saved-list)) | |
1063 (if (= 0 calculator-saved-ptr) | |
1064 (format "[%s]" (length calculator-saved-list)) | |
1065 (format "[%s/%s]" | |
1066 (- (length calculator-saved-list) | |
1067 calculator-saved-ptr) | |
1068 (length calculator-saved-list))))) | |
1069 "")))) | |
1070 (let ((inhibit-read-only t)) | |
1071 (erase-buffer) | |
1072 (insert (calculator-get-prompt))) | |
1073 (set-buffer-modified-p nil) | |
1074 (if calculator-display-fragile | |
1075 (goto-char (1+ (length calculator-prompt))) | |
1076 (goto-char (1- (point))))) | |
1077 | |
33631 | 1078 ;;;--------------------------------------------------------------------- |
33491 | 1079 ;;; Stack computations |
1080 | |
27587 | 1081 (defun calculator-reduce-stack (prec) |
1082 "Reduce the stack using top operator. | |
1083 PREC is a precedence - reduce everything with higher precedence." | |
1084 (while | |
1085 (cond | |
1086 ((and (cdr (cdr calculator-stack)) ; have three values | |
1087 (consp (nth 0 calculator-stack)) ; two operators & num | |
1088 (numberp (nth 1 calculator-stack)) | |
1089 (consp (nth 2 calculator-stack)) | |
1090 (eq '\) (nth 1 (nth 0 calculator-stack))) | |
1091 (eq '\( (nth 1 (nth 2 calculator-stack)))) | |
1092 ;; reduce "... ( x )" --> "... x" | |
1093 (setq calculator-stack | |
1094 (cons (nth 1 calculator-stack) | |
1095 (nthcdr 3 calculator-stack))) | |
1096 ;; another iteration | |
1097 t) | |
1098 ((and (cdr (cdr calculator-stack)) ; have three values | |
1099 (numberp (nth 0 calculator-stack)) ; two nums & operator | |
1100 (consp (nth 1 calculator-stack)) | |
1101 (numberp (nth 2 calculator-stack)) | |
1102 (= 2 (calculator-op-arity ; binary operator | |
1103 (nth 1 calculator-stack))) | |
1104 (<= prec ; with higher prec. | |
1105 (calculator-op-prec (nth 1 calculator-stack)))) | |
1106 ;; reduce "... x op y" --> "... r", r is the result | |
1107 (setq calculator-stack | |
1108 (cons (calculator-funcall | |
1109 (nth 2 (nth 1 calculator-stack)) | |
1110 (nth 2 calculator-stack) | |
1111 (nth 0 calculator-stack)) | |
1112 (nthcdr 3 calculator-stack))) | |
1113 ;; another iteration | |
1114 t) | |
1115 ((and (>= (length calculator-stack) 2) ; have two values | |
1116 (numberp (nth 0 calculator-stack)) ; number & operator | |
1117 (consp (nth 1 calculator-stack)) | |
1118 (= -1 (calculator-op-arity ; prefix-unary op | |
1119 (nth 1 calculator-stack))) | |
1120 (<= prec ; with higher prec. | |
1121 (calculator-op-prec (nth 1 calculator-stack)))) | |
1122 ;; reduce "... op x" --> "... r" for prefix op | |
1123 (setq calculator-stack | |
1124 (cons (calculator-funcall | |
1125 (nth 2 (nth 1 calculator-stack)) | |
1126 (nth 0 calculator-stack)) | |
1127 (nthcdr 2 calculator-stack))) | |
1128 ;; another iteration | |
1129 t) | |
1130 ((and (cdr calculator-stack) ; have two values | |
1131 (consp (nth 0 calculator-stack)) ; operator & number | |
1132 (numberp (nth 1 calculator-stack)) | |
1133 (= +1 (calculator-op-arity ; postfix-unary op | |
1134 (nth 0 calculator-stack))) | |
1135 (<= prec ; with higher prec. | |
1136 (calculator-op-prec (nth 0 calculator-stack)))) | |
1137 ;; reduce "... x op" --> "... r" for postfix op | |
1138 (setq calculator-stack | |
1139 (cons (calculator-funcall | |
1140 (nth 2 (nth 0 calculator-stack)) | |
1141 (nth 1 calculator-stack)) | |
1142 (nthcdr 2 calculator-stack))) | |
1143 ;; another iteration | |
1144 t) | |
1145 ((and calculator-stack ; have one value | |
1146 (consp (nth 0 calculator-stack)) ; an operator | |
1147 (= 0 (calculator-op-arity ; 0-ary op | |
1148 (nth 0 calculator-stack)))) | |
1149 ;; reduce "... op" --> "... r" for 0-ary op | |
1150 (setq calculator-stack | |
1151 (cons (calculator-funcall | |
1152 (nth 2 (nth 0 calculator-stack))) | |
1153 (nthcdr 1 calculator-stack))) | |
1154 ;; another iteration | |
1155 t) | |
1156 ((and (cdr calculator-stack) ; have two values | |
1157 (numberp (nth 0 calculator-stack)) ; both numbers | |
1158 (numberp (nth 1 calculator-stack))) | |
1159 ;; get rid of redundant numbers: | |
1160 ;; reduce "... y x" --> "... x" | |
1161 ;; needed for 0-ary ops that puts more values | |
1162 (setcdr calculator-stack (cdr (cdr calculator-stack)))) | |
1163 (t ;; no more iterations | |
1164 nil)))) | |
1165 | |
33491 | 1166 (defun calculator-funcall (f &optional X Y) |
1167 "If F is a symbol, evaluate (F X Y). | |
1168 Otherwise, it should be a list, evaluate it with X, Y bound to the | |
1169 arguments." | |
1170 ;; remember binary ops for calculator-repR/L | |
1171 (if Y (setq calculator-last-opXY (list f X Y))) | |
1172 (condition-case nil | |
1173 ;; there used to be code here that returns 0 if the result was | |
1174 ;; smaller than calculator-epsilon (1e-15). I don't think this is | |
1175 ;; necessary now. | |
1176 (if (symbolp f) | |
1177 (cond ((and X Y) (funcall f X Y)) | |
1178 (X (funcall f X)) | |
1179 (t (funcall f))) | |
1180 ;; f is an expression | |
1181 (let* ((__f__ f) ; so we can get this value below... | |
1182 (TX (calculator-truncate X)) | |
1183 (TY (and Y (calculator-truncate Y))) | |
1184 (DX (if calculator-deg (/ (* X pi) 180) X)) | |
1185 (L calculator-saved-list) | |
1186 (Fbound (fboundp 'F)) | |
1187 (Fsave (and Fbound (symbol-function 'F))) | |
1188 (Dbound (fboundp 'D)) | |
1189 (Dsave (and Dbound (symbol-function 'D)))) | |
1190 ;; a shortened version of flet | |
1191 (fset 'F (function | |
1192 (lambda (&optional x y) | |
1193 (calculator-funcall __f__ x y)))) | |
1194 (fset 'D (function | |
1195 (lambda (x) | |
1196 (if calculator-deg (/ (* x 180) pi) x)))) | |
1197 (unwind-protect (eval f) | |
1198 (if Fbound (fset 'F Fsave) (fmakunbound 'F)) | |
1199 (if Dbound (fset 'D Dsave) (fmakunbound 'D))))) | |
1200 (error 0))) | |
1201 | |
27587 | 1202 (eval-when-compile ; silence the compiler |
1203 (or (fboundp 'event-key) | |
1204 (defun event-key (&rest _) nil)) | |
1205 (or (fboundp 'key-press-event-p) | |
1206 (defun key-press-event-p (&rest _) nil))) | |
1207 | |
33631 | 1208 ;;;--------------------------------------------------------------------- |
33491 | 1209 ;;; Input interaction |
1210 | |
27904
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
1211 (defun calculator-last-input (&optional keys) |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
1212 "Last char (or event or event sequence) that was read. |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
1213 Optional string argument KEYS will force using it as the keys entered." |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
1214 (let ((inp (or keys (this-command-keys)))) |
27587 | 1215 (if (or (stringp inp) (not (arrayp inp))) |
1216 inp | |
1217 ;; this translates kp-x to x and [tries to] create a string to | |
1218 ;; lookup operators | |
1219 (let* ((i -1) (converted-str (make-string (length inp) ? )) k) | |
1220 ;; converts an array to a string the ops lookup with keypad | |
1221 ;; input | |
1222 (while (< (setq i (1+ i)) (length inp)) | |
1223 (setq k (aref inp i)) | |
1224 ;; if Emacs will someday have a event-key, then this would | |
1225 ;; probably be modified anyway | |
1226 (and (fboundp 'event-key) (key-press-event-p k) | |
33491 | 1227 (event-key k) (setq k (event-key k))) |
27587 | 1228 ;; assume all symbols are translatable with an ascii-character |
1229 (and (symbolp k) | |
1230 (setq k (or (get k 'ascii-character) ? ))) | |
1231 (aset converted-str i k)) | |
1232 converted-str)))) | |
1233 | |
1234 (defun calculator-clear-fragile (&optional op) | |
1235 "Clear the fragile flag if it was set, then maybe reset all. | |
1236 OP is the operator (if any) that caused this call." | |
1237 (if (and calculator-display-fragile | |
1238 (or (not op) | |
1239 (= -1 (calculator-op-arity op)) | |
1240 (= 0 (calculator-op-arity op)))) | |
1241 ;; reset if last calc finished, and now get a num or prefix or 0-ary | |
33491 | 1242 ;; op |
27587 | 1243 (calculator-reset)) |
1244 (setq calculator-display-fragile nil)) | |
1245 | |
1246 (defun calculator-digit () | |
1247 "Enter a single digit." | |
1248 (interactive) | |
1249 (let ((inp (aref (calculator-last-input) 0))) | |
1250 (if (and (or calculator-display-fragile | |
1251 (not (numberp (car calculator-stack)))) | |
1252 (cond | |
1253 ((not calculator-input-radix) (<= inp ?9)) | |
1254 ((eq calculator-input-radix 'bin) (<= inp ?1)) | |
1255 ((eq calculator-input-radix 'oct) (<= inp ?7)) | |
1256 (t t))) | |
1257 ;; enter digit if starting a new computation or have an op on the | |
33491 | 1258 ;; stack |
27587 | 1259 (progn |
1260 (calculator-clear-fragile) | |
1261 (let ((digit (upcase (char-to-string inp)))) | |
1262 (if (equal calculator-curnum "0") | |
1263 (setq calculator-curnum nil)) | |
1264 (setq calculator-curnum | |
1265 (concat (or calculator-curnum "") digit))) | |
1266 (calculator-update-display))))) | |
1267 | |
1268 (defun calculator-decimal () | |
1269 "Enter a decimal period." | |
1270 (interactive) | |
1271 (if (and (not calculator-input-radix) | |
1272 (or calculator-display-fragile | |
1273 (not (numberp (car calculator-stack)))) | |
1274 (not (and calculator-curnum | |
1275 (string-match "[.eE]" calculator-curnum)))) | |
1276 ;; enter the period on the same condition as a digit, only if no | |
33491 | 1277 ;; period or exponent entered yet |
27587 | 1278 (progn |
1279 (calculator-clear-fragile) | |
1280 (setq calculator-curnum (concat (or calculator-curnum "0") ".")) | |
1281 (calculator-update-display)))) | |
1282 | |
1283 (defun calculator-exp () | |
1284 "Enter an `E' exponent character, or a digit in hex input mode." | |
1285 (interactive) | |
1286 (if calculator-input-radix | |
1287 (calculator-digit) | |
1288 (if (and (or calculator-display-fragile | |
1289 (not (numberp (car calculator-stack)))) | |
1290 (not (and calculator-curnum | |
1291 (string-match "[eE]" calculator-curnum)))) | |
33491 | 1292 ;; same condition as above, also no E so far |
27587 | 1293 (progn |
1294 (calculator-clear-fragile) | |
1295 (setq calculator-curnum (concat (or calculator-curnum "1") "e")) | |
1296 (calculator-update-display))))) | |
1297 | |
27904
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
1298 (defun calculator-op (&optional keys) |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
1299 "Enter an operator on the stack, doing all necessary reductions. |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
1300 Optional string argument KEYS will force using it as the keys entered." |
27587 | 1301 (interactive) |
33491 | 1302 (catch 'op-error |
1303 (let* ((last-inp (calculator-last-input keys)) | |
1304 (op (assoc last-inp calculator-operators))) | |
1305 (calculator-clear-fragile op) | |
1306 (if (and calculator-curnum (/= (calculator-op-arity op) 0)) | |
1307 (setq calculator-stack | |
1308 (cons (calculator-curnum-value) calculator-stack))) | |
1309 (setq calculator-curnum nil) | |
1310 (if (and (= 2 (calculator-op-arity op)) | |
1311 (not (and calculator-stack | |
1312 (numberp (nth 0 calculator-stack))))) | |
1313 ;; we have a binary operator but no number - search for a prefix | |
1314 ;; version | |
1315 (let ((rest-ops calculator-operators)) | |
1316 (while (not (equal last-inp (car (car rest-ops)))) | |
1317 (setq rest-ops (cdr rest-ops))) | |
1318 (setq op (assoc last-inp (cdr rest-ops))) | |
1319 (if (not (and op (= -1 (calculator-op-arity op)))) | |
1320 ;;(error "Binary operator without a first operand") | |
1321 (progn | |
1322 (message "Binary operator without a first operand") | |
1323 (if calculator-electric-mode | |
1324 (progn (sit-for 1) (message nil))) | |
1325 (throw 'op-error nil))))) | |
1326 (calculator-reduce-stack | |
1327 (cond ((eq (nth 1 op) '\() 10) | |
1328 ((eq (nth 1 op) '\)) 0) | |
1329 (t (calculator-op-prec op)))) | |
1330 (if (or (and (= -1 (calculator-op-arity op)) | |
1331 (numberp (car calculator-stack))) | |
1332 (and (/= (calculator-op-arity op) -1) | |
1333 (/= (calculator-op-arity op) 0) | |
1334 (not (numberp (car calculator-stack))))) | |
1335 ;;(error "Unterminated expression") | |
1336 (progn | |
1337 (message "Unterminated expression") | |
1338 (if calculator-electric-mode | |
1339 (progn (sit-for 1) (message nil))) | |
1340 (throw 'op-error nil))) | |
1341 (setq calculator-stack (cons op calculator-stack)) | |
1342 (calculator-reduce-stack (calculator-op-prec op)) | |
1343 (and (= (length calculator-stack) 1) | |
1344 (numberp (nth 0 calculator-stack)) | |
1345 ;; the display is fragile if it contains only one number | |
1346 (setq calculator-display-fragile t) | |
1347 ;; add number to the saved-list | |
1348 calculator-add-saved | |
1349 (if (= 0 calculator-saved-ptr) | |
1350 (setq calculator-saved-list | |
1351 (cons (car calculator-stack) calculator-saved-list)) | |
1352 (let ((p (nthcdr (1- calculator-saved-ptr) | |
1353 calculator-saved-list))) | |
1354 (setcdr p (cons (car calculator-stack) (cdr p)))))) | |
1355 (calculator-update-display)))) | |
27587 | 1356 |
1357 (defun calculator-op-or-exp () | |
1358 "Either enter an operator or a digit. | |
33491 | 1359 Used with +/- for entering them as digits in numbers like 1e-3 (there is |
1360 no need for negative numbers since these are handled by unary | |
1361 operators)." | |
27587 | 1362 (interactive) |
1363 (if (and (not calculator-display-fragile) | |
1364 calculator-curnum | |
1365 (string-match "[eE]$" calculator-curnum)) | |
1366 (calculator-digit) | |
1367 (calculator-op))) | |
1368 | |
33631 | 1369 ;;;--------------------------------------------------------------------- |
33491 | 1370 ;;; Input/output modes (not display) |
1371 | |
27587 | 1372 (defun calculator-dec/deg-mode () |
1373 "Set decimal mode for display & input, if decimal, toggle deg mode." | |
1374 (interactive) | |
1375 (if calculator-curnum | |
1376 (setq calculator-stack | |
1377 (cons (calculator-curnum-value) calculator-stack))) | |
1378 (setq calculator-curnum nil) | |
1379 (if (or calculator-input-radix calculator-output-radix) | |
1380 (progn (setq calculator-input-radix nil) | |
1381 (setq calculator-output-radix nil)) | |
1382 ;; already decimal - toggle degrees mode | |
1383 (setq calculator-deg (not calculator-deg))) | |
1384 (calculator-update-display t)) | |
1385 | |
27904
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
1386 (defun calculator-radix-mode (&optional keys) |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
1387 "Set input and display radix modes. |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
1388 Optional string argument KEYS will force using it as the keys entered." |
27587 | 1389 (interactive) |
27904
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
1390 (calculator-radix-input-mode keys) |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
1391 (calculator-radix-output-mode keys)) |
27587 | 1392 |
27904
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
1393 (defun calculator-radix-input-mode (&optional keys) |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
1394 "Set input radix modes. |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
1395 Optional string argument KEYS will force using it as the keys entered." |
27587 | 1396 (interactive) |
1397 (if calculator-curnum | |
1398 (setq calculator-stack | |
1399 (cons (calculator-curnum-value) calculator-stack))) | |
1400 (setq calculator-curnum nil) | |
1401 (setq calculator-input-radix | |
27904
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
1402 (let ((inp (calculator-last-input keys))) |
27587 | 1403 (cdr (assq (upcase (aref inp (1- (length inp)))) |
1404 calculator-char-radix)))) | |
1405 (calculator-update-display)) | |
1406 | |
27904
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
1407 (defun calculator-radix-output-mode (&optional keys) |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
1408 "Set display radix modes. |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
1409 Optional string argument KEYS will force using it as the keys entered." |
27587 | 1410 (interactive) |
1411 (if calculator-curnum | |
1412 (setq calculator-stack | |
1413 (cons (calculator-curnum-value) calculator-stack))) | |
1414 (setq calculator-curnum nil) | |
1415 (setq calculator-output-radix | |
27904
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
1416 (let ((inp (calculator-last-input keys))) |
27587 | 1417 (cdr (assq (upcase (aref inp (1- (length inp)))) |
1418 calculator-char-radix)))) | |
1419 (calculator-update-display t)) | |
1420 | |
33631 | 1421 ;;;--------------------------------------------------------------------- |
33491 | 1422 ;;; Saved values list |
1423 | |
27587 | 1424 (defun calculator-save-on-list () |
1425 "Evaluate current expression, put result on the saved values list." | |
1426 (interactive) | |
1427 (let ((calculator-add-saved t)) ; marks the result to be added | |
1428 (calculator-enter))) | |
1429 | |
1430 (defun calculator-clear-saved () | |
1431 "Clear the list of saved values in `calculator-saved-list'." | |
1432 (interactive) | |
1433 (setq calculator-saved-list nil) | |
33491 | 1434 (setq calculator-saved-ptr 0) |
27587 | 1435 (calculator-update-display t)) |
1436 | |
1437 (defun calculator-saved-move (n) | |
1438 "Go N elements up the list of saved values." | |
1439 (interactive) | |
1440 (and calculator-saved-list | |
1441 (or (null calculator-stack) calculator-display-fragile) | |
1442 (progn | |
1443 (setq calculator-saved-ptr | |
1444 (max (min (+ n calculator-saved-ptr) | |
1445 (length calculator-saved-list)) | |
1446 0)) | |
1447 (if (nth calculator-saved-ptr calculator-saved-list) | |
1448 (setq calculator-stack | |
1449 (list (nth calculator-saved-ptr calculator-saved-list)) | |
1450 calculator-display-fragile t) | |
27904
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
1451 (calculator-reset)) |
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
1452 (calculator-update-display)))) |
27587 | 1453 |
1454 (defun calculator-saved-up () | |
1455 "Go up the list of saved values." | |
1456 (interactive) | |
1457 (calculator-saved-move +1)) | |
1458 | |
1459 (defun calculator-saved-down () | |
1460 "Go down the list of saved values." | |
1461 (interactive) | |
1462 (calculator-saved-move -1)) | |
1463 | |
33631 | 1464 ;;;--------------------------------------------------------------------- |
33491 | 1465 ;;; Misc functions |
1466 | |
27587 | 1467 (defun calculator-open-paren () |
1468 "Equivalents of `(' use this." | |
1469 (interactive) | |
27904
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
1470 (calculator-op "(")) |
27587 | 1471 |
1472 (defun calculator-close-paren () | |
1473 "Equivalents of `)' use this." | |
1474 (interactive) | |
27904
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
1475 (calculator-op ")")) |
27587 | 1476 |
1477 (defun calculator-enter () | |
27904
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
1478 "Evaluate current expression." |
27587 | 1479 (interactive) |
27904
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
1480 (calculator-op "=")) |
27587 | 1481 |
1482 (defun calculator-backspace () | |
1483 "Backward delete a single digit or a stack element." | |
1484 (interactive) | |
1485 (if calculator-curnum | |
1486 (setq calculator-curnum | |
1487 (if (> (length calculator-curnum) 1) | |
1488 (substring calculator-curnum | |
1489 0 (1- (length calculator-curnum))) | |
1490 nil)) | |
1491 (setq calculator-stack (cdr calculator-stack))) | |
1492 (calculator-update-display)) | |
1493 | |
1494 (defun calculator-clear () | |
1495 "Clear current number." | |
1496 (interactive) | |
1497 (setq calculator-curnum nil) | |
1498 (cond | |
1499 ;; if the current number is from the saved-list - remove it | |
1500 ((and calculator-display-fragile | |
1501 calculator-saved-list | |
1502 (= (car calculator-stack) | |
1503 (nth calculator-saved-ptr calculator-saved-list))) | |
1504 (if (= 0 calculator-saved-ptr) | |
1505 (setq calculator-saved-list (cdr calculator-saved-list)) | |
1506 (let ((p (nthcdr (1- calculator-saved-ptr) | |
1507 calculator-saved-list))) | |
1508 (setcdr p (cdr (cdr p))) | |
1509 (setq calculator-saved-ptr (1- calculator-saved-ptr)))) | |
1510 (if calculator-saved-list | |
1511 (setq calculator-stack | |
1512 (list (nth calculator-saved-ptr calculator-saved-list))) | |
1513 (calculator-reset))) | |
1514 ;; reset if fragile or double clear | |
1515 ((or calculator-display-fragile (eq last-command this-command)) | |
1516 (calculator-reset))) | |
1517 (calculator-update-display)) | |
1518 | |
1519 (defun calculator-copy () | |
1520 "Copy current number to the `kill-ring'." | |
1521 (interactive) | |
39430
48633cf4ce7c
(calculator-copy-displayer): New user-option.
Gerd Moellmann <gerd@gnu.org>
parents:
38436
diff
changeset
|
1522 (let ((calculator-displayer |
48633cf4ce7c
(calculator-copy-displayer): New user-option.
Gerd Moellmann <gerd@gnu.org>
parents:
38436
diff
changeset
|
1523 (or calculator-copy-displayer calculator-displayer)) |
48633cf4ce7c
(calculator-copy-displayer): New user-option.
Gerd Moellmann <gerd@gnu.org>
parents:
38436
diff
changeset
|
1524 (calculator-displayers |
48633cf4ce7c
(calculator-copy-displayer): New user-option.
Gerd Moellmann <gerd@gnu.org>
parents:
38436
diff
changeset
|
1525 (if calculator-copy-displayer nil calculator-displayers))) |
48633cf4ce7c
(calculator-copy-displayer): New user-option.
Gerd Moellmann <gerd@gnu.org>
parents:
38436
diff
changeset
|
1526 (calculator-enter) |
48633cf4ce7c
(calculator-copy-displayer): New user-option.
Gerd Moellmann <gerd@gnu.org>
parents:
38436
diff
changeset
|
1527 ;; remove trailing spaces and and an index |
48633cf4ce7c
(calculator-copy-displayer): New user-option.
Gerd Moellmann <gerd@gnu.org>
parents:
38436
diff
changeset
|
1528 (let ((s (cdr calculator-stack-display))) |
48633cf4ce7c
(calculator-copy-displayer): New user-option.
Gerd Moellmann <gerd@gnu.org>
parents:
38436
diff
changeset
|
1529 (and s |
48633cf4ce7c
(calculator-copy-displayer): New user-option.
Gerd Moellmann <gerd@gnu.org>
parents:
38436
diff
changeset
|
1530 (if (string-match "^\\([^ ]+\\) *\\(\\[[0-9/]+\\]\\)? *$" s) |
48633cf4ce7c
(calculator-copy-displayer): New user-option.
Gerd Moellmann <gerd@gnu.org>
parents:
38436
diff
changeset
|
1531 (setq s (match-string 1 s))) |
48633cf4ce7c
(calculator-copy-displayer): New user-option.
Gerd Moellmann <gerd@gnu.org>
parents:
38436
diff
changeset
|
1532 (kill-new s))))) |
27587 | 1533 |
1534 (defun calculator-set-register (reg) | |
1535 "Set a register value for REG." | |
1536 (interactive "cRegister to store into: ") | |
1537 (let* ((as (assq reg calculator-registers)) | |
1538 (val (progn (calculator-enter) (car calculator-stack)))) | |
1539 (if as | |
1540 (setcdr as val) | |
1541 (setq calculator-registers | |
1542 (cons (cons reg val) calculator-registers))) | |
1543 (message (format "[%c] := %S" reg val)))) | |
1544 | |
1545 (defun calculator-put-value (val) | |
1546 "Paste VAL as if entered. | |
1547 Used by `calculator-paste' and `get-register'." | |
1548 (if (and (numberp val) | |
1549 ;; (not calculator-curnum) | |
1550 (or calculator-display-fragile | |
1551 (not (numberp (car calculator-stack))))) | |
1552 (progn | |
1553 (calculator-clear-fragile) | |
39430
48633cf4ce7c
(calculator-copy-displayer): New user-option.
Gerd Moellmann <gerd@gnu.org>
parents:
38436
diff
changeset
|
1554 (setq calculator-curnum (let ((calculator-displayer "%S")) |
48633cf4ce7c
(calculator-copy-displayer): New user-option.
Gerd Moellmann <gerd@gnu.org>
parents:
38436
diff
changeset
|
1555 (calculator-num-to-string val))) |
27587 | 1556 (calculator-update-display)))) |
1557 | |
1558 (defun calculator-paste () | |
1559 "Paste a value from the `kill-ring'." | |
1560 (interactive) | |
1561 (calculator-put-value | |
33491 | 1562 (let ((str (current-kill 0))) |
33631 | 1563 (and calculator-paste-decimals |
1564 (string-match "\\([0-9]+\\)\\(\\.[0-9]+\\)?\\(e[0-9]+\\)?" | |
1565 str) | |
1566 (or (match-string 1 str) | |
1567 (match-string 2 str) | |
1568 (match-string 3 str)) | |
1569 (setq str (concat (match-string 1 str) | |
1570 (or (match-string 2 str) ".0") | |
1571 (match-string 3 str)))) | |
33491 | 1572 (condition-case nil (car (read-from-string str)) |
1573 (error nil))))) | |
27587 | 1574 |
1575 (defun calculator-get-register (reg) | |
1576 "Get a value from a register REG." | |
1577 (interactive "cRegister to get value from: ") | |
1578 (calculator-put-value (cdr (assq reg calculator-registers)))) | |
1579 | |
1580 (defun calculator-help () | |
1581 ;; this is used as the quick reference screen you get with `h' | |
1582 "Quick reference: | |
1583 * numbers/operators/parens/./e - enter expressions | |
1584 + - * / \\(div) %(rem) _(-X,postfix) ;(1/X,postfix) ^(exp) L(og) | |
1585 Q(sqrt) !(fact) S(in) C(os) T(an) |(or) #(xor) &(and) ~(not) | |
1586 * >/< repeats last binary operation with its 2nd (1st) arg as postfix op | |
33491 | 1587 * I inverses next trig function * '/\"/{} - display/display args |
1588 * D - switch to all-decimal, or toggle deg/rad mode | |
27587 | 1589 * B/O/H/X - binary/octal/hex mode for i/o (X is a shortcut for H) |
1590 * i/o - prefix for d/b/o/x - set only input/output modes | |
1591 * enter/= - evaluate current expr. * s/g - set/get a register | |
1592 * space - evaluate & save on list * l/v - list total/average | |
1593 * up/down/C-p/C-n - browse saved * C-delete - clear all saved | |
27904
af501f05394a
(calculator-use-menu): New option.
Gerd Moellmann <gerd@gnu.org>
parents:
27587
diff
changeset
|
1594 * C-insert - copy whole expr. * C-return - evaluate, copy, exit |
27587 | 1595 * insert - paste a number * backspace- delete backwards |
1596 * delete - clear argument or list value or whole expression (twice) | |
1597 * escape/q - exit." | |
1598 (interactive) | |
1599 (if (eq last-command 'calculator-help) | |
1600 (let ((mode-name "Calculator") | |
1601 (major-mode 'calculator-mode) | |
1602 (g-map (current-global-map)) | |
1603 (win (selected-window))) | |
1604 (require 'ehelp) | |
1605 (if calculator-electric-mode | |
1606 (use-global-map calculator-saved-global-map)) | |
33631 | 1607 (if (or (not calculator-electric-mode) |
1608 ;; XEmacs has a problem with electric-describe-mode | |
1609 (string-match "XEmacs" (emacs-version))) | |
1610 (describe-mode) | |
1611 (electric-describe-mode)) | |
27587 | 1612 (if calculator-electric-mode |
1613 (use-global-map g-map)) | |
1614 (select-window win) ; these are for XEmacs (also below) | |
1615 (message nil)) | |
1616 (let ((one (one-window-p t)) | |
1617 (win (selected-window)) | |
1618 (help-buf (get-buffer-create "*Help*"))) | |
1619 (save-window-excursion | |
1620 (with-output-to-temp-buffer "*Help*" | |
1621 (princ (documentation 'calculator-help))) | |
1622 (if one | |
1623 (shrink-window-if-larger-than-buffer | |
1624 (get-buffer-window help-buf))) | |
1625 (message | |
1626 "`%s' again for more help, any other key continues normally." | |
1627 (calculator-last-input)) | |
1628 (select-window win) | |
1629 (sit-for 360)) | |
1630 (select-window win)))) | |
1631 | |
1632 (defun calculator-quit () | |
1633 "Quit calculator." | |
1634 (interactive) | |
1635 (set-buffer calculator-buffer) | |
1636 (let ((inhibit-read-only t)) (erase-buffer)) | |
1637 (if (not calculator-electric-mode) | |
1638 (progn | |
1639 (condition-case nil | |
1640 (while (get-buffer-window calculator-buffer) | |
1641 (delete-window (get-buffer-window calculator-buffer))) | |
1642 (error nil)) | |
1643 (kill-buffer calculator-buffer))) | |
1644 (setq calculator-buffer nil) | |
1645 (message "Calculator done.") | |
1646 (if calculator-electric-mode (throw 'calculator-done nil))) | |
1647 | |
1648 (defun calculator-save-and-quit () | |
1649 "Quit the calculator, saving the result on the `kill-ring'." | |
1650 (interactive) | |
1651 (calculator-enter) | |
1652 (calculator-copy) | |
1653 (calculator-quit)) | |
1654 | |
1655 (defun calculator-repR (x) | |
1656 "Repeats the last binary operation with its second argument and X. | |
1657 To use this, apply a binary operator (evaluate it), then call this." | |
1658 (if calculator-last-opXY | |
1659 ;; avoid rebinding calculator-last-opXY | |
1660 (let ((calculator-last-opXY calculator-last-opXY)) | |
1661 (calculator-funcall | |
1662 (car calculator-last-opXY) x (nth 2 calculator-last-opXY))) | |
1663 x)) | |
1664 | |
1665 (defun calculator-repL (x) | |
1666 "Repeats the last binary operation with its first argument and X. | |
1667 To use this, apply a binary operator (evaluate it), then call this." | |
1668 (if calculator-last-opXY | |
1669 ;; avoid rebinding calculator-last-opXY | |
1670 (let ((calculator-last-opXY calculator-last-opXY)) | |
1671 (calculator-funcall | |
1672 (car calculator-last-opXY) (nth 1 calculator-last-opXY) x)) | |
1673 x)) | |
1674 | |
1675 (defun calculator-fact (x) | |
1676 "Simple factorial of X." | |
1677 (let ((r (if (<= x 10) 1 1.0))) | |
1678 (while (> x 0) | |
1679 (setq r (* r (truncate x))) | |
1680 (setq x (1- x))) | |
1681 r)) | |
1682 | |
1683 (defun calculator-truncate (n) | |
1684 "Truncate N, return 0 in case of overflow." | |
1685 (condition-case nil (truncate n) (error 0))) | |
1686 | |
1687 | |
1688 (provide 'calculator) | |
1689 | |
52401 | 1690 ;;; arch-tag: a1b9766c-af8a-4a74-b466-65ad8eeb0c73 |
27587 | 1691 ;;; calculator.el ends here |