Add async spinner extension methods and related documentation

This commit is contained in:
Phil Scott 2025-01-28 10:20:24 -05:00
parent 92daeb739d
commit 05ce33615e
7 changed files with 873 additions and 1 deletions

View File

@ -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"]

View File

@ -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"]

73
docs/input/live/async.md Normal file
View File

@ -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.
<?# AsciiCast cast="await-spinner" /?>
<?# Alert ?>
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.
<?#/ Alert ?>
## 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<T>
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);
```

View File

@ -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 {

View File

@ -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();
}
}

View File

@ -0,0 +1,92 @@
namespace Spectre.Console.Extensions;
/// <summary>
/// Provides extension methods for running tasks with a spinner animation.
/// </summary>
public static class SpinnerExtensions
{
/// <summary>
/// Runs a task with a spinner animation.
/// </summary>
/// <param name="task">The task to run.</param>
/// <param name="spinner">The spinner to use.</param>
/// <param name="style">The style to apply to the spinner.</param>
/// <param name="ansiConsole">The console to write to.</param>
/// <returns>The result of the task.</returns>
public static async Task Spinner(this Task task, Spinner? spinner = null, Style? style = null, IAnsiConsole? ansiConsole = null)
{
await SpinnerInternal<object>(task, spinner ?? Console.Spinner.Known.Default, style, ansiConsole);
}
/// <summary>
/// Runs a task with a spinner animation.
/// </summary>
/// <typeparam name="T">The type of the task result.</typeparam>
/// <param name="task">The task to run.</param>
/// <param name="spinner">The spinner to use.</param>
/// <param name="style">The style to apply to the spinner.</param>
/// <param name="ansiConsole">The console to write to.</param>
/// <returns>The result of the task.</returns>
public static async Task<T> Spinner<T>(this Task<T> task, Spinner? spinner = null, Style? style = null, IAnsiConsole? ansiConsole = null)
{
return (await SpinnerInternal<T>(task, spinner ?? Console.Spinner.Known.Default, style, ansiConsole))!;
}
private static async Task<T?> SpinnerInternal<T>(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<T> 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();
}
}
}

View File

@ -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