Add esc_printer_actor

This commit is contained in:
Emery Hemingway 2024-05-30 20:51:11 +03:00
parent 1bf29bdf02
commit 32f8cd792c
4 changed files with 133 additions and 1 deletions

View File

@ -241,6 +241,39 @@ Examples:
---
## esc_printer_actor
A basic [ESC/P](https://en.wikipedia.org/wiki/ESC/P) printer controller.
Takes a path to a printer device file as a command line argument and publishes a `<printer @cap #:any @device-path string>` to its environment.
The capability in this assertion is an entity that prints the strings it receives as messages.
While the `<bold>` or `<italic>` is asserted to this entity the printer will go into the corresponding font mode (if the printer supports it).
Sample Syndicate server script:
```
<require-service <daemon printer>>
? <printer ?printer> [
$log ?? <log "-" { line: ?line }> [
$printer ! $text
$printer ! "\r\n"
# Print log messages.
]
]
? <service-object <daemon printer> ?cap> [
$cap ? <printer ?printer ?device> [
$config <printer $printer>
]
]
<daemon printer {
argv: [ "/bin/esc_printer_actor" "/dev/usb/lp0"]
protocol: application/syndicate
}>
```
## http_client
The inverse of `http-driver`.

View File

@ -7,7 +7,7 @@
"bom-ref": "pkg:nim/syndicate_utils",
"name": "syndicate_utils",
"description": "Utilites for Syndicated Actors and Synit",
"version": "20240523",
"version": "20240530",
"authors": [
{
"name": "Emery Hemingway"
@ -41,6 +41,10 @@
"name": "nim:bin:mintsturdyref",
"value": "mintsturdyref"
},
{
"name": "nim:bin:esc-printer-actor",
"value": "esc_printer_actor"
},
{
"name": "nim:bin:msg",
"value": "msg"

84
src/esc_printer_actor.nim Normal file
View File

@ -0,0 +1,84 @@
# SPDX-FileCopyrightText: ☭ Emery Hemingway
# SPDX-License-Identifier: Unlicense
## ESC/P printer control actor.
import
std/[cmdline, oserrors, posix, sets],
preserves, preserves/sugar,
syndicate, syndicate/relays,
./private/esc_p
proc echo(args: varargs[string, `$`]) {.used.} =
stderr.writeLine(args)
type
HandleSet = HashSet[Handle]
Printer = ref object of Entity
device: cint
boldHandles, italicHandles, superscriptHandles, subscriptHandles: HandleSet
proc write(printer: Printer; s: string) {.inline.} =
if posix.write(printer.device, s[0].addr, s.len) < 0:
osLastError().osErrorMsg().quit()
proc writeLine(printer: Printer; s: string) {.inline.} =
printer.write(s)
printer.write("\r\n")
method message(printer: Printer; t: Turn; a: AssertionRef) =
if a.value.isString:
printer.write(a.value.string)
# TODO: unicode?
# TODO: line breaks?
proc assert(printer: Printer; handles: var HandleSet; ctrl: string; h: Handle) =
if handles.len == 0: printer.write(ctrl)
handles.incl h
proc retract(printer: Printer; handles: var HandleSet; ctrl: string; h: Handle) =
handles.excl h
if handles.len == 0: printer.write(ctrl)
method publish(printer: Printer; t: Turn; a: AssertionRef; h: Handle) =
if a.value.isRecord("bold"):
printer.assert(printer.boldHandles, SelectBoldFont, h)
elif a.value.isRecord("italic"):
printer.assert(printer.italicHandles, SelectItalicFont, h)
elif a.value.isRecord("superscript"):
printer.assert(printer.superscriptHandles, SelectSuperScript, h)
elif a.value.isRecord("subscript"):
printer.assert(printer.subscriptHandles, SelectSubScript, h)
method retract(printer: Printer; t: Turn; h: Handle) =
if printer.boldHandles.contains h:
printer.retract(printer.boldHandles, CancelBoldFont, h)
elif printer.italicHandles.contains h:
printer.retract(printer.italicHandles, CanceItalicFont, h)
elif printer.superscriptHandles.contains h:
printer.retract(printer.superscriptHandles, CancelAltScript, h)
elif printer.subscriptHandles.contains h:
printer.retract(printer.subscriptHandles, CancelAltScript, h)
proc openPrinter(turn: Turn; devicePath: string): Printer =
new result
result.facet = turn.facet
result.device = posix.open(devicePath, O_WRONLY, 0)
result.write(InitializePrinter)
proc main =
let devicePath = paramStr(1)
runActor(devicePath) do (turn: Turn):
let printer = turn.newCap openPrinter(turn, devicePath)
resolveEnvironment(turn) do (turn: Turn; ds: Cap):
publish(turn, ds, initRecord(
toSymbol"printer", printer.embed, %devicePath))
main()

11
src/private/esc_p.nim Normal file
View File

@ -0,0 +1,11 @@
const
ESC* = "\x1b"
InitializePrinter* = ESC & "@"
CancelLine* = ESC & "\x18"
SelectBoldFont* = ESC & "E"
CancelBoldFont* = ESC & "F"
SelectItalicFont* = ESC & "4"
CanceItalicFont* = ESC & "5"
SelectSuperScript* = ESC & "S0"
SelectSubScript* = ESC & "S1"
CancelAltScript* = ESC & "T"