5

This seems so obvious that I feel sure that I've just missed something in the manual. I frequently do a calculation and then want to use that calculation elsewhere. But let's say my stack is currently:

--- Emacs Calculator Mode ---
1:  42
    .

Any way I've tried to copy the value 42 with incantations of M-w, what I get when I yank is

1:  42

including the newline.

The manual says

Although a whole line is always deleted, C-k with no argument copies only the number itself into the kill ring, whereas C-k with a prefix argument of 1 copies the number with its trailing newline.

but that only works with C-k, weirdly, not with M-w (though otherwise the commands respond to arguments similarly), and still, that doesn't solve my problem, as I still get the stack number.

Amazingly, even moving the cursor, setting mark on 4 and point after 2 to set a region (which is highlighted, making me think this should work) doesn't get my the value: it still gives me the entire line.

I know about M-x quick-calc, which lets me enter an algebraic expression into the minibuffer whose result is placed into the kill ring, but that's not helpful if I'm doing a complex calculation or simply want to use the normal Calc RPN interface. (While there are methods described about how to move a quick-calc result into the calculator stack, I don't see a way to gain access to the stack from quick-calc. $1, etc., refer to prior results of quick-calc instead.)

calc-copy-to-buffer is bound conveniently to y, but I often want to use the result in the minibuffer or even in another program via kill-ring/clipboard integration, so this isn't a solution, either.

Of course I can yank or copy to a buffer and then edit the result and re-kill the edited result, but I do this so frequently and again, it seems like such an obvious use case that I really think I'm just missing something.

(I know there are Orgmode and database solutions for bulk transfer of Calc data, but I just want a single value to yank; it shouldn't be that hard.)

1

Just after posting this, I found a solution I'm surprised I didn't think of sooner:

  1. Hit backtick (calc-edit) to edit the stack value.
  2. Kill the line in the edit buffer with C-w (editing it first if it suits your needs).
  3. C-c C-c to close the buffer (if you killed everything, the value gets restored on the stack, so it's equivalent to hitting C-c C-k).
  4. Yank or paste wherever you please.

Not quite the single-key solution I was expecting, but it'll do.

1

Here's some code to define a function to put the most recent thing in the calc stack into the kill ring.

(defun copy-calc-top ()
  "Copy the thing at the top of the calc stack."
  (interactive)
  (let ((val (calc-top)))
    (kill-new (if (Math-scalarp val)
                  (math-format-number val)
                (math-format-flat-expr-fancy val 0)))))

And we can bind it to a key.

(define-key calc-mode-map (kbd "M-w") #'copy-calc-top)

I think this should now work for most data types. It works for integers, floating point numbers, and dates.

  • 1
    Since the thing I use this for most frequently is date calculations, this wouldn't work for my purposes. I actually went down that road trying to define a function, but trying to make it general purpose by chaining a bunch of type-checking predicates was murder, so I gave up. – Trey Jul 6 '16 at 16:50
  • 1
    Btw, @zck, I tried to edit your answer to fix the missing close quote in the second line of the block, but I can't make an edit unless it's > 6 characters. – Trey Jul 6 '16 at 16:53
  • 1
    @Trey Thanks for pointing out the open string. I fixed it. Also, I just found #'math-format-flat-expr-fancy, which works for dates. I think it should work for most things. – zck Jul 6 '16 at 17:12
1

You can set mark and point, and save the region to the kill ring with kill-ring-save, which by default is bound to C-M-w in calc mode (instead of M-w as it is in most other modes).

1

Using C-x * y allows you to yank the result into the buffer of your choice, including the minibuffer. I'm not sure this will help you with yanking into another program, though. See here for more.

0

I thought exactly the same thing, found nothing and wrote this piece of code:

(with-eval-after-load 'calc
  (defun calc-copy-as-kill ()
    "Copy the top of stack as kill."
    (interactive)
    (let ((buffer (generate-new-buffer "*copy-here*")))
      (unwind-protect
          (progn
            (cl-letf
                (((symbol-function 'calc-find-writable-buffer)
                  (lambda (buf mode) buffer)))
              (call-interactively 'calc-copy-to-buffer))
            (with-current-buffer buffer
              (kill-new (buffer-substring-no-properties (point-min) (point-max))))
            (message "Copied the result: %s" (car kill-ring)))
        (and (buffer-name buffer)
             (kill-buffer buffer)))))

  (defun calc-copy-as-kill-and-quit ()
    "Copy the top of stack as kill and quit."
    (interactive)
    (calc-copy-as-kill)
    (calc-quit))

  (define-key calc-mode-map (kbd "W")       'calc-copy-as-kill)
  (define-key calc-mode-map (kbd "C-c C-c") 'calc-copy-as-kill-and-quit))

This is kind of a dirty hack to steal what calc-copy-to-buffer would paste into the last buffer and copy it as kill, but it works for me so far.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.