| .idea | ||
| src | ||
| .gitignore | ||
| example.bash | ||
| LICENSE | ||
| README.md | ||
g.bash
A Bash framework.
Documentation (WIP)
Global Helpers
g::eval [...command]- Execute a command, but w/ in-framework loggingg::silence [...command]- Execute a command, squashing all outputg::now- Get a timestamp in ISO8061g::bc [...args]- Execute abcmath statementg::awk [...inputs]- Execute anawkprint command
Utilties (g::util)
isNumeric [value]- Checks if a given value is a number with optional decimal and positive/negativetrue- A successful exit code/return value (0)false- A failure exit code/return value (1)returnToEcho [...command]- Execute a command that returnstrue/falseand instead echo1on success,0otherwiseuuid- Generate a UUIDuuid::underscore- Generate a UUID (underscore-separated)escape [value]- Bash-escape a value for safe use inevalstringsrealpath [path]- A non-GNU real path resolvertrace [?message] [?skip = frames to exclude]- Generate a stack trace with an optional message
Strings (g::str)
quote [str]- Surround a string in quoteseval [...args]- Execute a command and quote the outputlength [str]- Get the number of chars in a stringpadLeft [str] [length] [pad character=' ']- Left-pad a string to the given lengthpadRight [str] [length] [pad character=' ']- Right-pad a string to the given lengthpadCenter [str] [length] [pad character=' ']- Center-pad a string to the given lengthsubstring [str] [startAt] [length]- Get a substringoffset [str] [startAt]- Drop the firstncharacters of a stringreverse [str]- Reverse a stringstartsWith [haystack] [needle]- Check if the haystack starts with the needleendsWith [haystack] [needle]- Check if the haystack ends with the needletrim [str]- Trim the whitespace from either end of the stringindexOf [str] [substring]- Print the character index where thesubstringappears, if any (returnsg::util::falseif no match)replace [str] [find] [replace]- Find-and-replace all occurrences in a stringreplace::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 arrayassoc::hasKey [key] [array]- Checks if an associative array has a given keyjoin [delimiter] [array]- Implodes a list of values to a string using the given delimiter
Math (g::math)
- Constants (
g::math::c)e- Euler's constantln2- Natural log of 2ln10- Natural log of 10pi- Pisqrt05- Square root of 1/2sqrt2- Square root of 2
abs [num]- Absolute value of a numbercubeRoot [num]- Cube root of a numbersquareRoot [num]- Square root of a numberlessThan [left] [right]- Check ifleft < rightgreaterThan [left] [right]- Check ifleft > rightequalTo [left] [right]- Check ifleft == right, numericallyisPositive [num]- Check ifnum > 0isNegative [num]- Check ifnum < 0signOf [num]- Prints the leading sign of a number (either+or-)mod [num] [modulus]- Compute the modulus of a numberceiling [num]- Round the number up to the nearest inttruncate [num]- Truncate the number to an intfloor [num]- Round the number down to the nearest intexponent [num] [power]- Computenum^powercos [num]- Cosine of a numbersine [num]- Sine of a numbertan [num]- Tangent of a numberln [num]- Natural log of a numberlog10 [num]- Log base 10 of a numberlog2 [num]- Log base 2 of a numberlog [num] [base]- Arbitrary base logarithmrandom- Get a random floatmax [...nums]- Get the max value of some numbersmin [...nums]- Get the min value of some numbersround [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 fileexists [path]- Checks if a file existsdirectoryExists [path]- Checks if a directory existstouch [path]- Create a file if it does not existtruncate [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.bashand will only be loaded once)resolve [path] [?up=1]- Resolve the path of a source file relative to the current scriptexists [path] [?up=1]- Check if a source file exists relative to the current scriptforce [path] [?up=1]- Resolve and load a source file, bypassing the cachehas [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 filegetDefault- Get the default name of the config fileinit [?name]- Make sure a config file existsget [name] [?default value]- Get a value from the default config fileget::forFile [file] [name] [?default value]- Get a value from a non-default config fileset [name] [value]- Store a value in the default config fileset::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 slashesresolve [...parts]- Concat path parts and determine the real pathresolveFrom [base dir] [...parts]- Concat path parts and determine the real path relative to some base directorycd [...parts]- Resolve path parts and change directoriestmp- 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 targetenableAllTargets- Enable log outputs for ALL targetsall- Shorthand to enable the highest verbosity for ALL targetsgetLevel- Get the current logging levelsetLevel [name]- Set a new logging levelenable [target=stdout|stderr|file] [?param]- Enable logging to the specified targetdisable [target=stdout|stderr|file]- Disable logging to the specified targetg::error [output] [?target]- Write a log message at theerrorlevel, optionally for a specific target- Same format for
g::warn,g::info,g::debug,g::verbose, andg::internal
- Same format for
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, returningg::util::trueif successfulacquire [name]- Acquire a lock, sleeping until it is availableholds [name]- Check if we currently hold the given lockrelease [name]- Release the given lock if heldsingleton- Throw an error if this script is being executed concurrentlysingleton::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 applicationget [name] [?default value]- Get the value of an app-scoped variableset [name] [value]- Set the value of an app-scoped variablehas [name]- Check if the app-scope has a variable with the given nameusage- Print usage information for the current applicationinvoke [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 appexists [name]- Check if a given command exists in the current appdescription [name]- Get the description for a command in the current apparg [name] [?description] [?default value]- Add a positional argument to the current commandflag [name] [?description]- Add a position-less flag option. Ifnametrails with a=, then a value is expectedrest [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 argumentg::arg::has [uuid] [name]- Checks if a positional argument was providedg::arg::rest [uuid]- Get all the unmatched CLI arguments/flagsg::flag [uuid] [name]- Get the value of a position-less flagg::flag::has [uuid] [name]- Checks if a position-less flag was specified