Subject: bug#21648: 25.0.50; [PATCH] Add ability to specify radix for the yanked number in calc-yank

From: Kaushal Modi <[email-masked]>
Date: Thu, 8 Oct 2015 22:56:30 -0400

Thanks for the feedback.

The below code has every suggestion implemented except for the
`math-numberstring-p`.
I will need to thing more about how to implement that.

Also the below condition might not be enough (even before we start thinking
about math-numberstring-p):

(or (null radix)
     (string-match-p "\\`[0-9]+#" thing-raw))

What if the user yanks the below string?

111
2#1111

In that case, the below code will generate the below if called using C-2 C-y

2#111
2#2#1111

The above case seems impractical. Or is it? Should we need to make the code
foolproof against such unusual cases?
If yes, then we need to ensure that either the radix prepending happens
only if all yanked lines are pristine

The below code has the following updated:
- Support for negative numbers!
- Error when user enters a non-integer or an integer <2 or >36
- Support for prepending the radix-notation to multiline yanks (assuming
the yanks do not fit in the above mentioned strange case)
- Made the referenced long message a bit concise.

======

(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* (radix-num
                   radix-notation
                   (thing-raw (if (fboundp 'current-kill)
                                  (current-kill 0 t)
                                (car kill-ring-yank-pointer)))
                   (thing (if (or (null radix)
                                  (string-match-p "\\`\\-*[0-9]+#"
thing-raw))
                              thing-raw
                            (progn
                              (setq radix-notation
                                    (if (listp radix)
                                        (progn
                                          (setq radix-num
                                                (read-number
                                                 "Set radix for yanked
number (2-36): "))
                                          (if (and (integerp radix-num)
                                                   (<= 2 radix-num)
                                                   (>= 36 radix-num))
                                              (concat (number-to-string
radix-num) "#")
                                            (error (concat "The radix has
to be an "
                                                           "integer between
2 and 36."))))
                                      (cond ((eq radix 2) "2#")
                                            ((eq radix 8) "8#")
                                            ((eq radix 0) "10#")
                                            ((eq radix 6) "16#")
                                            (t (progn
                                                 (message
                                                  (concat "No radix
prepended "
                                                          "for invalid
numeric "
                                                          "prefix %0d.")
                                                  radix)
                                                 "")))))
                              ;; Ensure that the radix-notation is prefixed
                              ;; correctly even for multi-line yanks like
                              ;; 111
                              ;; 1111
                              (replace-regexp-in-string
                               "^\\(\\-*\\)\\(.*\\)"
                               (concat "\\1" radix-notation "\\2")
                               thing-raw)))))
              (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))))))))

--
Kaushal Modi