🖨️ esc/pos implementation in gleam

refactor: command buffer now public and can be turned back to bitarray

okk.moe 8cf7b6c8 88e60dda

verified
+201 -141
+31 -32
src/escpos.gleam
··· 23 //// ``` 24 25 import escpos/image 26 - import escpos/printer.{type CommandBuffer, CommandBuffer} 27 import escpos/protocol 28 import gleam/bit_array 29 import gleam/bool ··· 38 39 /// Creates a new empty command buffer. 40 pub fn new() -> CommandBuffer { 41 - CommandBuffer(<<>>) 42 } 43 44 /// Writes text to the buffer. 45 pub fn write(cb: CommandBuffer, text: String) -> CommandBuffer { 46 - append(cb, bit_array.from_string(text)) 47 } 48 49 /// Writes text to the buffer followed by a newline. 50 pub fn writeln(cb: CommandBuffer, text: String) -> CommandBuffer { 51 - append(cb, bit_array.from_string(text)) 52 - |> append(protocol.lf) 53 } 54 55 /// Enables or disables bold text. 56 pub fn bold(cb: CommandBuffer, b: Bool) -> CommandBuffer { 57 - append(cb, protocol.bold(b)) 58 } 59 60 /// Enables or disables underlined text. 61 pub fn underline(cb: CommandBuffer, b: Bool) -> CommandBuffer { 62 - append(cb, protocol.underline(b)) 63 } 64 65 /// Enables or disables double-strike text. 66 pub fn double_strike(cb: CommandBuffer, b: Bool) -> CommandBuffer { 67 - append(cb, protocol.double_strike(b)) 68 } 69 70 /// Enables or disables reverse (white on black) text. 71 pub fn reverse(cb: CommandBuffer, b: Bool) -> CommandBuffer { 72 - append(cb, protocol.reverse(b)) 73 } 74 75 /// Enables or disables upside-down text. 76 pub fn upside_down(cb: CommandBuffer, b: Bool) -> CommandBuffer { 77 - append(cb, protocol.upside_down(b)) 78 } 79 80 /// Enables or disables character smoothing. 81 pub fn smooth(cb: CommandBuffer, b: Bool) -> CommandBuffer { 82 - append(cb, protocol.smooth(b)) 83 } 84 85 /// Enables or disables 180-degree rotation. 86 pub fn flip(cb: CommandBuffer, b: Bool) -> CommandBuffer { 87 - append(cb, protocol.flip(b)) 88 } 89 90 /// Sets the printer font. 91 pub fn font(cb: CommandBuffer, font: Font) -> CommandBuffer { 92 - append(cb, protocol.font(font)) 93 } 94 95 /// Resets the font to the default (FontA). 96 pub fn reset_font(cb: CommandBuffer) -> CommandBuffer { 97 - append(cb, protocol.font(protocol.FontA)) 98 } 99 100 /// Sets text alignment (Left, Center, or Right). 101 pub fn align(cb: CommandBuffer, justify: Justify) -> CommandBuffer { 102 ensure_new_line(cb) 103 - |> append(protocol.justify(justify)) 104 } 105 106 /// Sets text size multiplier (1-8 for width and height). 107 pub fn text_size(cb: CommandBuffer, width: Int, height: Int) -> CommandBuffer { 108 - append(cb, protocol.character_size(width, height)) 109 } 110 111 /// Resets text size to normal (1x1). 112 pub fn reset_text_size(cb: CommandBuffer) -> CommandBuffer { 113 - append(cb, protocol.character_size(1, 1)) 114 } 115 116 /// Performs a full paper cut. 117 pub fn cut(cb: CommandBuffer) -> CommandBuffer { 118 - append(cb, protocol.cut(protocol.Full)) 119 } 120 121 /// Performs a partial paper cut, leaving a small portion connected. 122 pub fn partial_cut(cb: CommandBuffer) -> CommandBuffer { 123 - append(cb, protocol.cut(protocol.Partial)) 124 } 125 126 /// Appends a single newline. 127 pub fn new_line(cb: CommandBuffer) -> CommandBuffer { 128 - append(cb, protocol.lf) 129 } 130 131 /// Feeds the specified number of lines. 132 pub fn line_feed(cb: CommandBuffer, lines: Int) -> CommandBuffer { 133 - append(cb, protocol.line_feed(lines)) 134 } 135 136 /// Resets the printer to its initial state. 137 pub fn reset(cb: CommandBuffer) -> CommandBuffer { 138 - append(cb, protocol.init) 139 } 140 141 /// Prints a monochrome image prepared by the `image` module. ··· 153 /// ``` 154 pub fn image(cb: CommandBuffer, image: image.PrintableImage) -> CommandBuffer { 155 ensure_new_line(cb) 156 - |> append(protocol.image_to_graphics_buffer( 157 image.pixels(image), 158 image.width(image), 159 image.height(image), ··· 162 protocol.Scale1x, 163 protocol.Color1, 164 )) 165 - |> append(protocol.print_graphics_buffer()) 166 } 167 168 /// Appends raw bytes to the buffer. 169 pub fn raw(cb: CommandBuffer, data: BitArray) -> CommandBuffer { 170 - append(cb, data) 171 - } 172 - 173 - fn append(cb: CommandBuffer, data: BitArray) -> CommandBuffer { 174 - bit_array.append(cb.data, data) 175 - |> CommandBuffer 176 } 177 178 fn ensure_new_line(cb: CommandBuffer) -> CommandBuffer { ··· 183 } 184 185 fn is_new_line(cb: CommandBuffer) -> Bool { 186 - use <- bool.guard(when: cb.data == <<>>, return: True) 187 case 188 - bit_array.slice(from: cb.data, at: bit_array.byte_size(cb.data), take: -3) 189 { 190 Ok(<<27, "d", _>>) -> True 191 Ok(<<_, _, 10>>) -> True
··· 23 //// ``` 24 25 import escpos/image 26 + import escpos/printer.{type CommandBuffer} 27 import escpos/protocol 28 import gleam/bit_array 29 import gleam/bool ··· 38 39 /// Creates a new empty command buffer. 40 pub fn new() -> CommandBuffer { 41 + printer.new_buffer() 42 } 43 44 /// Writes text to the buffer. 45 pub fn write(cb: CommandBuffer, text: String) -> CommandBuffer { 46 + printer.append_to_buffer(cb, bit_array.from_string(text)) 47 } 48 49 /// Writes text to the buffer followed by a newline. 50 pub fn writeln(cb: CommandBuffer, text: String) -> CommandBuffer { 51 + printer.append_to_buffer(cb, bit_array.from_string(text)) 52 + |> printer.append_to_buffer(protocol.lf) 53 } 54 55 /// Enables or disables bold text. 56 pub fn bold(cb: CommandBuffer, b: Bool) -> CommandBuffer { 57 + printer.append_to_buffer(cb, protocol.bold(b)) 58 } 59 60 /// Enables or disables underlined text. 61 pub fn underline(cb: CommandBuffer, b: Bool) -> CommandBuffer { 62 + printer.append_to_buffer(cb, protocol.underline(b)) 63 } 64 65 /// Enables or disables double-strike text. 66 pub fn double_strike(cb: CommandBuffer, b: Bool) -> CommandBuffer { 67 + printer.append_to_buffer(cb, protocol.double_strike(b)) 68 } 69 70 /// Enables or disables reverse (white on black) text. 71 pub fn reverse(cb: CommandBuffer, b: Bool) -> CommandBuffer { 72 + printer.append_to_buffer(cb, protocol.reverse(b)) 73 } 74 75 /// Enables or disables upside-down text. 76 pub fn upside_down(cb: CommandBuffer, b: Bool) -> CommandBuffer { 77 + printer.append_to_buffer(cb, protocol.upside_down(b)) 78 } 79 80 /// Enables or disables character smoothing. 81 pub fn smooth(cb: CommandBuffer, b: Bool) -> CommandBuffer { 82 + printer.append_to_buffer(cb, protocol.smooth(b)) 83 } 84 85 /// Enables or disables 180-degree rotation. 86 pub fn flip(cb: CommandBuffer, b: Bool) -> CommandBuffer { 87 + printer.append_to_buffer(cb, protocol.flip(b)) 88 } 89 90 /// Sets the printer font. 91 pub fn font(cb: CommandBuffer, font: Font) -> CommandBuffer { 92 + printer.append_to_buffer(cb, protocol.font(font)) 93 } 94 95 /// Resets the font to the default (FontA). 96 pub fn reset_font(cb: CommandBuffer) -> CommandBuffer { 97 + printer.append_to_buffer(cb, protocol.font(protocol.FontA)) 98 } 99 100 /// Sets text alignment (Left, Center, or Right). 101 pub fn align(cb: CommandBuffer, justify: Justify) -> CommandBuffer { 102 ensure_new_line(cb) 103 + |> printer.append_to_buffer(protocol.justify(justify)) 104 } 105 106 /// Sets text size multiplier (1-8 for width and height). 107 pub fn text_size(cb: CommandBuffer, width: Int, height: Int) -> CommandBuffer { 108 + printer.append_to_buffer(cb, protocol.character_size(width, height)) 109 } 110 111 /// Resets text size to normal (1x1). 112 pub fn reset_text_size(cb: CommandBuffer) -> CommandBuffer { 113 + printer.append_to_buffer(cb, protocol.character_size(1, 1)) 114 } 115 116 /// Performs a full paper cut. 117 pub fn cut(cb: CommandBuffer) -> CommandBuffer { 118 + printer.append_to_buffer(cb, protocol.cut(protocol.Full)) 119 } 120 121 /// Performs a partial paper cut, leaving a small portion connected. 122 pub fn partial_cut(cb: CommandBuffer) -> CommandBuffer { 123 + printer.append_to_buffer(cb, protocol.cut(protocol.Partial)) 124 } 125 126 /// Appends a single newline. 127 pub fn new_line(cb: CommandBuffer) -> CommandBuffer { 128 + printer.append_to_buffer(cb, protocol.lf) 129 } 130 131 /// Feeds the specified number of lines. 132 pub fn line_feed(cb: CommandBuffer, lines: Int) -> CommandBuffer { 133 + printer.append_to_buffer(cb, protocol.line_feed(lines)) 134 } 135 136 /// Resets the printer to its initial state. 137 pub fn reset(cb: CommandBuffer) -> CommandBuffer { 138 + printer.append_to_buffer(cb, protocol.init) 139 } 140 141 /// Prints a monochrome image prepared by the `image` module. ··· 153 /// ``` 154 pub fn image(cb: CommandBuffer, image: image.PrintableImage) -> CommandBuffer { 155 ensure_new_line(cb) 156 + |> printer.append_to_buffer(protocol.image_to_graphics_buffer( 157 image.pixels(image), 158 image.width(image), 159 image.height(image), ··· 162 protocol.Scale1x, 163 protocol.Color1, 164 )) 165 + |> printer.append_to_buffer(protocol.print_graphics_buffer()) 166 } 167 168 /// Appends raw bytes to the buffer. 169 pub fn raw(cb: CommandBuffer, data: BitArray) -> CommandBuffer { 170 + printer.append_to_buffer(cb, data) 171 } 172 173 fn ensure_new_line(cb: CommandBuffer) -> CommandBuffer { ··· 178 } 179 180 fn is_new_line(cb: CommandBuffer) -> Bool { 181 + use <- bool.guard(when: printer.buffer_to_bits(cb) == <<>>, return: True) 182 case 183 + bit_array.slice( 184 + from: printer.buffer_to_bits(cb), 185 + at: bit_array.byte_size(printer.buffer_to_bits(cb)), 186 + take: -3, 187 + ) 188 { 189 Ok(<<27, "d", _>>) -> True 190 Ok(<<_, _, 10>>) -> True
+7 -5
src/escpos/document.gleam
··· 18 //// ``` 19 20 import escpos/image 21 - import escpos/printer.{type CommandBuffer, CommandBuffer} 22 import escpos/protocol 23 import gleam/bit_array 24 import gleam/list ··· 121 122 /// Compiles a list of commands into a binary command buffer ready for printing. 123 pub fn render(document: List(Command)) -> CommandBuffer { 124 - upside_down_pass(document) 125 - |> build_ast 126 - |> compile_ast 127 - |> CommandBuffer 128 } 129 130 /// Applies style modifiers to a group of commands. Styles are automatically
··· 18 //// ``` 19 20 import escpos/image 21 + import escpos/printer.{type CommandBuffer} 22 import escpos/protocol 23 import gleam/bit_array 24 import gleam/list ··· 121 122 /// Compiles a list of commands into a binary command buffer ready for printing. 123 pub fn render(document: List(Command)) -> CommandBuffer { 124 + printer.new_buffer() 125 + |> printer.append_to_buffer( 126 + upside_down_pass(document) 127 + |> build_ast 128 + |> compile_ast, 129 + ) 130 } 131 132 /// Applies style modifiers to a group of commands. Styles are automatically
+19 -2
src/escpos/printer.gleam
··· 21 //// ``` 22 23 import escpos/protocol 24 import gleam/result 25 import mug 26 import simplifile 27 28 - @internal 29 - pub type CommandBuffer { 30 CommandBuffer(data: BitArray) 31 } 32 ··· 103 UsbPrinter(_) -> Ok(Nil) 104 } 105 }
··· 21 //// ``` 22 23 import escpos/protocol 24 + import gleam/bit_array 25 import gleam/result 26 import mug 27 import simplifile 28 29 + // Holds the constructed BitArray to be sent to the printer 30 + pub opaque type CommandBuffer { 31 CommandBuffer(data: BitArray) 32 } 33 ··· 104 UsbPrinter(_) -> Ok(Nil) 105 } 106 } 107 + 108 + // Creates an empty CommandBuffer 109 + pub fn new_buffer() -> CommandBuffer { 110 + CommandBuffer(<<>>) 111 + } 112 + 113 + // Appends BitArray to CommandBuffer 114 + pub fn append_to_buffer(buffer: CommandBuffer, data: BitArray) -> CommandBuffer { 115 + bit_array.append(buffer.data, data) 116 + |> CommandBuffer 117 + } 118 + 119 + /// Returns the raw BitArray from CommandBuffer 120 + pub fn buffer_to_bits(buffer: CommandBuffer) -> BitArray { 121 + buffer.data 122 + }
+144 -102
test/escpos_test.gleam
··· 1 import escpos 2 import escpos/document 3 - import escpos/printer.{CommandBuffer} 4 import escpos/protocol 5 import gleeunit 6 ··· 18 // --- escpos (imperative) tests --- 19 20 pub fn new_test() { 21 - let CommandBuffer(data) = escpos.new() 22 assert data == <<>> 23 } 24 25 pub fn write_test() { 26 - let CommandBuffer(data) = escpos.new() |> escpos.write("Hi") 27 assert data == <<"Hi">> 28 } 29 30 pub fn writeln_test() { 31 - let CommandBuffer(data) = escpos.new() |> escpos.writeln("Hi") 32 assert data == <<"Hi", 10>> 33 } 34 35 pub fn bold_test() { 36 - let CommandBuffer(data) = 37 - escpos.new() 38 - |> escpos.bold(True) 39 - |> escpos.write("Hi") 40 - |> escpos.bold(False) 41 assert data == <<27, "E", 1, "Hi", 27, "E", 0>> 42 } 43 44 pub fn underline_test() { 45 - let CommandBuffer(data) = 46 - escpos.new() 47 - |> escpos.underline(True) 48 - |> escpos.write("Hi") 49 - |> escpos.underline(False) 50 assert data == <<27, "-", 1, "Hi", 27, "-", 0>> 51 } 52 53 pub fn double_strike_test() { 54 - let CommandBuffer(data) = 55 - escpos.new() 56 - |> escpos.double_strike(True) 57 - |> escpos.write("Hi") 58 - |> escpos.double_strike(False) 59 assert data == <<27, "G", 1, "Hi", 27, "G", 0>> 60 } 61 62 pub fn reverse_test() { 63 - let CommandBuffer(data) = 64 - escpos.new() 65 - |> escpos.reverse(True) 66 - |> escpos.write("Hi") 67 - |> escpos.reverse(False) 68 assert data == <<29, "B", 1, "Hi", 29, "B", 0>> 69 } 70 71 pub fn upside_down_imperative_test() { 72 - let CommandBuffer(data) = 73 - escpos.new() 74 - |> escpos.upside_down(True) 75 - |> escpos.write("Hi") 76 - |> escpos.upside_down(False) 77 assert data == <<27, "{", 1, "Hi", 27, "{", 0>> 78 } 79 80 pub fn smooth_test() { 81 - let CommandBuffer(data) = 82 - escpos.new() 83 - |> escpos.smooth(True) 84 - |> escpos.write("Hi") 85 - |> escpos.smooth(False) 86 assert data == <<29, "b", 1, "Hi", 29, "b", 0>> 87 } 88 89 pub fn flip_test() { 90 - let CommandBuffer(data) = 91 - escpos.new() 92 - |> escpos.flip(True) 93 - |> escpos.write("Hi") 94 - |> escpos.flip(False) 95 assert data == <<27, "V", 1, "Hi", 27, "V", 0>> 96 } 97 98 pub fn font_test() { 99 - let CommandBuffer(data) = 100 - escpos.new() 101 - |> escpos.font(protocol.FontB) 102 - |> escpos.write("Hi") 103 - |> escpos.reset_font 104 assert data == <<27, "M", 1, "Hi", 27, "M", 0>> 105 } 106 107 pub fn align_from_empty_test() { 108 // Empty buffer counts as new line, so no LF inserted 109 - let CommandBuffer(data) = 110 - escpos.new() 111 - |> escpos.align(protocol.Center) 112 assert data == <<27, "a", 1>> 113 } 114 115 pub fn align_after_text_test() { 116 // Text doesn't end with newline, so LF is inserted before justify 117 - let CommandBuffer(data) = 118 - escpos.new() 119 - |> escpos.write("Hi") 120 - |> escpos.align(protocol.Right) 121 assert data == <<"Hi", 10, 27, "a", 2>> 122 } 123 124 pub fn align_after_newline_test() { 125 // Already on a new line, so no extra LF 126 - let CommandBuffer(data) = 127 - escpos.new() 128 - |> escpos.writeln("Hi") 129 - |> escpos.align(protocol.Left) 130 assert data == <<"Hi", 10, 27, "a", 0>> 131 } 132 133 pub fn text_size_test() { 134 - let CommandBuffer(data) = 135 - escpos.new() 136 - |> escpos.text_size(3, 2) 137 assert data == <<29, "!", 0:1, 2:3, 0:1, 1:3>> 138 } 139 140 pub fn reset_text_size_test() { 141 - let CommandBuffer(data) = 142 - escpos.new() 143 - |> escpos.text_size(3, 3) 144 - |> escpos.reset_text_size 145 assert data == <<29, "!", 0:1, 2:3, 0:1, 2:3, 29, "!", 0:1, 0:3, 0:1, 0:3>> 146 } 147 148 pub fn cut_test() { 149 - let CommandBuffer(data) = escpos.new() |> escpos.cut 150 assert data == <<29, "V", 0>> 151 } 152 153 pub fn partial_cut_test() { 154 - let CommandBuffer(data) = escpos.new() |> escpos.partial_cut 155 assert data == <<29, "V", 1>> 156 } 157 158 pub fn new_line_test() { 159 - let CommandBuffer(data) = escpos.new() |> escpos.new_line 160 assert data == <<10>> 161 } 162 163 pub fn line_feed_test() { 164 - let CommandBuffer(data) = escpos.new() |> escpos.line_feed(5) 165 assert data == <<27, "d", 5>> 166 } 167 168 pub fn line_feed_clamps_low_test() { 169 - let CommandBuffer(data) = escpos.new() |> escpos.line_feed(0) 170 assert data == <<27, "d", 1>> 171 } 172 173 pub fn line_feed_clamps_high_test() { 174 - let CommandBuffer(data) = escpos.new() |> escpos.line_feed(999) 175 assert data == <<27, "d", 255>> 176 } 177 178 pub fn reset_test() { 179 - let CommandBuffer(data) = escpos.new() |> escpos.reset 180 assert data == <<27, "@">> 181 } 182 183 pub fn raw_test() { 184 - let CommandBuffer(data) = escpos.new() |> escpos.raw(<<1, 2, 3>>) 185 assert data == <<1, 2, 3>> 186 } 187 ··· 190 const init = <<27, "@">> 191 192 pub fn render_empty_test() { 193 - let CommandBuffer(data) = document.render([]) 194 assert data == init 195 } 196 197 pub fn render_line_test() { 198 - let CommandBuffer(data) = document.render([document.line([document.text("Hi")])]) 199 assert data == <<init:bits, "Hi", 27, "d", 1>> 200 } 201 202 pub fn render_text_test() { 203 - let CommandBuffer(data) = document.render([document.text("Hi")]) 204 assert data == <<init:bits, "Hi">> 205 } 206 207 pub fn render_bold_styled_test() { 208 - let CommandBuffer(data) = 209 - document.render([ 210 - document.styled([document.bold()], [document.line([document.text("Hi")])]), 211 - ]) 212 // init, bold on, text, LF, bold off 213 assert data == <<init:bits, 27, "E", 1, "Hi", 27, "d", 1, 27, "E", 0>> 214 } 215 216 pub fn render_underline_styled_test() { 217 - let CommandBuffer(data) = 218 - document.render([ 219 - document.styled([document.underline()], [document.text("Hi")]), 220 - ]) 221 assert data == <<init:bits, 27, "-", 1, "Hi", 27, "-", 0>> 222 } 223 224 pub fn render_justify_center_test() { 225 - let CommandBuffer(data) = 226 - document.render([ 227 - document.styled([document.justify(protocol.Center)], [ 228 - document.line([document.text("Hi")]), 229 ]), 230 - ]) 231 // init, justify center, text, LF, justify left 232 assert data == <<init:bits, 27, "a", 1, "Hi", 27, "d", 1, 27, "a", 0>> 233 } 234 235 pub fn render_cut_test() { 236 - let CommandBuffer(data) = document.render([document.cut()]) 237 // init, line_feed(3), full cut 238 assert data == <<init:bits, 27, "d", 3, 29, "V", 0>> 239 } 240 241 pub fn render_partial_cut_test() { 242 - let CommandBuffer(data) = document.render([document.partial_cut()]) 243 assert data == <<init:bits, 27, "d", 3, 29, "V", 1>> 244 } 245 246 pub fn render_line_feed_test() { 247 - let CommandBuffer(data) = document.render([document.line_feed(5)]) 248 assert data == <<init:bits, 27, "d", 5>> 249 } 250 251 pub fn render_raw_test() { 252 - let CommandBuffer(data) = document.render([document.raw(<<1, 2, 3>>)]) 253 assert data == <<init:bits, 1, 2, 3>> 254 } 255 256 pub fn render_nested_styles_revert_test() { 257 - let CommandBuffer(data) = 258 - document.render([ 259 - document.styled([document.bold()], [ 260 - document.text("a"), 261 - document.styled([document.underline()], [document.text("b")]), 262 - document.text("c"), 263 ]), 264 - ]) 265 // init, bold on, "a", underline on, "b", underline off, "c", bold off 266 assert data 267 == << ··· 270 } 271 272 pub fn render_styles_dont_leak_test() { 273 - let CommandBuffer(data) = 274 - document.render([ 275 - document.styled([document.bold()], [document.text("a")]), 276 - document.text("b"), 277 - ]) 278 // bold should be off for "b" 279 assert data == <<init:bits, 27, "E", 1, "a", 27, "E", 0, "b">> 280 }
··· 1 import escpos 2 import escpos/document 3 + import escpos/printer 4 import escpos/protocol 5 import gleeunit 6 ··· 18 // --- escpos (imperative) tests --- 19 20 pub fn new_test() { 21 + let data = printer.buffer_to_bits(escpos.new()) 22 assert data == <<>> 23 } 24 25 pub fn write_test() { 26 + let data = printer.buffer_to_bits(escpos.new() |> escpos.write("Hi")) 27 assert data == <<"Hi">> 28 } 29 30 pub fn writeln_test() { 31 + let data = printer.buffer_to_bits(escpos.new() |> escpos.writeln("Hi")) 32 assert data == <<"Hi", 10>> 33 } 34 35 pub fn bold_test() { 36 + let data = 37 + printer.buffer_to_bits( 38 + escpos.new() 39 + |> escpos.bold(True) 40 + |> escpos.write("Hi") 41 + |> escpos.bold(False), 42 + ) 43 assert data == <<27, "E", 1, "Hi", 27, "E", 0>> 44 } 45 46 pub fn underline_test() { 47 + let data = 48 + printer.buffer_to_bits( 49 + escpos.new() 50 + |> escpos.underline(True) 51 + |> escpos.write("Hi") 52 + |> escpos.underline(False), 53 + ) 54 assert data == <<27, "-", 1, "Hi", 27, "-", 0>> 55 } 56 57 pub fn double_strike_test() { 58 + let data = 59 + printer.buffer_to_bits( 60 + escpos.new() 61 + |> escpos.double_strike(True) 62 + |> escpos.write("Hi") 63 + |> escpos.double_strike(False), 64 + ) 65 assert data == <<27, "G", 1, "Hi", 27, "G", 0>> 66 } 67 68 pub fn reverse_test() { 69 + let data = 70 + printer.buffer_to_bits( 71 + escpos.new() 72 + |> escpos.reverse(True) 73 + |> escpos.write("Hi") 74 + |> escpos.reverse(False), 75 + ) 76 assert data == <<29, "B", 1, "Hi", 29, "B", 0>> 77 } 78 79 pub fn upside_down_imperative_test() { 80 + let data = 81 + printer.buffer_to_bits( 82 + escpos.new() 83 + |> escpos.upside_down(True) 84 + |> escpos.write("Hi") 85 + |> escpos.upside_down(False), 86 + ) 87 assert data == <<27, "{", 1, "Hi", 27, "{", 0>> 88 } 89 90 pub fn smooth_test() { 91 + let data = 92 + printer.buffer_to_bits( 93 + escpos.new() 94 + |> escpos.smooth(True) 95 + |> escpos.write("Hi") 96 + |> escpos.smooth(False), 97 + ) 98 assert data == <<29, "b", 1, "Hi", 29, "b", 0>> 99 } 100 101 pub fn flip_test() { 102 + let data = 103 + printer.buffer_to_bits( 104 + escpos.new() 105 + |> escpos.flip(True) 106 + |> escpos.write("Hi") 107 + |> escpos.flip(False), 108 + ) 109 assert data == <<27, "V", 1, "Hi", 27, "V", 0>> 110 } 111 112 pub fn font_test() { 113 + let data = 114 + printer.buffer_to_bits( 115 + escpos.new() 116 + |> escpos.font(protocol.FontB) 117 + |> escpos.write("Hi") 118 + |> escpos.reset_font, 119 + ) 120 assert data == <<27, "M", 1, "Hi", 27, "M", 0>> 121 } 122 123 pub fn align_from_empty_test() { 124 // Empty buffer counts as new line, so no LF inserted 125 + let data = 126 + printer.buffer_to_bits( 127 + escpos.new() 128 + |> escpos.align(protocol.Center), 129 + ) 130 assert data == <<27, "a", 1>> 131 } 132 133 pub fn align_after_text_test() { 134 // Text doesn't end with newline, so LF is inserted before justify 135 + let data = 136 + printer.buffer_to_bits( 137 + escpos.new() 138 + |> escpos.write("Hi") 139 + |> escpos.align(protocol.Right), 140 + ) 141 assert data == <<"Hi", 10, 27, "a", 2>> 142 } 143 144 pub fn align_after_newline_test() { 145 // Already on a new line, so no extra LF 146 + let data = 147 + printer.buffer_to_bits( 148 + escpos.new() 149 + |> escpos.writeln("Hi") 150 + |> escpos.align(protocol.Left), 151 + ) 152 assert data == <<"Hi", 10, 27, "a", 0>> 153 } 154 155 pub fn text_size_test() { 156 + let data = 157 + printer.buffer_to_bits( 158 + escpos.new() 159 + |> escpos.text_size(3, 2), 160 + ) 161 assert data == <<29, "!", 0:1, 2:3, 0:1, 1:3>> 162 } 163 164 pub fn reset_text_size_test() { 165 + let data = 166 + printer.buffer_to_bits( 167 + escpos.new() 168 + |> escpos.text_size(3, 3) 169 + |> escpos.reset_text_size, 170 + ) 171 assert data == <<29, "!", 0:1, 2:3, 0:1, 2:3, 29, "!", 0:1, 0:3, 0:1, 0:3>> 172 } 173 174 pub fn cut_test() { 175 + let data = printer.buffer_to_bits(escpos.new() |> escpos.cut) 176 assert data == <<29, "V", 0>> 177 } 178 179 pub fn partial_cut_test() { 180 + let data = printer.buffer_to_bits(escpos.new() |> escpos.partial_cut) 181 assert data == <<29, "V", 1>> 182 } 183 184 pub fn new_line_test() { 185 + let data = printer.buffer_to_bits(escpos.new() |> escpos.new_line) 186 assert data == <<10>> 187 } 188 189 pub fn line_feed_test() { 190 + let data = printer.buffer_to_bits(escpos.new() |> escpos.line_feed(5)) 191 assert data == <<27, "d", 5>> 192 } 193 194 pub fn line_feed_clamps_low_test() { 195 + let data = printer.buffer_to_bits(escpos.new() |> escpos.line_feed(0)) 196 assert data == <<27, "d", 1>> 197 } 198 199 pub fn line_feed_clamps_high_test() { 200 + let data = printer.buffer_to_bits(escpos.new() |> escpos.line_feed(999)) 201 assert data == <<27, "d", 255>> 202 } 203 204 pub fn reset_test() { 205 + let data = printer.buffer_to_bits(escpos.new() |> escpos.reset) 206 assert data == <<27, "@">> 207 } 208 209 pub fn raw_test() { 210 + let data = printer.buffer_to_bits(escpos.new() |> escpos.raw(<<1, 2, 3>>)) 211 assert data == <<1, 2, 3>> 212 } 213 ··· 216 const init = <<27, "@">> 217 218 pub fn render_empty_test() { 219 + let data = printer.buffer_to_bits(document.render([])) 220 assert data == init 221 } 222 223 pub fn render_line_test() { 224 + let data = 225 + printer.buffer_to_bits( 226 + document.render([document.line([document.text("Hi")])]), 227 + ) 228 assert data == <<init:bits, "Hi", 27, "d", 1>> 229 } 230 231 pub fn render_text_test() { 232 + let data = printer.buffer_to_bits(document.render([document.text("Hi")])) 233 assert data == <<init:bits, "Hi">> 234 } 235 236 pub fn render_bold_styled_test() { 237 + let data = 238 + printer.buffer_to_bits( 239 + document.render([ 240 + document.styled([document.bold()], [ 241 + document.line([document.text("Hi")]), 242 + ]), 243 + ]), 244 + ) 245 // init, bold on, text, LF, bold off 246 assert data == <<init:bits, 27, "E", 1, "Hi", 27, "d", 1, 27, "E", 0>> 247 } 248 249 pub fn render_underline_styled_test() { 250 + let data = 251 + printer.buffer_to_bits( 252 + document.render([ 253 + document.styled([document.underline()], [document.text("Hi")]), 254 + ]), 255 + ) 256 assert data == <<init:bits, 27, "-", 1, "Hi", 27, "-", 0>> 257 } 258 259 pub fn render_justify_center_test() { 260 + let data = 261 + printer.buffer_to_bits( 262 + document.render([ 263 + document.styled([document.justify(protocol.Center)], [ 264 + document.line([document.text("Hi")]), 265 + ]), 266 ]), 267 + ) 268 // init, justify center, text, LF, justify left 269 assert data == <<init:bits, 27, "a", 1, "Hi", 27, "d", 1, 27, "a", 0>> 270 } 271 272 pub fn render_cut_test() { 273 + let data = printer.buffer_to_bits(document.render([document.cut()])) 274 // init, line_feed(3), full cut 275 assert data == <<init:bits, 27, "d", 3, 29, "V", 0>> 276 } 277 278 pub fn render_partial_cut_test() { 279 + let data = printer.buffer_to_bits(document.render([document.partial_cut()])) 280 assert data == <<init:bits, 27, "d", 3, 29, "V", 1>> 281 } 282 283 pub fn render_line_feed_test() { 284 + let data = printer.buffer_to_bits(document.render([document.line_feed(5)])) 285 assert data == <<init:bits, 27, "d", 5>> 286 } 287 288 pub fn render_raw_test() { 289 + let data = 290 + printer.buffer_to_bits(document.render([document.raw(<<1, 2, 3>>)])) 291 assert data == <<init:bits, 1, 2, 3>> 292 } 293 294 pub fn render_nested_styles_revert_test() { 295 + let data = 296 + printer.buffer_to_bits( 297 + document.render([ 298 + document.styled([document.bold()], [ 299 + document.text("a"), 300 + document.styled([document.underline()], [document.text("b")]), 301 + document.text("c"), 302 + ]), 303 ]), 304 + ) 305 // init, bold on, "a", underline on, "b", underline off, "c", bold off 306 assert data 307 == << ··· 310 } 311 312 pub fn render_styles_dont_leak_test() { 313 + let data = 314 + printer.buffer_to_bits( 315 + document.render([ 316 + document.styled([document.bold()], [document.text("a")]), 317 + document.text("b"), 318 + ]), 319 + ) 320 // bold should be off for "b" 321 assert data == <<init:bits, 27, "E", 1, "a", 27, "E", 0, "b">> 322 }