### Kestrel LSP Configuration Example
Source: https://kestrel-lang.com/docs/tooling/kestrel-lsp
Example configuration for the Kestrel LSP server, specifying settings for diagnostics and completion.
```toml
[diagnostics]
unused-binding = "warn" # off | warn | error
[completion]
include-stdlib = true
auto-import = true
```
--------------------------------
### Install Kestrel Toolchain
Source: https://kestrel-lang.com/docs/getting-started/installation
Installs Kestrel and Flock binaries into ~/.kestrel/bin. Ensure your PATH is updated.
```sh
curl -fsSL https://kestrel-lang.org/install.sh | sh
```
--------------------------------
### Install Kestrel Toolchain
Source: https://kestrel-lang.com
Installs Jessup, the Kestrel version manager, the latest stable toolchain, the VS Code extension, and the Claude Code / Codex plugin.
```shell
$ curl -fsSL https://kestrel-lang.com/install | sh
```
--------------------------------
### Implement 'Hello' Endpoint and Main Application Logic
Source: https://kestrel-lang.com/docs/guides/web-app/project-setup
Set up the main application logic, including defining a handler for the root route, initializing the database connection, and starting the Perch server.
```swift
module notes.main
import perch.app.(App)
import perch.request.(Request)
import perch.response.(Response)
import perch.middleware.(Logger)
import perch.json_body.(JsonBody)
import quill.value.(Value)
import talon.sqlite.shared_database.(SharedDatabase)
import datetime.(Instant)
import notes.context.(AppCtx)
func hello(req: Request, ctx: AppCtx) -> Response {
let now = Instant.now();
var obj = Dictionary[String, Value]();
obj.insert("status", Value.Str("ok"));
obj.insert("time", Value.Str("\(now)"));
Response.ok(JsonBody(fromRaw: Value.Obj(obj)))
}
@main
func main() {
let db = match SharedDatabase("notes.db") {
.Ok(d) => d,
.Err(e) => {
println("Failed to open database: " + e.description());
return
}
};
let ctx = AppCtx(db: db);
var app = App[AppCtx](ctx);
app.use(Logger[AppCtx]());
app.route(get: "/", hello);
let port: UInt16 = 8080;
println("Notes app listening on http://localhost:8080");
match app.listen(port) {
.Ok(_) => {},
.Err(e) => { println("Error: " + e.description()); }
}
}
```
--------------------------------
### Flock Project Structure
Source: https://kestrel-lang.com/docs/getting-started/flock
Example of a typical Kestrel project layout after initialization with `flock init`.
```text
my-project/
flock.toml — manifest
src/
main.ks
target/ — build output, gitignored
```
--------------------------------
### Main Function Example
Source: https://kestrel-lang.com/docs/organization
The main entry point of the program, creating a Player instance and calling its takeDamage method. This demonstrates how to import and use types from other modules.
```swift
// main.ks
module Main
import Game.Player.Player
@main
func main() -> lang.i64 {
var p = Player(name: "Morgana", hp: 100)
p.takeDamage(25)
0
}
```
--------------------------------
### Kestrel HTTP Server with Perch Framework
Source: https://kestrel-lang.com
An example of building a web server using Kestrel and the Perch framework. It demonstrates setting up routes, middleware, and handling requests.
```kestrel
import perch.app.(App)
import perch.request.(Request)
import perch.response.(Response)
import perch.middleware.(Logger)
import http.content.(Text, JsonBody)
struct Ctx: Cloneable {
func clone() -> Ctx {
Ctx()
}
}
var app = App(Ctx());
app.use(Logger());
app.route(get: "/hello/:name", { (req: Request, ctx: Ctx) in
let name = req.param("name") ?? "world";
Response.ok(Text("Hello, \(name)!"))
});
app.listen(8080);
```
--------------------------------
### Kestrel Application Setup and Routing
Source: https://kestrel-lang.com/docs/guides/web-app/api
Initializes the Kestrel application, sets up the database connection, applies middleware, and defines API routes for note management. Includes error handling for database initialization and connection.
```swift
module notes.main
import perch.app.(App)
import perch.request.(Request)
import perch.response.(Response)
import perch.middleware.(Logger)
import talon.sqlite.shared_database.(SharedDatabase)
import notes.context.(AppCtx)
import notes.db.(initSchema)
import notes.handlers.(
handleListNotes, handleCreateNote,
handleGetNote, handleUpdateNote, handleDeleteNote
)
@main
func main() {
match initSchema("notes.db") {
.Ok(_) => {},
.Err(e) => {
println("Failed to initialize database: " + e.description());
return
}
};
let db = match SharedDatabase("notes.db") {
.Ok(d) => d,
.Err(e) => {
println("Failed to open database: " + e.description());
return
}
};
let ctx = AppCtx(db: db);
var app = App[AppCtx](ctx);
app.use(Logger[AppCtx]());
app.route(get: "/notes", handleListNotes);
app.route(post: "/notes", handleCreateNote);
app.route(get: "/notes/:id", handleGetNote);
app.route(post: "/notes/:id", handleUpdateNote);
app.route(delete: "/notes/:id", handleDeleteNote);
let port: UInt16 = 8080;
println("Notes app listening on http://localhost:8080");
match app.listen(port) {
.Ok(_) => {},
.Err(e) => { println("Error: " + e.description()); }
}
}
```
--------------------------------
### Install Kestrel Skill
Source: https://kestrel-lang.com/docs/getting-started/kestrel-skill
Registers the Kestrel skill globally for use with Claude. This command should be run from your terminal.
```sh
claude --add-skill kestrel
```
--------------------------------
### Verify Kestrel Installation
Source: https://kestrel-lang.com/docs/getting-started/installation
Checks if Kestrel and Flock are installed and accessible by running their version commands. If not found, open a new terminal.
```sh
kestrel --version
flock --version
```
--------------------------------
### Common Dictionary Methods
Source: https://kestrel-lang.com/docs/collections/dictionaries
Provides examples of common dictionary methods for checking size, emptiness, key existence, and accessing keys and values.
```swift
scores.count
scores.isEmpty
scores.contains(key: "alice")
scores.keys // view over keys
scores.values // view over values
```
--------------------------------
### Adding a Dependency to Flock
Source: https://kestrel-lang.com/docs/getting-started/flock
Example of how to add a dependency to the `flock.toml` manifest file.
```toml
[dependencies]
serde = "0.4"
```
--------------------------------
### Configure Kestrel LSP in Neovim
Source: https://kestrel-lang.com/docs/getting-started/lsp-extension
Setup for the Kestrel language server in Neovim using nvim-lspconfig. Ensure the 'kestrel-lsp' command is in your PATH and a 'flock.toml' file exists in your project root.
```lua
require('lspconfig').kestrel.setup {
cmd = { "kestrel-lsp" },
filetypes = { "kestrel" },
root_dir = require('lspconfig.util').root_pattern("flock.toml"),
}
```
--------------------------------
### Create a Note using cURL
Source: https://kestrel-lang.com/docs/guides/web-app/api
Demonstrates how to create a new note using a cURL command. This example shows the HTTP POST request with JSON payload for creating a note.
```bash
# Create a note
curl -X POST http://localhost:8080/notes \
-H "Content-Type: application/json" \
-d '{"title":"My first note","body":"Hello from Kestrel!"}'
```
--------------------------------
### Protocol Refinement Example
Source: https://kestrel-lang.com/docs/protocols/inheritance-rules
Demonstrates a protocol 'Comparable' refining another protocol 'Equatable'. A type conforming to 'Comparable' must satisfy requirements of both.
```swift
protocol Equatable {
func isEqual(to other: Self) -> Bool
}
protocol Comparable: Equatable {
func compare(other: Self) -> Ordering
}
```
--------------------------------
### Kestrel Iterator Chain Examples
Source: https://kestrel-lang.com/docs/collections
Illustrates using the iterator chain for common collection operations like filtering and folding (reducing).
```kestrel
let evens = xs.filter { it % 2 == 0 }
let sum = xs.iter().fold(from: 0) { (acc, n) in acc + n }
```
--------------------------------
### Method with Generics and Constraints
Source: https://kestrel-lang.com/docs/functions/methods
Methods can utilize generics and constraints, similar to regular functions. This example shows a `dot` method with a generic type `T` constrained by `VectorLike`.
```kestrel
extend Vector {
func dot[T](with other: T) -> Float64 where T: VectorLike {
// ...
}
}
v1.dot(with: v2)
```
--------------------------------
### Note JSON Response Structure
Source: https://kestrel-lang.com/docs/guides/web-app/api
Example of a JSON response for a single note, including the `created_at` field with an RFC 3339 timestamp.
```json
{"id":1,"title":"My first note","body":"Hello from Kestrel!","created_at":"2026-05-27T15:30:05Z"}
```
--------------------------------
### Example Diagnostic Message
Source: https://kestrel-lang.com/docs/reference/diagnostics
Illustrates the format of a typical Kestrel compiler error message, showing the code, severity, location, and suggested fix.
```text
error[E203]: cannot infer type of empty array
--> src/main.ks:14:13
|
14 | let xs = []
| ^^
|
= help: write `let xs: [Int] = []`, or use `[Int]()`
```
--------------------------------
### Modify Kestrel Program Message
Source: https://kestrel-lang.com/docs/getting-started/hello-world
Example of how to change the output message and define a simple function in Kestrel. Incremental compilation allows for quick iteration.
```kestrel
print("Hello, \(name())!")
func name() -> String {
"Kestrel"
}
```
--------------------------------
### Player Struct and Extension
Source: https://kestrel-lang.com/docs/organization
Defines a public Player struct with name and hp, and an extension to add a takeDamage method. This snippet is part of a larger example demonstrating module organization.
```swift
// game/player.ks
module Game.Player
import std.io.stdio.println
public struct Player {
public let name: String
public var hp: Int
}
public extend Player {
public mutating func takeDamage(amount: Int) {
self.hp = self.hp - amount
println("\(self.name) takes \(amount) damage")
}
}
```
--------------------------------
### Initialize Flock Project and Navigate
Source: https://kestrel-lang.com/docs/guides/web-app/project-setup
Use flock init to create a new project and cd to enter the project directory.
```bash
flock init notes-app
cd notes-app
```
--------------------------------
### Define a Protocol with a Required Read-Only Property
Source: https://kestrel-lang.com/docs/protocols/defining
Protocols can require properties. `{ get }` declares a read-only requirement. `{ get set }` requires it to be writable.
```swift
protocol Named {
var name: String { get }
}
```
--------------------------------
### Create Kestrel Project
Source: https://kestrel-lang.com/docs/getting-started/hello-world
Use these commands to create a new Kestrel project directory and initialize its manifest file.
```shell
mkdir hello && cd hello
flock init
```
--------------------------------
### Uninstall Kestrel Toolchain
Source: https://kestrel-lang.com/docs/getting-started/installation
Removes all installed Kestrel components. Your projects remain unaffected.
```sh
kestrel uninstall
```
--------------------------------
### Get a single note
Source: https://kestrel-lang.com/docs/guides/web-app/api
Retrieve a specific note by its ID using this curl command.
```bash
curl http://localhost:8080/notes/1
```
--------------------------------
### Initialize Database Schema for Users and Notes
Source: https://kestrel-lang.com/docs/guides/web-app/auth
Sets up the necessary tables (users, tokens, notes) in the SQLite database for authentication and note management. Ensure the database file is deleted if it exists from previous steps to apply the fresh schema.
```swift
public func initSchema(path: String) -> () throws SqliteError {
let db = try Database(path);
try db.execute("""
CREATE TABLE IF NOT EXISTS users (
id INTEGER PRIMARY KEY AUTOINCREMENT,
email TEXT NOT NULL UNIQUE,
salt TEXT NOT NULL,
password_hash TEXT NOT NULL
)
""");
try db.execute("""
CREATE TABLE IF NOT EXISTS tokens (
id INTEGER PRIMARY KEY AUTOINCREMENT,
user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
token TEXT NOT NULL UNIQUE
)
""");
try db.execute("""
CREATE TABLE IF NOT EXISTS notes (
id INTEGER PRIMARY KEY AUTOINCREMENT,
title TEXT NOT NULL,
body TEXT NOT NULL,
created_at INTEGER NOT NULL DEFAULT (strftime('%s', 'now')),
user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE
)
""");
.Ok(())
}
```
--------------------------------
### Kestrel Hello World Program
Source: https://kestrel-lang.com/docs/getting-started/hello-world
The basic 'Hello, World!' program in Kestrel. This is the entry point for a Kestrel application.
```kestrel
module Main
@main
func main() {
println("Hello, world!")
}
```
--------------------------------
### Creating Arrays
Source: https://kestrel-lang.com/docs/collections/arrays
Demonstrates different ways to initialize arrays, including literal syntax, empty arrays with type annotation, and repeating a value.
```swift
let xs: [Int] = [1, 2, 3]
let empty: [String] = []
let zeroes: [Int] = Array(repeating: 0, count: 10)
```
--------------------------------
### Creating Dictionaries
Source: https://kestrel-lang.com/docs/collections/dictionaries
Demonstrates how to create dictionaries using literal syntax. Use [:] for an empty dictionary.
```swift
let ages: Dictionary[String, Int] = ["alice": 30, "bob": 27]
let empty: Dictionary[String, Int] = [:]
```
--------------------------------
### Verify API Endpoint with curl
Source: https://kestrel-lang.com/docs/guides/web-app/project-setup
Use curl to send an HTTP GET request to the root endpoint and check the JSON response.
```bash
curl http://localhost:8080/
```
--------------------------------
### Build a Simple HTML Card
Source: https://kestrel-lang.com/docs/guides/web-app/frontend
Demonstrates creating a basic HTML card with a heading and paragraph using the html-builder library. It shows how to combine elements and render the final HTML string.
```swift
import html.builder.(div, h1, p, text, cls)
let card = div([cls("card")]) {
h1 { text("Hello") } +
p { text("World") }
};
let html = card.render();
//
```
--------------------------------
### Access Dictionary and Handle Optional Values
Source: https://kestrel-lang.com/docs/tour/text-adventure
Demonstrates using a `Dictionary` to store rooms and safely accessing values using `Optional` and `if let` for unwrapping. Handles cases where a key might not exist.
```swift
import std.collections.Dictionary
func play(rooms: Dictionary[String, Room], start: String) {
var current = start;
let lookup = rooms(current);
if let .Some(room) = lookup {
room.describe();
} else {
println("You wandered off the map.");
}
}
```
--------------------------------
### Returning Multiple Values from a Function
Source: https://kestrel-lang.com/docs/collections/tuples
Provides an example of a Swift function that returns a tuple containing the minimum and maximum values from an array of integers.
```swift
func minMax(of xs: [Int]) -> (Int, Int) {
var lo = xs(0)
var hi = xs(0)
for n in xs {
if n < lo { lo = n }
if n > hi { hi = n }
}
(lo, hi)
}
let (low, high) = minMax(of: [3, 1, 4, 1, 5, 9, 2, 6])
```
--------------------------------
### Define a Protocol and Conform Types
Source: https://kestrel-lang.com/docs/tour/text-adventure
Defines a `Place` protocol with required methods and conforms existing `Room` and new `Shrine` structs to it. Enables abstracting over different types of locations.
```swift
protocol Place {
func name() -> String
func describe()
}
extend Room: Place {
public func name() -> String { self.name }
public func describe() { /* as before */ }
}
struct Shrine {
let deity: String
let blessing: String
}
extend Shrine: Place {
public func name() -> String { "Shrine of \(self.deity)" }
public func describe() {
println("A shrine to \(self.deity). It offers: \(self.blessing).");
}
}
```
--------------------------------
### Kestrel Function Definitions and Main Execution
Source: https://kestrel-lang.com
Demonstrates Kestrel's syntax for function definitions, optional types, pattern matching, and a basic loop for iteration. This version uses explicit protocol method calls.
```kestrel
func findUser(id: Int64) -> Optional[User] {
let user = match users.get(id).tryExtract() {
.Continue(v) => v,
.Break(r) => return fromResidual(r)
};
if user.age.compare(18) == .Less { return Optional.None };
user
}
func greet(id: Int64) -> String {
let user = findUser(id).coalesce(default: { User(name: "guest", age: 0) });
var s = DefaultStringInterpolation(literalCapacity: 7, interpolationCount: 1);
s.appendLiteral("Hello, ");
user.name.format(into: s);
s.appendLiteral("!");
String(interpolation: s)
}
@main
func main() {
var it = Array(arrayLiteral: LiteralSlice("Alice", "Bob", "Carol")).iter();
loop {
match it.next() {
.Some(name) => print(name),
.None => break
}
}
}
```
--------------------------------
### Constrain Extensions with a Where Clause
Source: https://kestrel-lang.com/docs/generics/where-clauses
Apply an extension to a type only when specific conformance constraints are met. This example adds a 'max()' method to 'Container' extensions where the 'Item' type is 'Comparable'.
```swift
extend Container where Item: Comparable {
public func max() -> Optional[Item] { /* ... */ }
}
```
--------------------------------
### Initialize SQLite Schema
Source: https://kestrel-lang.com/docs/guides/web-app/database
Opens a database connection and creates the 'notes' table if it doesn't exist. Handles potential SQLite errors during schema creation.
```swift
module notes.db
import talon.sqlite.database.(Database)
import talon.sqlite.error.(SqliteError)
public func initSchema(path: String) -> () throws SqliteError {
let db = try Database(path);
try db.execute("""
CREATE TABLE IF NOT EXISTS notes (
id INTEGER PRIMARY KEY AUTOINCREMENT,
title TEXT NOT NULL,
body TEXT NOT NULL,
created_at INTEGER NOT NULL DEFAULT (strftime('%s', 'now'))
)
""");
.Ok(())
}
```
--------------------------------
### Run Kestrel Project
Source: https://kestrel-lang.com/docs/getting-started/hello-world
Builds and runs the Kestrel project. The compiled binary is placed in the 'target/' directory.
```shell
flock run
```
--------------------------------
### Create an Application Shell with Navigation
Source: https://kestrel-lang.com/docs/guides/web-app/frontend
Builds a common application layout including a header with navigation, a brand link, and a 'New Note' button, along with a main content area. This function is designed to wrap the primary content of different pages.
```kestrel
public func appShell(content: () -> Document) -> Document {
page("Notes") {
header([cls("topbar")]) {
nav([cls("topbar-nav")]) {
anchor([href("/")]) { raw("Notes") } +
div([cls("topbar-actions")]) {
anchor([href("/new"), cls("btn btn-primary")]) { text("New Note") }
}
}
} +
mainEl([id("content")]) { content() }
}
}
```
--------------------------------
### Define a Protocol with a Required Method
Source: https://kestrel-lang.com/docs/protocols/defining
A protocol declaration lists the methods, properties, and associated types a conforming type must provide. This example shows a required `toString()` method.
```swift
protocol Printable {
func toString() -> String
}
```
--------------------------------
### Creating Tuples
Source: https://kestrel-lang.com/docs/collections/tuples
Demonstrates different ways to create tuples in Swift, including inferred types, explicitly typed tuples, and tuples with labeled elements.
```swift
let pair = (42, "answer")
let triple: (Int, Int, Int) = (1, 2, 3)
let labeled = (x: 3, y: 4)
```
--------------------------------
### Register New User
Source: https://kestrel-lang.com/docs/guides/web-app/auth
A curl command to register a new user with email and password.
```bash
# Register
curl -X POST http://localhost:8080/auth/register \
-H "Content-Type: application/json" \
-d '{"email":"alice@example.com","password":"secret123"}'
```
--------------------------------
### Define a basic function with parameters and return type
Source: https://kestrel-lang.com/docs/functions
Functions are declared using 'func', followed by the name, parameters, and return type. The last expression in the body is the return value.
```kestrel
func add(x: Int, y: Int) -> Int { x + y }
```
--------------------------------
### Update Note Detail Toolbar with HTMX
Source: https://kestrel-lang.com/docs/guides/web-app/htmx
This snippet shows how to update the Back, Edit, and Delete controls in a note detail view using HTMX attributes for GET, POST, and DELETE requests. It specifies the target element for content swapping and updates the browser URL.
```swift
div([cls("note-toolbar")]) {
button([cls("btn"),
hxGet("/fragments/notes"),
hxTarget("#content"),
hxSwap("innerHTML"),
hxPushUrl("/")]) { text("Back") } +
div([cls("toolbar-actions")]) {
button([cls("btn"),
hxGet("/fragments/note/" + noteId + "/edit"),
hxTarget("#content"),
hxSwap("innerHTML"),
hxPushUrl("/note/" + noteId + "/edit")]) { text("Edit") } +
button([cls("btn btn-danger"),
hxDelete("/fragments/note/" + noteId),
hxTarget("#content"),
hxSwap("innerHTML"),
hxPushUrl("/"),
hxConfirm("Delete this note?")]) { text("Delete") }
}
}
```
--------------------------------
### Call Schema Initialization in Main
Source: https://kestrel-lang.com/docs/guides/web-app/database
Initializes the SQLite database schema on application startup and handles any initialization errors. Uses a SharedDatabase for the main application connection.
```swift
@main
func main() {
match initSchema("notes.db") {
.Ok(_) => {},
.Err(e) => {
println("Failed to initialize database: " + e.description());
return
}
};
let db = match SharedDatabase("notes.db") {
// ... rest unchanged
};
}
```
--------------------------------
### User Registration Handler
Source: https://kestrel-lang.com/docs/guides/web-app/auth
Handles the registration of new users. It parses the request body, checks for existing email, hashes the password with a generated salt, creates the user in the database, and returns a success response.
```swift
module notes.handlers
import perch.request.(Request)
import perch.response.(Response)
import perch.json_body.(JsonBody)
import quill.value.(Value)
import notes.context.(AppCtx)
import notes.helpers.(errorJson, parseBody)
import notes.requests.(RegisterRequest, LoginRequest)
import notes.db.(findUserByEmail, findPasswordByEmail, createUser, createToken)
import notes.crypto.(hashPassword, generateSalt, generateToken)
public func handleRegister(req: Request, ctx: AppCtx) -> Response {
let body = match parseBody[RegisterRequest](req.body) {
.Ok(b) => b,
.Err(resp) => return resp
};
let db = ctx.db;
guard let .Ok(existingUser) = findUserByEmail(db, body.email) else {
return Response.internalServerError()
}
if let .Some(_) = existingUser {
return Response.conflict(JsonBody(fromRaw: errorJson("Email already registered")))
};
let salt = generateSalt();
let passwordHash = hashPassword(body.password, salt);
guard let .Ok(user) = createUser(db, body.email, salt, passwordHash) else {
return Response.internalServerError()
}
guard let .Ok(json) = JsonBody(user) else { return Response.internalServerError() }
Response.created(json)
}
```
--------------------------------
### Updating Note Card with HTMX Attributes
Source: https://kestrel-lang.com/docs/guides/web-app/htmx
This function updates the `noteCard` UI component to use HTMX attributes for fetching and displaying note details. It configures HTMX to perform a GET request to a fragment endpoint, swap the response into the '#content' element, and update the browser's URL.
```swift
func noteCard(note: Note) -> Document {
let preview = if note.body.byteCount > 140 {
note.body.asSlice().subslice(from: 0, to: 140).toOwned() + "..."
} else {
note.body
};
let noteId = note.id.formatted();
let dateStr = formatNoteDate(note.createdAt);
div([cls("note-card"),
hxGet("/fragments/note/" + noteId),
hxTarget("#content"),
hxSwap("innerHTML"),
hxPushUrl("/note/" + noteId)]) {
div([cls("note-card-title")]) { text(note.title) } +
div([cls("note-card-preview")]) { text(preview) } +
div([cls("note-card-date")]) { text(dateStr) }
}
}
```
--------------------------------
### Constructing Optional Values
Source: https://kestrel-lang.com/docs/error-handling/optional
Demonstrates explicit construction of Optional values and optional promotion during function returns.
```swift
let nothing: Optional[Int] = .None
let something: Optional[Int] = .Some(42)
func cached(key: String) -> Optional[String] {
"hit" // promoted to .Some("hit") at return
}
```
--------------------------------
### Define and Call a Simple Function
Source: https://kestrel-lang.com/docs/tour/text-adventure
Defines a function to describe a location and calls it. Demonstrates basic function definition and positional parameter usage.
```swift
module Main
import std.io.stdio.println
func describe(location: String) {
println("You stand in \(location).");
}
@main
func main() -> lang.i64 {
describe("a damp cave");
0
}
```
--------------------------------
### Import Database Schema Initialization
Source: https://kestrel-lang.com/docs/guides/web-app/database
Imports the initSchema function to be used in the main application logic.
```swift
import notes.db.(initSchema)
```
--------------------------------
### Configure Project Dependencies in flock.toml
Source: https://kestrel-lang.com/docs/guides/web-app/project-setup
Add necessary dependencies for a Perch web application, including Perch itself and other utilities like Quill and Talon-SQLite.
```toml
[package]
name = "notes-app"
version = "0.1.0"
[dependencies]
perch = { path = "../../lang/perch" }
talon-sqlite = { path = "../../lang/talon-sqlite" }
quill = { path = "../../lang/quill" }
quill-json = { path = "../../lang/quill-json" }
http = { path = "../../lang/http" }
html-builder = { path = "../../lang/html-builder" }
datetime = { path = "../../lang/datetime" }
crypto = { path = "../../lang/crypto" }
```
--------------------------------
### Kestrel Collection Iteration with `for`
Source: https://kestrel-lang.com/docs/collections
Shows how to iterate over Kestrel collections using the `for` loop for both arrays and dictionaries.
```kestrel
for x in xs { /* ... */ }
for (key, value) in ages { /* ... */ }
```
--------------------------------
### Create a Note with Authentication
Source: https://kestrel-lang.com/docs/guides/web-app/auth
A curl command to create a new note, including the authentication token and note content in the request.
```bash
# Create a note as Alice
curl -X POST http://localhost:8080/api/notes \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"title":"Private note","body":"Only Alice can see this."}'
```
--------------------------------
### Define a Struct and Extend Methods
Source: https://kestrel-lang.com/docs/tour/text-adventure
Defines a `Room` struct with properties and extends it to add a `describe` method. Shows `let` for immutable fields and `var` for mutable ones.
```swift
struct Room {
let name: String
let description: String
var exits: [String]
}
extend Room {
func describe() {
println("\(self.name): \(self.description)");
println("Exits: \(self.exits)");
}
}
```
--------------------------------
### Define Application Context Structure
Source: https://kestrel-lang.com/docs/guides/web-app/project-setup
Create an AppCtx struct to hold shared application state, such as a database connection. It must conform to Cloneable for Perch.
```swift
module notes.context
import talon.sqlite.shared_database.(SharedDatabase)
public struct AppCtx: Cloneable {
public var db: SharedDatabase
public func clone() -> AppCtx {
AppCtx(db: self.db.clone())
}
}
```
--------------------------------
### Kestrel Function Definitions with Syntactic Sugar
Source: https://kestrel-lang.com
Shows Kestrel's more concise syntax using syntactic sugar for optional types, null coalescing, string interpolation, and for-in loops.
```kestrel
func findUser(id: Int64) -> User? {
let user = try users.get(id);
if user.age < 18 { return null };
user
}
func greet(id: Int64) -> String {
let user = findUser(id) ?? User(name: "guest", age: 0);
"Hello, \(user.name)!"
}
@main
func main() {
for name in ["Alice", "Bob", "Carol"] {
print(name)
}
}
```
--------------------------------
### Kestrel Collection Literals
Source: https://kestrel-lang.com/docs/collections
Demonstrates the literal syntax for creating Kestrel's collection types: Array, Dictionary, Set, and Tuple.
```kestrel
let xs: [Int] = [1, 2, 3] // Array
let ages: Dictionary[String, Int] = ["alice": 30] // Dictionary
let tags: Set[String] = ["urgent", "pending"] // Set
let pair: (Int, String) = (42, "answer") // Tuple
```
--------------------------------
### User Login Handler
Source: https://kestrel-lang.com/docs/guides/web-app/auth
Handles user login by verifying credentials. It parses the request, finds the user's password hash, compares it with the provided password, and generates an authentication token upon successful verification.
```swift
module notes.handlers
import perch.request.(Request)
import perch.response.(Response)
import perch.json_body.(JsonBody)
import quill.value.(Value)
import notes.context.(AppCtx)
import notes.helpers.(errorJson, parseBody)
import notes.requests.(RegisterRequest, LoginRequest)
import notes.db.(findUserByEmail, findPasswordByEmail, createUser, createToken)
import notes.crypto.(hashPassword, generateSalt, generateToken)
public func handleLogin(req: Request, ctx: AppCtx) -> Response {
let body = match parseBody[LoginRequest](req.body) {
.Ok(b) => b,
.Err(resp) => return resp
};
let db = ctx.db;
guard let .Ok(some passwordRow) = findPasswordByEmail(db, body.email) else {
return Response.unauthorized()
}
let hash = hashPassword(body.password, passwordRow.salt);
guard hash == passwordRow.passwordHash else {
return Response.unauthorized()
}
let token = generateToken();
guard let .Ok(_) = createToken(db, passwordRow.id, token.clone()) else {
return Response.internalServerError()
}
var obj = Dictionary[String, Value]();
obj.insert("token", Value.Str(token));
Response.ok(JsonBody(fromRaw: Value.Obj(obj)))
}
```
--------------------------------
### Using the 'try' Operator
Source: https://kestrel-lang.com/docs/error-handling/result
Demonstrates how the 'try' operator simplifies handling Results by unwrapping success values or returning errors from the surrounding function.
```swift
func setup() -> Result[Server, LoadError] {
let config = try loadConfig(at: "/etc/app.toml")
let port = try parsePort(config.port)
.Ok(Server(config: config, port: port))
}
```
--------------------------------
### Flock Manifest Configuration
Source: https://kestrel-lang.com/docs/getting-started/flock
Basic `flock.toml` file defining package name and version.
```toml
[package]
name = "my-project"
version = "0.1.0"
[dependencies]
```
--------------------------------
### Add Methods to All Protocol Conformer
Source: https://kestrel-lang.com/docs/protocols/extending
This snippet demonstrates how to add new methods (`isZero`, `isPositive`) to all types conforming to the `Counter` protocol. These methods become available automatically without needing to be implemented in each conforming type.
```swift
protocol Counter {
var value: Int { get }
}
extend Counter {
public func isZero() -> Bool {
self.value == 0
}
public func isPositive() -> Bool {
self.value > 0
}
}
```
--------------------------------
### Alternative Empty Collection Initialization
Source: https://kestrel-lang.com/docs/concepts/type-inference
An alternative way to initialize an empty collection with a specified type using the type name followed by parentheses.
```swift
let x = [Int]() // also ok
```
--------------------------------
### Publishing a Library with Flock
Source: https://kestrel-lang.com/docs/tooling/flock
Command to publish a library to the Flock registry. Requires a complete [package] section in flock.toml and the FLOCK_ORG environment variable to be set.
```sh
flock publish
```
--------------------------------
### Basic Enum Matching
Source: https://kestrel-lang.com/docs/enums/pattern-matching
Use `match` to execute different expressions based on enum variants. The first matching arm runs.
```swift
match status {
.Active => "running",
.Paused => "halted",
.Stopped => "off"
}
```
--------------------------------
### Function Composition with Protocol Constraints
Source: https://kestrel-lang.com/docs/protocols/inheritance-rules
Illustrates composing protocol requirements directly in a function's 'where' clause, avoiding the need to define a new named protocol for combined capabilities.
```swift
func process[T](item: T) where T: Drawable, T: Hashable { /* ... */ }
```
--------------------------------
### Mapping and Unwrapping Optional
Source: https://kestrel-lang.com/docs/error-handling/optional
Demonstrates using map to apply a function within an Optional and unwrap with a default value.
```swift
let length = name.map { it.chars.count }
.unwrap(or: 0)
```
--------------------------------
### List all notes
Source: https://kestrel-lang.com/docs/guides/web-app/api
Use this curl command to retrieve a list of all notes from the API.
```bash
curl http://localhost:8080/notes
```
--------------------------------
### Typical flock.toml Manifest
Source: https://kestrel-lang.com/docs/tooling/flock
Defines package identity, metadata, and project dependencies. Ensure the [package] section includes name, version, description, author, and license. Dependencies are listed under [dependencies] with version constraints.
```toml
[package]
name = "my-app"
version = "0.1.0"
description = "A short description"
author = "you"
license = "MIT"
[dependencies]
kestrel/quill = { version = "0.2.1" }
```
--------------------------------
### Unwrapping Optional with match
Source: https://kestrel-lang.com/docs/error-handling/optional
Illustrates using match to handle both Some and None cases of an Optional as an expression.
```swift
let label = match settings.get("theme") {
.Some(value) => value,
.None => "default"
}
```
--------------------------------
### Configure Kestrel LSP in Helix
Source: https://kestrel-lang.com/docs/getting-started/lsp-extension
Configuration for the Kestrel language server in Helix. This requires the 'kestrel-lsp' command to be available and a 'flock.toml' file to define the project root.
```toml
[[language]]
name = "kestrel"
file-types = ["ks"]
language-server = { command = "kestrel-lsp" }
roots = ["flock.toml"]
```
--------------------------------
### Define an Instance Method
Source: https://kestrel-lang.com/docs/functions/methods
Define an instance method within an `extend` block. The method operates on the instance implicitly referred to by `self`.
```kestrel
struct Circle {
let radius: Float64
}
extend Circle {
func area() -> Float64 {
3.14159 * self.radius * self.radius
}
}
let c = Circle(radius: 2.0)
let a = c.area()
```
--------------------------------
### Optional Promotion at Return Position
Source: https://kestrel-lang.com/docs/error-handling
A plain value is automatically promoted to `Optional.Some(value)` when returned from a function expecting `Optional[T]`. This enhances readability by reducing explicit wrapping.
```kestrel
func cached(key: String) -> Optional[String] {
"hello" // promoted to .Some("hello") — no need to write it explicitly
}
```
--------------------------------
### Define a Basic Struct
Source: https://kestrel-lang.com/docs/structs
Defines a simple struct 'Point' with two integer fields, 'x' and 'y'. A memberwise initializer is automatically synthesized.
```kestrel
struct Point { let x: Int let y: Int }
let origin = Point(x: 0, y: 0)
let p = Point(x: 3, y: 4)
println("(\(p.x), \(p.y))")
```
--------------------------------
### Import Statements for Routing and Middleware
Source: https://kestrel-lang.com/docs/guides/web-app/auth
Imports necessary modules for building route groups, authentication middleware, and handlers.
```swift
import perch.router.(GroupBuilder)
import notes.middleware.(AuthMiddleware)
import notes.handlers.(handleRegister, handleLogin)
```
--------------------------------
### Module Declaration
Source: https://kestrel-lang.com/docs/organization
Every Kestrel file begins with a module declaration to define its namespace.
```swift
module Game.Player
// ...declarations live here
```
--------------------------------
### Combining Multiple Protocols
Source: https://kestrel-lang.com/docs/protocols/inheritance-rules
Shows how a protocol 'Sortable' can inherit from multiple parent protocols like 'Comparable' and 'Hashable'.
```swift
protocol Sortable: Comparable, Hashable {
// Sortable's own requirements, if any
}
```
--------------------------------
### Mapping and Chaining Results
Source: https://kestrel-lang.com/docs/error-handling/result
Shows how to use 'map' to transform the success value and 'mapErr' to transform the error value within a Result chain.
```swift
let port: Result[Int, LoadError] =
loadConfig(at: "/etc/app.toml")
.map { it.port }
.mapErr { .Corrupt(reason: "\(it)") }
```
--------------------------------
### Basic Array Indexing
Source: https://kestrel-lang.com/docs/collections/arrays
Shows how to access elements by index and modify them if the array is mutable. Note that default subscripting panics on out-of-bounds access.
```swift
let first = xs(0) // 1
xs(0) = 99 // requires xs to be `var`
```
--------------------------------
### List Notes for Authenticated User
Source: https://kestrel-lang.com/docs/guides/web-app/auth
A curl command to list notes, verifying that only the authenticated user's notes are returned.
```bash
# List notes — only Alice's notes appear
curl -H "Authorization: Bearer $TOKEN" http://localhost:8080/api/notes
```
--------------------------------
### Define a function with labeled parameters
Source: https://kestrel-lang.com/docs/functions
Labeled parameters use a label at the call site, followed by the bind name inside the function body. This improves call-site readability.
```kestrel
func send(to recipient: String, body content: String) { /* ... */ }
```
--------------------------------
### Create New Note
Source: https://kestrel-lang.com/docs/guides/web-app/database
Inserts a new note into the database with the provided title and body. The creation timestamp is automatically handled by SQLite. Returns the newly created note.
```swift
public func createNote(db: some SqliteExecutor, title: String, body: String) -> Note throws SqliteError {
try db.execute("""
INSERT INTO notes (title, body) VALUES (\(title), \(body))
""");
let rows = try db.query[Note]("""
SELECT id, title, body, created_at FROM notes WHERE rowid = last_insert_rowid()
""");
.Ok(rows(0))
}
```
--------------------------------
### Dictionary Lookup
Source: https://kestrel-lang.com/docs/collections/dictionaries
Shows how to look up values by key, which returns an Optional. Use if let to safely unwrap the value. The unwrap(or:) method provides a default value if the key is not found.
```swift
let alice = ages("alice") // .Some(30)
let mallory = ages("mallory") // .None
if let .Some(age) = ages("alice") {
println("alice is \(age)")
}
```
```swift
let bobAge = ages("bob").unwrap(or: 0)
```
--------------------------------
### User Database Queries
Source: https://kestrel-lang.com/docs/guides/web-app/auth
Defines functions for interacting with the user database, including finding users by email, retrieving password hashes, and creating new user records. These functions are essential for user authentication and management.
```Kestrel
module notes.db
import talon.sqlite.executor.(SqliteExecutor)
import talon.sqlite.error.(SqliteError)
import notes.models.(User, PasswordRow)
public func findUserByEmail(db: some SqliteExecutor, email: String) -> User? throws SqliteError {
let rows = try db.query[User]("""
SELECT id, email FROM users WHERE email = \(email)
""");
if rows.count > 0 { .Ok(.Some(rows(0))) } else { .Ok(.None) }
}
public func findPasswordByEmail(db: some SqliteExecutor, email: String) -> PasswordRow? throws SqliteError {
let rows = try db.query[PasswordRow]("""
SELECT id, salt, password_hash FROM users WHERE email = \(email)
""");
if rows.count > 0 { .Ok(.Some(rows(0))) } else { .Ok(.None) }
}
public func createUser(db: some SqliteExecutor, email: String, salt: String, passwordHash: String) -> User throws SqliteError {
try db.execute("""
INSERT INTO users (email, salt, password_hash)
VALUES (\(email), \(salt), \(passwordHash))
""");
let rows = try db.query[User]("""
SELECT id, email FROM users WHERE rowid = last_insert_rowid()
""");
.Ok(rows(0))
}
```
--------------------------------
### Define a Static Method
Source: https://kestrel-lang.com/docs/functions/methods
Define a `static` method for operations that do not require an instance, such as factory functions or utility methods. Call static methods on the type itself.
```kestrel
extend Point {
static func origin() -> Point {
Point(x: 0, y: 0)
}
}
let p = Point.origin()
```