A little read-string utility using an Org Mode buffer
While extending Emacs, I wished to have a super cool note capturing buffer like Org Capture.
What I wished for was a utility function that would set up a buffer where to write my text (so to have a little space instead of the super-small minibuffer), and return the text once done.
So far I always defaulted to the trustworthy read-string, ignoring my cravings.
Today I decided to bake my own.
I admit to have only looked into the Org Mode code to see if I could reuse their implementation. I couldn't because they define a function to overwrite the ctrl-c-ctrl-c keybinding to do their tricks and I don't want to use that mechanism for this little utility.
If you know a built-in that does this already, I would be happy to discover that I wasted my time :)
If not, here you can find what I achieved:
(defun my/override-keybiding-in-buffer (key command)
"Override KEY with COMMAND in buffer."
(interactive "KSet key buffer-locally: \nCSet key %s buffer-locally to command: ")
(let ((oldmap (current-local-map))
(newmap (make-sparse-keymap)))
(when oldmap
(set-keymap-parent newmap oldmap))
(define-key newmap key command)
(use-local-map newmap)))
(defun my/read-string-from-buffer (prompt callback)
"Make on `org-mode' buffer with PROMPT and run CALLBACK on C-c C-c."
(let ((current-buffer (current-buffer)))
(switch-to-buffer (get-buffer-create "*read-string-from-buffer*"))
(erase-buffer)
(org-mode)
(insert (concat "# Press C-c C-c to continue, C-c C-k to cancel\n# " prompt "\n\n"))
(goto-char (point-max))
(my/override-keybiding-in-buffer
(kbd "C-c C-c")
`(lambda ()
(interactive)
(let ((contents (string-trim
(buffer-substring
(save-excursion (goto-char (point-min)) (forward-line 2) (point))
(point-max)))))
(switch-to-buffer ,current-buffer)
(funcall ',callback contents))))
(my/override-keybiding-in-buffer
(kbd "C-c C-k")
(lambda ()
(interactive)
(kill-buffer)))))
Note that my/override-keybiding-in-buffer is something I extracted
from my moldable-emacs package and that sets a local key binding in the
current buffer.
The signature of my/read-string-from-buffer is simple: a prompt
argument for a string with your instructions for the user and a
callback function to use the text the user has inserted.
You can try this out like this:
(my/read-string-from-buffer "write something here" (lambda (text) (message "this is what you inserted:\n%s" text )))
Having this will make a few use cases more enjoyable for me and I really hope something like this is (or will land) in Emacs core already. Hope you find it useful too!
Happy texting!