Some time ago I bought a cheap Chinese thermoprinter off eBay. As expected the printers firmware is really awkward to use (including binary control codes used to switch between char sets such as bold, italic, underlined, etc.). The obvious solution was to write a library to parse a more sensible representation and send it to be printed.
Since there might, at some point, be other users wanting to print to my acquisition the architecture is intended to be present a somewhat usable interface to the uninitiated.
Recently I created a new branch in thermoprint called rewrite.
The new macroscopic architecture I´m currently aiming for is quite similar to the old one:
Features I intend to implement include:
Reasonable test coverage using QuickCheck, HUnit.
Automatic testing with cabal facilitated by hspec.The Website should provide some richer formats than bbcode which will probably find inclusion in the payload datastructure such as lists, checklists, tables, etc.
The cli-tool should be able to use these too (the input will probably end up being json-formatted).
I already have a prototype. It’s quite bug-ridden and has recently developed serious problems actually printing after working satisfactorily for a few weeks.
It also does not include a web-interface and I am quite unsatisfied with the overall code quality.
The 685 lines of code can be found in the repo as well.
Currently the rewrite contains a single file of moment – spec/src/Thermoprint/Printout.hs – wherein we define the payload for the api – our take on a structured document format (somewhat inspired by pandoc):
-- | A 'Printout' is a sequence of visually seperated 'Paragraph's
type Printout = Seq Paragraph
-- | A 'Paragraph' is a non-seperated sequence of 'Chunk's
type Paragraph = Seq Chunk
-- | We introduce both 'Chunk' and 'Paragraph' mainly to allow 'Raw'.
--
-- Were we to disallow 'Raw', 'Block' would be identical to 'Paragraph'
data Chunk = Cooked Block -- ^ text semantically structured to be rendered in accordance with the display format of printer
| Raw ByteString -- ^ direct instructions to the printer
deriving (Generic, NFData, Show, CoArbitrary)
-- | 'Block' is the entry point for our structured document format
data Block = Line Line -- ^ a single 'Line' of text
| VSpace Integer -- ^ vertical space of height equivalent to 'Integer' lines
| NewlSep (Seq Block) -- ^ A sequence of 'Block's seperated by newlines
deriving (Generic, NFData, Show, CoArbitrary)
{- | A 'Line' is one of:
* a single word
* horizontal space equivalent to the width of 'Integer' `em`.
* a sequence of words seperated by spaces
We don't export all constructors and instead encourage the use of 'text'.
-}
data Line = Word Text
| HSpace Integer
| SpaceSep (Seq Line)
deriving (Generic, NFData, Show, CoArbitrary)
(The code is verbatim as of 8307d7e).