A Bash framework.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
Garrett Mills c5141fd19e
Start better documentation + fix bug in g::source
2 months ago
.idea Start documentation 3 years ago
src Start better documentation + fix bug in g::source 2 months ago
.gitignore Initial commit 3 years ago
LICENSE Initial commit 3 years ago
README.md Start better documentation + fix bug in g::source 2 months ago
example.bash Start documentation 3 years ago

README.md

g.bash

A Bash framework.

Documentation (WIP)

Global Helpers

  • g::eval [...command] - Execute a command, but w/ in-framework logging
  • g::silence [...command] - Execute a command, squashing all output
  • g::now - Get a timestamp in ISO8061
  • g::bc [...args] - Execute a bc math statement
  • g::awk [...inputs] - Execute an awk print command

Utilties (g::util)

  • isNumeric [value] - Checks if a given value is a number with optional decimal and positive/negative
  • true - A successful exit code/return value (0)
  • false - A failure exit code/return value (1)
  • returnToEcho [...command] - Execute a command that returns true/false and instead echo 1 on success, 0 otherwise
  • uuid - Generate a UUID
  • uuid::underscore - Generate a UUID (underscore-separated)
  • escape [value] - Bash-escape a value for safe use in eval strings
  • realpath [path] - A non-GNU real path resolver
  • trace [?message] [?skip = frames to exclude] - Generate a stack trace with an optional message

Strings (g::str)

  • quote [str] - Surround a string in quotes
  • eval [...args] - Execute a command and quote the output
  • length [str] - Get the number of chars in a string
  • padLeft [str] [length] [pad character=' '] - Left-pad a string to the given length
  • padRight [str] [length] [pad character=' '] - Right-pad a string to the given length
  • padCenter [str] [length] [pad character=' '] - Center-pad a string to the given length
  • substring [str] [startAt] [length] - Get a substring
  • offset [str] [startAt] - Drop the first n characters of a string
  • reverse [str] - Reverse a string
  • startsWith [haystack] [needle] - Check if the haystack starts with the needle
  • endsWith [haystack] [needle] - Check if the haystack ends with the needle
  • trim [str] - Trim the whitespace from either end of the string
  • indexOf [str] [substring] - Print the character index where the substring appears, if any (returns g::util::false if no match)
  • replace [str] [find] [replace] - Find-and-replace all occurrences in a string
  • replace::once [str] [find] [replace] - Find-and-replace the first occurrence in a string

Arrays (g::arr)

Note: When passing an array as an argument to a function, it should be passed as "${array[@]}"

  • includes [value] [array] - Checks if a given value exists in the array
  • assoc::hasKey [key] [array] - Checks if an associative array has a given key
  • join [delimiter] [array] - Implodes a list of values to a string using the given delimiter

Math (g::math)

  • Constants (g::math::c)
    • e - Euler's constant
    • ln2 - Natural log of 2
    • ln10 - Natural log of 10
    • pi - Pi
    • sqrt05 - Square root of 1/2
    • sqrt2 - Square root of 2
  • abs [num] - Absolute value of a number
  • cubeRoot [num] - Cube root of a number
  • squareRoot [num] - Square root of a number
  • lessThan [left] [right] - Check if left < right
  • greaterThan [left] [right] - Check if left > right
  • equalTo [left] [right] - Check if left == right, numerically
  • isPositive [num] - Check if num > 0
  • isNegative [num] - Check if num < 0
  • signOf [num] - Prints the leading sign of a number (either + or -)
  • mod [num] [modulus] - Compute the modulus of a number
  • ceiling [num] - Round the number up to the nearest int
  • truncate [num] - Truncate the number to an int
  • floor [num] - Round the number down to the nearest int
  • exponent [num] [power] - Compute num^power
  • cos [num] - Cosine of a number
  • sine [num] - Sine of a number
  • tan [num] - Tangent of a number
  • ln [num] - Natural log of a number
  • log10 [num] - Log base 10 of a number
  • log2 [num] - Log base 2 of a number
  • log [num] [base] - Arbitrary base logarithm
  • random - Get a random float
  • max [...nums] - Get the max value of some numbers
  • min [...nums] - Get the min value of some numbers
  • round [num] [precision] - Round a number to the specified number of decimal points

Files (g::file)

  • appendString [path] [string] - Append the string contents to the end of a file
  • exists [path] - Checks if a file exists
  • directoryExists [path] - Checks if a directory exists
  • touch [path] - Create a file if it does not exist
  • truncate [path] - If a file exists, empty its contents

Source Code (g::source)

g::source allows you to organize your scripts into multiple files, and perform filesystem-relative source imports. Similarly, it will prevent the same source file from being re-imported multiple times.

Example:

# index.bash
g::source src/setup
g::source src/logging

# src/setup.bash
g::source logging

# src/logging.bash
# This file is included once
  • g::source [path] [?up=1] - Load a source file relative to the current script (must end in .bash and will only be loaded once)
  • resolve [path] [?up=1] - Resolve the path of a source file relative to the current script
  • exists [path] [?up=1] - Check if a source file exists relative to the current script
  • force [path] [?up=1] - Resolve and load a source file, bypassing the cache
  • has [path] [?up=1] - Check if the given source file has been loaded

Configuration File (g::config)

Provides a simple key-value way of storing persistent configuration.

Example:

echo "Last run: $(g::config::get last-run Never)"
g::config::set 'last-run' "$(g::now)"
  • setDefault [name] - Set the default name of the config file
  • getDefault - Get the default name of the config file
  • init [?name] - Make sure a config file exists
  • get [name] [?default value] - Get a value from the default config file
  • get::forFile [file] [name] [?default value] - Get a value from a non-default config file
  • set [name] [value] - Store a value in the default config file
  • set::forFile [file] [name] [value] - Store a value in a non-default config file

Paths (g::path)

  • concat [path] [...parts] - Combine path segments into a path, accounting for leading and trailing slashes
  • resolve [...parts] - Concat path parts and determine the real path
  • resolveFrom [base dir] [...parts] - Concat path parts and determine the real path relative to some base directory
  • cd [...parts] - Resolve path parts and change directories
  • tmp - Get a temp file path (and mark it for cleanup)
  • tmpdir - Get a temp dir path (and mark it for cleanup)

Errors (g::error)

  • throw [message] - Throw an error
  • (global) try
  • (global) catch

Logging (g::log)

g::log provides level- and target-aware logging output. The internal level is used by g.bash itself.

Available levels: error | warn | info | debug | verbose | internal

  • enableTarget [name] - Enable log outputs for the given target
  • enableAllTargets - Enable log outputs for ALL targets
  • all - Shorthand to enable the highest verbosity for ALL targets
  • getLevel - Get the current logging level
  • setLevel [name] - Set a new logging level
  • enable [target=stdout|stderr|file] [?param] - Enable logging to the specified target
  • disable [target=stdout|stderr|file] - Disable logging to the specified target
  • g::error [output] [?target] - Write a log message at the error level, optionally for a specific target
    • Same format for g::warn, g::info, g::debug, g::verbose, and g::internal
  • g::log::rotate - Archive the log file to a timestamped version and start a new one

Locks (g::lock)

  • try [name] - Try to acquire a lock, returning g::util::true if successful
  • acquire [name] - Acquire a lock, sleeping until it is available
  • holds [name] - Check if we currently hold the given lock
  • release [name] - Release the given lock if held
  • singleton - Throw an error if this script is being executed concurrently
  • singleton::acquire - Wait for other instances of this script to finish

App Framework (g::app)

g::app is a way of defining multi-directive CLI applications with argument/option parsing.

Each application is broken up into "commands," and each command can have multiple arguments/flags.

Your source code can provide multiple applications (switching between them using g::app) with app-scoped storage.

  • g::app [?name=app] [?description] - Create a new top-level application
  • get [name] [?default value] - Get the value of an app-scoped variable
  • set [name] [value] - Set the value of an app-scoped variable
  • has [name] - Check if the app-scope has a variable with the given name
  • usage - Print usage information for the current application
  • invoke [command] [...args] - Invoke a command in the current application

Defining Commands (g::app::command)

A command is an invokable sub-command function for an application, which can have multiple flags and positional arguments associated with it.

When a command is executed, its arguments are parsed and a function app::<app name>::<command name> is called. Basic example:

g::app myapp "An example application"

g::app::command greet "Greeting command"
g::app::command::arg name "Name of the person to greet" "World"
g::app::command::flag greeting= "Override the greeting"

function app::myapp::greet() {
    local args="$1"
    name="$(g::arg "$args" name)"
    greeting="$(g::flag "$args" greeting)"
    if [ -z "$greeting" ]; then
        greeting="Hello,"
    fi

    echo "$greeting $name"
}
  • g::app::command [name] [?description] - Start defining a new command in the current app
  • exists [name] - Check if a given command exists in the current app
  • description [name] - Get the description for a command in the current app
  • arg [name] [?description] [?default value] - Add a positional argument to the current command
  • flag [name] [?description] - Add a position-less flag option. If name trails with a =, then a value is expected
  • rest [name] [?description] - Register a rest-argument ([...args]) for the current command

Accessing Arguments

When arguments for a command are parsed, they are stored in an "argument set." The argument set is a series of data structures containing the parsed/validated flags & positional arguments.

The argument set ID is passed to the command handler as the only parameter ($1) and can be used to look up the values of flags and arguments.

  • g::args [uuid] - Get the raw arguments from a parsed set (akin to $@)
  • g::arg [uuid] [name] - Get the value of a positional argument
  • g::arg::has [uuid] [name] - Checks if a positional argument was provided
  • g::arg::rest [uuid] - Get all the unmatched CLI arguments/flags
  • g::flag [uuid] [name] - Get the value of a position-less flag
  • g::flag::has [uuid] [name] - Checks if a position-less flag was specified