import gleam/int import gleam/io import gleam/list import gleam/result import string_width.{Left, Size, Top} // we will render a simple help menu for a command-line app here. // the help menu will automatically adjust based on the width of the terminal. type Command { Command(name: String, description: String) } const commands = [ Command( name: "build", description: "Build and bundle your application.\nThe generated bundle calls your apps' main function. If your main function accepts a single argument of type List(String), all additional command-line arguments will be passed there.", ), Command( name: "dev", description: "Start a file watcher that automatically recompiles your app on all file changes, and then re-runs your tests. Compilation errors or test failures will be displayed in an overlay, and if everything succeeds, your window will automatically hot-reload.", ), Command(name: "help", description: "Show this help text."), ] pub fn main() { // get the size of the terminal, or fallback to a default size. let term_size = string_width.get_terminal_size() |> result.unwrap(Size(rows: 24, columns: 80)) // how big does the left-hand side need to be? let left_width = list.fold(commands, 0, fn(max, cmd) { int.max(max, string_width.line(cmd.name)) }) // add some gap between both columns and compute the size of the right side. let gap = 4 // set a maximum width of 60 for the right column to improve readability. let right_width = int.min(60, term_size.columns - left_width - gap) commands |> list.map(fn(cmd) { [ cmd.name |> pink // make sure all left-hand sides are padded to left_width |> string_width.align(left_width, Left, with: " "), // word wrap the right-hand side such that it fits into our column. // if the description would overflow 10 lines, truncate it. cmd.description |> string_width.limit( to: Size(rows: 10, columns: right_width), ellipsis: "…", ) // make sure that if we used styles those would wrap properly |> string_width.inline_styles, ] // build the column layout; // the name should be aligned with the top of the description |> string_width.stack_horizontal(place: Top, gap:, with: " ") }) // combine the help text of all commands, adding a line of space in between. |> string_width.stack_vertical(align: Left, gap: 1, with: " ") |> io.println } // string_width is agnostic to the way you add styles to your strings. // maybe check out gleam_community_ansi! fn pink(str: String) { "\u{1b}[38;5;207m" <> str <> "\u{1b}[m" }