tui-checkbox 0.4.5

A customizable checkbox widget for Ratatui TUI applications
Documentation
#!/usr/bin/env nu
# ──────────────────────────────────────────────────────────────────────────────
# tui-checkbox — Bump crate version
# ──────────────────────────────────────────────────────────────────────────────
# Usage:
#   nu scripts/bump_version.nu <new_version>
#
# Example:
#   nu scripts/bump_version.nu 0.5.0
#
# What it does:
#   1. Validates the supplied semantic version string.
#   2. Updates `package.version` in Cargo.toml.
#   3. Updates the version badge in README.md (if present).
#   4. Runs `cargo fmt`, `cargo clippy`, and `cargo test`.
#   5. Generates / updates the CHANGELOG via git-cliff (if installed).
#   6. Creates a Git commit and an annotated tag.
# ──────────────────────────────────────────────────────────────────────────────

use ci/publish.nu [is-published]

# Validate that a string looks like a semver (MAJOR.MINOR.PATCH with optional pre-release).
def validate_version [version: string] {
    let pattern = '^\d+\.\d+\.\d+(-[a-zA-Z0-9.]+)?$'
    if ($version | find --regex $pattern | is-empty) {
        print $"(ansi red)Error:(ansi reset) '($version)' is not a valid semantic version."
        exit 1
    }
}

# Replace the package.version line in Cargo.toml.
def update_package_version [version: string] {
    let cargo = (open Cargo.toml --raw)
    let updated = ($cargo | str replace --regex '(?m)^version\s*=\s*"[^"]+"' $'version = "($version)"')
    $updated | save --force Cargo.toml
    print $"(ansi green)✓(ansi reset) Updated package.version → ($version)"
}

# Update the crates.io version badge in README.md (if the badge exists).
def update_readme_badge [version: string] {
    if not ("README.md" | path exists) {
        print $"(ansi yellow)⚠(ansi reset) README.md not found — skipping badge update."
        return
    }
    let readme = (open README.md --raw)
    if ($readme =~ 'version-[0-9]+\.[0-9]+\.[0-9]+-blue') {
        let updated = (
            $readme
            | str replace --all --regex 'version-[0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9]+)?-blue' $"version-($version)-blue"
        )
        $updated | save --force README.md
        print $"(ansi green)✓(ansi reset) Updated README.md version badge."
    } else {
        print $"(ansi yellow)⚠(ansi reset) No version badge found in README.md — skipping."
    }
}

def main [
    new_version: string,  # New version in X.Y.Z format
    --yes (-y),           # Skip confirmation prompt (non-interactive)
] {
    print ""
    print $"(ansi cyan)══════════════════════════════════════════════════════════════(ansi reset)"
    print $"(ansi cyan)  tui-checkbox — Bump Version(ansi reset)"
    print $"(ansi cyan)══════════════════════════════════════════════════════════════(ansi reset)"
    print ""

    # 0. Read current version
    let current_version = (open Cargo.toml | get package.version)
    print $"  Current version : (ansi yellow)($current_version)(ansi reset)"
    print $"  New version     : (ansi green)($new_version)(ansi reset)"
    print ""

    if $current_version == $new_version {
        print $"(ansi yellow)⚠(ansi reset) Version is already ($new_version). Nothing to do."
        exit 0
    }

    # 1. Validate
    validate_version $new_version
    print $"(ansi green)✓(ansi reset) Version string validated."

    # 1b. Refuse to reuse a version that is already published on crates.io.
    let crate_name = (open Cargo.toml | get package.name)
    if (is-published $crate_name $new_version) {
        print $"(ansi red)✗(ansi reset) ($crate_name)@($new_version) is already published on crates.io."
        print $"  Pick a higher version — e.g. (ansi green)just release <next-version>(ansi reset)."
        exit 1
    }
    print $"(ansi green)✓(ansi reset) ($new_version) is not yet on crates.io."

    # 2. Update package version
    update_package_version $new_version

    # 3. Update README badge
    update_readme_badge $new_version

    # 4. Update Cargo.lock
    print ""
    print $"(ansi cyan)── cargo update ────────────────────────────────────────────(ansi reset)"
    cargo update -p tui-checkbox
    print $"(ansi green)✓(ansi reset) Cargo.lock updated."

    # 5. cargo fmt
    print ""
    print $"(ansi cyan)── cargo fmt ───────────────────────────────────────────────(ansi reset)"
    cargo fmt
    print $"(ansi green)✓(ansi reset) cargo fmt completed."

    # 6. cargo clippy
    print ""
    print $"(ansi cyan)── cargo clippy ────────────────────────────────────────────(ansi reset)"
    cargo clippy -- -D warnings
    print $"(ansi green)✓(ansi reset) cargo clippy passed."

    # 7. cargo test
    print ""
    print $"(ansi cyan)── cargo test ──────────────────────────────────────────────(ansi reset)"
    cargo test --all-features --all-targets
    print $"(ansi green)✓(ansi reset) cargo test passed."

    # 7b. Nushell script tests
    print ""
    print $"(ansi cyan)── nu tests ────────────────────────────────────────(ansi reset)"
    nu scripts/tests/run_all.nu
    print $"(ansi green)✓(ansi reset) Nushell tests passed."

    # 7c. Packaging dry-run — validates the exact tree we are about to tag.
    #     The tree is intentionally dirty here (Cargo.toml/lock just changed),
    #     so --allow-dirty is required for the dry-run.
    print ""
    print $"(ansi cyan)── cargo publish --dry-run ────────────────────────(ansi reset)"
    cargo publish --dry-run --allow-dirty
    print $"(ansi green)✓(ansi reset) Packaging dry-run passed."

    # 8. Changelog (git-cliff)
    print ""
    print $"(ansi cyan)── changelog ───────────────────────────────────────────────(ansi reset)"
    if (which git-cliff | is-not-empty) {
        git-cliff --output CHANGELOG.md --tag $"v($new_version)"
        print $"(ansi green)✓(ansi reset) CHANGELOG.md updated via git-cliff."
    } else {
        print $"(ansi yellow)⚠(ansi reset) git-cliff not found — skipping changelog generation."
    }

    # 9. Git commit & tag
    print ""
    print $"(ansi cyan)── git commit & tag ────────────────────────────────────────(ansi reset)"
    git add -A
    git commit -m $"chore: bump version to ($new_version)"
    git tag -a $"v($new_version)" -m $"Release v($new_version)"
    print $"(ansi green)✓(ansi reset) Committed and tagged v($new_version)."

    print ""
    print $"(ansi green)══════════════════════════════════════════════════════════════(ansi reset)"
    print $"(ansi green)  tui-checkbox version bumped to ($new_version) 🚀(ansi reset)"
    print $"(ansi green)══════════════════════════════════════════════════════════════(ansi reset)"
    print ""
    print "  Next steps:"
    print $"    git push origin main --tags"
    print ""
}