Skip to main content

Your First Script

This guide will walk you through creating and running your first Utah script.

Hello World

Let's start with the classic "Hello World" example.

Step 1: Create the Script

Create a new file called hello.shx:

console.log("Hello, Utah!");

Step 2: Compile the Script

Use the Utah CLI to compile your script:

utah compile hello.shx

This generates hello.sh with the following content:

#!/bin/bash
echo "Hello, Utah!"

Step 3: Run the Script

Execute the generated bash script:

./hello.sh

Output:

Hello, Utah!

Adding Variables

Let's enhance our script with variables and string interpolation:

Create variables.shx:

const appName: string = "Utah";
let userName: string = "Developer";
let version: number = 1.0;

console.log("Welcome to ${appName}!");
console.log("Hello, ${userName}");
console.log("Version: ${version}");

Compile and run:

utah compile variables.shx
./variables.sh

Generated bash code (variables.sh):

#!/bin/bash
readonly appName="Utah"
userName="Developer"
version="1.0"

echo "Welcome to ${appName}!"
echo "Hello, ${userName}"
echo "Version: ${version}"

Output:

Welcome to Utah!
Hello, Developer
Version: 1.0

Working with Functions

Utah supports function declarations with type annotations:

Create functions.shx:

function greet(name: string): void {
console.log("Hello, ${name}!");
}

function add(a: number, b: number): number {
return a + b;
}

// Call functions
greet("Utah User");

let result: number = add(5, 3);
console.log("5 + 3 = ${result}");

Generated bash code:

#!/bin/bash

greet() {
local name="$1"
echo "Hello, ${name}!"
}

add() {
local a="$1"
local b="$2"
echo $((a + b))
}

greet "Utah User"
result=$(add 5 3)
echo "5 + 3 = ${result}"

Control Flow Examples

Conditional Logic

Create conditionals.shx:

let score: number = 85;

if (score >= 90) {
console.log("Excellent!");
} else if (score >= 70) {
console.log("Good job!");
} else {
console.log("Keep trying!");
}

Loops

Create loops.shx:

// For loop
for (let i: number = 1; i <= 3; i++) {
console.log("Count: ${i}");
}

// Array iteration
let fruits: string[] = ["apple", "banana", "orange"];
for (let fruit: string in fruits) {
console.log("Fruit: ${fruit}");
}

Working with Arrays

Create arrays.shx:

let numbers: number[] = [1, 2, 3, 4, 5];
let names: string[] = ["Alice", "Bob", "Charlie"];

console.log("First number: ${numbers[0]}");
console.log("Array length: ${array.length(numbers)}");
console.log("Is empty: ${array.isEmpty(numbers)}");

// Check if array contains an item
if (array.contains(names, "Alice")) {
console.log("Alice is in the list");
}

Using Built-in Functions

Utah provides many built-in functions for common tasks:

Create builtin.shx:

// File system operations
if (fs.exists("README.md")) {
console.log("README.md exists");
}

// Check if command is installed
if (os.isInstalled("git")) {
console.log("Git is available");
} else {
console.log("Git is not installed");
}

// Get current OS
let currentOS: string = os.getOS();
console.log("Running on: ${currentOS}");

// Generate random number
let randomNum: number = utility.random(1, 10);
console.log("Random number: ${randomNum}");

Error Handling

Use try/catch blocks for robust error handling:

Create error-handling.shx:

try {
let content: string = fs.readFile("nonexistent.txt");
console.log(content);
}
catch {
console.log("Error: File not found");
}

console.log("Script continues...");

Working with JSON

Utah provides excellent JSON support:

Create json-example.shx:

// Ensure JSON dependencies are available
json.installDependencies();

let configJson: string = "{\"app\": {\"name\": \"MyApp\", \"port\": 8080}}";

if (json.isValid(configJson)) {
let config: object = json.parse(configJson);
let appName: string = json.get(config, ".app.name");
let port: number = json.get(config, ".app.port");

console.log("App: ${appName}");
console.log("Port: ${port}");
} else {
console.log("Invalid JSON");
}

Script Metadata and Arguments

Create scripts that accept command-line arguments:

Create cli-script.shx:

script.description("My first CLI script");

// Define arguments
args.define("--name", "-n", "Your name", "string", false, "World");
args.define("--count", "-c", "Number of greetings", "number", false, 1);
args.define("--verbose", "-v", "Enable verbose output");

// Handle help
if (args.has("--help")) {
args.showHelp();
exit(0);
}

// Get argument values
let name: string = args.get("--name");
let count: number = args.get("--count");
let verbose: boolean = args.has("--verbose");

if (verbose) {
console.log("Verbose mode enabled");
}

for (let i: number = 1; i <= count; i++) {
console.log("Hello, ${name}!");
}

Run with arguments:

utah compile cli-script.shx
./cli-script.sh --name "Utah User" --count 3 --verbose

Best Practices for Your First Scripts

1. Use Type Annotations

Always specify types for better code clarity:

// Good
let userName: string = "Alice";
let count: number = 42;

// Less clear
let userName = "Alice";
let count = 42;

2. Handle Errors Gracefully

Use try/catch for operations that might fail:

try {
let result: string = someRiskyOperation();
console.log(result);
}
catch {
console.log("Operation failed, but script continues");
}

3. Validate Dependencies

Check for required tools before using them:

if (!os.isInstalled("git")) {
console.log("This script requires git. Please install it first.");
exit(1);
}

4. Use Descriptive Variable Names

Make your code self-documenting:

// Good
let databaseConnectionString: string = "localhost:5432";
let maxRetryAttempts: number = 3;

// Less clear
let db: string = "localhost:5432";
let max: number = 3;

5. Add Script Descriptions

Document what your script does:

script.description("Automated backup script for project files");

Common Patterns

Configuration Loading

if (fs.exists("config.json")) {
let configContent: string = fs.readFile("config.json");
let config: object = json.parse(configContent);
// Use configuration
} else {
console.log("No configuration file found, using defaults");
}

Environment Detection

let environment: string = env.get("NODE_ENV", "development");
let isProduction: boolean = environment == "production";

if (isProduction) {
console.log("Running in production mode");
} else {
console.log("Running in development mode");
}

Backup Operations

timer.start();
// More complex operations...
let timestamp: string = timer.current();
let backupDir: string = "backup_${timestamp}";

if (!fs.exists(backupDir)) {
// Create backup directory
console.log("Creating backup directory: ${backupDir}");
}

Next Steps

Now that you've created your first Utah script, you can:

  1. Learn more syntax: Basic Syntax Guide
  2. Explore language features: Variables and Types
  3. Discover built-in functions: Function Reference
  4. Study advanced patterns: Best Practices Guide

Troubleshooting

Script Won't Compile

  1. Check for syntax errors:

    utah compile --verbose script.shx
  2. Verify file extension is .shx

  3. Ensure proper type annotations

Generated Script Won't Run

  1. Check file permissions:

    chmod +x script.sh
  2. Verify bash availability:

    which bash
  3. Check for missing dependencies:

    utah run script.shx  # This will show dependency errors

Getting Help