-
Notifications
You must be signed in to change notification settings - Fork 4
/
todo_lists.gleam
102 lines (93 loc) · 2.14 KB
/
todo_lists.gleam
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
import glam/doc.{type Document}
import gleam/io
import gleam/list
pub type TodoList =
List(Task)
pub type Task {
Task(status: Status, description: String, subtasks: TodoList)
}
pub type Status {
Todo
Done
InProgress
}
/// Pretty prints a `TodoList`:
/// - each task is preceded by a bullet that indicates its status
/// - each list of subtasks is indented by 2 spaces more than its father
/// - each task should _always_ be on its own line, no matter how wide the
/// maximum line width
///
/// ## Examples
///
/// ```gleam
/// [
/// Task(Todo, "foo", []),
/// Task(InProgress, "bar", []),
/// Task(Done, "baz", []),
/// ]
/// |> tasks_to_doc
/// |> doc.to_string(10_000)
/// // ->
/// // - [ ] foo
/// // - […] bar
/// // - [X] baz
/// ```
///
/// ```gleam
/// [
/// Task(InProgress, "foo", [
/// Task(Done, "bar", [
/// Task(Todo, "baz", [])
/// ])
/// ]),
/// ]
/// |> tasks_to_doc
/// |> doc.to_string(10_000)
/// // ->
/// // - […] foo
/// // - [X] bar
/// // - [ ] baz
/// ```
///
pub fn tasks_to_doc(tasks: TodoList) -> Document {
list.map(tasks, task_to_doc)
|> doc.join(with: doc.soft_break)
|> doc.force_break
}
fn task_to_doc(task: Task) -> Document {
let task_line = status_to_bullet(task.status) <> " " <> task.description
let task_doc = doc.from_string(task_line)
case list.is_empty(task.subtasks) {
True -> task_doc
False ->
[task_doc, doc.soft_break, tasks_to_doc(task.subtasks)]
|> doc.concat
|> doc.nest(by: 2)
}
}
fn status_to_bullet(status: Status) -> String {
case status {
Todo -> "- [ ]"
Done -> "- [X]"
InProgress -> "- […]"
}
}
pub fn example_todo_list() -> TodoList {
[
Task(InProgress, "publish Glam v1.1.0", [
Task(InProgress, "write a tutorial on todo lists", []),
Task(InProgress, "add `doc.flex_break`", [
Task(Done, "add the appropriate type variant", []),
Task(Done, "implement the missing cases", []),
Task(Todo, "add some tests", []),
]),
]),
Task(Todo, "get some sleep", []),
]
}
pub fn main() {
example_todo_list()
|> tasks_to_doc
|> doc.to_string(10_000)
|> io.println
}