aboutsummaryrefslogtreecommitdiffstats
path: root/lisp
diff options
context:
space:
mode:
authorRichard M. Stallman2004-12-21 11:38:36 +0000
committerRichard M. Stallman2004-12-21 11:38:36 +0000
commit761d3eb391b4b58f121ef624b3e0c720f4470c9f (patch)
tree7cf6b46e0b87fcdb456207ede2d9594372a575ff /lisp
parentb6e8e8e55dba10595b059df3638a85b10c3d3d1f (diff)
downloademacs-761d3eb391b4b58f121ef624b3e0c720f4470c9f.tar.gz
emacs-761d3eb391b4b58f121ef624b3e0c720f4470c9f.zip
(calculator-radix-grouping-mode)
(calculator-radix-grouping-digits) (calculator-radix-grouping-separator): New defcustoms for the new radix grouping mode functionality. (calculator-mode-hook): Now used in electric mode too. (calculator-mode-map): Some new keys. (calculator-message): New function. Some new calls. (calculator-string-to-number): New function, (calculator-curnum-value): Use it. (calculator-rotate-displayer, calculator-rotate-displayer-back) (calculator-displayer-prev, calculator-displayer-next): Change digit group size when in radix mode. (calculator-number-to-string): Renamed from calculator-num-to-string. Now deals with digit grouping in radix mode.
Diffstat (limited to 'lisp')
-rw-r--r--lisp/calculator.el220
1 files changed, 144 insertions, 76 deletions
diff --git a/lisp/calculator.el b/lisp/calculator.el
index a9410ae961c..76ff4053c7f 100644
--- a/lisp/calculator.el
+++ b/lisp/calculator.el
@@ -4,6 +4,7 @@
4 4
5;; Author: Eli Barzilay <eli@barzilay.org> 5;; Author: Eli Barzilay <eli@barzilay.org>
6;; Keywords: tools, convenience 6;; Keywords: tools, convenience
7;; Time-stamp: <2002-07-13 01:14:35 eli>
7 8
8;; This file is part of GNU Emacs. 9;; This file is part of GNU Emacs.
9 10
@@ -100,6 +101,20 @@ at runtime."
100 :type 'integer 101 :type 'integer
101 :group 'calculator) 102 :group 'calculator)
102 103
104(defcustom calculator-radix-grouping-mode t
105 "*Use digit grouping in radix output mode.
106If this is set, chunks of `calculator-radix-grouping-digits' characters
107will be separated by `calculator-radix-grouping-separator' when in radix
108output mode is active (determined by `calculator-output-radix').")
109
110(defcustom calculator-radix-grouping-digits 4
111 "*The number of digits used for grouping display in radix modes.
112See `calculator-radix-grouping-mode'.")
113
114(defcustom calculator-radix-grouping-separator "'"
115 "*The separator used in radix grouping display.
116See `calculator-radix-grouping-mode'.")
117
103(defcustom calculator-remove-zeros t 118(defcustom calculator-remove-zeros t
104 "*Non-nil value means delete all redundant zero decimal digits. 119 "*Non-nil value means delete all redundant zero decimal digits.
105If this value is not t, and not nil, redundant zeros are removed except 120If this value is not t, and not nil, redundant zeros are removed except
@@ -163,7 +178,11 @@ Otherwise show as a negative number."
163 :group 'calculator) 178 :group 'calculator)
164 179
165(defcustom calculator-mode-hook nil 180(defcustom calculator-mode-hook nil
166 "*List of hook functions for `calculator-mode' to run." 181 "*List of hook functions for `calculator-mode' to run.
182Note: if `calculator-electric-mode' is on, then this hook will get
183activated in the minibuffer - in that case it should not do much more
184than local key settings and other effects that will change things
185outside the scope of calculator related code."
167 :type 'hook 186 :type 'hook
168 :group 'calculator) 187 :group 'calculator)
169 188
@@ -387,7 +406,7 @@ Used for repeating operations in calculator-repR/L.")
387 "oD" "oH" "oX" "oO" "oB") 406 "oD" "oH" "oX" "oO" "oB")
388 (calculator-rotate-displayer "'") 407 (calculator-rotate-displayer "'")
389 (calculator-rotate-displayer-back "\"") 408 (calculator-rotate-displayer-back "\"")
390 (calculator-displayer-pref "{") 409 (calculator-displayer-prev "{")
391 (calculator-displayer-next "}") 410 (calculator-displayer-next "}")
392 (calculator-saved-up [up] [?\C-p]) 411 (calculator-saved-up [up] [?\C-p])
393 (calculator-saved-down [down] [?\C-n]) 412 (calculator-saved-down [down] [?\C-n])
@@ -399,10 +418,10 @@ Used for repeating operations in calculator-repR/L.")
399 (calculator-save-and-quit [(control return)] 418 (calculator-save-and-quit [(control return)]
400 [(control kp-enter)]) 419 [(control kp-enter)])
401 (calculator-paste [insert] [(shift insert)] 420 (calculator-paste [insert] [(shift insert)]
402 [mouse-2]) 421 [paste] [mouse-2] [?\C-y])
403 (calculator-clear [delete] [?\C-?] [?\C-d]) 422 (calculator-clear [delete] [?\C-?] [?\C-d])
404 (calculator-help [?h] [??] [f1] [help]) 423 (calculator-help [?h] [??] [f1] [help])
405 (calculator-copy [(control insert)]) 424 (calculator-copy [(control insert)] [copy])
406 (calculator-backspace [backspace]) 425 (calculator-backspace [backspace])
407 ))) 426 )))
408 (while p 427 (while p
@@ -536,7 +555,7 @@ Used for repeating operations in calculator-repR/L.")
536 ,@(mapcar (lambda (x) (nth 1 x)) radix-selectors) 555 ,@(mapcar (lambda (x) (nth 1 x)) radix-selectors)
537 "---" 556 "---"
538 ,@(mapcar (lambda (x) (nth 2 x)) radix-selectors))) 557 ,@(mapcar (lambda (x) (nth 2 x)) radix-selectors)))
539 ("Decimal Dislpay" 558 ("Decimal Display"
540 ,@(mapcar (lambda (d) 559 ,@(mapcar (lambda (d)
541 (vector (cadr d) 560 (vector (cadr d)
542 ;; Note: inserts actual object here 561 ;; Note: inserts actual object here
@@ -611,10 +630,11 @@ The prompt indicates the current modes:
611* \"=?\": (? is B/O/H) the display radix (when input is decimal); 630* \"=?\": (? 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. 631* \"??\": (? is D/B/O/H) 1st char for input radix, 2nd for display.
613 632
614Also, the quote character can be used to switch display modes for 633Also, the quote key can be used to switch display modes for decimal
615decimal numbers (double-quote rotates back), and the two brace 634numbers (double-quote rotates back), and the two brace characters
616characters (\"{\" and \"}\" change display parameters that these 635\(\"{\" and \"}\" change display parameters that these displayers use (if
617displayers use (if they handle such). 636they handle such). If output is using any radix mode, then these keys
637toggle digit grouping mode and the chunk size.
618 638
619Values can be saved for future reference in either a list of saved 639Values can be saved for future reference in either a list of saved
620values, or in registers. 640values, or in registers.
@@ -683,6 +703,7 @@ See the documentation for `calculator-mode' for more information."
683 (setq calculator-saved-global-map (current-global-map)) 703 (setq calculator-saved-global-map (current-global-map))
684 (use-local-map nil) 704 (use-local-map nil)
685 (use-global-map calculator-mode-map) 705 (use-global-map calculator-mode-map)
706 (run-hooks 'calculator-mode-hook)
686 (unwind-protect 707 (unwind-protect
687 (catch 'calculator-done 708 (catch 'calculator-done
688 (Electric-command-loop 709 (Electric-command-loop
@@ -717,6 +738,12 @@ See the documentation for `calculator-mode' for more information."
717 (if (and calculator-restart-other-mode calculator-electric-mode) 738 (if (and calculator-restart-other-mode calculator-electric-mode)
718 (calculator))) 739 (calculator)))
719 740
741(defun calculator-message (string &rest arguments)
742 "Same as `message', but special handle of electric mode."
743 (apply 'message string arguments)
744 (if calculator-electric-mode
745 (progn (sit-for 1) (message nil))))
746
720;;;--------------------------------------------------------------------- 747;;;---------------------------------------------------------------------
721;;; Operators 748;;; Operators
722 749
@@ -818,82 +845,116 @@ The string is set not to exceed the screen width."
818 (concat calculator-prompt 845 (concat calculator-prompt
819 (substring prompt (+ trim (length calculator-prompt))))))) 846 (substring prompt (+ trim (length calculator-prompt)))))))
820 847
821(defun calculator-curnum-value () 848(defun calculator-string-to-number (str)
822 "Get the numeric value of the displayed number string as a float." 849 "Convert the given STR to a number, according to the value of
850`calculator-input-radix'."
823 (if calculator-input-radix 851 (if calculator-input-radix
824 (let ((radix 852 (let ((radix
825 (cdr (assq calculator-input-radix 853 (cdr (assq calculator-input-radix
826 '((bin . 2) (oct . 8) (hex . 16))))) 854 '((bin . 2) (oct . 8) (hex . 16)))))
827 (i -1) (value 0)) 855 (i -1) (value 0) (new-value 0))
828 ;; assume valid input (upcased & characters in range) 856 ;; assume mostly valid input (e.g., characters in range)
829 (while (< (setq i (1+ i)) (length calculator-curnum)) 857 (while (< (setq i (1+ i)) (length str))
830 (setq value 858 (setq new-value
831 (+ (let ((ch (aref calculator-curnum i))) 859 (let* ((ch (upcase (aref str i)))
832 (- ch (if (<= ch ?9) ?0 (- ?A 10)))) 860 (n (cond ((< ch ?0) nil)
833 (* radix value)))) 861 ((<= ch ?9) (- ch ?0))
862 ((< ch ?A) nil)
863 ((<= ch ?Z) (- ch (- ?A 10)))
864 (t nil))))
865 (if (and n (<= 0 n) (< n radix))
866 (+ n (* radix value))
867 (progn
868 (calculator-message
869 "Warning: Ignoring bad input character `%c'." ch)
870 (sit-for 1)
871 value))))
872 (if (if (< new-value 0) (> value 0) (< value 0))
873 (calculator-message "Warning: Overflow in input."))
874 (setq value new-value))
834 value) 875 value)
835 (car 876 (car (read-from-string
836 (read-from-string 877 (cond ((equal "." str) "0.0")
837 (cond 878 ((string-match "[eE][+-]?$" str) (concat str "0"))
838 ((equal "." calculator-curnum) 879 ((string-match "\\.[0-9]\\|[eE]" str) str)
839 "0.0") 880 ((string-match "\\." str)
840 ((string-match "[eE][+-]?$" calculator-curnum) 881 ;; do this because Emacs reads "23." as an integer
841 (concat calculator-curnum "0")) 882 (concat str "0"))
842 ((string-match "\\.[0-9]\\|[eE]" calculator-curnum) 883 ((stringp str) (concat str ".0"))
843 calculator-curnum) 884 (t "0.0"))))))
844 ((string-match "\\." calculator-curnum) 885
845 ;; do this because Emacs reads "23." as an integer 886(defun calculator-curnum-value ()
846 (concat calculator-curnum "0")) 887 "Get the numeric value of the displayed number string as a float."
847 ((stringp calculator-curnum) 888 (calculator-string-to-number calculator-curnum))
848 (concat calculator-curnum ".0"))
849 (t "0.0"))))))
850 889
851(defun calculator-rotate-displayer (&optional new-disp) 890(defun calculator-rotate-displayer (&optional new-disp)
852 "Switch to the next displayer on the `calculator-displayers' list. 891 "Switch to the next displayer on the `calculator-displayers' list.
853Can be called with an optional argument NEW-DISP to force rotation to 892Can be called with an optional argument NEW-DISP to force rotation to
854that argument." 893that argument.
894If radix output mode is active, toggle digit grouping."
855 (interactive) 895 (interactive)
856 (setq calculator-displayers 896 (cond
857 (if (and new-disp (memq new-disp calculator-displayers)) 897 (calculator-output-radix
858 (let ((tmp nil)) 898 (setq calculator-radix-grouping-mode
859 (while (not (eq (car calculator-displayers) new-disp)) 899 (not calculator-radix-grouping-mode))
860 (setq tmp (cons (car calculator-displayers) tmp)) 900 (calculator-message
861 (setq calculator-displayers (cdr calculator-displayers))) 901 "Digit grouping mode %s."
862 (setq calculator-displayers 902 (if calculator-radix-grouping-mode "ON" "OFF")))
863 (nconc calculator-displayers (nreverse tmp)))) 903 (t
864 (nconc (cdr calculator-displayers) 904 (setq calculator-displayers
865 (list (car calculator-displayers))))) 905 (if (and new-disp (memq new-disp calculator-displayers))
866 (message "Using %s." (cadr (car calculator-displayers))) 906 (let ((tmp nil))
867 (if calculator-electric-mode 907 (while (not (eq (car calculator-displayers) new-disp))
868 (progn (sit-for 1) (message nil))) 908 (setq tmp (cons (car calculator-displayers) tmp))
909 (setq calculator-displayers
910 (cdr calculator-displayers)))
911 (setq calculator-displayers
912 (nconc calculator-displayers (nreverse tmp))))
913 (nconc (cdr calculator-displayers)
914 (list (car calculator-displayers)))))
915 (calculator-message
916 "Using %s." (cadr (car calculator-displayers)))))
869 (calculator-enter)) 917 (calculator-enter))
870 918
871(defun calculator-rotate-displayer-back () 919(defun calculator-rotate-displayer-back ()
872 "Like `calculator-rotate-displayer', but rotates modes back." 920 "Like `calculator-rotate-displayer', but rotates modes back.
921If radix output mode is active, toggle digit grouping."
873 (interactive) 922 (interactive)
874 (calculator-rotate-displayer (car (last calculator-displayers)))) 923 (calculator-rotate-displayer (car (last calculator-displayers))))
875 924
876(defun calculator-displayer-prev () 925(defun calculator-displayer-prev ()
877 "Send the current displayer function a 'left argument. 926 "Send the current displayer function a 'left argument.
878This is used to modify display arguments (if the current displayer 927This is used to modify display arguments (if the current displayer
879function supports this)." 928function supports this).
929If radix output mode is active, increase the grouping size."
880 (interactive) 930 (interactive)
881 (and (car calculator-displayers) 931 (if calculator-output-radix
882 (let ((disp (caar calculator-displayers))) 932 (progn (setq calculator-radix-grouping-digits
883 (cond ((symbolp disp) (funcall disp 'left)) 933 (1+ calculator-radix-grouping-digits))
884 ((and (consp disp) (eq 'std (car disp))) 934 (calculator-enter))
885 (calculator-standard-displayer 'left (cadr disp))))))) 935 (and (car calculator-displayers)
936 (let ((disp (caar calculator-displayers)))
937 (cond
938 ((symbolp disp) (funcall disp 'left))
939 ((and (consp disp) (eq 'std (car disp)))
940 (calculator-standard-displayer 'left (cadr disp))))))))
886 941
887(defun calculator-displayer-next () 942(defun calculator-displayer-next ()
888 "Send the current displayer function a 'right argument. 943 "Send the current displayer function a 'right argument.
889This is used to modify display arguments (if the current displayer 944This is used to modify display arguments (if the current displayer
890function supports this)." 945function supports this).
946If radix output mode is active, decrease the grouping size."
891 (interactive) 947 (interactive)
892 (and (car calculator-displayers) 948 (if calculator-output-radix
893 (let ((disp (caar calculator-displayers))) 949 (progn (setq calculator-radix-grouping-digits
894 (cond ((symbolp disp) (funcall disp 'right)) 950 (max 2 (1- calculator-radix-grouping-digits)))
895 ((and (consp disp) (eq 'std (car disp))) 951 (calculator-enter))
896 (calculator-standard-displayer 'right (cadr disp))))))) 952 (and (car calculator-displayers)
953 (let ((disp (caar calculator-displayers)))
954 (cond
955 ((symbolp disp) (funcall disp 'right))
956 ((and (consp disp) (eq 'std (car disp)))
957 (calculator-standard-displayer 'right (cadr disp))))))))
897 958
898(defun calculator-remove-zeros (numstr) 959(defun calculator-remove-zeros (numstr)
899 "Get a number string NUMSTR and remove unnecessary zeroes. 960 "Get a number string NUMSTR and remove unnecessary zeroes.
@@ -995,7 +1056,7 @@ the 'left or 'right when one of the standard modes is used."
995 (calculator-remove-zeros str)) 1056 (calculator-remove-zeros str))
996 "e" (number-to-string exp)))))) 1057 "e" (number-to-string exp))))))
997 1058
998(defun calculator-num-to-string (num) 1059(defun calculator-number-to-string (num)
999 "Convert NUM to a displayable string." 1060 "Convert NUM to a displayable string."
1000 (cond 1061 (cond
1001 ((and (numberp num) calculator-output-radix) 1062 ((and (numberp num) calculator-output-radix)
@@ -1015,6 +1076,14 @@ the 'left or 'right when one of the standard modes is used."
1015 (?6 . "110") (?7 . "111"))))))) 1076 (?6 . "110") (?7 . "111")))))))
1016 (string-match "^0*\\(.+\\)" s) 1077 (string-match "^0*\\(.+\\)" s)
1017 (setq str (match-string 1 s)))) 1078 (setq str (match-string 1 s))))
1079 (if calculator-radix-grouping-mode
1080 (let ((d (/ (length str) calculator-radix-grouping-digits))
1081 (r (% (length str) calculator-radix-grouping-digits)))
1082 (while (>= (setq d (1- d)) (if (zerop r) 1 0))
1083 (let ((i (+ r (* d calculator-radix-grouping-digits))))
1084 (setq str (concat (substring str 0 i)
1085 calculator-radix-grouping-separator
1086 (substring str i)))))))
1018 (upcase 1087 (upcase
1019 (if (and (not calculator-2s-complement) (< num 0)) 1088 (if (and (not calculator-2s-complement) (< num 0))
1020 (concat "-" str) 1089 (concat "-" str)
@@ -1051,7 +1120,7 @@ If optional argument FORCE is non-nil, don't use the cached string."
1051 ;; customizable display for a single value 1120 ;; customizable display for a single value
1052 (caar calculator-displayers) 1121 (caar calculator-displayers)
1053 calculator-displayer))) 1122 calculator-displayer)))
1054 (mapconcat 'calculator-num-to-string 1123 (mapconcat 'calculator-number-to-string
1055 (reverse calculator-stack) 1124 (reverse calculator-stack)
1056 " ")) 1125 " "))
1057 " " 1126 " "
@@ -1319,9 +1388,8 @@ Optional string argument KEYS will force using it as the keys entered."
1319 (if (not (and op (= -1 (calculator-op-arity op)))) 1388 (if (not (and op (= -1 (calculator-op-arity op))))
1320 ;;(error "Binary operator without a first operand") 1389 ;;(error "Binary operator without a first operand")
1321 (progn 1390 (progn
1322 (message "Binary operator without a first operand") 1391 (calculator-message
1323 (if calculator-electric-mode 1392 "Binary operator without a first operand")
1324 (progn (sit-for 1) (message nil)))
1325 (throw 'op-error nil))))) 1393 (throw 'op-error nil)))))
1326 (calculator-reduce-stack 1394 (calculator-reduce-stack
1327 (cond ((eq (nth 1 op) '\() 10) 1395 (cond ((eq (nth 1 op) '\() 10)
@@ -1334,9 +1402,7 @@ Optional string argument KEYS will force using it as the keys entered."
1334 (not (numberp (car calculator-stack))))) 1402 (not (numberp (car calculator-stack)))))
1335 ;;(error "Unterminated expression") 1403 ;;(error "Unterminated expression")
1336 (progn 1404 (progn
1337 (message "Unterminated expression") 1405 (calculator-message "Unterminated expression")
1338 (if calculator-electric-mode
1339 (progn (sit-for 1) (message nil)))
1340 (throw 'op-error nil))) 1406 (throw 'op-error nil)))
1341 (setq calculator-stack (cons op calculator-stack)) 1407 (setq calculator-stack (cons op calculator-stack))
1342 (calculator-reduce-stack (calculator-op-prec op)) 1408 (calculator-reduce-stack (calculator-op-prec op))
@@ -1540,7 +1606,7 @@ Optional string argument KEYS will force using it as the keys entered."
1540 (setcdr as val) 1606 (setcdr as val)
1541 (setq calculator-registers 1607 (setq calculator-registers
1542 (cons (cons reg val) calculator-registers))) 1608 (cons (cons reg val) calculator-registers)))
1543 (message (format "[%c] := %S" reg val)))) 1609 (calculator-message "[%c] := %S" reg val)))
1544 1610
1545(defun calculator-put-value (val) 1611(defun calculator-put-value (val)
1546 "Paste VAL as if entered. 1612 "Paste VAL as if entered.
@@ -1552,24 +1618,26 @@ Used by `calculator-paste' and `get-register'."
1552 (progn 1618 (progn
1553 (calculator-clear-fragile) 1619 (calculator-clear-fragile)
1554 (setq calculator-curnum (let ((calculator-displayer "%S")) 1620 (setq calculator-curnum (let ((calculator-displayer "%S"))
1555 (calculator-num-to-string val))) 1621 (calculator-number-to-string val)))
1556 (calculator-update-display)))) 1622 (calculator-update-display))))
1557 1623
1558(defun calculator-paste () 1624(defun calculator-paste ()
1559 "Paste a value from the `kill-ring'." 1625 "Paste a value from the `kill-ring'."
1560 (interactive) 1626 (interactive)
1561 (calculator-put-value 1627 (calculator-put-value
1562 (let ((str (current-kill 0))) 1628 (let ((str (replace-regexp-in-string
1563 (and calculator-paste-decimals 1629 "^ *\\(.+[^ ]\\) *$" "\\1" (current-kill 0))))
1630 (and (not calculator-input-radix)
1631 calculator-paste-decimals
1564 (string-match "\\([0-9]+\\)\\(\\.[0-9]+\\)?\\(e[0-9]+\\)?" 1632 (string-match "\\([0-9]+\\)\\(\\.[0-9]+\\)?\\(e[0-9]+\\)?"
1565 str) 1633 str)
1566 (or (match-string 1 str) 1634 (or (match-string 1 str)
1567 (match-string 2 str) 1635 (match-string 2 str)
1568 (match-string 3 str)) 1636 (match-string 3 str))
1569 (setq str (concat (match-string 1 str) 1637 (setq str (concat (or (match-string 1 str) "0")
1570 (or (match-string 2 str) ".0") 1638 (or (match-string 2 str) ".0")
1571 (match-string 3 str)))) 1639 (or (match-string 3 str) ""))))
1572 (condition-case nil (car (read-from-string str)) 1640 (condition-case nil (calculator-string-to-number str)
1573 (error nil))))) 1641 (error nil)))))
1574 1642
1575(defun calculator-get-register (reg) 1643(defun calculator-get-register (reg)
@@ -1678,7 +1746,7 @@ To use this, apply a binary operator (evaluate it), then call this."
1678 (while (> x 0) 1746 (while (> x 0)
1679 (setq r (* r (truncate x))) 1747 (setq r (* r (truncate x)))
1680 (setq x (1- x))) 1748 (setq x (1- x)))
1681 r)) 1749 (+ 0.0 r)))
1682 1750
1683(defun calculator-truncate (n) 1751(defun calculator-truncate (n)
1684 "Truncate N, return 0 in case of overflow." 1752 "Truncate N, return 0 in case of overflow."