diff --git a/docs/input/assets/casts/await-spinner-plain.cast b/docs/input/assets/casts/await-spinner-plain.cast new file mode 100644 index 0000000..25c43bc --- /dev/null +++ b/docs/input/assets/casts/await-spinner-plain.cast @@ -0,0 +1,332 @@ +{"version": 2, "width": 42, "height": 4, "title": "await-spinner (plain)", "env": {"TERM": "Spectre.Console"}} +[0, "o", "Loading the rocket ship "] +[0, "o", "\u001B[?25l"] +[0, "o", "\u280B"] +[0, "o", "\u001B[1D"] +[0.094, "o", "\u001B[?25l"] +[0.094, "o", "\u2819"] +[0.094, "o", "\u001B[1D"] +[0.188, "o", "\u001B[?25l"] +[0.188, "o", "\u2839"] +[0.188, "o", "\u001B[1D"] +[0.266, "o", "\u001B[?25l"] +[0.266, "o", "\u2838"] +[0.266, "o", "\u001B[1D"] +[0.36, "o", "\u001B[?25l"] +[0.36, "o", "\u283C"] +[0.36, "o", "\u001B[1D"] +[0.453, "o", "\u001B[?25l"] +[0.453, "o", "\u2834"] +[0.453, "o", "\u001B[1D"] +[0.563, "o", "\u001B[?25l"] +[0.563, "o", "\u2826"] +[0.563, "o", "\u001B[1D"] +[0.656, "o", "\u001B[?25l"] +[0.656, "o", "\u2827"] +[0.656, "o", "\u001B[1D"] +[0.75, "o", "\u001B[?25l"] +[0.75, "o", "\u2807"] +[0.75, "o", "\u001B[1D"] +[0.844, "o", "\u001B[?25l"] +[0.844, "o", "\u280F"] +[0.844, "o", "\u001B[1D"] +[0.922, "o", "\u001B[?25l"] +[0.922, "o", "\u280B"] +[0.922, "o", "\u001B[1D"] +[1.016, "o", "\u001B[?25l"] +[1.016, "o", "\u2819"] +[1.016, "o", "\u001B[1D"] +[1.11, "o", "\u001B[?25l"] +[1.11, "o", "\u2839"] +[1.11, "o", "\u001B[1D"] +[1.203, "o", "\u001B[?25l"] +[1.203, "o", "\u2838"] +[1.203, "o", "\u001B[1D"] +[1.297, "o", "\u001B[?25l"] +[1.297, "o", "\u283C"] +[1.297, "o", "\u001B[1D"] +[1.391, "o", "\u001B[?25l"] +[1.391, "o", "\u2834"] +[1.391, "o", "\u001B[1D"] +[1.485, "o", "\u001B[?25l"] +[1.485, "o", "\u2826"] +[1.485, "o", "\u001B[1D"] +[1.578, "o", "\u001B[?25l"] +[1.578, "o", "\u2827"] +[1.578, "o", "\u001B[1D"] +[1.672, "o", "\u001B[?25l"] +[1.672, "o", "\u2807"] +[1.672, "o", "\u001B[1D"] +[1.75, "o", "\u001B[?25l"] +[1.75, "o", "\u280F"] +[1.75, "o", "\u001B[1D"] +[1.828, "o", "\u001B[?25l"] +[1.828, "o", "\u280B"] +[1.828, "o", "\u001B[1D"] +[1.906, "o", "\u001B[?25l"] +[1.906, "o", "\u2819"] +[1.906, "o", "\u001B[1D"] +[2, "o", "\u001B[?25l"] +[2, "o", "\u2839"] +[2, "o", "\u001B[1D"] +[2.11, "o", "\u001B[?25l"] +[2.11, "o", "\u2838"] +[2.11, "o", "\u001B[1D"] +[2.203, "o", "\u001B[?25l"] +[2.203, "o", "\u283C"] +[2.203, "o", "\u001B[1D"] +[2.297, "o", "\u001B[?25l"] +[2.297, "o", "\u2834"] +[2.297, "o", "\u001B[1D"] +[2.391, "o", "\u001B[?25l"] +[2.391, "o", "\u2826"] +[2.391, "o", "\u001B[1D"] +[2.485, "o", "\u001B[?25l"] +[2.485, "o", "\u2827"] +[2.485, "o", "\u001B[1D"] +[2.578, "o", "\u001B[?25l"] +[2.578, "o", "\u2807"] +[2.578, "o", "\u001B[1D"] +[2.656, "o", "\u001B[?25l"] +[2.656, "o", "\u280F"] +[2.656, "o", "\u001B[1D"] +[2.735, "o", "\u001B[?25l"] +[2.735, "o", "\u280B"] +[2.735, "o", "\u001B[1D"] +[2.828, "o", "\u001B[?25l"] +[2.828, "o", "\u2819"] +[2.828, "o", "\u001B[1D"] +[2.922, "o", "\u001B[?25l"] +[2.922, "o", "\u2839"] +[2.922, "o", "\u001B[1D"] +[3.016, "o", "\u001B[?25l"] +[3.016, "o", "\u2838"] +[3.016, "o", "\u001B[1D"] +[3.094, "o", "\u001B[?25l"] +[3.094, "o", "\u283C"] +[3.094, "o", "\u001B[1D"] +[3.188, "o", "\u001B[?25l"] +[3.188, "o", "\u2834"] +[3.188, "o", "\u001B[1D"] +[3.281, "o", "\u001B[?25l"] +[3.281, "o", "\u2826"] +[3.281, "o", "\u001B[1D"] +[3.375, "o", "\u001B[?25l"] +[3.375, "o", "\u2827"] +[3.375, "o", "\u001B[1D"] +[3.453, "o", "\u001B[?25l"] +[3.453, "o", "\u2807"] +[3.453, "o", "\u001B[1D"] +[3.516, "o", " "] +[3.516, "o", "\u001B[1D"] +[3.516, "o", "\u001B[?25h"] +[3.516, "o", "\u001B[32mDone\u001B[0m\r\n"] +[3.516, "o", "Firing up the engines "] +[3.516, "o", "\u001B[?25l"] +[3.516, "o", "[ ]"] +[3.516, "o", "\u001B[6D"] +[3.61, "o", "\u001B[?25l"] +[3.61, "o", "[= ]"] +[3.61, "o", "\u001B[6D"] +[3.703, "o", "\u001B[?25l"] +[3.703, "o", "[== ]"] +[3.703, "o", "\u001B[6D"] +[3.797, "o", "\u001B[?25l"] +[3.797, "o", "[=== ]"] +[3.797, "o", "\u001B[6D"] +[3.875, "o", "\u001B[?25l"] +[3.875, "o", "[ ===]"] +[3.875, "o", "\u001B[6D"] +[3.953, "o", "\u001B[?25l"] +[3.953, "o", "[ ==]"] +[3.953, "o", "\u001B[6D"] +[4.063, "o", "\u001B[?25l"] +[4.063, "o", "[ =]"] +[4.063, "o", "\u001B[6D"] +[4.156, "o", "\u001B[?25l"] +[4.156, "o", "[ ]"] +[4.156, "o", "\u001B[6D"] +[4.25, "o", "\u001B[?25l"] +[4.25, "o", "[ =]"] +[4.25, "o", "\u001B[6D"] +[4.328, "o", "\u001B[?25l"] +[4.328, "o", "[ ==]"] +[4.328, "o", "\u001B[6D"] +[4.406, "o", "\u001B[?25l"] +[4.406, "o", "[ ===]"] +[4.406, "o", "\u001B[6D"] +[4.5, "o", "\u001B[?25l"] +[4.5, "o", "[====]"] +[4.5, "o", "\u001B[6D"] +[4.594, "o", "\u001B[?25l"] +[4.594, "o", "[=== ]"] +[4.594, "o", "\u001B[6D"] +[4.688, "o", "\u001B[?25l"] +[4.688, "o", "[== ]"] +[4.688, "o", "\u001B[6D"] +[4.781, "o", "\u001B[?25l"] +[4.781, "o", "[= ]"] +[4.781, "o", "\u001B[6D"] +[4.86, "o", "\u001B[?25l"] +[4.86, "o", "[ ]"] +[4.86, "o", "\u001B[6D"] +[4.953, "o", "\u001B[?25l"] +[4.953, "o", "[= ]"] +[4.953, "o", "\u001B[6D"] +[5.031, "o", "\u001B[?25l"] +[5.031, "o", "[== ]"] +[5.031, "o", "\u001B[6D"] +[5.125, "o", "\u001B[?25l"] +[5.125, "o", "[=== ]"] +[5.125, "o", "\u001B[6D"] +[5.219, "o", "\u001B[?25l"] +[5.219, "o", "[ ===]"] +[5.219, "o", "\u001B[6D"] +[5.313, "o", "\u001B[?25l"] +[5.313, "o", "[ ==]"] +[5.313, "o", "\u001B[6D"] +[5.422, "o", "\u001B[?25l"] +[5.422, "o", "[ =]"] +[5.422, "o", "\u001B[6D"] +[5.5, "o", "\u001B[?25l"] +[5.5, "o", "[ ]"] +[5.5, "o", "\u001B[6D"] +[5.594, "o", "\u001B[?25l"] +[5.594, "o", "[ =]"] +[5.594, "o", "\u001B[6D"] +[5.672, "o", "\u001B[?25l"] +[5.672, "o", "[ ==]"] +[5.672, "o", "\u001B[6D"] +[5.766, "o", "\u001B[?25l"] +[5.766, "o", "[ ===]"] +[5.766, "o", "\u001B[6D"] +[5.86, "o", "\u001B[?25l"] +[5.86, "o", "[====]"] +[5.86, "o", "\u001B[6D"] +[5.953, "o", "\u001B[?25l"] +[5.969, "o", "[=== ]"] +[5.969, "o", "\u001B[6D"] +[6.063, "o", "\u001B[?25l"] +[6.063, "o", "[== ]"] +[6.063, "o", "\u001B[6D"] +[6.156, "o", "\u001B[?25l"] +[6.156, "o", "[= ]"] +[6.156, "o", "\u001B[6D"] +[6.25, "o", "\u001B[?25l"] +[6.25, "o", "[ ]"] +[6.25, "o", "\u001B[6D"] +[6.328, "o", "\u001B[?25l"] +[6.328, "o", "[= ]"] +[6.328, "o", "\u001B[6D"] +[6.422, "o", "\u001B[?25l"] +[6.422, "o", "[== ]"] +[6.422, "o", "\u001B[6D"] +[6.516, "o", "\u001B[?25l"] +[6.516, "o", "[=== ]"] +[6.516, "o", "\u001B[6D"] +[6.61, "o", "\u001B[?25l"] +[6.61, "o", "[ ===]"] +[6.61, "o", "\u001B[6D"] +[6.703, "o", "\u001B[?25l"] +[6.703, "o", "[ ==]"] +[6.703, "o", "\u001B[6D"] +[6.797, "o", "\u001B[?25l"] +[6.797, "o", "[ =]"] +[6.797, "o", "\u001B[6D"] +[6.891, "o", "\u001B[?25l"] +[6.891, "o", "[ ]"] +[6.891, "o", "\u001B[6D"] +[6.922, "o", " "] +[6.922, "o", "\u001B[6D"] +[6.922, "o", "\u001B[?25h"] +[6.922, "o", "\u001B[32mDone\u001B[0m\r\n"] +[6.922, "o", "Blasting into orbit "] +[6.922, "o", "\u001B[?25l"] +[6.922, "o", "\u2631"] +[6.922, "o", "\u001B[1D"] +[7.031, "o", "\u001B[?25l"] +[7.031, "o", "\u2632"] +[7.031, "o", "\u001B[1D"] +[7.141, "o", "\u001B[?25l"] +[7.141, "o", "\u2634"] +[7.141, "o", "\u001B[1D"] +[7.25, "o", "\u001B[?25l"] +[7.25, "o", "\u2631"] +[7.25, "o", "\u001B[1D"] +[7.36, "o", "\u001B[?25l"] +[7.36, "o", "\u2632"] +[7.36, "o", "\u001B[1D"] +[7.485, "o", "\u001B[?25l"] +[7.485, "o", "\u2634"] +[7.485, "o", "\u001B[1D"] +[7.594, "o", "\u001B[?25l"] +[7.594, "o", "\u2631"] +[7.594, "o", "\u001B[1D"] +[7.703, "o", "\u001B[?25l"] +[7.703, "o", "\u2632"] +[7.703, "o", "\u001B[1D"] +[7.813, "o", "\u001B[?25l"] +[7.813, "o", "\u2634"] +[7.813, "o", "\u001B[1D"] +[7.922, "o", "\u001B[?25l"] +[7.922, "o", "\u2631"] +[7.922, "o", "\u001B[1D"] +[8.031, "o", "\u001B[?25l"] +[8.031, "o", "\u2632"] +[8.031, "o", "\u001B[1D"] +[8.141, "o", "\u001B[?25l"] +[8.141, "o", "\u2634"] +[8.141, "o", "\u001B[1D"] +[8.25, "o", "\u001B[?25l"] +[8.25, "o", "\u2631"] +[8.25, "o", "\u001B[1D"] +[8.375, "o", "\u001B[?25l"] +[8.375, "o", "\u2632"] +[8.375, "o", "\u001B[1D"] +[8.485, "o", "\u001B[?25l"] +[8.485, "o", "\u2634"] +[8.485, "o", "\u001B[1D"] +[8.594, "o", "\u001B[?25l"] +[8.594, "o", "\u2631"] +[8.594, "o", "\u001B[1D"] +[8.703, "o", "\u001B[?25l"] +[8.703, "o", "\u2632"] +[8.703, "o", "\u001B[1D"] +[8.813, "o", "\u001B[?25l"] +[8.813, "o", "\u2634"] +[8.813, "o", "\u001B[1D"] +[8.938, "o", "\u001B[?25l"] +[8.938, "o", "\u2631"] +[8.938, "o", "\u001B[1D"] +[9.047, "o", "\u001B[?25l"] +[9.047, "o", "\u2632"] +[9.047, "o", "\u001B[1D"] +[9.156, "o", "\u001B[?25l"] +[9.156, "o", "\u2634"] +[9.156, "o", "\u001B[1D"] +[9.266, "o", "\u001B[?25l"] +[9.266, "o", "\u2631"] +[9.266, "o", "\u001B[1D"] +[9.375, "o", "\u001B[?25l"] +[9.375, "o", "\u2632"] +[9.375, "o", "\u001B[1D"] +[9.485, "o", "\u001B[?25l"] +[9.485, "o", "\u2634"] +[9.485, "o", "\u001B[1D"] +[9.594, "o", "\u001B[?25l"] +[9.594, "o", "\u2631"] +[9.594, "o", "\u001B[1D"] +[9.719, "o", "\u001B[?25l"] +[9.719, "o", "\u2632"] +[9.719, "o", "\u001B[1D"] +[9.828, "o", "\u001B[?25l"] +[9.828, "o", "\u2634"] +[9.828, "o", "\u001B[1D"] +[9.938, "o", "\u001B[?25l"] +[9.938, "o", "\u2631"] +[9.938, "o", "\u001B[1D"] +[9.953, "o", " "] +[9.953, "o", "\u001B[1D"] +[9.953, "o", "\u001B[?25h"] +[9.953, "o", "\u001B[31mOh no\u001B[0m\r\n"] + diff --git a/docs/input/assets/casts/await-spinner-rich.cast b/docs/input/assets/casts/await-spinner-rich.cast new file mode 100644 index 0000000..aaf4448 --- /dev/null +++ b/docs/input/assets/casts/await-spinner-rich.cast @@ -0,0 +1,326 @@ +{"version": 2, "width": 42, "height": 4, "title": "await-spinner (rich)", "env": {"TERM": "Spectre.Console"}} +[0, "o", "Loading the rocket ship "] +[0, "o", "\u001B[?25l"] +[0, "o", "\u280B"] +[0, "o", "\u001B[1D"] +[0.094, "o", "\u001B[?25l"] +[0.094, "o", "\u2819"] +[0.094, "o", "\u001B[1D"] +[0.172, "o", "\u001B[?25l"] +[0.172, "o", "\u2839"] +[0.172, "o", "\u001B[1D"] +[0.266, "o", "\u001B[?25l"] +[0.266, "o", "\u2838"] +[0.266, "o", "\u001B[1D"] +[0.36, "o", "\u001B[?25l"] +[0.36, "o", "\u283C"] +[0.36, "o", "\u001B[1D"] +[0.453, "o", "\u001B[?25l"] +[0.453, "o", "\u2834"] +[0.453, "o", "\u001B[1D"] +[0.547, "o", "\u001B[?25l"] +[0.547, "o", "\u2826"] +[0.547, "o", "\u001B[1D"] +[0.641, "o", "\u001B[?25l"] +[0.641, "o", "\u2827"] +[0.641, "o", "\u001B[1D"] +[0.719, "o", "\u001B[?25l"] +[0.719, "o", "\u2807"] +[0.719, "o", "\u001B[1D"] +[0.797, "o", "\u001B[?25l"] +[0.797, "o", "\u280F"] +[0.797, "o", "\u001B[1D"] +[0.891, "o", "\u001B[?25l"] +[0.891, "o", "\u280B"] +[0.891, "o", "\u001B[1D"] +[0.969, "o", "\u001B[?25l"] +[0.969, "o", "\u2819"] +[0.969, "o", "\u001B[1D"] +[1.078, "o", "\u001B[?25l"] +[1.078, "o", "\u2839"] +[1.094, "o", "\u001B[1D"] +[1.25, "o", "\u001B[?25l"] +[1.25, "o", "\u2838"] +[1.266, "o", "\u001B[1D"] +[1.407, "o", "\u001B[?25l"] +[1.407, "o", "\u283C"] +[1.422, "o", "\u001B[1D"] +[1.532, "o", "\u001B[?25l"] +[1.532, "o", "\u2834"] +[1.532, "o", "\u001B[1D"] +[1.61, "o", "\u001B[?25l"] +[1.61, "o", "\u2826"] +[1.61, "o", "\u001B[1D"] +[1.703, "o", "\u001B[?25l"] +[1.703, "o", "\u2827"] +[1.703, "o", "\u001B[1D"] +[1.782, "o", "\u001B[?25l"] +[1.782, "o", "\u2807"] +[1.782, "o", "\u001B[1D"] +[1.86, "o", "\u001B[?25l"] +[1.86, "o", "\u280F"] +[1.86, "o", "\u001B[1D"] +[1.953, "o", "\u001B[?25l"] +[1.953, "o", "\u280B"] +[1.953, "o", "\u001B[1D"] +[2.047, "o", "\u001B[?25l"] +[2.047, "o", "\u2819"] +[2.047, "o", "\u001B[1D"] +[2.125, "o", "\u001B[?25l"] +[2.125, "o", "\u2839"] +[2.125, "o", "\u001B[1D"] +[2.219, "o", "\u001B[?25l"] +[2.219, "o", "\u2838"] +[2.219, "o", "\u001B[1D"] +[2.313, "o", "\u001B[?25l"] +[2.313, "o", "\u283C"] +[2.313, "o", "\u001B[1D"] +[2.407, "o", "\u001B[?25l"] +[2.407, "o", "\u2834"] +[2.407, "o", "\u001B[1D"] +[2.5, "o", "\u001B[?25l"] +[2.5, "o", "\u2826"] +[2.5, "o", "\u001B[1D"] +[2.594, "o", "\u001B[?25l"] +[2.594, "o", "\u2827"] +[2.594, "o", "\u001B[1D"] +[2.688, "o", "\u001B[?25l"] +[2.688, "o", "\u2807"] +[2.688, "o", "\u001B[1D"] +[2.782, "o", "\u001B[?25l"] +[2.782, "o", "\u280F"] +[2.782, "o", "\u001B[1D"] +[2.875, "o", "\u001B[?25l"] +[2.875, "o", "\u280B"] +[2.875, "o", "\u001B[1D"] +[2.969, "o", "\u001B[?25l"] +[2.969, "o", "\u2819"] +[2.969, "o", "\u001B[1D"] +[3.063, "o", "\u001B[?25l"] +[3.063, "o", "\u2839"] +[3.063, "o", "\u001B[1D"] +[3.157, "o", "\u001B[?25l"] +[3.157, "o", "\u2838"] +[3.157, "o", "\u001B[1D"] +[3.25, "o", "\u001B[?25l"] +[3.25, "o", "\u283C"] +[3.25, "o", "\u001B[1D"] +[3.344, "o", "\u001B[?25l"] +[3.344, "o", "\u2834"] +[3.344, "o", "\u001B[1D"] +[3.469, "o", "\u001B[?25l"] +[3.469, "o", "\u2826"] +[3.469, "o", "\u001B[1D"] +[3.563, "o", "\u001B[?25l"] +[3.563, "o", "\u2827"] +[3.563, "o", "\u001B[1D"] +[3.563, "o", " "] +[3.563, "o", "\u001B[1D"] +[3.563, "o", "\u001B[?25h"] +[3.563, "o", "\u001B[38;5;2mDone\u001B[0m\r\n"] +[3.563, "o", "Firing up the engines "] +[3.563, "o", "\u001B[?25l"] +[3.563, "o", "[ ]"] +[3.563, "o", "\u001B[6D"] +[3.672, "o", "\u001B[?25l"] +[3.672, "o", "[= ]"] +[3.672, "o", "\u001B[6D"] +[3.75, "o", "\u001B[?25l"] +[3.75, "o", "[== ]"] +[3.75, "o", "\u001B[6D"] +[3.844, "o", "\u001B[?25l"] +[3.844, "o", "[=== ]"] +[3.844, "o", "\u001B[6D"] +[3.953, "o", "\u001B[?25l"] +[3.953, "o", "[ ===]"] +[3.953, "o", "\u001B[6D"] +[4.047, "o", "\u001B[?25l"] +[4.047, "o", "[ ==]"] +[4.047, "o", "\u001B[6D"] +[4.157, "o", "\u001B[?25l"] +[4.157, "o", "[ =]"] +[4.157, "o", "\u001B[6D"] +[4.25, "o", "\u001B[?25l"] +[4.25, "o", "[ ]"] +[4.25, "o", "\u001B[6D"] +[4.344, "o", "\u001B[?25l"] +[4.344, "o", "[ =]"] +[4.344, "o", "\u001B[6D"] +[4.438, "o", "\u001B[?25l"] +[4.438, "o", "[ ==]"] +[4.438, "o", "\u001B[6D"] +[4.532, "o", "\u001B[?25l"] +[4.532, "o", "[ ===]"] +[4.532, "o", "\u001B[6D"] +[4.625, "o", "\u001B[?25l"] +[4.625, "o", "[====]"] +[4.625, "o", "\u001B[6D"] +[4.719, "o", "\u001B[?25l"] +[4.719, "o", "[=== ]"] +[4.719, "o", "\u001B[6D"] +[4.828, "o", "\u001B[?25l"] +[4.844, "o", "[== ]"] +[4.86, "o", "\u001B[6D"] +[4.953, "o", "\u001B[?25l"] +[4.953, "o", "[= ]"] +[4.953, "o", "\u001B[6D"] +[5.047, "o", "\u001B[?25l"] +[5.047, "o", "[ ]"] +[5.047, "o", "\u001B[6D"] +[5.141, "o", "\u001B[?25l"] +[5.141, "o", "[= ]"] +[5.141, "o", "\u001B[6D"] +[5.235, "o", "\u001B[?25l"] +[5.235, "o", "[== ]"] +[5.235, "o", "\u001B[6D"] +[5.328, "o", "\u001B[?25l"] +[5.328, "o", "[=== ]"] +[5.328, "o", "\u001B[6D"] +[5.422, "o", "\u001B[?25l"] +[5.422, "o", "[ ===]"] +[5.422, "o", "\u001B[6D"] +[5.532, "o", "\u001B[?25l"] +[5.532, "o", "[ ==]"] +[5.532, "o", "\u001B[6D"] +[5.625, "o", "\u001B[?25l"] +[5.625, "o", "[ =]"] +[5.625, "o", "\u001B[6D"] +[5.719, "o", "\u001B[?25l"] +[5.719, "o", "[ ]"] +[5.719, "o", "\u001B[6D"] +[5.813, "o", "\u001B[?25l"] +[5.813, "o", "[ =]"] +[5.813, "o", "\u001B[6D"] +[5.907, "o", "\u001B[?25l"] +[5.907, "o", "[ ==]"] +[5.907, "o", "\u001B[6D"] +[6, "o", "\u001B[?25l"] +[6, "o", "[ ===]"] +[6, "o", "\u001B[6D"] +[6.094, "o", "\u001B[?25l"] +[6.094, "o", "[====]"] +[6.094, "o", "\u001B[6D"] +[6.188, "o", "\u001B[?25l"] +[6.188, "o", "[=== ]"] +[6.188, "o", "\u001B[6D"] +[6.282, "o", "\u001B[?25l"] +[6.282, "o", "[== ]"] +[6.282, "o", "\u001B[6D"] +[6.375, "o", "\u001B[?25l"] +[6.375, "o", "[= ]"] +[6.375, "o", "\u001B[6D"] +[6.453, "o", "\u001B[?25l"] +[6.453, "o", "[ ]"] +[6.453, "o", "\u001B[6D"] +[6.547, "o", "\u001B[?25l"] +[6.547, "o", "[= ]"] +[6.547, "o", "\u001B[6D"] +[6.625, "o", "\u001B[?25l"] +[6.625, "o", "[== ]"] +[6.625, "o", "\u001B[6D"] +[6.703, "o", "\u001B[?25l"] +[6.703, "o", "[=== ]"] +[6.703, "o", "\u001B[6D"] +[6.797, "o", "\u001B[?25l"] +[6.797, "o", "[ ===]"] +[6.797, "o", "\u001B[6D"] +[6.891, "o", "\u001B[?25l"] +[6.891, "o", "[ ==]"] +[6.891, "o", "\u001B[6D"] +[6.969, "o", " "] +[6.969, "o", "\u001B[6D"] +[6.969, "o", "\u001B[?25h"] +[6.969, "o", "\u001B[38;5;2mDone\u001B[0m\r\n"] +[6.969, "o", "Blasting into orbit "] +[6.969, "o", "\u001B[?25l"] +[6.969, "o", "\u2631"] +[6.969, "o", "\u001B[1D"] +[7.078, "o", "\u001B[?25l"] +[7.078, "o", "\u2632"] +[7.078, "o", "\u001B[1D"] +[7.172, "o", "\u001B[?25l"] +[7.172, "o", "\u2634"] +[7.172, "o", "\u001B[1D"] +[7.282, "o", "\u001B[?25l"] +[7.282, "o", "\u2631"] +[7.282, "o", "\u001B[1D"] +[7.375, "o", "\u001B[?25l"] +[7.375, "o", "\u2632"] +[7.375, "o", "\u001B[1D"] +[7.485, "o", "\u001B[?25l"] +[7.485, "o", "\u2634"] +[7.485, "o", "\u001B[1D"] +[7.594, "o", "\u001B[?25l"] +[7.594, "o", "\u2631"] +[7.594, "o", "\u001B[1D"] +[7.703, "o", "\u001B[?25l"] +[7.703, "o", "\u2632"] +[7.703, "o", "\u001B[1D"] +[7.813, "o", "\u001B[?25l"] +[7.813, "o", "\u2634"] +[7.813, "o", "\u001B[1D"] +[7.922, "o", "\u001B[?25l"] +[7.922, "o", "\u2631"] +[7.922, "o", "\u001B[1D"] +[8.032, "o", "\u001B[?25l"] +[8.032, "o", "\u2632"] +[8.032, "o", "\u001B[1D"] +[8.125, "o", "\u001B[?25l"] +[8.125, "o", "\u2634"] +[8.125, "o", "\u001B[1D"] +[8.235, "o", "\u001B[?25l"] +[8.235, "o", "\u2631"] +[8.235, "o", "\u001B[1D"] +[8.344, "o", "\u001B[?25l"] +[8.344, "o", "\u2632"] +[8.344, "o", "\u001B[1D"] +[8.453, "o", "\u001B[?25l"] +[8.453, "o", "\u2634"] +[8.453, "o", "\u001B[1D"] +[8.563, "o", "\u001B[?25l"] +[8.563, "o", "\u2631"] +[8.563, "o", "\u001B[1D"] +[8.657, "o", "\u001B[?25l"] +[8.657, "o", "\u2632"] +[8.657, "o", "\u001B[1D"] +[8.766, "o", "\u001B[?25l"] +[8.766, "o", "\u2634"] +[8.766, "o", "\u001B[1D"] +[8.86, "o", "\u001B[?25l"] +[8.86, "o", "\u2631"] +[8.86, "o", "\u001B[1D"] +[8.969, "o", "\u001B[?25l"] +[8.969, "o", "\u2632"] +[8.969, "o", "\u001B[1D"] +[9.078, "o", "\u001B[?25l"] +[9.078, "o", "\u2634"] +[9.078, "o", "\u001B[1D"] +[9.203, "o", "\u001B[?25l"] +[9.203, "o", "\u2631"] +[9.203, "o", "\u001B[1D"] +[9.313, "o", "\u001B[?25l"] +[9.313, "o", "\u2632"] +[9.313, "o", "\u001B[1D"] +[9.407, "o", "\u001B[?25l"] +[9.407, "o", "\u2634"] +[9.407, "o", "\u001B[1D"] +[9.516, "o", "\u001B[?25l"] +[9.516, "o", "\u2631"] +[9.516, "o", "\u001B[1D"] +[9.625, "o", "\u001B[?25l"] +[9.625, "o", "\u2632"] +[9.625, "o", "\u001B[1D"] +[9.719, "o", "\u001B[?25l"] +[9.719, "o", "\u2634"] +[9.735, "o", "\u001B[1D"] +[9.828, "o", "\u001B[?25l"] +[9.828, "o", "\u2631"] +[9.828, "o", "\u001B[1D"] +[9.938, "o", "\u001B[?25l"] +[9.938, "o", "\u2632"] +[9.938, "o", "\u001B[1D"] +[10, "o", " "] +[10, "o", "\u001B[1D"] +[10, "o", "\u001B[?25h"] +[10, "o", "\u001B[38;5;9mOh no\u001B[0m\r\n"] + diff --git a/docs/input/live/async.md b/docs/input/live/async.md new file mode 100644 index 0000000..7f0a9e3 --- /dev/null +++ b/docs/input/live/async.md @@ -0,0 +1,73 @@ +Title: Async Extensions +Order: 11 +Description: "Async Extensions provides extension methods for running tasks with an inline animations." +Highlights: + - Extension methods for running tasks with spinner animations + - Support for both void and generic Task types + - Customizable spinner styles and console output +Reference: + - T:Spectre.Console.Extensions.SpinnerExtensions +Xref: spinner-extensions +--- + +The Async Spinner Extension provides convenient extension methods for running tasks with an inline spinner animations in the console. + + + + + The spinner animation is not thread safe, and using it together with other interactive + components such as prompts, progress displays or other status displays is not supported. + + +## Usage + +The extension methods allow you to easily add spinner animations to any Task execution: + +```csharp +// Basic usage with void Task +await someTask.Spinner(); + +// With generic Task +var result = await someTaskWithResult.Spinner( + Spinner.Known.Star, + new Style(foreground: Color.Green)); + +// With custom console +await someTask.Spinner( + Spinner.Known.Dots, + style: Style.Plain, + ansiConsole: customConsole); +``` + +## Features + +The spinner extensions provide: + +- Support for both void Tasks and Tasks with return values +- Customizable spinner animations using any Spectre.Console Spinner +- Optional styling for the spinner animation +- Ability to specify a custom IAnsiConsole instance + +## Examples + +Here's a more complete example showing different ways to use the spinner extensions: + +```csharp +// Basic spinner with default settings +await Task.Delay(1000) + .Spinner(Spinner.Known.Dots); + +// Customized spinner with style +var result = await CalculateSomething() + .Spinner( + Spinner.Known.Star, + new Style(foreground: Color.Green)); + +// Using with a custom console +await ProcessData() + .Spinner( + new Spinner(new[] { "⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏" }, 80), + new Style(foreground: Color.Blue), + customConsole); +``` + diff --git a/docs/input/tailwind.css b/docs/input/tailwind.css index 4304f7e..569aa8e 100644 --- a/docs/input/tailwind.css +++ b/docs/input/tailwind.css @@ -17,7 +17,7 @@ and the ascii terminal player. /* temp styling for alerts */ .alert-warning { - @apply p-4 border border-yellow-300 bg-yellow-100 text-yellow-800 dark:border-orange-700/50 dark:bg-orange-800/50 dark:text-orange-300/90 rounded shadow-sm text-sm; + @apply p-4 border border-yellow-300 bg-yellow-100 text-yellow-800 dark:border-red-700/50 dark:bg-red-800/50 dark:text-red-100/90 rounded shadow-sm text-sm; } .alert-warning p { diff --git a/resources/scripts/Generator/Commands/AsciiCast/Samples/AwaitSpinnerSample.cs b/resources/scripts/Generator/Commands/AsciiCast/Samples/AwaitSpinnerSample.cs new file mode 100644 index 0000000..d6b7164 --- /dev/null +++ b/resources/scripts/Generator/Commands/AsciiCast/Samples/AwaitSpinnerSample.cs @@ -0,0 +1,36 @@ +using System.Threading.Tasks; +using Generator.Commands.Samples; +using Spectre.Console; +using Spectre.Console.Extensions; + +namespace Generator.Commands.AsciiCast.Samples; + +public class AwaitSpinnerSample : BaseSample +{ + private static async Task DoSomethingAsync(int value) + { + await Task.Delay(value); + } + + public override (int Cols, int Rows) ConsoleSize { get; } = (40, 4); + + public override void Run(IAnsiConsole console) + { + Task.Run(async () => + { + AnsiConsole.Write("Loading the rocket ship "); + await DoSomethingAsync(3500).Spinner(Spinner.Known.Dots); + AnsiConsole.MarkupLine("[green]Done[/]"); + + AnsiConsole.Write("Firing up the engines "); + await DoSomethingAsync(3400).Spinner(Spinner.Known.BouncingBar); + AnsiConsole.MarkupLine("[green]Done[/]"); + + AnsiConsole.Write("Blasting into orbit "); + await DoSomethingAsync(3025).Spinner(Spinner.Known.Hamburger); + AnsiConsole.MarkupLine("[red]Oh no[/]"); + + }).Wait(); + + } +} \ No newline at end of file diff --git a/src/Spectre.Console/Extensions/AnsiConsoleExtensions.Async.cs b/src/Spectre.Console/Extensions/AnsiConsoleExtensions.Async.cs new file mode 100644 index 0000000..3450488 --- /dev/null +++ b/src/Spectre.Console/Extensions/AnsiConsoleExtensions.Async.cs @@ -0,0 +1,92 @@ +namespace Spectre.Console.Extensions; + +/// +/// Provides extension methods for running tasks with a spinner animation. +/// +public static class SpinnerExtensions +{ + /// + /// Runs a task with a spinner animation. + /// + /// The task to run. + /// The spinner to use. + /// The style to apply to the spinner. + /// The console to write to. + /// The result of the task. + public static async Task Spinner(this Task task, Spinner? spinner = null, Style? style = null, IAnsiConsole? ansiConsole = null) + { + await SpinnerInternal(task, spinner ?? Console.Spinner.Known.Default, style, ansiConsole); + } + + /// + /// Runs a task with a spinner animation. + /// + /// The type of the task result. + /// The task to run. + /// The spinner to use. + /// The style to apply to the spinner. + /// The console to write to. + /// The result of the task. + public static async Task Spinner(this Task task, Spinner? spinner = null, Style? style = null, IAnsiConsole? ansiConsole = null) + { + return (await SpinnerInternal(task, spinner ?? Console.Spinner.Known.Default, style, ansiConsole))!; + } + + private static async Task SpinnerInternal(Task task, Spinner spinner, Style? style = null, IAnsiConsole? ansiConsole = null) + { + ansiConsole ??= AnsiConsole.Console; + + style ??= Style.Plain; + var currentFrame = 0; + var cancellationTokenSource = new CancellationTokenSource(); + + // Start spinner animation in background + var spinnerTask = Task.Run( + async () => + { + while (!cancellationTokenSource.Token.IsCancellationRequested) + { + ansiConsole.Cursor.Show(false); + + var spinnerFrame = spinner.Frames[currentFrame]; + + // Write the spinner frame + ansiConsole.Write(new Text(spinnerFrame, style)); + ansiConsole.Write(new ControlCode(AnsiSequences.CUB(spinnerFrame.Length))); + + currentFrame = (currentFrame + 1) % spinner.Frames.Count; + await Task.Delay(spinner.Interval, cancellationTokenSource.Token); + } + }, cancellationTokenSource.Token); + + try + { + // Wait for the actual task to complete + if (task is Task taskWithResult) + { + var result = await taskWithResult; + await cancellationTokenSource.CancelAsync(); + await spinnerTask.ContinueWith(_ => { }, TaskContinuationOptions.OnlyOnCanceled); + + return result; + } + else + { + await task; + await cancellationTokenSource.CancelAsync(); + await spinnerTask.ContinueWith(_ => { }, TaskContinuationOptions.OnlyOnCanceled); + + return default; + } + } + finally + { + var spinnerFrame = spinner.Frames[currentFrame]; + + ansiConsole.Write(new string(' ', spinnerFrame.Length)); + ansiConsole.Write(new ControlCode(AnsiSequences.CUB(spinnerFrame.Length))); + ansiConsole.Cursor.Show(); + await cancellationTokenSource.CancelAsync(); + } + } +} \ No newline at end of file diff --git a/src/Spectre.Console/Internal/Polyfill/CancellationToken.cs b/src/Spectre.Console/Internal/Polyfill/CancellationToken.cs new file mode 100644 index 0000000..4d0e62c --- /dev/null +++ b/src/Spectre.Console/Internal/Polyfill/CancellationToken.cs @@ -0,0 +1,13 @@ +#if NETSTANDARD2_0 +namespace Spectre.Console +{ + internal static class CancellationTokenHelpers + { + public static Task CancelAsync(this CancellationTokenSource cts) + { + cts.Cancel(); + return Task.CompletedTask; + } + } +} +#endif \ No newline at end of file