;;; calc-yank.el --- kill-ring functionality for Calc
-;; Copyright (C) 1990-1993, 2001-2015 Free Software Foundation, Inc.
+;; Copyright (C) 1990-1993, 2001-2016 Free Software Foundation, Inc.
;; Author: David Gillespie <daveg@synaptics.com>
-;; Maintainer: Jay Belanger <jay.p.belanger@gmail.com>
;; This file is part of GNU Emacs.
(interactive "r")
(calc-kill-region top bot t))
+(defun math-number-regexp (radix-num)
+ "Return a regexp which will match a Calc number base RADIX-NUM."
+ (let* ((digit-range
+ (cond
+ ;; radix 2 to 10
+ ((and (<= 2 radix-num)
+ (>= 10 radix-num))
+ (concat "[0-"
+ (number-to-string (1- radix-num))
+ "]"))
+ ;; radix 11
+ ((= 11 radix-num) "[0-9aA]")
+ ;; radix 12+
+ (t
+ (concat "[0-9"
+ "a-" (format "%c" (+ (- ?a 11) radix-num))
+ "A-" (format "%c" (+ (- ?A 11) radix-num))
+ "]"))))
+ (integer-regexp (concat digit-range "+"))
+ (decimal-regexp (concat digit-range "+\\." digit-range "*")))
+ (concat
+ " *\\("
+ ;; "e" notation
+ "[-_+]?" decimal-regexp "[eE][-+]?[0-9]+"
+ "\\|"
+ "[-_+]?" integer-regexp "[eE][-+]?[0-9]+"
+ "\\|"
+ ;; Integer+fractions
+ "[-_+]?" integer-regexp "*[:/]" integer-regexp "[:/]" integer-regexp
+ "\\|"
+ ;; Fractions
+ "[-_+]?" integer-regexp "[:/]" integer-regexp
+ "\\|"
+ ;; Decimal point
+ "[-_+]?" decimal-regexp
+ "\\|"
+ ;; Integers
+ "[-_+]?" integer-regexp
+ "\\) *\\(\n\\|\\'\\)")))
+
;; This function uses calc-last-kill if possible to get an exact result,
;; otherwise it just parses the yanked string.
;; Modified to use Emacs 19 extended concept of kill-ring. -- daveg 12/15/96
;;;###autoload
-(defun calc-yank ()
- (interactive)
+(defun calc-yank (radix)
+ "Yank a value into the Calculator buffer.
+
+Valid numeric prefixes for RADIX: 0, 2, 6, 8
+No radix notation is prepended for any other numeric prefix.
+
+If RADIX is 2, prepend \"2#\" - Binary.
+If RADIX is 8, prepend \"8#\" - Octal.
+If RADIX is 0, prepend \"10#\" - Decimal.
+If RADIX is 6, prepend \"16#\" - Hexadecimal.
+
+If RADIX is a non-nil list (created using \\[universal-argument]), the user
+will be prompted to enter the radix in the minibuffer.
+
+If RADIX is nil or if the yanked string already has a calc radix prefix, the
+yanked string will be passed on directly to the Calculator buffer without any
+alteration."
+ (interactive "P")
(calc-wrapper
(calc-pop-push-record-list
0 "yank"
- (let ((thing (if (fboundp 'current-kill)
- (current-kill 0 t)
- (car kill-ring-yank-pointer))))
- (if (eq (car-safe calc-last-kill) thing)
- (cdr calc-last-kill)
- (if (stringp thing)
- (let ((val (math-read-exprs (calc-clean-newlines thing))))
- (if (eq (car-safe val) 'error)
- (progn
- (setq val (math-read-exprs thing))
- (if (eq (car-safe val) 'error)
- (error "Bad format in yanked data")
- val))
- val))))))))
+ (let* (radix-num
+ radix-notation
+ valid-num-regexp
+ (thing-raw
+ (if (fboundp 'current-kill)
+ (current-kill 0 t)
+ (car kill-ring-yank-pointer)))
+ (thing
+ (if (or (null radix)
+ ;; Match examples: -2#10, 10\n(10#10,01)
+ (string-match-p "^[-(]*[0-9]\\{1,2\\}#" thing-raw))
+ thing-raw
+ (progn
+ (if (listp radix)
+ (progn
+ (setq radix-num
+ (read-number
+ "Set radix for yanked content (2-36): "))
+ (when (not (and (integerp radix-num)
+ (<= 2 radix-num)
+ (>= 36 radix-num)))
+ (error (concat "The radix has to be an "
+ "integer between 2 and 36."))))
+ (setq radix-num
+ (cond ((eq radix 2) 2)
+ ((eq radix 8) 8)
+ ((eq radix 0) 10)
+ ((eq radix 6) 16)
+ (t (message
+ (concat "No radix prepended "
+ "for invalid *numeric* "
+ "prefix %0d.")
+ radix)
+ nil))))
+ (if radix-num
+ (progn
+ (setq radix-notation
+ (concat (number-to-string radix-num) "#"))
+ (setq valid-num-regexp
+ (math-number-regexp radix-num))
+ ;; Ensure that the radix-notation is prefixed
+ ;; correctly even for multi-line yanks like below,
+ ;; 111
+ ;; 1111
+ (replace-regexp-in-string
+ valid-num-regexp
+ (concat radix-notation "\\&")
+ thing-raw))
+ thing-raw)))))
+ (if (eq (car-safe calc-last-kill) thing-raw)
+ (cdr calc-last-kill)
+ (if (stringp thing)
+ (let ((val (math-read-exprs (calc-clean-newlines thing))))
+ (if (eq (car-safe val) 'error)
+ (progn
+ (setq val (math-read-exprs thing))
+ (if (eq (car-safe val) 'error)
+ (error "Bad format in yanked data")
+ val))
+ val))))))))
;;; The Calc set- and get-register commands are modified versions of functions
;;; in register.el
(insert (propertize
(concat
(or title title "Calc Edit Mode. ")
- (format-message "Press ‘C-c C-c’")
+ (format-message "Press `C-c C-c'")
(if allow-ret "" " or RET")
- (format-message " to finish, ‘C-x k RET’ to cancel.\n\n"))
+ (format-message " to finish, `C-x k RET' to cancel.\n\n"))
'font-lock-face 'italic 'read-only t 'rear-nonsticky t 'front-sticky t))
(make-local-variable 'calc-edit-top)
(setq calc-edit-top (point))))