๐Ÿ“ฆ sleepyfran / duets

๐Ÿ“„ Message.fs ยท 54 lines
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[<AutoOpen>]
module Duets.Cli.Components.Message

open FSharp.Control
open Spectre.Console

/// Renders a message into the screen.
let showMessage text = text |> AnsiConsole.MarkupLine

/// Renders an inline message into the screen.
let showInlineMessage text = text |> AnsiConsole.Markup

/// Streams a message from an async iterator, applying the given function for
/// styling on each token.
let streamStyled styleFn iter =
    iter
    |> AsyncSeq.iter (styleFn >> showInlineMessage)
    |> Async.RunSynchronously

/// Streams a message from an async iterator, normally used to show messages
/// coming from the language model.
let streamMessage iter =
    let mutable accumulated = ""

    AnsiConsole
        .Live(Markup(""))
        .Start(fun ctx ->
            iter
            |> AsyncSeq.iter (fun token ->
                accumulated <- accumulated + token

                // Updating the target with an empty string would cause an
                // exception to be thrown, so skip an update if we have nothing.
                if accumulated = "" then
                    ()
                else
                    ctx.UpdateTarget(Markup(accumulated)))
            |> Async.RunSynchronously)

/// Renders a path into the screen.
let showPath path =
    let mutable path = TextPath path

    path.RootStyle <- Style(foreground = Color.Green)
    path.SeparatorStyle <- Style(foreground = Color.Green)
    path.StemStyle <- Style(foreground = Color.Blue)
    path.LeafStyle <- Style(foreground = Color.Yellow)

    AnsiConsole.Write path
    AnsiConsole.WriteLine()

/// Renders an exception into the screen.
let showException = AnsiConsole.WriteException