tui-piechart 0.3.2

A customizable pie chart widget for Ratatui TUI applications
Documentation
#!/usr/bin/env nu
# Prepare a release: update Cargo.toml version, regenerate CHANGELOG.md,
# and write RELEASE_NOTES.md for the GitHub/Gitea release body.
#
# Usage: nu scripts/release_prepare.nu <tag>
# Example: nu scripts/release_prepare.nu v0.3.2

# ── Helpers ───────────────────────────────────────────────────────────────────

# Read the current [package] version from a Cargo.toml string.
export def read_package_version [content: string] {
    $content
    | lines
    | reduce --fold { in_pkg: false, version: "" } { |line, acc|
        let new_in_pkg = if ($line =~ '^\[package\]') {
            true
        } else if ($acc.in_pkg and ($line =~ '^\[')) {
            false
        } else {
            $acc.in_pkg
        }

        let new_version = if ($acc.in_pkg and ($line =~ '^version\s*=\s*"[^"]*"')) {
            $line
            | parse --regex 'version\s*=\s*"(?P<v>[^"]+)"'
            | get v
            | first
        } else {
            $acc.version
        }

        { in_pkg: $new_in_pkg, version: $new_version }
    }
    | get version
}

# Replace the version line inside [package] only.
export def update_package_version [lines: list<string>, new_version: string] {
    let result = $lines | reduce --fold { in_pkg: false, lines: [] } { |line, acc|
        let new_in_pkg = if ($line =~ '^\[package\]') {
            true
        } else if ($acc.in_pkg and ($line =~ '^\[')) {
            false
        } else {
            $acc.in_pkg
        }

        let new_line = if ($acc.in_pkg and ($line =~ '^version\s*=\s*"[^"]*"')) {
            $'version = "($new_version)"'
        } else {
            $line
        }

        { in_pkg: $new_in_pkg, lines: ($acc.lines | append $new_line) }
    }
    $result.lines
}

# Build the RELEASE_NOTES.md content for tui-piechart.
export def build_release_notes [version: string, cliff_changes: string, last_tag: string] {
    let changes_header = if ($last_tag | is-empty) {
        "### 🎉 Initial Release"
    } else {
        $"### 📝 Changes since ($last_tag):"
    }

    [
        $"# tui-piechart ($version)"
        ""
        "## 🚀 What's New"
        ""
        $changes_header
        ""
        $cliff_changes
        ""
        "## 📦 Installation"
        ""
        "Add this to your `Cargo.toml`:"
        ""
        "```toml"
        "[dependencies]"
        $"tui-piechart = \"($version)\""
        "```"
        ""
        "Or install with cargo:"
        ""
        "```bash"
        "cargo add tui-piechart"
        "```"
        ""
        "## 🚀 Quick Start"
        ""
        "```rust"
        "use ratatui::style::Color;"
        "use tui_piechart::{PieChart, PieSlice};"
        ""
        "let slices = vec!["
        "    PieSlice::new(\"Rust\", 45.0, Color::Red),"
        "    PieSlice::new(\"Go\", 30.0, Color::Blue),"
        "];"
        "let piechart = PieChart::new(slices);"
        "```"
    ] | str join "\n"
}

# ── Main ──────────────────────────────────────────────────────────────────────

def main [
    tag: string,  # The release tag, e.g. "v0.3.2"
] {
    let green  = (ansi green)
    let cyan   = (ansi cyan)
    let red    = (ansi red)
    let yellow = (ansi yellow)
    let reset  = (ansi reset)

    # Strip leading 'v' to get the bare version number
    let version = ($tag | str replace --regex '^v' '')

    print $"($cyan)════════════════════════════════════════($reset)"
    print $"($cyan)  tui-piechart Release Prepare: ($tag)($reset)"
    print $"($cyan)════════════════════════════════════════($reset)"
    print ""

    # ── Step 1: Update Cargo.toml ─────────────────────────────────────────────
    print $"($cyan)Step 1/5: Updating Cargo.toml to ($version)...($reset)"

    let cargo_content = open Cargo.toml --raw
    let cargo_lines   = ($cargo_content | lines)

    let final_lines = update_package_version $cargo_lines $version
    $final_lines | str join "\n" | save --force Cargo.toml

    # Verify
    let got = read_package_version (open Cargo.toml --raw)
    if $got != $version {
        error make { msg: $"($red)Failed to update Cargo.toml \(got ($got), expected ($version)\)($reset)" }
    }
    print $"($green)✓ Cargo.toml updated to ($version)($reset)"

    # ── Step 2: Regenerate CHANGELOG.md ──────────────────────────────────────
    print ""
    print $"($cyan)Step 2/5: Regenerating CHANGELOG.md...($reset)"
    run-external "git-cliff" "--config" "cliff.toml" "--latest" "--output" "CHANGELOG.md"
    print $"($green)✓ CHANGELOG.md written($reset)"

    # ── Step 3: Generate per-release diff (CLIFF_CHANGES.md) ─────────────────
    print ""
    print $"($cyan)Step 3/5: Generating release diff...($reset)"

    let last_tag_result = (do { run-external "git" "describe" "--tags" "--abbrev=0" "HEAD^" } | complete)
    let last_tag = if $last_tag_result.exit_code == 0 {
        $last_tag_result.stdout | str trim
    } else {
        ""
    }

    if ($last_tag | is-empty) {
        print $"($yellow)  No previous tag found — generating full history for ($tag)($reset)"
        run-external "git-cliff" "--config" "cliff.toml" "--tag" $tag "--strip" "header" "--output" "CLIFF_CHANGES.md"
    } else {
        print $"  Diff range: ($last_tag)..($tag)"
        run-external "git-cliff" "--config" "cliff.toml" $"($last_tag)..($tag)" "--strip" "header" "--output" "CLIFF_CHANGES.md"
    }
    print $"($green)✓ CLIFF_CHANGES.md written($reset)"

    # ── Step 4: Build RELEASE_NOTES.md ────────────────────────────────────────
    print ""
    print $"($cyan)Step 4/5: Writing RELEASE_NOTES.md...($reset)"

    let cliff_changes = open CLIFF_CHANGES.md --raw
    let notes = build_release_notes $version $cliff_changes $last_tag
    $notes | save --force RELEASE_NOTES.md
    print $"($green)✓ RELEASE_NOTES.md written($reset)"

    # ── Step 5: Clean up temp file ────────────────────────────────────────────
    print ""
    print $"($cyan)Step 5/5: Cleaning up...($reset)"
    if ("CLIFF_CHANGES.md" | path exists) {
        rm CLIFF_CHANGES.md
    }
    print $"($green)✓ Temp files removed($reset)"

    # ── Summary ───────────────────────────────────────────────────────────────
    print ""
    print $"($cyan)════════════════════════════════════════($reset)"
    print $"($green)✓ Release ($tag) prepared successfully! 🚀($reset)"
    print $"($cyan)════════════════════════════════════════($reset)"
    print ""
    print "Files written:"
    print $"  ($green)Cargo.toml($reset)          version → ($version)"
    print $"  ($green)CHANGELOG.md($reset)        full history"
    print $"  ($green)RELEASE_NOTES.md($reset)    release body for ($tag)"
}