As the readers of my blog know, I’m a heavy Ledger user. One thing that annoyed me was the fact that I couldn’t use my numeric keypad to enter amounts. The reason was simple – the “comma” key on that keypad inserted a comma in Emacs and not a period. For a long time I suspected that the reason for that was that I had a Polish locale set somewhere in the system (we use a decimal comma in Poland and period is a thousand separator). In fact, I have a mixture of Polish and English locales – I want sorting to work correctly for the Polish alphabet, but I want programs to talk to me in English. One reason is that some programs have very poor translations; a more important one is that searching the Internet for error messages is easier when they are in English.
Anyway, I finally decided to do something about my problem. When I typed C-h c , (pressing the keypad comma), I saw this:
, 'COMMA' (translated from <kp-separator>) runs the command self-insert-command
so I searched Emacs sources for the string kp-separator and found this in simple.el:
;; Make the keypad keys act like ordinary typing keys. If people add
;; bindings for the function key symbols, then those bindings will
;; override these, so this shouldn't interfere with any existing
;; bindings.
;; Also tell read-char how to handle these keys.
(mapc
(lambda (keypad-normal)
(let ((keypad (nth 0 keypad-normal))
(normal (nth 1 keypad-normal)))
(put keypad 'ascii-character normal)
(define-key function-key-map (vector keypad) (vector normal))))
;; See also kp-keys bound in bindings.el.
'((kp-space ?\s)
(kp-tab ?\t)
(kp-enter ?\r)
(kp-separator ?,)
(kp-equal ?=)
;; Do the same for various keys that are represented as symbols under
;; GUIs but naturally correspond to characters.
(backspace 127)
(delete 127)
(tab ?\t)
(linefeed ?\n)
(clear ?\C-l)
(return ?\C-m)
(escape ?\e)
))
I’m not sure what (put keypad 'ascii-character normal) does (and searching for ascii-character suggest something connected with the dark arts of terminal emulation, so I decided not to pursue this further to preserve my sanity), but the rest is pretty clear – apparently, the “keypad separator” is hardcoded to enter a comma in Emacs. Well, not that clear – it still touches another murky corner of Emacs, key translations – but at least I knew what to do. I put this in my init.el:
(keymap-set function-key-map "<kp-separator>" ".")
and from now on I can type numbers with decimal part using my numeric keypad.
While at that, I decided to revisit my fast-calc command I wrote about over ten years ago. I figured that since I’m using the numeric keypad, I could make use of the Calc key my laptop has there. I didn’t want to bind it to fast-calc, since pressing C-u Calc to get the value with the currency is not very ergonomic, so I decided to write an auxiliary command which works like fast-calc but with the meaning of the prefix argument reversed. Of course, I also needed to know how to bind the Calc key, but that is easy – when I press C-h c Calc, Emacs tells me what it calls that key. So, here is my fast-calc.el file after the changes.
;; -*- lexical-binding: t; -*-
;; Fast calculation: interactively replace simple arithmetic
;; expressions with their values in arbitrary buffers
(defvar fast-calc-suffix " PLN"
"The default suffix for C-u M-x fast-calc. Useful in ledger-mode.")
(defun fast-calc (currency)
"Replace the arithmetic expression to the left of the point with its
value. The arithmetic expression is defined as a simple regex match.
With prefix arg, round to two digits after the decimal point and
add the currency suffix"
(interactive "P")
(when (looking-back "[-+/*().0-9]\\{2,\\} *"
(line-beginning-position)
t)
(replace-match
(save-match-data
(calc-eval (if currency
(list
(concat (match-string-no-properties 0) "+0.0")
'calc-float-format
'(fix 2))
(match-string-no-properties 0))))
t t)
(if currency (insert fast-calc-suffix))))
(defun fast-calc-with-prefix-arg-flipped (arg)
"Call `fast-calc' with the meaning of the prefix arg flipped."
(interactive "P")
(fast-calc (not arg)))
(global-set-key (kbd "C-z c") #'fast-calc)
(global-set-key (kbd "<XF86Calculator>")
#'fast-calc-with-prefix-arg-flipped)
And that’s it. Now using Ledger is even more streamlined for me!
CategoryEnglish, CategoryBlog, CategoryEmacs, CategoryLedger