]> code.delx.au - gnu-emacs/blobdiff - lisp/calculator.el
Merge from origin/emacs-25
[gnu-emacs] / lisp / calculator.el
index 3d44b6d86c580b2b78a0ed1f4644da5bf2733267..523bf98180ab6e46847a7cedbaf709f22a00b763 100644 (file)
@@ -1,6 +1,6 @@
 ;;; calculator.el --- a calculator for Emacs  -*- lexical-binding: t -*-
 
-;; Copyright (C) 1998, 2000-2015 Free Software Foundation, Inc.
+;; Copyright (C) 1998, 2000-2016 Free Software Foundation, Inc.
 
 ;; Author: Eli Barzilay <eli@barzilay.org>
 ;; Keywords: tools, convenience
@@ -161,6 +161,8 @@ This makes it possible to paste big integers since they will be read as
 floats, otherwise the Emacs reader will fail on them."
   :type  'boolean
   :group 'calculator)
+(make-obsolete-variable 'calculator-paste-decimals
+                        "it is no longer used." nil)
 
 (defcustom calculator-copy-displayer nil
   "If non-nil, this is any value that can be used for
@@ -377,12 +379,13 @@ Used for repeating operations in calculator-repR/L.")
 ;;;---------------------------------------------------------------------
 ;;; Key bindings
 
-(defun calculator-define-key (key cmd &optional map)
-  ;; arranges for unbound alphabetic keys to be used as their un/shifted
-  ;; versions if those are bound (mimics the usual Emacs global
-  ;; bindings)
+(defun calculator-define-key (key cmd map)
+  ;; Arranges for unbound alphabetic keys to be used as their un/shifted
+  ;; versions if those are bound (mimics the usual Emacs global bindings).
+  ;; FIXME: We should adjust Emacs's native "fallback to unshifted binding"
+  ;; such that it can also be used here, rather than having to use a hack like
+  ;; this one.
   (let* ((key  (if (stringp key) (kbd key) key))
-         (map  (or map calculator-mode-map))
          (omap (keymap-parent map)))
     (define-key map key cmd)
     ;; "other" map, used for case-flipped bindings
@@ -391,7 +394,7 @@ Used for repeating operations in calculator-repR/L.")
       (suppress-keymap omap t)
       (set-keymap-parent map omap))
     (let ((m omap))
-      ;; bind all case-flipped versions
+      ;; Bind all case-flipped versions.
       (dotimes (i (length key))
         (let* ((c (aref key i))
                (k (vector c))
@@ -402,7 +405,7 @@ Used for repeating operations in calculator-repR/L.")
                                     (or (<= ?A c ?Z) (<= ?a c ?z)))
                            (define-key m (vector (logxor 32 c)) x)))))
           (cond ((= i (1- (length key)))
-                 ;; prefer longer sequences
+                 ;; Prefer longer sequences.
                  (unless (keymapp b) (funcall defkey cmd)))
                 ((keymapp b) (setq m b))
                 (t (let ((sub (make-sparse-keymap)))
@@ -799,7 +802,7 @@ Adds MORE-OPS to `calculator-operator', called initially to handle
   (let ((added-ops nil))
     (dolist (op more-ops)
       (unless (eq (car op) 'nobind)
-        (calculator-define-key (car op) 'calculator-op))
+        (calculator-define-key (car op) 'calculator-op calculator-mode-map))
       (push (if (eq (car op) 'nobind) (cdr op) op)
             added-ops))
     ;; added-ops come first, but in correct order
@@ -855,39 +858,13 @@ The result should not exceed the screen width."
   "Convert the given STR to a number, according to the value of
 `calculator-input-radix'."
   (if calculator-input-radix
-    (let ((radix
-           (cdr (assq calculator-input-radix
-                      '((bin . 2) (oct . 8) (hex . 16)))))
-          (i -1) (value 0) (new-value 0))
-      ;; assume mostly valid input (e.g., characters in range)
-      (while (< (setq i (1+ i)) (length str))
-        (setq new-value
-              (let* ((ch (upcase (aref str i)))
-                     (n (cond ((< ch ?0)  nil)
-                              ((<= ch ?9) (- ch ?0))
-                              ((< ch ?A)  nil)
-                              ((<= ch ?Z) (- ch (- ?A 10)))
-                              (t          nil))))
-                (if (and n (<= 0 n) (< n radix))
-                  (+ n (* radix value))
-                  (progn
-                    (calculator-message
-                     "Warning: Ignoring bad input character `%c'." ch)
-                    (sit-for 1)
-                    value))))
-        (when (if (< new-value 0) (> value 0) (< value 0))
-          (calculator-message "Warning: Overflow in input."))
-        (setq value new-value))
-      value)
-    (car (read-from-string
-          (cond ((equal "." str) "0.0")
-                ((string-match-p "[eE][+-]?$" str) (concat str "0"))
-                ((string-match-p "\\.[0-9]\\|[eE]" str) str)
-                ((string-match-p "\\." str)
-                 ;; do this because Emacs reads "23." as an integer
-                 (concat str "0"))
-                ((stringp str) (concat str ".0"))
-                (t "0.0"))))))
+    (string-to-number str (cadr (assq calculator-input-radix
+                                      '((bin 2) (oct 8) (hex 16)))))
+    (let* ((str (replace-regexp-in-string
+                 "\\.\\([^0-9].*\\)?$" ".0\\1" str))
+           (str (replace-regexp-in-string
+                 "[eE][+-]?\\([^0-9].*\\)?$" "e0\\1" str)))
+      (string-to-number str))))
 
 (defun calculator-push-curnum ()
   "Push the numeric value of the displayed number to the stack."
@@ -1329,7 +1306,8 @@ Used with +/- for entering them as digits in numbers like 1e-3 (there is
 no need for negative numbers since these are handled by unary
 operators)."
   (interactive)
-  (if (and (not calculator-display-fragile)
+  (if (and (not calculator-input-radix)
+           (not calculator-display-fragile)
            calculator-curnum
            (string-match-p "[eE]$" calculator-curnum))
     (calculator-digit)
@@ -1497,25 +1475,27 @@ Used by `calculator-paste' and `get-register'."
              (or calculator-display-fragile
                  (not (numberp (car calculator-stack)))))
     (calculator-clear-fragile)
-    (setq calculator-curnum (let ((calculator-displayer "%S"))
-                              (calculator-number-to-string val)))
+    (setq calculator-curnum
+          (let ((calculator-displayer "%S")
+                (calculator-radix-grouping-mode nil)
+                (calculator-output-radix calculator-input-radix))
+            (calculator-number-to-string val)))
     (calculator-update-display)))
 
-(defun calculator-paste ()
-  "Paste a value from the `kill-ring'."
-  (interactive)
-  (calculator-put-value
-   (let ((str (replace-regexp-in-string
-               "^ *\\(.+[^ ]\\) *$" "\\1" (current-kill 0))))
-     (when (and (not calculator-input-radix)
-                calculator-paste-decimals
-                (string-match
-                 "\\([0-9]+\\)\\(\\.[0-9]+\\)?\\(e[0-9]+\\)?"
-                 str))
-       (setq str (concat (or (match-string 1 str) "0")
-                         (or (match-string 2 str) ".0")
-                         (or (match-string 3 str) ""))))
-     (ignore-errors (calculator-string-to-number str)))))
+(defun calculator-paste (arg)
+  "Paste a value from the `kill-ring'.
+
+With a prefix argument, paste the raw string as a sequence of key
+presses, which can be used to paste expressions.  Note that this
+is literal; examples: spaces will store values, pasting \"1+2\"
+will not produce 3 if it's done you're entering a number or after
+a multiplication."
+  (interactive "P")
+  (let ((str (current-kill 0)))
+    (if arg
+      (setq unread-command-events
+            `(,@(listify-key-sequence str) ,@unread-command-events))
+      (calculator-put-value (calculator-string-to-number str)))))
 
 (defun calculator-register-read-with-preview (prompt)
   "Similar to `register-read-with-preview' but for calculator