1
mirror of https://gitlab.com/jessieh/qrprinter.git synced 2025-05-22 10:41:46 +00:00
qrprinter/src/qrprinter.fnl

112 lines
4.2 KiB
Fennel

;; qrprinter.fnl
;; Provides utilities for encoding and printing strings as QR codes
;; -------------------------------------------------------------------------- ;;
;; License
;; Copyright (C) 2021 Jessie Hildebrandt
;; This program is free software: you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
;; along with this program. If not, see <https://www.gnu.org/licenses/>.
;; -------------------------------------------------------------------------- ;;
;; Local modules
(local qrencode (require :qrprinter.ffi.qrencode))
;; -------------------------------------------------------------------------- ;;
;; Helper functions
;; ---------------------------------- ;;
;; Padding
(fn generate_sequence [element size]
"Return a sequential table of `element` with length `size`."
(let [row []]
(for [_ 1 size]
(table.insert row element))
row))
(fn pad_sequence [sequence element amount]
"Return a sequential table containing `sequence` padded with `amount` count of `element`."
(let [padded_sequence [(unpack sequence)]]
(for [_ 1 amount]
(table.insert padded_sequence 1 element)
(table.insert padded_sequence element))
padded_sequence))
(fn pad_qr [qr amount]
"Return 2D sequential table `qr` padded with `amount` count of white modules."
(let [blank_row (generate_sequence false (length qr))
padded_qr (pad_sequence qr blank_row amount)]
(icollect [_ row (ipairs padded_qr)]
(pad_sequence row false amount))))
;; ---------------------------------- ;;
;; Printing
(fn print_qr [qr black_cell white_cell ?options]
"Print 2D sequential table `qr` to stdout.
Black modules will be printed as `black_cell`, and white modules will be printed as `white_cell`.
`?options` is optional and may contain two keys:
- invert: If non-nil, the output colors will be inverted.
- padding: Amount of blank modules to print around QR code. If nil, defaults to 2."
(let [invert? (?. ?options :invert)
padding (or (?. ?options :padding) 2)
padded_qr (pad_qr qr padding)
[black_cell white_cell] (if invert? [white_cell black_cell] [black_cell white_cell])
row_strings (icollect [_ row (ipairs padded_qr)]
(accumulate [row_string ""
_ module_black? (ipairs row)]
(.. row_string (if module_black? black_cell white_cell))))]
(print (table.concat row_strings "\n"))))
;; -------------------------------------------------------------------------- ;;
;; Module functions
;; Some Fennel naming conventions are eschewed here because these are Lua-facing library functions
;; and the names would be mangled during compilation.
;; e.g. ?options -> _3foptions, invert? -> invert_3f
(fn encode_string [string]
"Encode string `string` into a table representing a QR code.
Returns a 2D sequential table of true/false values representing black/white QR modules."
(qrencode.encode_string_8_bit string))
(fn print_qr_ascii [qr options]
"Print QR code `qr` to stdout using ASCII characters."
(let [black_cell " "
white_cell "##"]
(print_qr qr black_cell white_cell options)))
(fn print_qr_ansi [qr options]
"Print QR code `qr` to stdout using ANSI escape sequences."
(let [black_cell "\27[40m \27[0m"
white_cell "\27[47m \27[0m"]
(print_qr qr black_cell white_cell options)))
(fn print_qr_utf8 [qr options]
"Print QR code `qr` to stdout using UTF8 block elements."
(let [black_cell " "
white_cell "██"]
(print_qr qr black_cell white_cell options)))
;; -------------------------------------------------------------------------- ;;
;; Provide qrprinter module
{: encode_string
: print_qr_ascii
: print_qr_ansi
: print_qr_utf8
:print_qr print_qr_ansi}