Builtins Reference
Logos built-in functions. Use try for error handling on functions marked (try).
Try Expressions v0.4
Functions marked (try) return {ok, value, error}. Use try to unwrap
and propagate errors:
Functions that return result tables:
- File I/O: fileRead, fileWrite, fileAppend, fileDelete, fileMkdir, fileReadDir, fileGlob, fileCopy, fileMove
- System: run, shell
- JSON: parseJson, toJson, prettyJson
- HTTP: httpGet, httpPost, httpPut, httpPatch, httpDelete
// Verbose error checking:
let res = fileRead("data.json")
if !res.ok { return res.error }
let data = res.value
// With try (v0.4+):
let data = try fileRead("data.json")Try + Pipe v0.4
// Modern error handling with try + pipe (v0.4)
// Errors propagate automatically through the chain
// Fetch and transform user data
fn getUserStats(id) {
return try httpGet("https://api.example.com/users/" + str(id))
|> try parseJson
|> map(fn(u) -> table{
name: u.name,
email: u.email,
score: u.score,
})
}
// Safe file processing pipeline
fn processFile(path) {
return try fileRead(path)
|> try parseJson
|> filter(fn(d) -> d.active)
|> map(fn(d) -> d.name)
}
// Chained JSON operations
let config = try fileRead("config.json")
|> try parseJson
|> filter(fn(c) -> c.enabled)
|> map(fn(c) -> c.settings)I/O
print(args...) Prints all args with trailing newline (v0.4.5)printn(args...) Prints without trailing newline (v0.4.5)input(prompt?) Reads line from stdin, optional promptprompt(msg) Shows message, waits for inputconfirm(msg) Shows (y/n), returns boolselect(msg, opts) Numbered menu, returns choiceclear() Clears terminal screen// print() - outputs with trailing newline (v0.4.5, default)
// printn() - outputs without trailing newline (v0.4.5)
print("Hello!")
printn("No newline")
print("Next line")
// input() - reads one line from user (no prompt)
let name = input()
print("You typed: " + name)
// prompt(message) - shows message AND reads input
let age = prompt("Enter your age: ")
print("You are " + age)
// confirm() - yes/no question, returns true/false
if confirm("Delete all files?") {
print("Deleted!")
}
// select() - numbered menu, returns chosen value
let choice = select("Pick a color:", ["red", "green", "blue"])
print("You chose: " + choice)
// clear() - clear the terminal
clear()confirm()
if confirm("Delete this file?") {
print("Deleting...")
try fileDelete("data.txt")
} else {
print("Cancelled")
}select()
let choice = select("Pick a color:", ["red", "green", "blue"])
if choice == "red" {
print(colorRed("You picked red"))
} else if choice == "green" {
print(colorGreen("You picked green"))
}Color Output
colorRed(s) Red textcolorGreen(s) Green textcolorYellow(s) Yellow textcolorBlue(s) Blue textcolorBold(s) Bold textprint(colorRed("Error"))
print(colorGreen("Success"))
print(colorBold(colorYellow("Warning")))Type Functions
type(value) Returns type name stringlen(value) Length of string/array/tableFile Operations try
fileRead(path) Read file (try)fileWrite(path, data) Write file (try)fileAppend(path, data) Append to file (try)fileExists(path) Check if exists (bool)fileDelete(path) Delete file (try)fileMkdir(path) Create dir (try)fileReadDir(path) List dir (try)fileGlob(pattern) Glob files (try)fileCopy(src, dst) Copy file (try)fileMove(src, dst) Move file (try)// File functions return {ok, value, error}
// Use try to unwrap and propagate errors (v0.4+)
let content = try fileRead("config.json")
print("File has ${len(content)} characters")
let written = try fileWrite("output.txt", "Hello, World!")
print("Written: ${written}")
try fileAppend("log.txt", "New log entry\n")
if fileExists("data.json") {
let data = try fileRead("data.json")
print(data)
}
try fileMkdir("backup/2024/january")
let files = try fileReadDir(".")
for item in files {
print("Found: " + item)
}
let globRes = try fileGlob("*.lgs")
for script in globRes {
print("Script: " + script)
}String Operations
upper(s) Uppercaselower(s) Lowercasetrim(s) Remove whitespacereplace(s, old, new) Replace allsplit(s, sep) Split into arrayjoin(arr, sep) Join with separatorcontains(s, sub) Check substringindexOf(s, sub) Find index (-1 if none)startsWith(s, prefix) Check prefixendsWith(s, suffix) Check suffixrepeat(s, n) Repeat stringslice(s, start, end) Substringformat(tmpl, ...) Format with {}let s = " Hello, World! "
print(upper(s))
print(lower(s))
print(trim(s))
print(replace("banana", "a", "o"))
print(str(contains("hello", "ell")))
print(str(startsWith("hello", "he")))
print(str(endsWith("hello", "lo")))
let words = split("a,b,c,d", ",")
print(join(words, "-"))
print(repeat("ha", 3))
print(slice("hello", 1, 4))
print(format("Name: {}, Age: {}", "Bob", 25))Type Conversion
str(value) Convert to string (short alias)int(value) Convert to int (short alias)float(value) Convert to float (short alias)toStr(value) Convert to stringtoInt(value) Convert to inttoFloat(value) Convert to floattoBool(value) Convert to boollet n = int("42")
let f = float("3.14")
let s1 = str(42)
let s2 = str(3.14)
let b1 = toBool(true)
let b2 = toBool(false)
print(type(42))
print(type("hello"))
print(type([1,2,3]))Array Operations
push(arr, val) Add to endprepend(arr, val) Add to startpop(arr) Remove lastfirst(arr) First elementlast(arr) Last elementtail(arr) All except firstreverse(arr) Reverse ordersort(arr) Sort array (string or numeric)contains(arr, val) Check membershiprange(start, end, step?) 0 to end (exclusive). Use step=-1 for countdown.let nums = [1, 2, 3, 4, 5]
nums = push(nums, 6)
nums = prepend(nums, 0)
print(first(nums))
print(last(nums))
let popped = pop(nums)
print(str(popped))
let rest = tail(nums)
let reversed = reverse([1, 2, 3])
let sorted = sort([3, 1, 4, 1, 5])
print(str(contains([1, 2, 3], 2)))
// range() for numeric iteration (v0.4.2)
for i in range(0, 10) {
print(i)
}
// With step
for i in range(0, 20, 2) {
print(i) // 0, 2, 4, 6, ...
}
// Countdown
for i in range(5, 0, -1) {
print(i) // 5, 4, 3, 2
}Table Operations
keys(t) Array of keysvalues(t) Array of valueshas(t, key) Check if key existstableDelete(t, key) Remove keymerge(t1, t2) Merge tableslet user = table{
name: "Alice",
age: 30,
active: true,
}
print(user.name)
print(str(has(user, "email")))
let k = keys(user)
let v = values(user)
let updated = tableDelete(user, "age")
let extra = table{ role: "admin", age: 31 }
let merged = merge(user, extra)JSON try
parseJson(s) Parse JSON (try)toJson(value) To JSON string (try)prettyJson(t) Formatted JSON (try)// parseJson, toJson, prettyJson return {ok, value, error}
// Use try for clean error handling (v0.4+)
let data = try parseJson("{\"name\": \"Bob\", \"scores\": [95, 87, 92]}")
print(data["name"])
print(str(data["scores"][0]))
let obj = table{ "status": "ok", "count": 42 }
let jsonStr = try toJson(obj)
print(jsonStr)
let parsed = try parseJson("{\"user\": {\"name\": \"Alice\"}}")
print(try prettyJson(parsed))Math
mathAbs(n) Absolute valuemathPow(a, b) Power (a^b)mathSqrt(n) Square rootmathFloor(n) Round downmathCeil(n) Round upmathRound(n) Round nearestmathMin(a, b) MinimummathMax(a, b) MaximummathRandom() Random float 0-1mathRandomInt(a, b) Random int a-bmathPi() Pi constant print(str(mathAbs(-42)))
print(str(mathPow(2, 10)))
print(str(mathRandomInt(1, 6)))OS/System
pwd() Current directorycd(path) Change directoryenv(name) Get env varsetenv(n, v) Set env varargs() CLI args (user args at index 0). Not available in compiled binaries.sleep(ms) Wait millisecondsosname() "linux"/"darwin"exit(code?) Exit program (default code 1)run(cmd, ...) Run command (try)shell(cmd) Shell command (try)args() Important
Args are sliced to remove the binary path and script path. User arguments start at index 0:
// Running: lgs script.lgs --name "Alice" --verbose
let cliArgs = args()
print(len(cliArgs)) // 2 (not 4)
print(cliArgs[0]) // "--name"
print(cliArgs[1]) // "Alice"
// Binary and script paths are already removed
// Use with flags
if contains(cliArgs, "--verbose") {
print("Verbose mode enabled")
}run() try
// run() - executes a command directly (no shell)
// Use try for clean error handling (v0.4+)
let result = try run("ls", "-la")
print(result)
// With arguments
let gitResult = try run("git", "status")
print(gitResult)
let echoResult = try run("echo", "hello")
print(echoResult)shell() try
// shell() - executes command through shell (sh -c)
// Use try for clean error handling (v0.4+)
let dateResult = try shell("date")
print(dateResult)
// Shell features work!
let psResult = try shell("ps aux | grep node")
print(psResult)
// Variables
let pathResult = try shell("echo $HOME")
print(pathResult)
// Multiple commands
let multiResult = try shell("echo 'First' && echo 'Second'")
print(multiResult)Time
timeNow() Unix timestamp (sec)timeMs() Unix timestamp (ms)timeStr() "HH:MM:SS"dateStr() "YYYY-MM-DD"dateTimeStr() "YYYY-MM-DD HH:MM:SS"timeFormat(ts, fmt) Custom formatprint(str(timeNow()))
print(str(timeMs()))
print(timeStr())
print(dateStr())
print(dateTimeStr())
let ts = timeNow()
print(timeFormat(ts, "January 2, 2006"))
print(timeFormat(ts, "02/01/2006"))HTTP try + pipe
httpGet(url) GET request (try)httpGet(url, header) GET with headerhttpPost(url, body, header) POST requesthttpPut(url, body, header) PUT requesthttpPatch(url, body, header) PATCH requesthttpDelete(url, header) DELETE request// HTTP functions return {ok, value: {body, status}, error}
// body is a string, status is an integer HTTP status code
// All HTTP functions accept: (url, body?, headers?)
// body is optional for GET/DELETE; headers always optional
// GET - fetch data
let body = try httpGet("https://api.example.com/users")
print(body)
// GET with headers (authentication, custom headers)
let headers = table{
"Authorization": "Bearer " + env("API_TOKEN"),
"Content-Type": "application/json"
}
let data = try httpGet("https://api.example.com/private", headers)
// POST - create resource (url, body, headers?)
let payload = try toJson(table{ name: "Alice", email: "alice@example.com" })
let res = try httpPost("https://api.example.com/users", payload)
print("Created! Status: " + str(res.value.status))
// POST with all three args (url, body, headers)
let authHeaders = table{ "Authorization": "Bearer " + env("API_TOKEN") }
let createRes = try httpPost("https://api.example.com/users", payload, authHeaders)
// Tables are auto-serialized to JSON — no need for toJson() (v0.4.6)
let tablePayload = table{ name: "Alice", email: "alice@example.com" }
let autoRes = try httpPost("https://api.example.com/users", tablePayload)
// PUT - replace resource entirely (url, body, headers?)
let update = try toJson(table{ name: "Alice", id: 1 })
let putRes = try httpPut("https://api.example.com/users/1", update)
// PUT with headers
let putAuth = table{ "Authorization": "Bearer " + env("API_TOKEN") }
let putRes2 = try httpPut("https://api.example.com/users/1", update, putAuth)
// PATCH - partial update (url, body, headers?)
let patch = try toJson(table{ email: "newemail@example.com" })
let patchRes = try httpPatch("https://api.example.com/users/1", patch)
// DELETE - remove resource (url, headers?)
let delRes = try httpDelete("https://api.example.com/users/1")
print("Deleted! Status: " + str(delRes.value.status))
// DELETE with headers
let delAuth = table{ "Authorization": "Bearer " + env("API_TOKEN") }
let delRes2 = try httpDelete("https://api.example.com/users/1", delAuth)
// Handle non-2xx responses (status is included in response)
let res = httpGet("https://api.example.com/not-found")
if !res.ok {
print("Error: " + res.error)
} else if res.value.status >= 400 {
print("HTTP error: " + str(res.value.status))
} else {
print("Success: " + res.value.body)
}
// Pipes - fetch, parse, transform
let users = try httpGet("https://api.example.com/users")
|> try parseJson
|> filter(fn(u) -> u.active)
|> map(fn(u) -> u.name)Regex v0.4.3
reMatch(pattern, text) True if pattern matchesreFind(pattern, text) First match or nullreFindAll(pattern, text) Array of all matchesreReplace(pattern, text, repl) Replace all matchesreSplit(pattern, text) Split by patternreGroups(pattern, text) Capture groups array// reMatch - returns true/false if pattern matches
print(reMatch(`\d+`, "hello 123")) // true
print(reMatch(`\d+`, "hello world")) // false
// reFind - find first match, returns string or null
print(reFind(`\d+`, "there are 3 cats")) // "3"
print(reFind(`\d+`, "no numbers here")) // null
// reFindAll - find all matches, returns array
print(reFindAll(`\d+`, "3 cats and 12 dogs")) // ["3", "12"]
// reReplace - replace all matches
print(reReplace(`\d+`, "I have 3 cats", "X")) // "I have X cats"
// reSplit - split by pattern
print(reSplit(`\s+`, "split this string")) // ["split", "this", "string"]
// reGroups - extract capture groups
let email = "uthman@gmail.com"
let parts = reGroups(`(\w+)@(\w+)\.(\w+)`, email)
print(parts) // ["uthman", "gmail", "com"]