diff --git a/birdie_snapshots/test_multi_insert_spinner_inline_and_multi_insert_progress_inline.accepted b/birdie_snapshots/test_multi_insert_spinner_inline_and_multi_insert_progress_inline.accepted new file mode 100644 index 0000000..4646e9e --- /dev/null +++ b/birdie_snapshots/test_multi_insert_spinner_inline_and_multi_insert_progress_inline.accepted @@ -0,0 +1,43 @@ +--- +version: 1.2.4 +title: Test multi.insert_spinner_inline and multi.insert_progress_inline +file: ./test/glitzer_test.gleam +test_name: multi_insert_spinner_progress_test +--- +SameLine( + 100, + None, + LineState([ + #( + "s1", + Spinner(SpinnerStyle( + 100, + "", + State( + Frames(#("|", "/", "-", "\")), + //fn(a) { ... }, + "", + "", + 0, + False, + None, + ), + )), + ), + #( + "p1", + Progress(ProgressStyle( + "[", + "]", + Char(" "), + Char("#"), + None, + None, + None, + False, + 100, + State(0, False), + )), + ), + ]), +) \ No newline at end of file diff --git a/birdie_snapshots/test_multi_new_same_line.accepted b/birdie_snapshots/test_multi_new_same_line.accepted new file mode 100644 index 0000000..08cea75 --- /dev/null +++ b/birdie_snapshots/test_multi_new_same_line.accepted @@ -0,0 +1,7 @@ +--- +version: 1.2.4 +title: Test multi.new_same_line +file: ./test/glitzer_test.gleam +test_name: multi_new_same_line_test +--- +SameLine(100, None, LineState([])) \ No newline at end of file diff --git a/birdie_snapshots/test_progress_default_bar.accepted b/birdie_snapshots/test_progress_default_bar.accepted index 98ad664..649070b 100644 --- a/birdie_snapshots/test_progress_default_bar.accepted +++ b/birdie_snapshots/test_progress_default_bar.accepted @@ -1,5 +1,5 @@ --- -version: 1.1.6 +version: 1.2.4 title: Test progress.default_bar file: ./test/glitzer_test.gleam test_name: progress_default_bar_test @@ -12,6 +12,7 @@ ProgressStyle( None, None, None, + True, 100, State(0, False), ) \ No newline at end of file diff --git a/birdie_snapshots/test_progress_fancy_slim_arrow_bar.accepted b/birdie_snapshots/test_progress_fancy_slim_arrow_bar.accepted index 880a2b0..c9d5d14 100644 --- a/birdie_snapshots/test_progress_fancy_slim_arrow_bar.accepted +++ b/birdie_snapshots/test_progress_fancy_slim_arrow_bar.accepted @@ -1,5 +1,5 @@ --- -version: 1.1.6 +version: 1.2.4 title: Test progress.fancy_slim_arrow_bar file: ./test/glitzer_test.gleam test_name: progress_fancy_slim_arrow_bar_test @@ -12,6 +12,7 @@ ProgressStyle( Some(Char("—")), Some(Char("→")), Some(Char("→")), + True, 100, State(0, False), ) \ No newline at end of file diff --git a/birdie_snapshots/test_progress_fancy_slim_bar.accepted b/birdie_snapshots/test_progress_fancy_slim_bar.accepted index 575e788..6bb7b57 100644 --- a/birdie_snapshots/test_progress_fancy_slim_bar.accepted +++ b/birdie_snapshots/test_progress_fancy_slim_bar.accepted @@ -1,5 +1,5 @@ --- -version: 1.1.6 +version: 1.2.4 title: Test progress.fancy_slim_bar file: ./test/glitzer_test.gleam test_name: progress_fancy_slim_bar_test @@ -12,6 +12,7 @@ ProgressStyle( Some(Char("—")), None, None, + True, 100, State(0, False), ) \ No newline at end of file diff --git a/birdie_snapshots/test_progress_fancy_thick_bar.accepted b/birdie_snapshots/test_progress_fancy_thick_bar.accepted index 0f94d6e..3d4dfe3 100644 --- a/birdie_snapshots/test_progress_fancy_thick_bar.accepted +++ b/birdie_snapshots/test_progress_fancy_thick_bar.accepted @@ -1,5 +1,5 @@ --- -version: 1.1.6 +version: 1.2.4 title: Test progress.fancy_thick_bar file: ./test/glitzer_test.gleam test_name: progress_fancy_thick_bar_test @@ -12,6 +12,7 @@ ProgressStyle( Some(Char("█")), None, None, + True, 100, State(0, False), ) \ No newline at end of file diff --git a/birdie_snapshots/test_progress_new_bar.accepted b/birdie_snapshots/test_progress_new_bar.accepted index 0a6c72f..5a5c3cc 100644 --- a/birdie_snapshots/test_progress_new_bar.accepted +++ b/birdie_snapshots/test_progress_new_bar.accepted @@ -1,5 +1,5 @@ --- -version: 1.1.6 +version: 1.2.4 title: Test progress.new_bar file: ./test/glitzer_test.gleam test_name: progress_new_bar_test @@ -12,6 +12,7 @@ ProgressStyle( None, None, None, + True, 0, State(0, False), ) \ No newline at end of file diff --git a/birdie_snapshots/test_progress_slim_bar.accepted b/birdie_snapshots/test_progress_slim_bar.accepted index 88447be..dd66fbc 100644 --- a/birdie_snapshots/test_progress_slim_bar.accepted +++ b/birdie_snapshots/test_progress_slim_bar.accepted @@ -1,5 +1,5 @@ --- -version: 1.1.6 +version: 1.2.4 title: Test progress.slim_bar file: ./test/glitzer_test.gleam test_name: progress_slim_bar_test @@ -12,6 +12,7 @@ ProgressStyle( None, None, None, + True, 100, State(0, False), ) \ No newline at end of file diff --git a/birdie_snapshots/test_progress_tick.accepted b/birdie_snapshots/test_progress_tick.accepted index 3cb30d0..42ae07a 100644 --- a/birdie_snapshots/test_progress_tick.accepted +++ b/birdie_snapshots/test_progress_tick.accepted @@ -1,5 +1,5 @@ --- -version: 1.1.6 +version: 1.2.4 title: Test progress.tick file: ./test/glitzer_test.gleam test_name: progress_tick_test @@ -12,6 +12,7 @@ ProgressStyle( None, None, None, + True, 0, State(1, False), ) \ No newline at end of file diff --git a/birdie_snapshots/test_progress_tick_bar.accepted b/birdie_snapshots/test_progress_tick_bar.accepted index 4e24904..86297b6 100644 --- a/birdie_snapshots/test_progress_tick_bar.accepted +++ b/birdie_snapshots/test_progress_tick_bar.accepted @@ -1,5 +1,5 @@ --- -version: 1.1.6 +version: 1.2.4 title: Test progress.tick_bar file: ./test/glitzer_test.gleam test_name: progress_thick_bar_test @@ -12,6 +12,7 @@ ProgressStyle( None, None, None, + True, 100, State(0, False), ) \ No newline at end of file diff --git a/birdie_snapshots/test_progress_tick_by.accepted b/birdie_snapshots/test_progress_tick_by.accepted index 4ce230b..8b7804e 100644 --- a/birdie_snapshots/test_progress_tick_by.accepted +++ b/birdie_snapshots/test_progress_tick_by.accepted @@ -1,5 +1,5 @@ --- -version: 1.1.6 +version: 1.2.4 title: Test progress.tick_by file: ./test/glitzer_test.gleam test_name: progress_tick_by_test @@ -12,6 +12,7 @@ ProgressStyle( None, None, None, + True, 0, State(10, True), ) \ No newline at end of file diff --git a/birdie_snapshots/test_progress_with_empty.accepted b/birdie_snapshots/test_progress_with_empty.accepted index 0fd9598..69f7dd2 100644 --- a/birdie_snapshots/test_progress_with_empty.accepted +++ b/birdie_snapshots/test_progress_with_empty.accepted @@ -1,5 +1,5 @@ --- -version: 1.1.6 +version: 1.2.4 title: Test progress.with_empty file: ./test/glitzer_test.gleam test_name: progress_with_empty_test @@ -12,6 +12,7 @@ ProgressStyle( None, None, None, + True, 0, State(0, False), ) \ No newline at end of file diff --git a/birdie_snapshots/test_progress_with_fill.accepted b/birdie_snapshots/test_progress_with_fill.accepted index f2d93c0..2980336 100644 --- a/birdie_snapshots/test_progress_with_fill.accepted +++ b/birdie_snapshots/test_progress_with_fill.accepted @@ -1,5 +1,5 @@ --- -version: 1.1.6 +version: 1.2.4 title: Test progress.with_fill file: ./test/glitzer_test.gleam test_name: progress_with_fill_test @@ -12,6 +12,7 @@ ProgressStyle( None, None, None, + True, 0, State(0, False), ) \ No newline at end of file diff --git a/birdie_snapshots/test_progress_with_fill_finished.accepted b/birdie_snapshots/test_progress_with_fill_finished.accepted index 7e285a8..bcba8f3 100644 --- a/birdie_snapshots/test_progress_with_fill_finished.accepted +++ b/birdie_snapshots/test_progress_with_fill_finished.accepted @@ -1,5 +1,5 @@ --- -version: 1.1.6 +version: 1.2.4 title: Test progress.with_fill_finished file: ./test/glitzer_test.gleam test_name: progress_with_fill_finished_test @@ -12,6 +12,7 @@ ProgressStyle( Some(Char("#")), None, None, + True, 0, State(0, False), ) \ No newline at end of file diff --git a/birdie_snapshots/test_progress_with_fill_head.accepted b/birdie_snapshots/test_progress_with_fill_head.accepted index 23ed4b5..9145f4d 100644 --- a/birdie_snapshots/test_progress_with_fill_head.accepted +++ b/birdie_snapshots/test_progress_with_fill_head.accepted @@ -1,5 +1,5 @@ --- -version: 1.1.6 +version: 1.2.4 title: Test progress.with_fill_head file: ./test/glitzer_test.gleam test_name: progress_with_fill_head_test @@ -12,6 +12,7 @@ ProgressStyle( None, Some(Char("#")), None, + True, 0, State(0, False), ) \ No newline at end of file diff --git a/birdie_snapshots/test_progress_with_fill_head_finished.accepted b/birdie_snapshots/test_progress_with_fill_head_finished.accepted index 18f1570..00945a9 100644 --- a/birdie_snapshots/test_progress_with_fill_head_finished.accepted +++ b/birdie_snapshots/test_progress_with_fill_head_finished.accepted @@ -1,5 +1,5 @@ --- -version: 1.1.6 +version: 1.2.4 title: Test progress.with_fill_head_finished file: ./test/glitzer_test.gleam test_name: progress_with_fill_head_finished_test @@ -12,6 +12,7 @@ ProgressStyle( Some(Char("#")), None, None, + True, 0, State(0, False), ) \ No newline at end of file diff --git a/birdie_snapshots/test_progress_with_left_text.accepted b/birdie_snapshots/test_progress_with_left_text.accepted index 42565c1..be68104 100644 --- a/birdie_snapshots/test_progress_with_left_text.accepted +++ b/birdie_snapshots/test_progress_with_left_text.accepted @@ -1,5 +1,5 @@ --- -version: 1.1.6 +version: 1.2.4 title: Test progress.with_left_text file: ./test/glitzer_test.gleam test_name: progress_with_left_text_test @@ -12,6 +12,7 @@ ProgressStyle( None, None, None, + True, 0, State(0, False), ) \ No newline at end of file diff --git a/birdie_snapshots/test_progress_with_length.accepted b/birdie_snapshots/test_progress_with_length.accepted index 92f5c07..7d03d19 100644 --- a/birdie_snapshots/test_progress_with_length.accepted +++ b/birdie_snapshots/test_progress_with_length.accepted @@ -1,5 +1,5 @@ --- -version: 1.1.6 +version: 1.2.4 title: Test progress.with_length file: ./test/glitzer_test.gleam test_name: progress_with_length_test @@ -12,6 +12,7 @@ ProgressStyle( None, None, None, + True, 100, State(0, False), ) \ No newline at end of file diff --git a/birdie_snapshots/test_progress_with_right_text.accepted b/birdie_snapshots/test_progress_with_right_text.accepted index 8d3987a..8ee5283 100644 --- a/birdie_snapshots/test_progress_with_right_text.accepted +++ b/birdie_snapshots/test_progress_with_right_text.accepted @@ -1,5 +1,5 @@ --- -version: 1.1.6 +version: 1.2.4 title: Test progress.with_right_text file: ./test/glitzer_test.gleam test_name: progress_with_right_text_test @@ -12,6 +12,7 @@ ProgressStyle( None, None, None, + True, 0, State(0, False), ) \ No newline at end of file diff --git a/birdie_snapshots/test_progresss_finish.accepted b/birdie_snapshots/test_progresss_finish.accepted index f43e825..25d6add 100644 --- a/birdie_snapshots/test_progresss_finish.accepted +++ b/birdie_snapshots/test_progresss_finish.accepted @@ -1,5 +1,5 @@ --- -version: 1.1.6 +version: 1.2.4 title: Test progresss.finish file: ./test/glitzer_test.gleam test_name: progress_finish_test @@ -12,6 +12,7 @@ ProgressStyle( None, None, None, + True, 100, State(101, True), ) \ No newline at end of file diff --git a/src/glitzer/multi.gleam b/src/glitzer/multi.gleam new file mode 100644 index 0000000..6e85023 --- /dev/null +++ b/src/glitzer/multi.gleam @@ -0,0 +1,245 @@ +/// Run multiple spinners and progress bars at the same time! +/// For when you really have someting to say. +/// +/// Currently, this only supports running multiple indicators on the +/// same line using `multi.new_same_line`. +/// +/// Example: +/// +/// ```gleam +/// import gleam/yielder +/// import glitzer/multi +/// import glitzer/progress +/// import glitzer/spinner +/// +/// pub fn main() { +/// let multi = +/// multi.new_same_line() +/// |> multi.insert_spinner_inline("s1", spinner.pulsating_spinner()) +/// |> multi.insert_spinner_inline( +/// "s2", +/// spinner.with_tick_rate(spinner.default_spinner(), 500), +/// ) +/// |> multi.insert_progress_inline("p1", progress.fancy_slim_bar()) +/// |> multi.insert_progress_inline( +/// "p2", +/// progress.with_length(progress.fancy_thick_bar(), 10), +/// ) +/// |> multi.run_line +/// +/// yielder.range(0, 100_000_000) +/// |> yielder.run +/// +/// multi.tick_by_inline(multi, "p1", 50) +/// |> multi.tick_by_inline("p2", 10) +/// +/// yielder.range(0, 100_000_000) +/// |> yielder.run +/// } +/// ``` +/// +/// You can see that, when inserting an indicator using +/// `multi.insert_{progress,spinner}_inline`, you hand over a string before the +/// actual progress indicator. This string is the identifier of the indicator +/// and **has to be unique**. You use this ID to later address the spinner or +/// progress bar (e.g. with `multi.tick_by_inline`). +import gleam/int +import gleam/io +import gleam/list +import gleam/option.{type Option, None, Some} +import gleam/result +import gleam/yielder + +import repeatedly.{type Repeater} + +import glitzer/codes +import glitzer/progress.{type ProgressStyle} +import glitzer/spinner.{type SpinnerStyle} + +pub opaque type StyleWrapper { + Progress(ProgressStyle) + Spinner(SpinnerStyle) +} + +pub opaque type LineState { + LineState(line: List(#(String, StyleWrapper))) +} + +pub opaque type SameLine { + // Dict of a name, the character offset and the kind of style + // that should be printed. + SameLine( + refresh_rate: Int, + repeater: Option(Repeater(LineState)), + state: LineState, + ) +} + +/// Create a new `SameLine` that can print multiple spinners/progress bars on +/// the same line. +pub fn new_same_line() -> SameLine { + SameLine(state: LineState(line: []), refresh_rate: 100, repeater: None) +} + +/// Insert a `ProgressStyle` at the end of a given `SameLine`. +pub fn insert_progress_inline( + line l: SameLine, + name n: String, + progress p: ProgressStyle, +) -> SameLine { + SameLine( + ..l, + state: LineState( + line: list.append(l.state.line, [ + #(n, Progress(progress.with_newline_on_finished(p, False))), + ]), + ), + ) +} + +/// Insert a `SpinnerStyle` at the end of a given `SameLine`. +pub fn insert_spinner_inline( + line l: SameLine, + name n: String, + spinner s: SpinnerStyle, +) -> SameLine { + SameLine( + ..l, + state: LineState(line: list.append(l.state.line, [#(n, Spinner(s))])), + ) +} + +/// Run the line. This will print the whole line every `line.refresh_rate` +/// milliseconds. It will also automatically tick all inline spinners with +/// regard to their tick rate. +/// +///
+/// Example: +/// +/// ```gleam +/// let multi = +/// multi.new_same_line() +/// |> multi.insert_spinner_inline("s1", spinner.pulsating_spinner()) +/// |> multi.insert_spinner_inline( +/// "s2", +/// spinner.with_tick_rate(spinner.default_spinner(), 500), +/// ) +/// |> multi.run_line +/// ``` +///
+pub fn run_line(line l: SameLine) -> SameLine { + let repeater = + repeatedly.call(l.refresh_rate, l.state, fn(state, i) { + // reset the current line + io.print( + codes.hide_cursor_code + <> codes.clear_line_code + <> codes.return_line_start_code, + ) + let new_line = + // tick all spinners in the line + yielder.from_list(state.line) + |> yielder.map(fn(el) { + let #(name, value) = el + let value = case value { + Progress(p) -> Progress(p) + Spinner(s) -> { + // how much time passed? + let time_gone_by = i * l.refresh_rate + // how many times should the spinner have been ticked? + let spin_count = + result.unwrap(int.floor_divide(time_gone_by, s.tick_rate), 0) + // how much do we have to tick now? + let left_to_tick = spin_count - s.state.progress + Spinner(spinner.tick_by(s, left_to_tick)) + } + } + #(name, value) + }) + |> yielder.to_list + // print the new line + yielder.from_list(new_line) + |> yielder.each(fn(el) { + let #(_, value) = el + case value { + Progress(p) -> print_bar_inline(p) + Spinner(s) -> print_spinner_inline(s) + } + }) + LineState(line: new_line) + }) + SameLine(..l, repeater: Some(repeater)) +} + +fn print_bar_inline(p: ProgressStyle) { + io.print_error(progress.get_raw_bar(p) <> " ") +} + +fn print_spinner_inline(s: SpinnerStyle) { + io.print_error( + s.state.left_text + <> spinner.get_current_frame_string(s) + <> s.state.right_text + <> " ", + ) +} + +/// Tick a spinner or progress bar with the given name by 1. Does nothing if +/// the spinner/progress bar doesn't exist. +pub fn tick_inline(line l: SameLine, name n: String) -> SameLine { + let value = list.key_find(l.state.line, n) + let new_state = case value { + Ok(value) -> { + case value { + Progress(p) -> + LineState(line: list.key_set( + l.state.line, + n, + Progress(progress.tick(p)), + )) + Spinner(s) -> + LineState(line: list.key_set( + l.state.line, + n, + Spinner(spinner.tick(s)), + )) + } + } + Error(_) -> l.state + } + case l.repeater { + Some(r) -> repeatedly.set_state(r, new_state) + None -> Nil + } + SameLine(..l, state: new_state) +} + +/// Tick a spinner or progress bar with the given name by `i`. Does nothing if +/// the spinner/progress bar doesn't exist. +pub fn tick_by_inline(line l: SameLine, name n: String, i i: Int) -> SameLine { + let value = list.key_find(l.state.line, n) + let new_state = case value { + Ok(value) -> { + case value { + Progress(p) -> + LineState(line: list.key_set( + l.state.line, + n, + Progress(progress.tick_by(p, i)), + )) + Spinner(s) -> + LineState(line: list.key_set( + l.state.line, + n, + Spinner(spinner.tick_by(s, i)), + )) + } + } + Error(_) -> l.state + } + case l.repeater { + Some(r) -> repeatedly.set_state(r, new_state) + None -> Nil + } + SameLine(..l, state: new_state) +} diff --git a/src/glitzer/progress.gleam b/src/glitzer/progress.gleam index 3dff01d..06ba9f6 100644 --- a/src/glitzer/progress.gleam +++ b/src/glitzer/progress.gleam @@ -106,6 +106,7 @@ pub opaque type ProgressStyle { fill_finished: Option(Char), fill_head: Option(Char), fill_head_finished: Option(Char), + newline_on_finished: Bool, length: Int, state: State, ) @@ -123,6 +124,7 @@ pub fn default_bar() -> ProgressStyle { fill_finished: option.None, fill_head_finished: option.None, fill_head: option.None, + newline_on_finished: True, length: 100, state: State(progress: 0, finished: False), ) @@ -139,6 +141,7 @@ pub fn slim_bar() -> ProgressStyle { fill_finished: option.None, fill_head: option.None, fill_head_finished: option.None, + newline_on_finished: True, length: 100, state: State(progress: 0, finished: False), ) @@ -155,6 +158,7 @@ pub fn fancy_slim_bar() -> ProgressStyle { fill_finished: option.Some(Char(ansi.green(sym))), fill_head: option.None, fill_head_finished: option.None, + newline_on_finished: True, length: 100, state: State(progress: 0, finished: False), ) @@ -172,6 +176,7 @@ pub fn fancy_slim_arrow_bar() -> ProgressStyle { fill_finished: option.Some(Char(ansi.green(sym))), fill_head: option.Some(Char(ansi.red(sym_head))), fill_head_finished: option.Some(Char(ansi.green(sym_head))), + newline_on_finished: True, length: 100, state: State(progress: 0, finished: False), ) @@ -189,6 +194,7 @@ pub fn thick_bar() -> ProgressStyle { fill_finished: option.None, fill_head: option.None, fill_head_finished: option.None, + newline_on_finished: True, length: 100, state: State(progress: 0, finished: False), ) @@ -206,6 +212,7 @@ pub fn fancy_thick_bar() -> ProgressStyle { fill_finished: option.Some(Char(ansi.green(sym))), fill_head: option.None, fill_head_finished: option.None, + newline_on_finished: True, length: 100, state: State(progress: 0, finished: False), ) @@ -240,6 +247,7 @@ pub fn new_bar() -> ProgressStyle { fill_finished: option.None, fill_head: option.None, fill_head_finished: option.None, + newline_on_finished: True, length: 0, state: State(progress: 0, finished: False), ) @@ -295,6 +303,13 @@ pub fn with_fill_head_finished( ProgressStyle(..bar, fill_head_finished: option.Some(char)) } +pub fn with_newline_on_finished( + bar bar: ProgressStyle, + newline n: Bool, +) -> ProgressStyle { + ProgressStyle(..bar, newline_on_finished: n) +} + /// Add length to a progress bar. pub fn with_length(bar bar: ProgressStyle, length len: Int) -> ProgressStyle { ProgressStyle(..bar, length: len) @@ -386,6 +401,24 @@ pub fn print_bar(bar bar: ProgressStyle) { ) } +pub fn get_raw_bar(bar bar: ProgressStyle) -> String { + let bar = + ProgressStyle( + ..bar, + state: State(..bar.state, finished: bar.state.progress >= bar.length), + ) + let fill = + build_progress_fill(string_tree.new(), bar, bar.state.progress + 1, 0) + |> string_tree.to_string + + let end = case bar.state.finished && bar.newline_on_finished { + True -> "\n" + False -> "" + } + + bar.left <> fill <> bar.right <> end +} + fn build_progress_fill( fill: StringTree, bar: ProgressStyle, diff --git a/src/glitzer/spinner.gleam b/src/glitzer/spinner.gleam index be42a62..6d22de3 100644 --- a/src/glitzer/spinner.gleam +++ b/src/glitzer/spinner.gleam @@ -35,7 +35,7 @@ import repeatedly.{type Repeater} import glitzer/codes /// Contains everything that might get changed during runtime. -pub opaque type State { +pub type State { State( frames: Frames, frame_transform: fn(String) -> String, @@ -51,7 +51,7 @@ pub opaque type Frames { Frames(frames: Array(String)) } -pub opaque type SpinnerStyle { +pub type SpinnerStyle { SpinnerStyle(tick_rate: Int, finish_text: String, state: State) } @@ -320,7 +320,7 @@ pub fn print_spinner(spinner s: SpinnerStyle) -> Nil { ) } -fn get_current_frame_string(s: SpinnerStyle) -> String { +pub fn get_current_frame_string(s: SpinnerStyle) -> String { case glearray.get( s.state.frames.frames, diff --git a/test/glitzer_test.gleam b/test/glitzer_test.gleam index 332d572..ed2b929 100644 --- a/test/glitzer_test.gleam +++ b/test/glitzer_test.gleam @@ -1,6 +1,7 @@ import gleam/iterator import gleam/yielder import gleeunit +import glitzer/multi import birdie import pprint @@ -281,3 +282,19 @@ pub fn spinner_tick_by_test() { |> pprint.format |> birdie.snap(title: "Test spinner.tick_by") } + +pub fn multi_new_same_line_test() { + multi.new_same_line() + |> pprint.format + |> birdie.snap(title: "Test multi.new_same_line") +} + +pub fn multi_insert_spinner_progress_test() { + multi.new_same_line() + |> multi.insert_spinner_inline("s1", spinner.default_spinner()) + |> multi.insert_progress_inline("p1", progress.default_bar()) + |> pprint.format + |> birdie.snap( + title: "Test multi.insert_spinner_inline and multi.insert_progress_inline", + ) +}