- Add `show-arguments` recipe documenting all version update commands - Add `complete-update-interactive` recipe for manual confirmations - Maintain `complete-update` as automatic mode (no prompts) - Update `update-help` to reference new recipes and modes - Document 7-step workflow and step-by-step differences Changes: - complete-update: Automatic mode (recommended for CI/CD) - complete-update-interactive: Interactive mode (with confirmations) - show-arguments: Complete documentation of all commands and modes - Both modes share same 7-step workflow with different behavior in Step 4
770 lines
20 KiB
Markdown
770 lines
20 KiB
Markdown
# Nushell Code Rules and Patterns for AI Agents
|
|
|
|
## Fundamental Rules for AI-Friendly Nushell Code
|
|
|
|
### Rule 1: One Command, One Purpose
|
|
Every command must do exactly one thing. AI agents struggle with multi-purpose functions.
|
|
|
|
```nushell
|
|
# ✅ GOOD - Single purpose
|
|
def extract-errors [log_file: path] -> table {
|
|
open $log_file | lines | parse "{time} [{level}] {msg}" | where level == "ERROR"
|
|
}
|
|
|
|
# ❌ BAD - Multiple purposes
|
|
def process-logs [log_file: path, --extract-errors, --count-warnings, --save-output] {
|
|
# Too many responsibilities
|
|
}
|
|
```
|
|
|
|
### Rule 2: Explicit Type Signatures Always
|
|
AI agents need clear contracts. Never omit types.
|
|
|
|
```nushell
|
|
# ✅ GOOD - Complete type information
|
|
def calculate-average [numbers: list<float>] -> float {
|
|
$numbers | math avg
|
|
}
|
|
|
|
# ❌ BAD - Missing type information
|
|
def calculate-average [numbers] {
|
|
$numbers | math avg
|
|
}
|
|
```
|
|
|
|
### Rule 3: Return Early, Fail Fast
|
|
Check preconditions immediately. Don't nest error handling.
|
|
|
|
```nushell
|
|
# ✅ GOOD - Early returns
|
|
def process-file [path: path] -> table {
|
|
if not ($path | path exists) {
|
|
error make {msg: $"File not found: ($path)"}
|
|
}
|
|
|
|
if (ls $path | get size.0) > 100mb {
|
|
error make {msg: "File too large"}
|
|
}
|
|
|
|
open $path | process-data
|
|
}
|
|
|
|
# ❌ BAD - Nested conditionals
|
|
def process-file [path: path] -> table {
|
|
if ($path | path exists) {
|
|
if (ls $path | get size.0) <= 100mb {
|
|
open $path | process-data
|
|
} else {
|
|
error make {msg: "File too large"}
|
|
}
|
|
} else {
|
|
error make {msg: "File not found"}
|
|
}
|
|
}
|
|
```
|
|
|
|
## Essential Patterns for AI Code Generation
|
|
|
|
### Pattern 1: Command Template Pattern
|
|
Use this structure for EVERY command:
|
|
|
|
```nushell
|
|
# [PURPOSE]: Single-line description of what this does
|
|
# [INPUT]: Expected input format
|
|
# [OUTPUT]: Output format
|
|
# [EXAMPLE]: command-name "arg1" --flag value
|
|
def command-name [
|
|
required_param: type # Description of parameter
|
|
optional_param?: type # Optional parameter
|
|
--flag: type = default # Flag with default value
|
|
] -> return_type {
|
|
# Step 1: Validate inputs
|
|
# validation code here
|
|
|
|
# Step 2: Process data
|
|
# processing code here
|
|
|
|
# Step 3: Return result
|
|
# return statement
|
|
}
|
|
```
|
|
|
|
### Pattern 2: Pipeline Stage Pattern
|
|
Each pipeline stage must be self-contained and testable:
|
|
|
|
```nushell
|
|
# ✅ GOOD - Clear pipeline stages
|
|
def analyze-data [input: path] -> table {
|
|
load-data $input
|
|
| validate-schema
|
|
| clean-missing-values
|
|
| calculate-statistics
|
|
| format-output
|
|
}
|
|
|
|
# Each stage is a separate function
|
|
def load-data [path: path] -> table { open $path }
|
|
def validate-schema [data: table] -> table { $data | where column1 != null }
|
|
def clean-missing-values [data: table] -> table { $data | fill-null 0 }
|
|
def calculate-statistics [data: table] -> table { $data | group-by category | aggregate }
|
|
def format-output [data: table] -> table { $data | select relevant_columns }
|
|
```
|
|
|
|
### Pattern 3: Error Context Pattern
|
|
Always provide context for errors that AI can use to fix issues:
|
|
|
|
in Nushell 0.108, try-catch with error parameter might not be supported when assigning to variables.
|
|
|
|
```nushell
|
|
# ✅ GOOD - Detailed error context
|
|
def parse-config [config_path: path] -> record {
|
|
try {
|
|
open $config_path | from json
|
|
} catch {|e|
|
|
error make {
|
|
msg: $"Failed to parse config"
|
|
label: {
|
|
text: $"Invalid JSON at ($config_path)"
|
|
span: (metadata $config_path).span
|
|
}
|
|
help: "Check JSON syntax with: open $config_path | from json"
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
### Pattern 4: Data Validation Pattern
|
|
Validate data structure at boundaries:
|
|
|
|
```nushell
|
|
# ✅ GOOD - Explicit validation
|
|
def process-user-data [data: table] -> table {
|
|
# Define expected schema
|
|
let required_columns = ["id", "name", "email", "age"]
|
|
let actual_columns = ($data | columns)
|
|
|
|
# Validate columns exist
|
|
for col in $required_columns {
|
|
if $col not-in $actual_columns {
|
|
error make {msg: $"Missing required column: ($col)"}
|
|
}
|
|
}
|
|
|
|
# Validate data types
|
|
$data | each {|row|
|
|
if ($row.age | describe) != "int" {
|
|
error make {msg: $"Invalid age type for id ($row.id)"}
|
|
}
|
|
$row
|
|
}
|
|
}
|
|
```
|
|
|
|
## Critical Rules for AI Tool Integration
|
|
|
|
### Rule 4: No Side Effects in Functions
|
|
Functions must be pure unless explicitly named as mutations:
|
|
|
|
```nushell
|
|
# ✅ GOOD - Pure function
|
|
def calculate-tax [amount: float, rate: float] -> float {
|
|
$amount * $rate
|
|
}
|
|
|
|
# ✅ GOOD - Mutation clearly indicated
|
|
def write-to-file! [data: any, path: path] -> nothing {
|
|
$data | save $path
|
|
null
|
|
}
|
|
|
|
# ❌ BAD - Hidden side effect
|
|
def calculate-tax [amount: float, rate: float] -> float {
|
|
let result = $amount * $rate
|
|
$result | save "tax_log.txt" --append # Hidden side effect!
|
|
$result
|
|
}
|
|
```
|
|
|
|
### Rule 5: Atomic Operations
|
|
Every operation must be atomic - it either completely succeeds or completely fails:
|
|
|
|
```nushell
|
|
# ✅ GOOD - Atomic operation
|
|
def update-json-file [path: path, updates: record] -> nothing {
|
|
# Read, modify, write as single operation
|
|
let original = try { open $path } catch { {} }
|
|
let updated = ($original | merge $updates)
|
|
|
|
try {
|
|
$updated | save $path
|
|
} catch {|e|
|
|
error make {
|
|
msg: $"Failed to update ($path)"
|
|
help: "Ensure file is writable and valid JSON"
|
|
}
|
|
}
|
|
null
|
|
}
|
|
```
|
|
|
|
### Rule 6: Explicit Dependencies
|
|
Never rely on global state or environment without declaring it:
|
|
|
|
```nushell
|
|
# ✅ GOOD - Explicit dependencies
|
|
def api-request [
|
|
endpoint: string
|
|
--api-key: string = "" # Will use env if not provided
|
|
--base-url: string = ""
|
|
] -> any {
|
|
let key = if $api_key == "" { $env.API_KEY } else { $api_key }
|
|
let url = if $base_url == "" { $env.BASE_URL } else { $base_url }
|
|
|
|
http get $"($url)/($endpoint)" --headers {Authorization: $"Bearer ($key)"}
|
|
}
|
|
|
|
# ❌ BAD - Hidden dependencies
|
|
def api-request [endpoint: string] -> any {
|
|
http get $"($env.BASE_URL)/($endpoint)" --headers {Authorization: $"Bearer ($env.API_KEY)"}
|
|
}
|
|
```
|
|
|
|
## Structured Data Patterns
|
|
|
|
### Pattern 5: Table Transformation Pattern
|
|
Always use Nushell's table operations instead of loops:
|
|
|
|
```nushell
|
|
# ✅ GOOD - Table operations
|
|
def transform-sales [sales: table] -> table {
|
|
$sales
|
|
| insert quarter {|row| ($row.date | date quarter)}
|
|
| insert profit {|row| $row.revenue - $row.cost}
|
|
| group-by quarter
|
|
| transpose quarter data
|
|
| insert total {|row| $row.data | get profit | math sum}
|
|
}
|
|
|
|
# ❌ BAD - Manual iteration
|
|
def transform-sales [sales: table] -> table {
|
|
let result = []
|
|
for row in $sales {
|
|
let quarter = ($row.date | date quarter)
|
|
let profit = $row.revenue - $row.cost
|
|
# Manual accumulation
|
|
}
|
|
$result
|
|
}
|
|
```
|
|
|
|
### Pattern 6: Schema Definition Pattern
|
|
Define data schemas explicitly for AI understanding:
|
|
|
|
```nushell
|
|
# Schema definitions at module level
|
|
const USER_SCHEMA = {
|
|
id: "int"
|
|
name: "string"
|
|
email: "string"
|
|
created_at: "datetime"
|
|
active: "bool"
|
|
}
|
|
|
|
const API_RESPONSE_SCHEMA = {
|
|
status: "int"
|
|
data: "table"
|
|
error: "string?" # ? indicates optional
|
|
}
|
|
|
|
# Use schemas in functions
|
|
def validate-user [user: record] -> bool {
|
|
# Check against schema
|
|
for key in ($USER_SCHEMA | columns) {
|
|
if $key not-in ($user | columns) {
|
|
return false
|
|
}
|
|
}
|
|
true
|
|
}
|
|
```
|
|
|
|
## AI-Specific Patterns
|
|
|
|
### Pattern 7: Self-Documenting Code Pattern
|
|
Include inline documentation that AI can parse:
|
|
|
|
```nushell
|
|
def complex-calculation [
|
|
data: table # @format: [{x: float, y: float, weight: float}]
|
|
] -> record { # @returns: {mean: float, std: float, correlation: float}
|
|
# @algorithm: Weighted Pearson correlation
|
|
# @performance: O(n) time, O(1) space
|
|
|
|
let weighted_mean_x = (
|
|
$data
|
|
| reduce -f 0 {|row acc| $acc + ($row.x * $row.weight)}
|
|
| $in / ($data | get weight | math sum)
|
|
)
|
|
|
|
# ... rest of calculation
|
|
|
|
# @output: Statistical measures
|
|
{
|
|
mean: $weighted_mean_x
|
|
std: $std_dev
|
|
correlation: $correlation
|
|
}
|
|
}
|
|
```
|
|
|
|
### Pattern 8: Testable Unit Pattern
|
|
Every function must include test examples:
|
|
|
|
```nushell
|
|
# Function with embedded test cases
|
|
def parse-version [version: string] -> record {
|
|
# @test: "1.2.3" -> {major: 1, minor: 2, patch: 3}
|
|
# @test: "2.0.0-beta" -> {major: 2, minor: 0, patch: 0}
|
|
|
|
$version
|
|
| parse "{major}.{minor}.{patch}"
|
|
| get 0
|
|
| update major {|x| $x.major | into int}
|
|
| update minor {|x| $x.minor | into int}
|
|
| update patch {|x| $x.patch | into int}
|
|
}
|
|
|
|
# Separate test function
|
|
def test-parse-version [] {
|
|
assert ((parse-version "1.2.3") == {major: 1, minor: 2, patch: 3})
|
|
assert ((parse-version "2.0.0") == {major: 2, minor: 0, patch: 0})
|
|
}
|
|
```
|
|
|
|
### Pattern 9: Incremental Computation Pattern
|
|
Break complex computations into verifiable steps:
|
|
|
|
```nushell
|
|
# ✅ GOOD - Each step is verifiable
|
|
def analyze-dataset [data: path] -> record {
|
|
# Load and get shape
|
|
let dataset = (open $data)
|
|
let shape = {rows: ($dataset | length), cols: ($dataset | columns | length)}
|
|
print $"Loaded: ($shape.rows) rows, ($shape.cols) columns"
|
|
|
|
# Check for missing values
|
|
let missing = (check-missing $dataset)
|
|
print $"Missing values: ($missing)"
|
|
|
|
# Calculate statistics
|
|
let stats = (calculate-stats $dataset)
|
|
print $"Statistics calculated"
|
|
|
|
# Generate report
|
|
{
|
|
shape: $shape
|
|
missing: $missing
|
|
statistics: $stats
|
|
generated_at: (date now)
|
|
}
|
|
}
|
|
```
|
|
|
|
## Module Organization Rules
|
|
|
|
### Rule 7: Single Responsibility Modules
|
|
Each module handles one domain:
|
|
|
|
```nushell
|
|
# file: data_validation.nu
|
|
module data_validation {
|
|
export def validate-email [email: string] -> bool { }
|
|
export def validate-phone [phone: string] -> bool { }
|
|
export def validate-date [date: string] -> bool { }
|
|
}
|
|
|
|
# file: data_transformation.nu
|
|
module data_transformation {
|
|
export def normalize-text [text: string] -> string { }
|
|
export def parse-csv [path: path] -> table { }
|
|
export def to-json [data: any] -> string { }
|
|
}
|
|
```
|
|
|
|
### Rule 8: Explicit Exports
|
|
Only export what's needed:
|
|
|
|
```nushell
|
|
module api_client {
|
|
# Public API
|
|
export def get [endpoint: string] -> any {
|
|
make-request "GET" $endpoint
|
|
}
|
|
|
|
export def post [endpoint: string, data: any] -> any {
|
|
make-request "POST" $endpoint $data
|
|
}
|
|
|
|
# Private helper - not exported
|
|
def make-request [method: string, endpoint: string, data?: any] -> any {
|
|
# Implementation
|
|
}
|
|
}
|
|
```
|
|
|
|
## Performance Rules for AI Tools
|
|
|
|
### Rule 9: Lazy Evaluation
|
|
Don't compute until necessary:
|
|
|
|
```nushell
|
|
# ✅ GOOD - Lazy evaluation
|
|
def process-conditionally [
|
|
data: table
|
|
--expensive-analysis: bool = false
|
|
] -> any {
|
|
# Quick return for common case
|
|
if not $expensive_analysis {
|
|
return ($data | first 10)
|
|
}
|
|
|
|
# Expensive computation only when needed
|
|
$data
|
|
| complex-analysis
|
|
| generate-report
|
|
}
|
|
```
|
|
|
|
### Rule 10: Stream Large Data
|
|
Never load entire large files into memory:
|
|
|
|
```nushell
|
|
# ✅ GOOD - Streaming
|
|
def process-large-file [path: path] -> nothing {
|
|
open --raw $path
|
|
| lines
|
|
| each {|line|
|
|
$line | parse-and-process
|
|
}
|
|
| save output.jsonl
|
|
null
|
|
}
|
|
|
|
# ❌ BAD - Loading everything
|
|
def process-large-file [path: path] -> table {
|
|
let all_data = (open $path) # Loads entire file
|
|
$all_data | process-all
|
|
}
|
|
```
|
|
|
|
## Error Handling Rules
|
|
|
|
### Rule 11: Never Swallow Errors
|
|
Always propagate or handle errors explicitly:
|
|
|
|
```nushell
|
|
# ✅ GOOD - Explicit error handling
|
|
def safe-divide [a: float, b: float] -> float {
|
|
if $b == 0 {
|
|
error make {msg: "Division by zero"}
|
|
}
|
|
$a / $b
|
|
}
|
|
|
|
# ❌ BAD - Silent failure
|
|
def safe-divide [a: float, b: float] -> float {
|
|
if $b == 0 { 0 } else { $a / $b } # Hiding error!
|
|
}
|
|
```
|
|
|
|
### Rule 12: Structured Error Returns
|
|
Use consistent error structures:
|
|
|
|
```nushell
|
|
# Define error type
|
|
const ERROR_SCHEMA = {
|
|
success: "bool"
|
|
error: "string?"
|
|
data: "any?"
|
|
timestamp: "datetime"
|
|
}
|
|
|
|
def api-call [url: string] -> record {
|
|
try {
|
|
let response = (http get $url)
|
|
{
|
|
success: true
|
|
error: null
|
|
data: $response
|
|
timestamp: (date now)
|
|
}
|
|
} catch {|e|
|
|
{
|
|
success: false
|
|
error: $e.msg
|
|
data: null
|
|
timestamp: (date now)
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
## Code Generation Rules for AI
|
|
|
|
### Rule 13: Predictable Naming
|
|
Use consistent, predictable names:
|
|
|
|
```nushell
|
|
# Naming conventions AI can predict:
|
|
# - get-* : Returns data without modification
|
|
# - set-* : Updates data
|
|
# - is-* : Returns boolean
|
|
# - has-* : Checks existence
|
|
# - find-* : Searches for items
|
|
# - create-* : Creates new items
|
|
# - delete-* : Removes items
|
|
# - update-* : Modifies existing items
|
|
# - validate-*: Checks validity
|
|
# - parse-* : Converts formats
|
|
# - format-* : Outputs in specific format
|
|
|
|
def get-user [id: int] -> record { }
|
|
def is-valid-email [email: string] -> bool { }
|
|
def find-duplicates [list: list] -> list { }
|
|
def create-backup [path: path] -> path { }
|
|
def parse-json [text: string] -> any { }
|
|
```
|
|
|
|
### Rule 14: Consistent Parameter Order
|
|
Always use this parameter order:
|
|
|
|
```nushell
|
|
# Order: required positional, optional positional, flags
|
|
def command [
|
|
required1: type # Required parameters first
|
|
required2: type
|
|
optional?: type # Optional parameters second
|
|
--flag1: type # Boolean flags
|
|
--flag2: type = value # Flags with defaults
|
|
] -> return_type { }
|
|
```
|
|
|
|
### Rule 15: Return Type Consistency
|
|
Use consistent return types for similar operations:
|
|
|
|
```nushell
|
|
# All getters return record or null
|
|
def get-config [] -> record? {
|
|
try { open config.json } catch { null }
|
|
}
|
|
|
|
# All validators return bool
|
|
def validate-data [data: any] -> bool {
|
|
# validation logic
|
|
true # or false
|
|
}
|
|
|
|
# All transformers return same type as input
|
|
def transform-table [input: table] -> table {
|
|
$input | modifications
|
|
}
|
|
```
|
|
|
|
### Rule 16: Function Signature Syntax with Pipeline Types (Nushell 0.107.1+)
|
|
**CRITICAL**: When using return type annotations, use the pipeline signature: `[params]: input_type -> return_type`
|
|
|
|
```nushell
|
|
# ✅ GOOD - Complete pipeline signature
|
|
def process-data [input: string]: nothing -> table {
|
|
$input | from json
|
|
}
|
|
|
|
def calculate-sum [numbers: list<int>]: nothing -> int {
|
|
$numbers | math sum
|
|
}
|
|
|
|
def check-status []: nothing -> bool {
|
|
true
|
|
}
|
|
|
|
# ❌ BAD - Missing arrow (syntax error - will not parse!)
|
|
def process-data [input: string]: table {
|
|
$input | from json
|
|
}
|
|
|
|
# ⚠️ ALTERNATIVE - Omit return type entirely if unsure
|
|
def process-data [input: string] {
|
|
$input | from json
|
|
}
|
|
```
|
|
|
|
**Note**: The syntax is `[parameters]: input_type -> return_type`. Both the colon AND arrow are required when specifying return types. This has been the syntax since Nushell 0.107.1.
|
|
|
|
### Rule 17: String Interpolation - Always Use Parentheses
|
|
**CRITICAL**: In string interpolations, ALWAYS use parentheses `($var)` or `($expr)` for ALL interpolations.
|
|
|
|
```nushell
|
|
# ✅ GOOD - Parentheses for variables
|
|
print $"Processing file ($filename) at ($timestamp)"
|
|
print $"Server ($hostname) running on port ($port)"
|
|
print $"User ($username) has ($count) items"
|
|
|
|
# ✅ GOOD - Parentheses for expressions and function calls
|
|
print $"Total: (1 + 2 + 3)"
|
|
print $"Date: (date now | format date '%Y-%m-%d')"
|
|
print $"Size: ($data | length) items"
|
|
|
|
# ❌ BAD - Square brackets DO NOT interpolate!
|
|
print $"Processing file [$filename] at [$timestamp]"
|
|
# Output: "Processing file [$filename] at [$timestamp]" (LITERAL!)
|
|
|
|
# ❌ BAD - Without parentheses
|
|
print $"Server $hostname on port $port"
|
|
# This will cause a parse error
|
|
```
|
|
|
|
**Why**:
|
|
- Parentheses `($var)` or `($expr)` are the ONLY way to interpolate in Nushell strings
|
|
- Square brackets `[...]` are treated as literal characters (no interpolation)
|
|
- Both variables and expressions use the same syntax: `($something)`
|
|
- Consistent syntax reduces errors and improves maintainability
|
|
|
|
**Rule of thumb**:
|
|
- Variable? Use `($var)`
|
|
- Expression? Use `($expr)`
|
|
- Function call? Use `($fn arg)`
|
|
- **NEVER** use square brackets for interpolation!
|
|
|
|
## Quick Reference Card for AI Agents
|
|
|
|
```nushell
|
|
# TEMPLATE: Copy-paste this for new commands (Nushell 0.107.1+)
|
|
# [PURPOSE]:
|
|
# [INPUT]:
|
|
# [OUTPUT]:
|
|
# [EXAMPLE]:
|
|
def command-name [
|
|
param: type # Description
|
|
]: nothing -> return_type {
|
|
# NOTE: Use `: nothing -> return_type` for pipeline signature
|
|
|
|
# Validate
|
|
if VALIDATION_FAILS {
|
|
error make {msg: $"Clear error message for ($param)"}
|
|
# NOTE: ALWAYS use ($var) for string interpolation
|
|
}
|
|
|
|
# Process
|
|
let result = $param | pipeline
|
|
|
|
# Return
|
|
$result
|
|
}
|
|
|
|
# COMMON PATTERNS
|
|
# Load file: open $path
|
|
# Save file: $data | save $path
|
|
# Parse JSON: open $path | from json
|
|
# Parse CSV: open $path | from csv
|
|
# Filter table: $table | where column == value
|
|
# Transform: $table | update column {|row| expression}
|
|
# Group: $table | group-by column
|
|
# Sort: $table | sort-by column
|
|
# Select columns: $table | select col1 col2
|
|
# Check existence: $path | path exists
|
|
# Get env: $env.VAR_NAME? | default "value"
|
|
```
|
|
|
|
## Summary Checklist for AI-Compatible Nushell
|
|
|
|
✅ **Every function has:**
|
|
- Explicit type signatures with pipeline syntax `[param: type]: input_type -> return_type {`
|
|
- Single responsibility
|
|
- Early validation
|
|
- Clear error messages with `($var)` for ALL string interpolations
|
|
- Test examples
|
|
|
|
✅ **Never use:**
|
|
- Global state without declaration
|
|
- Hidden side effects
|
|
- Nested conditionals (prefer early returns)
|
|
- Manual loops for table operations
|
|
- Generic error messages
|
|
- Try-catch with error parameter in variable assignments (use `do { } | complete`)
|
|
- Square brackets `[$var]` for string interpolation (they don't work!)
|
|
- Function signatures without both colon AND arrow when specifying return types
|
|
|
|
✅ **Always prefer:**
|
|
- Pipeline operations over loops
|
|
- Pure functions over stateful
|
|
- Explicit over implicit
|
|
- Composition over complexity
|
|
- Streaming over loading
|
|
- Parentheses `($var)` for ALL string interpolations (variables and expressions)
|
|
|
|
✅ **For AI tools specifically:**
|
|
- Use predictable naming patterns
|
|
- Include operation markers (! for mutations)
|
|
- Document schemas inline
|
|
- Provide test cases
|
|
- Return consistent types
|
|
- Follow Nushell 0.107.1+ syntax requirements (colon + arrow for return types)
|
|
|
|
Following these rules and patterns ensures that AI agents like Claude Code can effectively read, understand, generate, and modify your Nushell code with high accuracy and reliability.
|
|
|
|
1. Try-Catch Block Pattern (10 files)
|
|
|
|
- Issue: Nushell 0.108 has stricter parsing for try-catch blocks
|
|
- Solution: Replace try {...} catch {...} with complete-based error handling:
|
|
let result = (do { ... } | complete)
|
|
if $result.exit_code == 0 { $result.stdout } else { error_value }
|
|
- Files fixed:
|
|
- workspace/version.nu
|
|
- workspace/migration.nu (4 blocks)
|
|
- user/config.nu
|
|
- config/loader.nu
|
|
- oci/client.nu (8 blocks - OCI currently disabled)
|
|
|
|
2. Function Signature Syntax (2 instances)
|
|
|
|
- Issue: Missing input type in signatures
|
|
- Old: def foo [x: string] -> bool
|
|
- New: def foo [x: string]: nothing -> bool
|
|
- Files fixed: workspace/helpers.nu
|
|
|
|
3. Boolean Flag Syntax (1 instance)
|
|
|
|
- Issue: Type annotations not allowed on boolean flags
|
|
- Old: --flag: bool = true
|
|
- New: --flag = true
|
|
- Files fixed: main_provisioning/contexts.nu
|
|
|
|
4. Variable Type Initialization (1 instance)
|
|
|
|
- Issue: Can't assign record to null variable in 0.108
|
|
- Old: mut var = null; $var = {record}
|
|
- New: mut var = {success: false}; $var = {record}
|
|
|
|
|
|
#" Before (fails in Nushell 0.107.1)
|
|
try {
|
|
# operations
|
|
result
|
|
} catch { |err|
|
|
log-error $"Failed: ($err.msg)"
|
|
default_value
|
|
}
|
|
|
|
# After (works in Nushell 0.107.1)
|
|
let result = (do {
|
|
# operations
|
|
result
|
|
} | complete)
|
|
|
|
if $result.exit_code == 0 {
|
|
$result.stdout
|
|
} else {
|
|
log-error $"Failed: ($result.stderr)"
|
|
default_value
|
|
}
|