86 lines
2.0 KiB
Gleam
86 lines
2.0 KiB
Gleam
import gleam/dict.{type Dict}
|
|
import gleam/list
|
|
import gleam/string
|
|
|
|
pub type Buffer =
|
|
Dict(#(Int, Int), String)
|
|
|
|
pub fn flush_buffer(buffer: Buffer, columns: Int, rows: Int) -> String {
|
|
list.range(1, rows)
|
|
|> list.map(fn(y) {
|
|
list.range(1, columns)
|
|
|> list.map(fn(x) {
|
|
case dict.get(buffer, #(x, y)) {
|
|
Ok(char) -> char
|
|
Error(_) -> " "
|
|
}
|
|
})
|
|
|> string.join("")
|
|
})
|
|
|> string.join("\r\n")
|
|
}
|
|
|
|
pub fn text(buffer: Buffer, text: String, x: Int, y: Int) -> Buffer {
|
|
text
|
|
|> string.to_graphemes
|
|
|> list.index_fold(buffer, fn(acc, char, i) {
|
|
dict.insert(acc, #(x + i, y), char)
|
|
})
|
|
}
|
|
|
|
pub fn box(buffer: Buffer, x: Int, y: Int, width: Int, height: Int) -> Buffer {
|
|
// TODO move box style to `layout.Style`
|
|
let box_chars = #("┌", "┐", "└", "┘", "─", "│")
|
|
let #(tl, tr, bl, br, hor, ver) = box_chars
|
|
|
|
case width < 2 || height < 2 {
|
|
True -> buffer
|
|
False -> {
|
|
buffer
|
|
|> dict.insert(#(x, y), tl)
|
|
|> dict.insert(#(x + width - 1, y), tr)
|
|
|> dict.insert(#(x, y + height - 1), bl)
|
|
|> dict.insert(#(x + width - 1, y + height - 1), br)
|
|
|> horizontal_line(x + 1, y, width - 2, hor)
|
|
|> horizontal_line(x + 1, y + height - 1, width - 2, hor)
|
|
|> vertical_line(x, y + 1, height - 2, ver)
|
|
|> vertical_line(x + width - 1, y + 1, height - 2, ver)
|
|
}
|
|
}
|
|
}
|
|
|
|
pub fn box_with_heading(
|
|
buffer: Buffer,
|
|
x: Int,
|
|
y: Int,
|
|
width: Int,
|
|
height: Int,
|
|
heading: String,
|
|
) -> Buffer {
|
|
let heading_margin = 1
|
|
box(buffer, x, y, width, height)
|
|
|> text(heading, x + heading_margin, y)
|
|
}
|
|
|
|
fn horizontal_line(
|
|
buffer: Buffer,
|
|
x: Int,
|
|
y: Int,
|
|
len: Int,
|
|
char: String,
|
|
) -> Buffer {
|
|
list.range(0, len - 1)
|
|
|> list.fold(buffer, fn(acc, i) { dict.insert(acc, #(x + i, y), char) })
|
|
}
|
|
|
|
fn vertical_line(
|
|
buffer: Buffer,
|
|
x: Int,
|
|
y: Int,
|
|
len: Int,
|
|
char: String,
|
|
) -> Buffer {
|
|
list.range(0, len - 1)
|
|
|> list.fold(buffer, fn(acc, i) { dict.insert(acc, #(x, y + i), char) })
|
|
}
|