This article was inspired by QR Codes on the Command-Line.
QR codes are nice: if you want to send e.g. a URL or a short string to your phone, just turn it into a QR code and scan it on the phone, no internet required.
Install qrencode
on your system:
pacman -S qrencode
Now a QR code can be generated in Emacs by directly calling the shell command, then dumping it to an ASCII art in the *Messages*
buffer:
(shell-command-to-string "qrencode 'hello world' -t UTF8 -o -")
Of course, we should utilize Emacs's ability to display images. Here's a Emacs command that prompts for the string, encodes it with qrencode
, and displays it in a nice PNG buffer.
kisaragi/qr-encode
(defun kisaragi/qr-encode (str &optional buf)
Encode STR as a QR code.
Return a new buffer or BUF with the code in it."
(interactive "MString to encode: ") ; Open a prompt; pass input as str
(let ((buffer (get-buffer-create (or buf "*QR Code*")))
(inhibit-read-only t)) ; make sure we can write the output
(with-current-buffer buffer
(delete-region (point-min) (point-max))) ; Clear the buffer
(make-process ; Start a process
:name "qrencode" :buffer buffer ; that writes stdout to `buffer'
:command `("qrencode" ,str "-t" "PNG" "-o" "-") ; "-o -" sends output to stdout
:coding 'no-conversion ; Don't encode stdout as string
:sentinel (lambda (process change)
(when (string= change "finished\n") ; If the process successfully exits,
(with-current-buffer
(process-buffer process) ; then go to the buffer,
(image-mode) ; display its contents as PNG,
(image-transform-fit-to-height))))) ; and resize it so it's not tiny
(when (called-interactively-p 'interactive)
(display-buffer buffer))
buffer))
In the Terminal
For as nice as GUI Emacs is, sometimes I just have to use Emacs in a terminal — specifically, on Android, under Termux. This version is what I have in my Emacs configuration right now (2019-09-24), which uses ASCII art output if it is run in a terminal.
kisaragi/qr-encode
with non-GUI support
(defun kisaragi/qr-encode (str &optional buf)
"Encode STR as a QR code.
Return a new buffer or BUF with the code in it."
(interactive "MString to encode: ")
(let ((buffer (get-buffer-create (or buf "*QR Code*")))
(format (if (display-graphic-p) "PNG" "UTF8")) ; use PNG in a graphical frame
(inhibit-read-only t))
(with-current-buffer buffer
(delete-region (point-min) (point-max)))
(make-process
:name "qrencode" :buffer buffer
:command `("qrencode" ,str "-t" ,format "-o" "-")
:coding 'no-conversion
;; seems only the filter function is able to move point to top
:filter (lambda (process string)
(with-current-buffer (process-buffer process) ; Make sure we're looking at the
(insert string) ; top of the output buffer
(goto-char (point-min))
(set-marker (process-mark process) (point))))
:sentinel (lambda (process change)
(when (string= change "finished\n")
(with-current-buffer (process-buffer process)
(cond ((string= format "PNG")
(image-mode)
(image-transform-fit-to-height))
(t ; decode the output as we
(text-mode) ; suppressed it at line 14
(decode-coding-region (point-min) (point-max) 'utf-8)))))))
(when (called-interactively-p 'interactive)
(display-buffer buffer))
buffer))