Libraries single page documentation
The source markdown file can be found here: lib-valet.md.
Documentation generated for the version 0.30.1455 (2025-08-18).
⚡ array::appendIfNotPresent
Add a value to an array if it is not already present. Works for normal and associative arrays.
Inputs:
$1
: array name as string:The variable name of the array.
$2
: value variable name as any:The variable name containing the value to add.
Returns:
${REPLY_CODE}
:- 0 if the value was added
- 1 if it was already present
Example usage:
declare myArray=( "a" "b" )
declare myValue="b"
array::appendIfNotPresent myArray myValue
printf '%s\n' "${myArray[@]}"
⚡ array::contains
Check if a value is in an array. It uses pure bash.
Inputs:
$1
: array name as string:The variable name of the array.
$2
: value variable name as any:The variable name containing the value to check.
Returns:
$?
: 0 if the value is in the array, 1 otherwise.
Example usage:
declare myArray=( "a" "b" )
declare myValue="b"
if array::contains myArray myValue; then "b is in the array"; fi
⚡ array::fuzzyFilterSort
Allows to fuzzy sort an array against a given searched string. Returns an array containing only the lines matching the searched string. The array is sorted by (in order):
- the index of the first matched character in the line
- the distance between the first and last matched characters in the line
- the original order in the list
Also returns an array containing the indexes of the matched items in the original array.
Inputs:
$1
: array name as string:The array name to fuzzy filter and sort.
$2
: search string as string:The variable name containing the search string to match.
Returns:
${REPLY_ARRAY[@]}
: An array containing the items sorted and filtered${REPLY_ARRAY2[@]}
: An array containing the indexes of the matched items in the original array
Example usage:
array::fuzzyFilterSort MY_ARRAY SEARCH_STRING
echo "${REPLY_ARRAY[*]}"
- All characters in the searched string must be found in the same order in the matched line.
- Use
shopt -s nocasematch
to make this function is case insensitive.- This function is not appropriate for large arrays (>10k elements), see
array::fuzzyFilterSortFileWithGrepAndGawk
for large arrays.
⚡ array::makeArraysSameSize
This function makes sure that all the arrays have the same size. It will add empty strings to the arrays that are too short.
Inputs:
$@
: array names as string:The variable names of each array to transform.
Example usage:
array::makeArraysSameSize "array1" "array2" "array3"
⚡ array::remove
Remove a value from an array. Works for normal and associative arrays.
Inputs:
$1
: array name as string:The variable name of the array.
$2
: value variable name as any:The variable name containing the value to remove.
Returns:
${REPLY_CODE}
:- 0 if the value was removed
- 1 if it was not present
Example usage:
declare myArray=( "a" "b" )
declare myValue="b"
array::remove myArray myValue
printf '%s\n' "${myArray[@]}"
⚡ array::sort
Sorts an array using the > bash operator (lexicographic order).
Inputs:
$1
: array name as string:The variable name of the array to sort (it will be sorted in place).
Example usage:
declare myArray=(z f b h a j)
array::sort myArray
echo "${myArray[*]}"
- This function uses a quicksort algorithm (hoarse partition).
- The sorting is not stable (the order of equal elements is not preserved).
- It is not appropriate for large array, use the
sort
binary for such cases.
⚡ array::sortWithCriteria
Sorts an array using multiple criteria. Excepts multiple arrays. The first array is the one to sort. The other arrays are used as criteria. Criteria are used in the order they are given. Each criteria array must have the same size as the array to sort. Each criteria array must containing integers representing the order of the elements. We first sort using the first criteria (from smallest to biggest), then the second, etc.
Inputs:
$1
: array name as string:The name of the array to sort (it will be sorted in place).
$@
: criteria array names as string:The names of the arrays to use as criteria. Each array must have the same size as the array to sort and contain only numbers.
Returns:
${REPLY_ARRAY[@]}
: An array that contains the corresponding indexes of the sorted array in the original array
Example usage:
declare myArray=( "a" "b" "c" )
declare criteria1=( 3 2 2 )
declare criteria2=( 1 3 2 )
array::sortWithCriteria myArray criteria1 criteria2
echo "${myArray[@]}"
# c b a
echo "${REPLY_ARRAY[@]}"
# 3 2 1
- This function uses a quicksort algorithm (hoarse partition).
- The sorting is not stable (the order of equal elements is not preserved).
- It is not appropriate for large array, use the
sort
binary for such cases.
⚡ bash::allVariablesCachedWithValue
Check if one or more variables are cached with the given value. If all the variables given already have the same value cached, the function will return true. Otherwise, it will return false and cache the given value in the variables.
Inputs:
$1
: variable name as string:the name of the variable to check
$2
: value as any:the value to check against the variable
$@
: variable/value pair as any:additional variable/value pairs to check
Returns:
$?
:- 0 if all the variables have the same value as the given value
- 1 otherwise
Example usage:
if bash::allVariablesCachedWithValue "MY_VAR" "my_value"; then
echo "MY_VAR is cached with the value 'my_value'"
else
echo "MY_VAR is not cached with the value 'my_value'"
fi
⚡ bash::catchErrors
This function runs a command and will catch any error that occurs instead of failing the program.
The execution will continue if an error occurs in the command, but each error will be stored for later processing.
For a function closer to a try/catch block, see bash::runInSubshell
.
Inputs:
$@
: command with args as string:The command to run.
Returns:
${GLOBAL_ERROR_TRAP_LAST_ERROR_CODE}
: the last error code encountered (or zero if none).${GLOBAL_ERROR_TRAP_ERROR_CODES}
: the list of error codes that occurred during the execution of the command.${GLOBAL_ERROR_TRAP_ERROR_STACKS}
: the list of error stacks that occurred during the execution of the command.
Example usage:
bash::catchErrors myFunction "arg1" "arg2"
if (( GLOBAL_ERROR_TRAP_LAST_ERROR_CODE != 0 )); then
core::fail "The command failed with code ${GLOBAL_ERROR_TRAP_LAST_ERROR_CODE}."
fi
While you can also put the execution of a command in an
if
(or in a pipeline) statement to effectively discard any errors happening in that command, the advantage of using this function is that the ERR trap is still triggered and you can use trace level debugging to see the caught issues. Additionally, it will report all the errors that occurred during the execution of the command.
⚡ bash::clearCachedVariables
Clear the cached variables used by bash::allVariablesCachedWithValue. This will unset all variables starting with TUI_CACHED.
Inputs:
$@
: variable names as any:(optional) the names of the variables to clear
(defaults to all cached variables)
Example usage:
bash::clearCachedVariables
bash::clearCachedVariables "MY_VAR" "ANOTHER_VAR"
⚡ bash::countArgs
Returns the number of arguments passed.
A convenient function that can be used to:
- count the files/directories in a directory:
bash::countArgs "${PWD}"/* && local numberOfFiles="${REPLY}"
- count the number of variables starting with VALET_
bash::countArgs "${!VALET_@}" && local numberOfVariables="${REPLY}"
Inputs:
Inputs:
$@
: arguments as any:the arguments to count
Returns:
${REPLY}
: The number of arguments passed.
Example usage:
bash::countArgs 1 2 3
⚡ bash::getBuiltinOutput
Capture the output of a builtin command. Can be used on bash builtins that produce output. It captures the stdout and stderr of said command.
This function is a lot more basic than exe::invoke
and does not support all its features.
Inputs:
$@
: command with arguments as string:The command to run.
Returns:
${REPLY_CODE}
:- 0 if the command was successful
- 1 otherwise.
${REPLY}
: The captured output.
Example usage:
bash::getBuiltinOutput declare -f bash::getBuiltinOutput
echo "${REPLY}"
⚡ bash::getMissingCommands
This function returns the list of not existing commands for the given names.
Inputs:
$@
: command names as string:the list of command names to check.
Returns:
$?
- 0 if there are not existing commands
- 1 otherwise.
${REPLY_ARRAY[@]}
: the list of not existing commands.
Example usage:
if bash::getMissingCommands "command1" "command2"; then
printf 'The following commands do not exist: %s' "${REPLY_ARRAY[*]}"
fi
⚡ bash::getMissingVariables
This function returns the list of undeclared variables for the given names.
Inputs:
$@
: variable names as string:the list of variable names to check.
Returns:
$?
- 0 if there are variable undeclared
- 1 otherwise.
${REPLY_ARRAY[@]}
: the list of undeclared variables.
Example usage:
if bash::getMissingVariables "var1" "var2"; then
printf 'The following variables are not declared: %s' "${REPLY_ARRAY[*]}"
fi
⚡ bash::injectCodeInFunction
This function injects code at the beginning or the end of a function and returns the modified function to be evaluated.
Creates an empty function if the function does not exist initially.
Inputs:
$1
: function name as string:The name of the function to inject the code into.
$2
: code as string:The code to inject.
${injectAtBeginning}
as bool:(optional) Whether to inject the code at the beginning of the function (or at the end).
(defaults to false)
Returns:
${REPLY}
: the modified function.${REPLY2}
: the original function.
Example usage:
bash::injectCodeInFunction myFunction "echo 'Hello!'" injectAtBeginning=true
bash::injectCodeInFunction myFunction "echo 'world!'"
eval "${REPLY}"
myFunction
⚡ bash::isCommand
Check if the given command exists.
Inputs:
$1
: command name as string:the command name to check.
Returns:
$?
- 0 if the command exists
- 1 otherwise.
Example usage:
if bash::isCommand "command1"; then
printf 'The command exists.'
fi
⚡ bash::isFdValid
Check if the given file descriptor is valid.
Inputs:
$1
: file descriptor as string:The file descriptor to check.
Returns:
$?
- 0 if the file descriptor is valid
- 1 otherwise.
Example usage:
if bash::isFdValid 1; then
echo "File descriptor 1 is valid."
fi
⚡ bash::isFunction
Check if the given function exists.
Inputs:
$1
: function name as string:the function name to check.
Returns:
$?
- 0 if the function exists
- 1 otherwise.
Example usage:
if bash::isFunction "function1"; then
printf 'The function exists.'
fi
⚡ bash::readStdIn
Read the content of the standard input. Will immediately return if the standard input is empty.
Returns:
${REPLY}
: The content of the standard input.
Example usage:
bash::readStdIn
echo "${REPLY}"
⚡ bash::runInSubshell
This functions runs a command in a subshell. The command can fail and can trigger errors; it will be caught and this function will return the exit code of the subshell. This function can almost be considered as a try/catch block for bash as the execution will stop on error but the error will be caught and stored for later processing instead of exiting the program.
Inputs:
$@
: command with args as string:The command to run in the subshell.
$_OPTION_EXIT_ON_FAIL
as bool:(optional) If set to true, the main program will exit with code 1 if the command fails.
(defaults to false)
Returns:
${REPLY_CODE}
: the exit code of the subshell.
Example usage:
bash::runInSubshell myFunction
if (( REPLY_CODE != 0 )); then
core::fail "The subshell failed with code ${REPLY_CODE}"
fi
_OPTION_EXIT_ON_FAIL=true bash::runInSubshell myFunction
This function exists because the behavior of bash subshells are not what you would expect. This function ensures that errors are properly handled and make the command list fail, it ensures that we run the exit trap and it gives you the correct exit code of the subshell. As a reminder, the error trap is not triggered for commands part of until while if ! || && tests, see https://www.gnu.org/software/bash/manual/bash.html#index-trap and https://www.gnu.org/software/bash/manual/bash.html#The-Set-Builtin-1.
⚡ bash::sleep
Sleep for the given amount of time. This is a pure bash replacement of sleep.
Inputs:
$1
: time as float:the time to sleep in seconds (can be a float) If 0, waits indefinitely.
Example usage:
bash::sleep 1.5
The sleep command is not a built-in command in bash, but a separate executable. When you use sleep, you are creating a new process.
⚡ benchmark::run
This function runs a benchmark on given functions.
First, it will run the 1st function (the baseline) for a given amount of time and mark the number of times it was able to run it.
Then, it will run all the functions for the same number of time and print the difference between the baseline and the other functions.
Inputs:
$1
: baseline as string:the name of the function to use as baseline
$@
: functions as string:The names of the functions to benchmark, comma separated.
${baselineTimeInSeconds}
as int:(optional) The time in seconds for which to run the baseline.
(defaults to 3)
${maxRuns}
as int:(optional) The maximum number of runs to do for each function. Set to -1 to run until the baseline time is reached.
(defaults to -1)
Example usage:
benchmark::run baseline function1 function2
benchmark::run baseline function1 function2 --- baselineTimeInSeconds=5 maxRuns=100
⚡ command::checkParsedResults
A convenience function to check the parsing results and fails with an error message if there are parsing errors. Will also display the help if the help option is true.
This should be called from a command function for which you want to check the parsing results.
It uses the variables help
and commandArgumentsErrors
to determine if the help should be displayed
and if there are parsing errors.
Example usage:
command::checkParsedResults
⚡ command::parseArguments
Parse the arguments and options of a function and return a string that can be evaluated to set the variables. This should be called from a command function for which you want to parse the arguments.
See the documentation for more details on the parser: https://jcaillon.github.io/valet/docs/new-commands/#-implement-your-command.
Inputs:
$@
: arguments as any:the arguments to parse
Returns:
${REPLY}
: a string that can be evaluated to set the parsed variables
Output example:
local arg1 option1
arg1="xxx"
option1="xxx"
Example usage:
command::parseArguments "$@"; eval "${REPLY}"
⚡ command::showHelp
Show the help for the current function. This should be called directly from a command function for which you want to display the help text.
Example usage:
command::showHelp
⚡ command::sourceFunction
Source the file associated with a command function. This allows you to call a command function without having to source the file manually.
Inputs:
$1
: function name as string:the function name
Example usage:
command::sourceFunction "functionName"
⚡ coproc::isRunning
This function checks if a coproc is running.
Inputs:
$1
: coproc variable name as string:The variable name to use for the coproc.
Returns:
$?
:- 0 if the coproc is running
- 1 if it is not
Example usage:
if coproc::isRunning "myCoproc"; then
echo "The coproc is running."
fi
⚡ coproc::kill
This function kills a coproc.
Inputs:
$1
: coproc variable name as string:The variable name to use for the coproc.
Example usage:
coproc::kill "myCoproc"
⚡ coproc::receiveMessage
This function receives a message from a given coproc.
Inputs:
$1
: coproc variable name as string:The variable name to use for the coproc.
Returns:
$?
:- 0 if a message was received successfully.
- 1 if the coproc is not running or no message could be received.
${REPLY}
: The received message.
Example usage:
if coproc::receiveMessage "myCoproc"; then
echo "Received message: ${REPLY}"
fi
⚡ coproc::run
This function runs commands in a coproc. Each command can be set to “:” in order to do nothing. It returns the file descriptors/PID of the coproc and defines functions to easily interact with the coproc.
Inputs:
$1
: coproc variable name as string:The variable name to use for the coproc. It will be used to store the coproc file descriptors and PID. <coproc_variable_name>[0] will be the input pipe file descriptor, <coproc_variable_name>[1] will be the output pipe file descriptor, <coproc_variable_name>_PID will be the PID of the coproc.
${initCommand}
as string:(optional) The command (will be evaluated) to run at the start of the coproc. Can exit to stop the coproc. Set to “:” to do nothing.
(defaults to “:”)
${loopCommand}
as string:(optional) The command (will be evaluated) to run in the coproc loop. Can exit to stop the coproc, can break or continue the loop. Set to “:” to do nothing.
(defaults to “:”)
${onMessageCommand}
as string:(optional) The command (will be evaluated) to run in the coproc loop when a message is received from the main thread. The command can expect to use the variable REPLY which contains the message (string) received from the main thread. The command can send messages to the main thread using the syntax printf “%s\0” “message” Can exit to stop the coproc, can break or continue the loop. Set to an empty string to not run any command on message.
(defaults to “”)
${endCommand}
as string:(optional) The command (will be evaluated) to run at the end of the coproc. Set to “:” to do nothing.
(defaults to “:”)
${waitForReadiness}
as bool:(optional) If true, the main thread will wait for the coproc to be ready before returning from this function (readiness is achieved after executing the init command in the coproc).
(defaults to false)
${keepOnlyLastMessage}
as bool:(optional) If true, the coproc will only keep the last message received from the main thread to evaluate the on message command.
(defaults to false)
${redirectLogsToFile}
as string:(optional) The path to a file where the logs of the coproc will be redirected.
(defaults to “”)
Returns:
${REPLY}
: The PID of the coproc.
Example usage:
waitForReadiness=true coproc::run "_MY_COPROC" initCommand loopCommand onMessageCommand
⚡ coproc::runInParallel
This function runs a list of commands in parallel with a maximum number of parallel coprocs.
Inputs:
$1
: job commands array name as string:The name of the array containing the commands to run. Each command string will be evaluated in a subshell. Each command should explicitly exit with a non-zero code if it fails and with zero if it succeeds.
${maxInParallel}
as int:(optional) The maximum number of parallel coprocs to run.
(defaults to 8)
${completedCallback}
as string:(optional) The name of the function to call when a coproc is completed (successfully or not). The function will receive the following arguments:
- $1 the coproc index
- $2 the coproc exit code
- $3 the percentage of coprocs already completed
- $4 the path of the file containing the accumulated logs of the coproc If the function sets REPLY to 1, the script will exit early. Otherwise it should set REPLY to 0. Set to an empty string to not call any callback function.
(defaults to “”)
${redirectLogs}
as bool:(optional) Redirect the logs of the coproc instead of printing them in the current file descriptor. The accumulated logs of the coproc will be available in the completed callback function.
(defaults to false)
${printRedirectedLogs}
as bool:(optional) This option allows to automatically redirect the logs of the coproc to a file and print the accumulated logs of a coproc when it is completed (successfully or not).
(defaults to false)
${coprocNamePrefix}
as string:(optional) The prefix to use for the coproc variable names. This is useful to avoid conflicts with other coproc variables.
(defaults to “COPROC_PARALLEL”)
Returns:
${REPLY}
: 0 if all the jobs completed, 1 if the completed callback function returned 1.${REPLY2}
: The number of successfully completed jobs.${REPLY_ARRAY[@]}
: an array containing the exit codes of the jobs.
Example usage:
declare -a jobCommands=("sleep 1" "sleep 2" "sleep 3")
coproc::runInParallel jobCommands maxParallelCoprocs=2
⚡ coproc::sendMessage
This function sends a message to a given coproc.
Inputs:
$1
: coproc variable name as string:The variable name to use for the coproc.
$2
: message as string:The message to send to the coproc.
Returns:
$?
:- 0 if the message was sent successfully.
- 1 if the coproc is not running or the message could not be sent.
Example usage:
coproc::sendMessage "myCoproc" "Hello, coproc!"
This printf call can cause the whole shell to exit with code 141 if there is an issue with the coproc. You will want to run this in a subshell to avoid exiting the main shell if your coproc is unstable.
⚡ coproc::wait
This function waits for a coproc to finish.
Inputs:
$1
: coproc variable name as string:The variable name to use for the coproc.
Returns:
${REPLY_CODE}
: The exit status of the coproc (or -1 if the coproc is not running).
Example usage:
coproc::wait "myCoproc"
⚡ core::createSavedFilePath
Returns the path to a new file stored in the user state directory under saved-files
.
Can be used to save the state of important temporary files generated during a program
execution.
Inputs:
${suffix}
as string:(optional) The suffix for the file to create.
(defaults to “”)
Returns:
${REPLY}
: The path to the created file.
Example usage:
core::createSavedFilePath
core::createSavedFilePath suffix="my-file"
printf '%s\n' "The file is ⌜${REPLY}⌝."
⚡ core::dump
Dumps information about the current bash session into a new file.
Inputs:
${dumpSuffix}
as string:(optional) The suffix for the file to create.
(defaults to “”)
Returns:
${REPLY}
: the path to the created file.
Example usage:
core::dump
⚡ core::exit
Exits the program with the given exit code.
We replace the builtin exit command to make sure that we can correctly capture where the exit was called and print the call stack.
Inputs:
$1
: exit code as int:(optional) the exit code to use, should be between 0 and 255
(defaults to 0)
${silent}
as bool:(optional) If true, will not print the exit message and call stack for non zero exit codes.
(defaults to false)
Example usage:
core::exit 0
core::exit 0 silent=true
⚡ core::fail
Displays an error message and then exit the program with error.
Inputs:
$1
: message as string:The error message to display
${exitCode}
as int:(optional) the exit code to use, should be between 1 and 255
(defaults to 1)
Example usage:
core::fail "This is an error message."
core::fail "This is an error message." exitCode=255
⚡ core::getConfigurationDirectory
Returns the path to the valet configuration directory. Creates it if missing.
Returns:
${REPLY}
: the path to the valet configuration directory
Example usage:
core::getConfigurationDirectory
local directory="${REPLY}"
The default configuration directory is
~/.config/valet
.
⚡ core::getExtensionsDirectory
Returns the path to the user extensions directory. Creates it if missing.
Returns:
${REPLY}
: the path to the valet user directory
Example usage:
core::getExtensionsDirectory
local directory="${REPLY}"
The default extensions directory is
~/.valet.d
.
⚡ core::getUserCacheDirectory
Returns the path to the valet local cache directory. Where user-specific non-essential (cached) data should be written (analogous to /var/cache). Creates it if missing.
Returns:
${REPLY}
: the path to the valet local state directory
Example usage:
core::getUserCacheDirectory
local directory="${REPLY}"
The default cache directory is
~/.cache/valet
.
⚡ core::getUserDataDirectory
Returns the path to the valet local data directory. Where user-specific data files should be written (analogous to /usr/share). Creates it if missing.
Returns:
${REPLY}
: the path to the valet local state directory
Example usage:
core::getUserDataDirectory
local directory="${REPLY}"
The default data directory is
~/.local/share/valet
.
⚡ core::getUserStateDirectory
Returns the path to the valet local cache directory. Where user-specific state files should be written (analogous to /var/lib). Ideal location for storing runtime information, logs, etc… Creates it if missing.
Returns:
${REPLY}
: the path to the valet local state directory
Example usage:
core::getUserStateDirectory
local directory="${REPLY}"
The default state directory is
~/.local/state/valet
.
⚡ core::getVersion
Returns the version of Valet.
Returns:
${REPLY}
: The version of Valet.
Example usage:
core::getVersion
printf '%s\n' "The version of Valet is ⌜${REPLY}⌝."
⚡ core::parseFunctionOptions
Parses the shell parameters passed as arguments and sets the REPLY variable to a string that can be evaluated to set the local variables required in the calling function.
This should be called when you need to parse the arguments of a function that has a finite number of arguments
(i.e. that uses $@ or $*) in which case we expect the shell parameters to be passed after a separator ---
.
Inputs:
$@
: arguments as any:The arguments to parse.
Returns:
${REPLY}
: The string to evaluate to set the local variables.
Example usage:
core::parseFunctionOptions 1 2 3 --- myOption=one
eval "${REPLY}"
# REPLY will be: local myOption="one"; set -- "${@:1:3}"
⚡ curl::download
This function is a wrapper around curl to save a request result in a file. It allows you to check the http status code and return 1 if it is not acceptable. It invokes curl with the following options (do not repeat them): -sSL -w “%{response_code}” -o ${2}.
Inputs:
$1
: url as string:The url to download
$@
: curl arguments as any:options for curl
${output}
as string:(optional) the file in which to save the output of curl. Set to an empty string to create a temporary file instead.
(defaults to “”)
${failOnError}
as bool:(optional) true/false to indicate if the function should fail in case the execution fails
(defaults to false)
${acceptableCodes}
as string:(optional) list of http status codes that are acceptable, comma separated
(defaults to 200,201,202,204,301,304,308)
Returns:
${REPLY_CODE}
:- 0 if the http status code is acceptable
- 1 otherwise
${REPLY}
: the path to the file where the content was saved${REPLY2}
: the content of curl stderr${REPLY3}
: the http status code
Example usage:
curl::download https://example.com --- output=/filePath
curl::download https://example2.com -H "header: value" --- failOnError=true acceptableCodes=200,201 output=/filePath
echo "The curl command ended with exit code ⌜${REPLY_CODE}⌝, the http return code was ⌜${REPLY2}⌝: ${REPLY}"
⚡ curl::request
This function is a wrapper around curl to save the content of a request in a variable. It allows you to check the http status code and return 1 if it is not acceptable. It invokes curl with the following options (do not repeat them): -sSL -w “%{response_code}” -o “tempfile”.
Inputs:
$1
: url as string:The url to request
$@
: curl arguments as any:options for curl
${failOnError}
as bool:(optional) true/false to indicate if the function should fail in case the execution fails
(defaults to false)
${acceptableCodes}
as string:(optional) list of http status codes that are acceptable, comma separated
(defaults to 200,201,202,204,301,304,308)
Returns:
${REPLY_CODE}
:- 0 if the http status code is acceptable
- 1 otherwise
${REPLY}
: the content of the request${REPLY2}
: the content of curl stderr${REPLY3}
: the http status code
Example usage:
curl::request https://example.com
curl::request https://example.com -X POST -H 'Authorization: token' --- failOnError=true
echo "The curl command ended with exit code ⌜${REPLY_CODE}⌝, the http return code was ⌜${REPLY2}⌝: ${REPLY}"
⚡ esc-codes::*
ANSI codes for text attributes, colors, cursor control, and other common escape sequences. These codes can be used to format text in the terminal.
These codes were selected because they are widely supported by terminals and they probably will cover all use cases. It is also advised to stick to the 4-bit colors which allows your application to adopt the color scheme of the terminal.
They are defined as variables and not as functions. Please check the content of the esc-codes to learn more: https://github.com/jcaillon/valet/blob/latest/libraries.d/esc-codes
References:
- https://jvns.ca/blog/2025/03/07/escape-code-standards/
- https://invisible-island.net/xterm/ctlseqs/ctlseqs.html
- https://en.wikipedia.org/wiki/ANSI_escape_code
- https://gist.github.com/fnky/458719343aabd01cfb17a3a4f7296797
- https://paulbourke.net/dataformats/ascii/
- https://www.aivosto.com/articles/control-characters.html
- https://github.com/tmux/tmux/blob/master/tools/ansicode.txt
- https://vt100.net/docs/vt102-ug/chapter5.html
- https://vt100.net/docs/vt100-ug/chapter3.html#S3.3
- https://github.com/tmux/tmux/blob/882fb4d295deb3e4b803eb444915763305114e4f/tools/ansicode.txt
Ascii graphics:
- https://gist.github.com/dsample/79a97f38bf956f37a0f99ace9df367b9
- https://en.wikipedia.org/wiki/List_of_Unicode_characters#Box_Drawing
- https://en.wikipedia.org/wiki/List_of_Unicode_characters#Block_Elements
An interesting read: https://sw.kovidgoyal.net/kitty/keyboard-protocol/
While it could be very handy to define a function for each of these instructions, it would also be slower to execute (function overhead + multiple printf calls).
⚡ exe::invoke
This function call an executable with its optional arguments.
By default it redirects the stdout and stderr and captures them to output variables. This makes the executes silent unless the executable fails. By default, it will exit (core::fail) if the executable returns a non-zero exit code.
This function should be used as a wrapper around any external program as it allows to easily mock the program during tests and facilitates debugging with trace level log.
Inputs:
$1
: executable as string:the executable or function to execute
$@
: arguments as any:the arguments to pass to the executable
${noFail}
as bool:(optional) A boolean to indicate if the function should call core::fail (exit) in case the execution fails. If true and the execution fails, the script will exit.
(defaults to false)
${replyPathOnly}
as bool:(optional) If set to true, the function will return the file path of the stdout and stderr files instead of their content. This will make the function faster.
(defaults to false)
${stdoutPath}
as string:(optional) The file path to use for the stdout of the executable. Otherwise a temporary work file will be used.
(defaults to “”)
${stderrPath}
as string:(optional) The file path to use for the stderr of the executable. Otherwise a temporary work file will be used.
(defaults to “”)
${stdinFile}
as bool:(optional) The file path to use as stdin for the executable.
(defaults to “”)
${stdin}
as string:(optional) The stdin content to pass to the executable. Can be empty if not used.
(defaults to “”)
${acceptableCodes}
as string:(optional) The acceptable error codes, comma separated. If the error code is matched, then REPLY_CODE is set to 0)
(defaults to 0)
${appendRedirect}
as bool:(optional) If true will append the output to the stdout/stderr files instead of overwriting them (» redirect). This is useful when you want to run the same command multiple times and keep the previous output. The stderr and stdout REPLY variables will both have the same content.
(defaults to false)
${groupRedirect}
as bool:(optional) If true will output stdout/stderr to the same file (&> redirect).
(defaults to false)
${noRedirection}
as bool:(optional) If set to true, the function will not redirect the stdout and stderr to temporary files.
(defaults to false)
Returns:
${REPLY_CODE}
: The exit code of the executable.${REPLY}
: The content of stdout (or file path to stdout ifreplyPathOnly=true
).${REPLY2}
: The content of stderr (or file path to stdout ifreplyPathOnly=true
).
Example usage:
# basic usage with some arguments:
exe::invoke git branch --list --sort=-committerdate
echo "${REPLY}"
# invoke a command that is allowed to return an error code:
exe::invoke risky-command --- noFail=true
echo "${REPLY_CODE}"
# invoke a command with custom stdout / stderr files and do not read the output into REPLY vars:
exe::invoke thing --- stdoutPath=/path/to/stdout stderrPath=/path/to/stderr replyPathOnly=true
# invoke a command and let the outputs go to the console:
exe::invoke cat file --- noRedirection=true
# invoke a command with stdin from a string:
exe::invoke cat --- stdin="Hello World"
- In windows, this is tremendously faster to do:
exe::invoke mycommand; myvar="${REPLY}"
than doing:myvar="$(mycommand)".
- On linux, it is slightly faster (but it might be slower if you don’t have SSD?).
- On linux, you can use a tmpfs directory for massive gains over subshells.
⚡ fs::cat
Print the content of a file to stdout. This is a pure bash equivalent of cat.
Inputs:
$1
: path as string:the file to print
Example usage:
fs::cat myFile
Also see log::printFile if you want to print a file for a user.
⚡ fs::cleanTempFiles
Removes all the temporary files and directories that were created by the
fs::createTempFile
and fs::createTempDirectory
functions.
Example usage:
fs::cleanTempFiles
⚡ fs::createDirectoryIfNeeded
Create the directory tree if needed.
Inputs:
$1
: path as string:The directory path to create.
Returns:
${REPLY}
: The absolute path to the directory.
Example usage:
fs::createDirectoryIfNeeded "/my/directory"
echo "${REPLY}"
⚡ fs::createFileIfNeeded
Make sure that the given file exists. Create the directory tree and the file if needed.
Inputs:
$1
: path as string:the file path to create
Returns:
${REPLY}
: The absolute path of the file.
Example usage:
fs::createFileIfNeeded "myFile"
echo "${REPLY}"
⚡ fs::createLink
Create a soft or hard link (original ← link).
Reminder:
- A soft (symbolic) link is a new file that contains a reference to another file or directory in the form of an absolute or relative path.
- A hard link is a directory entry that associates a new pathname with an existing file (inode + data block) on a file system.
See windows::createLink
for Windows.
Inputs:
$1
: linked path as string:the path to link to (the original file)
$2
: link path as string:the path where to create the link
${hardlink}
as boolean:(optional) True to create a hard link, false to create a symbolic link
(defaults to false)
${force}
as boolean:(optional) True to overwrite the link or file if it already exists. Otherwise, the function will fail on an existing link.
(defaults to false)
Example usage:
fs::createLink "/path/to/link" "/path/to/linked"
fs::createLink "/path/to/link" "/path/to/linked" hardlink=true force=true
The function uses the
ln
command.
⚡ fs::createTempDirectory
Creates a temporary directory.
Inputs:
${pathOnly}
as bool:(optional) If true, does not create the file, only returns the path.
(defaults to false)
Returns:
${REPLY}
: The created path.
Example usage:
fs::createTempDirectory
echo "${REPLY}"
fs::createTempDirectory pathOnly=true
Directories created this way are automatically cleaned up by the fs::cleanTempFiles function when valet ends.
⚡ fs::createTempFile
Creates a temporary file and return its path.
Inputs:
${pathOnly}
as bool:(optional) If true, does not create the file, only returns the path.
(defaults to false)
Returns:
${REPLY}
: The created path.
Example usage:
fs::createTempFile
echo "${REPLY}"
fs::createTempFile pathOnly=true
Files created this way are automatically cleaned up by the fs::cleanTempFiles function when valet ends.
⚡ fs::getCommandPath
Get the absolute path of a command.
Inputs:
$1
: command as string:the command to find
Returns:
${REPLY}
: The absolute path of the command (or empty if command not found).
Example usage:
fs::getCommandPath "command"
echo "${REPLY}"
⚡ fs::getFileLineCount
Get the number of lines in a file.
Inputs:
$1
: path as string:the file path to read
Returns:
${REPLY}
: The number of lines in the file.
Example usage:
fs::getFileLineCount "/path/to/file"
echo "${REPLY}"
TODO: fails to count the last line if empty
⚡ fs::getPwdRealPath
Get the real path of the current directory.
By default, the ${PWD}
variable is the logical path, which may contain symlinks.
Example usage:
fs::getPwdRealPath
echo "${REPLY}"
Returns:
${REPLY}
: The realpath for the current directory.
This is a pure bash alternative to
realpath
orreadlink
.
⚡ fs::getScriptDirectory
This function returns the absolute path of the directory of the script that called it.
Returns:
${REPLY}
: the directory of the script that called it.
Example usage:
fs::getScriptDirectory
echo "${REPLY}"
⚡ fs::head
Print the first lines of a file to stdout. This is a pure bash equivalent of head.
Inputs:
$1
: path as string:The file to print.
$2
: number of lines as int:The number of lines to print.
${toArray}
as bool:(optional) If true, the output will be stored in the variable
REPLY_ARRAY
instead of being printed to stdout.(defaults to false)
Example usage:
fs::head myFile 10
fs::head myFile 10 toArray=true
#TODO: faster with mapfile + quantum?
⚡ fs::isDirectoryWritable
Check if the directory is writable. Creates the directory if it does not exist.
Inputs:
$1
: directory as string:the directory to check
${testFileName}
as string:(optional) The name of the file to create in the directory to test the write access
(defaults to “writable-test-${BASHPID}”)
Returns:
$?
:- 0 if the directory is writable
- 1 otherwise
Example usage:
if fs::isDirectoryWritable "/path/to/directory"; then
echo "The directory is writable."
fi
⚡ fs::listDirectories
List all the directories in the given directory.
Inputs:
$1
: directory as string:the directory to list
${recursive}
as bool:(optional) true to list recursively, false otherwise
(defaults to false)
${includeHidden}
as bool:(optional) true to list hidden directories, false otherwise
(defaults to false)
${filter}
as string:(optional) A function name that is called to filter the directories that will be listed The function should return 0 if the path is to be kept, 1 otherwise. The function is called with the path as the first argument.
(defaults to “”)
${filterDirectory}
as string:(optional) A function name that is called to filter the directories (for recursive listing) The function should return 0 if the path is to be kept, 1 otherwise. The function is called with the path as the first argument.
(defaults to “”)
Returns:
${REPLY_ARRAY[@]}
: An array with the list of all the files.
Example usage:
fs::listDirectories "/path/to/directory" true true myFilterFunction
for path in "${REPLY_ARRAY[@]}"; do
printf '%s' "${path}"
done
⚡ fs::listFiles
List all the files in the given directory.
Inputs:
$1
: directory as string:the directory to list
${recursive}
as bool:(optional) true to list recursively, false otherwise
(defaults to false)
${includeHidden}
as bool:(optional) true to list hidden files, false otherwise
(defaults to false)
${filter}
as string:(optional) A function name that is called to filter the files that will be listed The function should return 0 if the path is to be kept, 1 otherwise. The function is called with the path as the first argument.
(defaults to “”)
${filterDirectory}
as string:(optional) A function name that is called to filter the directories (for recursive listing) The function should return 0 if the path is to be kept, 1 otherwise. The function is called with the path as the first argument.
(defaults to “”)
Returns:
${REPLY_ARRAY[@]}
: An array with the list of all the files.
Example usage:
fs::listFiles "/path/to/directory" true true myFilterFunction
for path in "${REPLY_ARRAY[@]}"; do
printf '%s' "${path}"
done
⚡ fs::listPaths
List all the paths in the given directory.
Inputs:
$1
: directory as string:the directory to list
${recursive}
as bool:(optional) true to list recursively, false otherwise
(defaults to false)
${includeHidden}
as bool:(optional) true to list hidden paths, false otherwise
(defaults to false)
${filter}
as string:(optional) A function name that is called to filter the paths that will be listed The function should return 0 if the path is to be kept, 1 otherwise. The function is called with the path as the first argument.
(defaults to “”)
${filterDirectory}
as string:(optional) A function name that is called to filter the directories (for recursive listing) The function should return 0 if the path is to be kept, 1 otherwise. The function is called with the path as the first argument.
(defaults to “”)
Returns:
${REPLY_ARRAY[@]}
: An array with the list of all the paths.
Example usage:
fs::listPaths "/path/to/directory" true true myFilterFunction myFilterDirectoryFunction
for path in "${REPLY_ARRAY[@]}"; do
printf '%s' "${path}"
done
- It will correctly list files under symbolic link directories.
- #TODO: see if we are faster with ** and then looping over dirs to check for symbolic links
- #TODO: introduce an optional (with default 10k) parameter to limit the number of results to avoid looping for too long
⚡ fs::readFile
Reads the content of a file and returns it in the global variable REPLY. Uses pure bash.
Inputs:
$1
: path as string:the file path to read
${maxCharacters}
as int:(optional) the maximum number of characters to read If set to 0, the whole file will be read.
(defaults to 0)
If the file does not exist, the function will return an empty string instead of failing.
Returns:
${REPLY}
: The content of the file.
Example usage:
fs::readFile /path/to/file
fs::readFile /path/to/file maxCharacters=100
echo "${REPLY}"
⚡ fs::tail
Print the last lines of a file to stdout. This is a pure bash equivalent of tail. However, because we have to read the whole file, it is not efficient for large files.
Inputs:
$1
: path as string:The file to print.
$2
: number of lines as int:The number of lines to print from the end of the file.
${toArray}
as bool:(optional) If true, the output will be stored in the variable
REPLY_ARRAY
instead of being printed to stdout.(defaults to false)
Example usage:
fs::tail myFile 10
#TODO: use mapfile quantum to not have to read the whole file in a single go.
⚡ fs::toAbsolutePath
This function returns the absolute path of a path.
If the path exists, it can be resolved to the real path, following symlinks,
using the option realpath=true
.
Inputs:
$1
: path as string:The path to translate to absolute path.
${realpath}
as bool:(optional) true to resolve the path to the real path, following symlinks.
(defaults to false)
Returns:
${REPLY}
: The absolute path of the path.
Example usage:
fs::toAbsolutePath "myPath"
fs::toAbsolutePath "myPath" realpath=true
echo "${REPLY}"
This is a pure bash alternative to
realpath
orreadlink
. The..
will be processed before following any symlinks, by removing the immediate pathname component.
⚡ include
Allows to include multiple library files.
It calls source
for each argument.
Useful if you don’t have arguments to pass to the sourced files.
Inputs:
$@
: libraries as string:The names of the libraries (array, interactive, string…) or the file paths to include.
Example usage:
include string array ./my/path
⚡ interactive::askForConfirmation
Ask the user to press the button to continue.
Inputs:
$1
: prompt as string:the prompt to display
Returns:
$?
:- 0 if the user pressed enter
- 1 otherwise
Example usage:
interactive::askForConfirmation "Press enter to continue."
⚡ interactive::askForConfirmationRaw
Ask the user to press the button to continue.
This raw version does not display the prompt or the answer.
Returns:
$?
:- 0 if the user pressed enter
- 1 otherwise
Example usage:
interactive::askForConfirmationRaw
⚡ interactive::displayAnswer
Displays an answer to a previous question.
The text is wrapped and put inside a box like so:
╭─────╮
│ No. ├──░
╰─────╯
Inputs:
$1
: answer as string:the answer to display
${width}
as int:(optional) the maximum width of the text in the dialog box
(defaults to “${GLOBAL_COLUMNS}”)
Example usage:
interactive::displayAnswer "My answer."
⚡ interactive::displayQuestion
Displays a question to the user.
The text is wrapped and put inside a box like so:
╭────────────────────────────────╮
░──┤ Is this an important question? │
╰────────────────────────────────╯
Inputs:
$1
: prompt as string:the prompt to display
${width}
as int:(optional) the maximum width of the text in the dialog box
(defaults to “${GLOBAL_COLUMNS}”)
Example usage:
interactive::displayPrompt "Do you want to continue?"
⚡ interactive::promptYesNo
Ask the user to yes or no.
- The user can switch between the two options with the arrow keys or space.
- The user can validate the choice with the enter key.
- The user can also validate immediately with the y or n key.
Dialog boxes are displayed for the question and answer.
Inputs:
$1
: prompt as string:the prompt to display
${default}
as bool:(optional) the default value to select
(defaults to true)
Returns:
$?
:- 0 if the user answered yes
- 1 otherwise
${REPLY}
: true or false.
Example usage:
if interactive::promptYesNo "Do you want to continue?"; then echo "Yes."; else echo "No."; fi
⚡ interactive::promptYesNoRaw
Ask the user to yes or no.
- The user can switch between the two options with the arrow keys or space.
- The user can validate the choice with the enter key.
- The user can also validate immediately with the y or n key.
This raw version does not display the prompt or the answer.
Inputs:
${default}
as bool:(optional) the default value to select
(defaults to true)
Returns:
$?
:- 0 if the user answered yes
- 1 otherwise
${REPLY}
: true or false.
Example usage:
interactive::promptYesNoRaw "Do you want to continue?" && local answer="${REPLY}"
⚡ log::debug
Displays a debug message.
Inputs:
$1
: message as string:the debug messages to display
Example usage:
log::debug "This is a debug message."
⚡ log::error
Displays an error message.
Inputs:
$1
: message as string:the error messages to display
Example usage:
log::error "This is an error message."
You probably want to exit immediately after an error and should consider using core::fail function instead.
⚡ log::errorTrace
Displays an error trace message. This is a trace message that is always displayed, independently of the log level. It can be used before a fatal error to display useful information.
Inputs:
$1
: message as string:the trace messages to display
Example usage:
log::errorTrace "This is a debug message."
⚡ log::getCallStack
This function returns the current function stack.
Inputs:
${stackToSkip}
as int:(optional) The number of stack to skip. For instance, a value of 1 will skip this function.
(defaults to 1)
${stackToSkipAtEnd}
as int:(optional) The number of stack to skip at the end.
(defaults to 0)
${wrapWidth}
as int:(optional) The width to wrap the call stack.
(defaults to 0)
Returns:
${REPLY}
: The call stack as a string.
Example usage:
log::getCallStack
echo "${REPLY}"
log::getCallStack stackToSkip=2 stackToSkipAtEnd=1 wrapWidth=80
For test purposes, you can set the
GLOBAL_STACK_FUNCTION_NAMES
,GLOBAL_STACK_SOURCE_FILES
andGLOBAL_STACK_LINE_NUMBERS
variables to simulate a call stack.
⚡ log::getLevel
Get the current log level.
Returns:
${REPLY}
: The current log level.
Example usage:
log::getLevel
printf '%s\n' "The log level is ⌜${REPLY}⌝."
⚡ log::info
Displays an info message.
Inputs:
$1
: message as string:the info messages to display
Example usage:
log::info "This is an info message."
⚡ log::isDebugEnabled
Check if the debug mode is enabled.
Returns:
$?
:- 0 if debug mode is enabled (log level is debug)
- 1 if disabled
Example usage:
if log::isDebugEnabled; then printf '%s\n' "Debug mode is active."; fi
⚡ log::isTraceEnabled
Check if the trace mode is enabled.
Returns:
$?
:- 0 if trace mode is enabled (log level is trace)
- 1 if disabled
Example usage:
if log::isTraceEnabled; then printf '%s\n' "Debug mode is active."; fi
⚡ log::printCallStack
This function prints the current function stack in the logs.
Inputs:
${stackToSkip}
as int:(optional) The number of stack to skip. For instance, a value of 2 will skip this function and the first calling function.
(defaults to 2)
${stackToSkipAtEnd}
as int:(optional) The number of stack to skip at the end.
(defaults to 0)
Example usage:
log::printCallStack
log::printCallStack stackToSkip=0
For test purposes, you can set the
GLOBAL_STACK_FUNCTION_NAMES
,GLOBAL_STACK_SOURCE_FILES
andGLOBAL_STACK_LINE_NUMBERS
variables to simulate a call stack.
⚡ log::printFile
Display a file content with line numbers in the logs. The file content will be aligned with the current log output and hard wrapped if necessary.
Inputs:
$1
: path as string:the file path to display.
${maxLines}
as int:(optional) Max lines to display, can be set to 0 to display all lines.
(defaults to 0)
Example usage:
log::printFile "/my/file/path"
log::printFile "/my/file/path" maxLines=10
⚡ log::printFileString
Display a file content with line numbers in the logs. The file content will be aligned with the current log output and hard wrapped if necessary.
Inputs:
$1
: content variable name as string:The name of the variable containing the file content to print.
${maxLines}
as int:(optional) Max lines to display, can be set to 0 to display all lines.
(defaults to 0)
Example usage:
log::printFileString "myvar"
log::printFileString "myvar" maxLines=10
This function is not at all suited for large strings, print the content to a file instead.
⚡ log::printRaw
Display something in the log stream. Does not check the log level.
Inputs:
$1
: content variable name as string:The variable name containing the content to print (can contain new lines).
Example usage:
log::printRaw "my line"
⚡ log::printString
Display a string in the log. The string will be aligned with the current log output and hard wrapped if necessary. Does not check the log level.
Inputs:
$1
: content as string:the content to log (can contain new lines)
${newLinePadString}
as string:(optional) the string with which to prepend each wrapped line
(defaults to “”)
Example usage:
log::printString "my line"
log::printString "my line" newLinePadString=" "
⚡ log::saveFile
Save the given file by copying it to a new file in the user local state directory
(using core::createSavedFilePath
).
Useful for debugging purposes, to save the state of a file during execution.
Inputs:
$1
: path as string:The file path to save.
${suffix}
as string:(optional) The suffix for the file to create.
(defaults to “”)
${silent}
as bool:(optional) if true, do not log the path of the saved file using
log::printString
(defaults to false)
Returns:
${REPLY}
: The path to the saved file.
Example usage:
log::saveFile "/my/file/path" "suffix" "important result file"
⚡ log::saveFileString
Save the given string to a new file in the user local state directory
(using core::createSavedFilePath
).
Useful for debugging purposes, to save the state of a string during execution.
Inputs:
$1
: content variable name as string:The variable name of the content to save.
${suffix}
as string:(optional) The suffix for the file to create.
(defaults to “”)
${silent}
as bool:(optional) if true, do not log the path of the saved file using
log::printString
(defaults to false)
Returns:
${REPLY}
: The path to the saved file.
Example usage:
log::saveFileString "my content" "suffix" "important result file"
⚡ log::setLevel
Set the log level.
Inputs:
$1
: log level as string:The log level to set (or defaults to info), acceptable values are:
- trace
- debug
- info
- success
- warning
- error
${silent}
as bool:(optional) true to silently switch log level, i.e. does not print a message
(defaults to false)
Example usage:
log::setLevel debug
log::setLevel debug silent=true
⚡ log::success
Displays a success message.
Inputs:
$1
: message as string:the success messages to display
Example usage:
log::success "This is a success message."
⚡ log::trace
Displays a trace message.
Inputs:
$1
: message as string:the trace messages to display
Example usage:
log::trace "This is a trace message."
⚡ log::warning
Displays a warning.
Inputs:
$1
: message as string:the warning messages to display
Example usage:
log::warning "This is a warning message."
⚡ profiler::disable
Disable the profiler if previously activated with profiler::enable.
Example usage:
profiler::disable
⚡ profiler::enable
Enables the profiler and start writing to the given file. The profiler will also be active in subshells of this current shell.
Inputs:
$1
: path as string:the file to write to.
Example usage:
profiler::enable "${HOME}/valet-profiler-${BASHPID}.txt"
There can be only one profiler active at a time.
⚡ profiler::pause
Pause the profiler if previously activated with profiler::enable.
Example usage:
profiler::pause
⚡ profiler::resume
Resume the profiler if previously paused with profiler::pause.
Example usage:
profiler::resume
⚡ progress::start
Shows a spinner / progress animation with configurable output including a progress bar.
The animation will be displayed until progress::stop is called or if the max number of frames is reached.
Outputs to stderr. This will run in the background and will not block the main thread. The main thread can continue to output logs while this animation is running.
Inputs:
$1{template}
as string:(optional) The template to display. The template can contain the following placeholders:
<spinner>
: the spinner animation<percent>
: the percentage of the progress bar<bar>
: the progress bar<message>
: the message to display- #TODO: add
<cGradient>
and<cDefault>
: colors the bar with a gradient (if colors enabled)
The default template is defined by the environment variable
VALET_CONFIG_PROGRESS_DEFAULT_TEMPLATE
.(defaults to “
░ ░ ”) ${size}
as int:(optional) The maximum width of the progress bar. The default size is defined by the environment variable
VALET_CONFIG_PROGRESS_BAR_DEFAULT_SIZE
.(defaults to 20)
${frameDelay}
as int:(optional) The time in milliseconds between each frame of the spinner. The default frame delay is defined by the environment variable
VALET_CONFIG_PROGRESS_DEFAULT_ANIMATION_DELAY
.(defaults to 200)
${maxFrames}
as int:(optional) The maximum number of frames to display.
(defaults to 9223372036854775807)
${spinnerFrames}
as string:(optional) The spinner to display (each character is a frame). Examples:
- ◐◓◑◒
- ▖▘▝▗
- ⣾⣽⣻⢿⡿⣟⣯⣷
- ⢄⢂⢁⡁⡈⡐⡠
- ◡⊙◠
- ▌▀▐▄
- ⠄⠆⠇⠋⠙⠸⠰⠠⠰⠸⠙⠋⠇⠆
The default spinner is defined by the environment variable
VALET_CONFIG_SPINNER_CHARACTERS
.(defaults to “⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏”)
${percentage}
as int:(optional) The default percentage to start with.
(defaults to 0)
${message}
as string:(optional) The default message to start with.
(defaults to “”)
Example usage:
progress::start template="<spinner>" "" 100
wait 4
progress::stop
progress::start template="<spinner> <percent> ░<bar>░ <message>" size=30 spinnerFrames="⢄⢂⢁⡁⡈⡐⡠"
IDX=0
while [[ ${IDX} -le 50 ]]; do
progress::update $((IDX * 2)) "Doing something ${IDX}/50..."
IDX=$((IDX + 1))
sleep 0.1
done
progress::stop
Important: all progress functions will only work if called from the same shell that started the progress bar.
⚡ progress::stop
Stop the progress bar.
Example usage:
progress::stop
⚡ progress::update
Update the progress bar with a new percentage and message.
The animation can be started with progress::start for more options. The animation will stop if the updated percentage is 100.
Inputs:
$1
: percent as int:the percentage of the progress bar (0 to 100)
$2
: message as string:(optional) the message to display
Example usage:
progress::update 50 "Doing something..."
⚡ regex::escapeRegexSpecialChars
Escapes special characters in a string to be used as a regex.
Inputs:
$1
: string to escape as string:The string to escape.
Returns:
${REPLY}
: The escaped string.
Example usage:
regex::escapeRegexSpecialChars "a.(b)"
echo "${REPLY}"
⚡ regex::getFirstGroup
Matches a string against a regex and returns the first captured group of the first match.
Inputs:
$1
: string variable name as string:The variable name containing the string to match.
$2
: regex as string:The regex to use for the match.
Returns:
${REPLY}
: The first capture group in the matched string. Empty if no match.
Example usage:
MY_STRING="name: julien"
regex::getFirstGroup MY_STRING "name:(.*)"
echo "${REPLY}"
Regex wiki: https://en.wikibooks.org/wiki/Regular_Expressions/POSIX-Extended_Regular_Expressions
⚡ regex::getFuzzySearchRegexFromSearchString
Allows to get a regex that can be used to fuzzy search a string. the -> ‘([^t]*)(t[^h]*h[^e]*e)’
Inputs:
$1
: search string as string:The variable name containing the search string to match.
Returns:
${_STRING_FUZZY_FILTER_REGEX}
: the regex
Example usage:
regex::getFuzzySearchRegexFromSearchString SEARCH_STRING
echo "${_STRING_FUZZY_FILTER_REGEX}"
⚡ regex::getMatches
Returns an array containing all the matched for a regex in a string.
Inputs:
$1
: string variable name as string:The variable name containing the string to match.
$2
: regex as string:The regex to use for the match.
${replacement}
as string:(optional) The replacement string to use on each match.
- Use \x to refer to the x-th capture group.
- Use \c to refer to replacement counter.
Set to an empty string to keep the matches as they are.
(defaults to “”)
${max}
as int:(optional) The number of matches to return. Set to -1 for unlimited replacements.
(defaults to -1)
Returns:
${REPLY_ARRAY[@]}
: An array containing all the matches.
Example usage:
MY_STRING="name: julien, name: john"
regex::getMatches MY_STRING "name: (.*)"
regex::getMatches MY_STRING "name: (.*)" max=1
for match in "${REPLY_ARRAY[@]}"; do
echo "${match}"
done
Regex wiki: https://en.wikibooks.org/wiki/Regular_Expressions/POSIX-Extended_Regular_Expressions
⚡ regex::replace
Replaces strings within a string using a regex.
Inputs:
$1
: string variable name as string:The variable name containing the string in which to do replacements.
$2
: regex as string:The regex to use for the match.
$3
: replacement string as string:The replacement string. Use \x to refer to the x-th capture group. Use \c to refer to replacement counter.
${max}
as int:(optional) The number of replacements to do. Set to -1 for unlimited replacements.
(defaults to -1)
${onlyMatches}
as bool:(optional) Instead of replacing with the regex, we keep only the matches. This can be used to extract information from a string.
(defaults to false)
Returns:
${REPLY}
: The string with replacements.
Example usage:
MY_STRING="name: julien"
regex::replace MY_STRING "name: (.*)" "\1"
regex::replace MY_STRING "name: (.*)" "\1" maxCount=1 onlyMatches=true
echo "${REPLY}"
Regex wiki: https://en.wikibooks.org/wiki/Regular_Expressions/POSIX-Extended_Regular_Expressions
⚡ sfzf::show
Displays a menu where the user can search and select an item. The menu is displayed in full screen. Each item can optionally have a description/details shown in a right panel. The user can search for an item by typing.
Inputs:
$1
: array name as string:The items to display (name of a global array).
${prompt}
as string:(optional) The prompt to display to the user (e.g. Please pick an item).
(defaults to “Select an item:”)
${itemDetailsCallback}
as string:(optional) The function to call when an item is selected this parameter can be left empty to hide the preview right pane; otherwise the callback function should have the following signature:
- $1: the current item
- $2: the item number;
- $3: the current panel width;
- it should return the details of the item in the
REPLY
variable.
(defaults to empty, no callback)
$(previewTitle)
as string:(optional) the title of the preview right pane (if any)
(defaults to “Details”)
Returns:
${REPLY}
: The selected item value (or empty).${REPLY2}
: The selected item index (from the original array). Or -1 if the user cancelled the selection
Example usage:
declare -g -a SELECTION_ARRAY
SELECTION_ARRAY=("blue" "red" "green" "yellow")
sfzf::show "What's your favorite color?" SELECTION_ARRAY
log::info "You selected: ⌜${REPLY}⌝ (index: ⌜${REPLY2}⌝)"
⚡ source
Allows to source/include a library file or sources a file.
When sourcing a library, omit the lib-
prefix.
It will source all user and core libraries with the given name.
It replaces the builtin source command to make sure that we do not source the same library twice. We replace source instead of creating a new function to allow us to specify the included file for spellcheck.
Inputs:
$1
: library name or path as string:the name of the library (array, interactive, string…) or the file path to include.
$@
: arguments as any:(optional) the arguments to pass to the sourced file (mimics the builtin source command).
$_OPTION_CONTINUE_IF_NOT_FOUND
as bool:(optional) Do not fail the program if we do not find a file to source, we simply return 1.
(defaults to false)
$_OPTION_RETURN_CODE_IF_ALREADY_INCLUDED
as int:(optional) The function return code if the given file or library was already included.
(defaults to 0)
Example usage:
source string
source ./my/path
_OPTION_CONTINUE_IF_NOT_FOUND=false _OPTION_RETURN_CODE_IF_ALREADY_INCLUDED=2 source ./my/path
- The file can be relative to the current script (script that calls this function).
- Use
builtin source
if you want to include the file even if it was already included.
⚡ string::convertCamelCaseToSnakeCase
This function convert a camelCase string to a SNAKE_CASE string. It uses pure bash. Removes all leading underscores.
Inputs:
$1
: string variable name as string:The variable name that contains the string to convert.
Returns:
${REPLY}
: the extracted field
Example usage:
MY_STRING="myCamelCaseString"
string::convertCamelCaseToSnakeCase MY_STRING
echo "${REPLY}"
⚡ string::convertKebabCaseToCamelCase
This function convert a kebab-case string to a camelCase string. It uses pure bash. Removes all leading dashes.
Inputs:
$1
: string variable name as string:The variable name that contains the string to convert.
Returns:
${REPLY}
: the extracted field
Example usage:
MY_STRING="my-kebab-case-string"
string::convertKebabCaseToCamelCase MY_STRING
echo "${REPLY}"
⚡ string::convertKebabCaseToSnakeCase
This function convert a kebab-case string to a SNAKE_CASE string. It uses pure bash. Removes all leading dashes.
Inputs:
$1
: string variable name as string:The variable name that contains the string to convert.
Returns:
${REPLY}
: the extracted field
Example usage:
MY_STRING="my-kebab-case-string"
string::convertKebabCaseToSnakeCase MY_STRING
echo "${REPLY}"
⚡ string::convertToHex
Convert a string to its hexadecimal representation.
Inputs:
$1
: string variable name as string:The variable name that contains the string to convert.
Returns:
${REPLY}
: the hexadecimal representation of the string
Example usage:
MY_STRING="This is a string"
string::convertToHex MY_STRING
echo "${REPLY}"
⚡ string::count
Counts the number of occurrences of a substring in a string.
Inputs:
$1
: string variable name as string:The variable name that contains the string in which to count occurrences.
$2
: substring as string:the substring to count
Returns:
${REPLY}
: the number of occurrences
Example usage:
MY_STRING="name,first_name,address"
string::count MY_STRING ","
echo "${REPLY}"
This is faster than looping over the string and check the substring.
⚡ string::doForEachLine
Execute a callback function for each item (e.g. line) of a string. The string is split using a separator (default to a new line) and the callback function is called for each item.
Inputs:
$1
: string variable name as string:The name of the variable containing the string.
$2
: callback function as string:The name of the function to execute for each item (line). The function is called with the following arguments:
- $1: the current item (line) content
The function must return 0 if we should continue to the next line, 1 otherwise.
(defaults to “”)
${separator}
as string:(optional) The separator character to use.
(defaults to $’\n')
Example usage:
string::doForEachLine myString myCallback
This function provides a convenient way to avoid using a “here string” and handles extra newlines (which is not the case with a “for loop” using parameter expansion and IFS=$’\n’). Here string is significantly slower than using this.
⚡ string::extractBetween
Extract the text between two strings within a string. Search for the first occurrence of the start string and the first occurrence (after the start index) of the end string. Both start and end strings are excluded in the extracted text. Both start and end strings must be found to extract something.
Inputs:
$1
: string variable name as string:The variable name that contains the string from which to extract a text.
$2
: start string as string:the start string (if empty, then it will extract from the beginning of the string)
$3
: end string as string:the end string (if empty, then it will extract until the end of the string)
Returns:
${REPLY}
: the extracted text
Example usage:
MY_STRING="This is a long text"
string::extractBetween MY_STRING "is a " " text"
local extractedText="${REPLY}"
⚡ string::getField
Allows to get the nth element of a string separated by a given separator. This is the equivalent of the cut command “cut -d”${separator}" -f"${fieldNumber}"" but it uses pure bash to go faster.
Inputs:
$1
: string variable name as string:The variable name that contains the string to extract from.
$2
: field number as int:The field number to get (starting at 0).
${separator}
as string:The separator to use.
(defaults to $’\t')
Returns:
${REPLY}
: the extracted field
Example usage:
MY_STRING="field1 field2 field3"
string::getField MY_STRING 1 separator=" "
echo "${REPLY}"
This is faster than:
- using read into an array from a here string
- using bash parameter expansion to remove before/after the separator
⚡ string::getIndexOf
Find the first index of a string within another string.
Inputs:
$1
: string variable name as string:The variable name that contains the string from which to find an index.
$2
: search as string:the string to search
${startingIndex}
as int:(optional) the starting index
(defaults to 0)
Returns:
${REPLY}
: the index of the substring in the string or -1 if not found.
Example usage:
MY_STRING="This is a long text"
string::getIndexOf MY_STRING "long" startingIndex=2
string::getIndexOf MY_STRING "long"
echo "${REPLY}"
⚡ string::head
Get the first nth items (e.g. lines) of a string.
Inputs:
$1
: string variable name as string:The variable name that contains the string from which to get the first occurrences.
$2
: nb items as int:The number of items (lines) to extract.
${separator}
as string:(optional) The separator character to use.
(defaults to $’\n')
Returns:
${REPLY}
: The extracted string.
Example usage:
MY_STRING="line1"$'\n'"line2"$'\n'"line3"
string::head MY_STRING 2
echo "${REPLY}"
⚡ string::highlight
Highlight characters in a string.
Inputs:
$1
: text variable name as string:The variable name that contains the text to highlight.
$2
: characters variable name as string:The variable name that contains characters to highlight.
${highlightCode}
as string:(optional) The ANSI code to use for highlighting. The default value can be set using the variable STYLE_COLOR_ACCENT.
(defaults to $’\e’"[95m"}")
${resetCode}
as string:(optional) The ANSI code to use for resetting the highlighting. The default value can be set using the variable STYLE_COLOR_DEFAULT.
(defaults to $’\e’"[0m")
Returns:
${REPLY}
: the highlighted text
Example usage:
string::highlight "This is a text to highlight." "ttttt"
echo "${REPLY}"
- All characters to highlight must be found in the same order in the matched line.
- This functions is case insensitive.
⚡ string::numberToUniqueId
Converts a number into a unique and human readable string of the same length.
Inputs:
$1
: number as int:The number to convert.
Returns:
${REPLY}
: the unique string.
Example usage:
string::numberToUniqueId 12345
echo "${REPLY}"
⚡ string::removeTextFormatting
Removes all text formatting from the given string. This includes colors, bold, underline, etc.
Inputs:
$1
: text variable name as string:The variable name that contains the text to remove formatting from.
Example usage:
string::removeTextFormatting "myText"
echo "${myText}"
⚡ string::split
Split a string into an array using a separator.
Inputs:
$1
: string variable name as string:The variable name that contains the string to split.
$2
: separators as string:The separator characters to use.
Returns:
${REPLY_ARRAY[@]}
: the array of strings
Example usage:
MY_STRING="name,first_name,address"
string::split MY_STRING ","
ARRAY=("${REPLY_ARRAY[@]}")
This is faster than using read into an array from a here string.
⚡ string::trimAll
Trim all whitespaces and truncate spaces.
Inputs:
$1
: string variable name as string:The variable name that contains the string to trim.
Returns:
${REPLY}
: the extracted field
Example usage:
MY_STRING=" example "$'\t'" string "$'\n'
string::trimAll MY_STRING
echo "${REPLY}"
⚡ string::trimEdges
Trim leading and trailing characters (defaults to whitespaces).
Inputs:
$1
: string variable name as string:The variable name that contains the string to trim.
${charsToTrim}
as string:The characters to trim.
(defaults to $’ \t\n')
Returns:
${REPLY}
: the extracted field
Example usage:
MY_STRING=" example string "
string::trimEdges MY_STRING
echo "${REPLY}"
⚡ string::wrapCharacters
Allows to hard wrap the given string at the given width. Wrapping is done at character boundaries, see string::warpText for word wrapping. Optionally appends padding characters on each new line.
Inputs:
$1
: text variable name as string:The variable name that contains the text to wrap.
${width}
as string:(optional) The width to wrap the text at. Note that length of the new line pad string is subtracted from the width to make sure the text fits in the given width.
(defaults to “${GLOBAL_COLUMNS}”)
${newLinePadString}
as string:(optional) The characters to apply as padding on the left of each new line. E.g. ’ ’ will add 2 spaces on the left of each new line.
(defaults to 0)
${firstLineWidth}
as int:(optional) The width to use for the first line.
(defaults to “${width}”)
Returns:
${REPLY}
: the wrapped string${REPLY2}
: the length taken on the last line
Example usage:
string::wrapCharacters "This-is-a-long-text"
string::wrapCharacters "This-is-a-long-text-that-should-be-wrapped-at-20-characters." width=20 newLinePadString="---" firstLineWidth=5
echo "${REPLY}"
- This function is written in pure bash and is faster than calling the fold command.
- It considers escape sequence for text formatting and does not count them as visible characters.
- Leading spaces after a newly wrapped line are removed.
⚡ string::wrapWords
Allows to soft wrap the given text at the given width. Wrapping is done at word boundaries. Optionally appends padding characters on each new line.
Inputs:
$1
: text variable name as string:The variable name that contains the text to wrap.
${width}
as string:(optional) The width to wrap the text at. Note that length of the new line pad string is subtracted from the width to make sure the text fits in the given width.
(defaults to “${GLOBAL_COLUMNS}”)
${newLinePadString}
as string:(optional) The characters to apply as padding on the left of each new line. E.g. ’ ’ will add 2 spaces on the left of each new line.
(defaults to 0)
${firstLineWidth}
as int:(optional) The width to use for the first line.
(defaults to “${width}”)
Returns:
${REPLY}
: the wrapped text
Example usage:
string::wrapWords "This is a long text."
string::wrapWords "This is a long text wrapped at 20 characters." width=20 newLinePadString="---" firstLineWidth=20
echo "${REPLY}"
- This function is written in pure bash and is faster than calling the fold command.
- This function effectively trims all the extra spaces in the text (leading, trailing but also in the middle).
- It considers escape sequence for text formatting and does not count them as visible characters.
⚡ system::addToPath
Add the given path to the PATH environment variable for various shells, by adding the appropriate export command to the appropriate file.
Will also export the PATH variable in the current bash.
Inputs:
$1
: path as string:the path to add to the PATH environment variable.
Example usage:
system::addToPath "/path/to/bin"
⚡ system::getArchitecture
Returns the CPU architecture of the current machine.
Returns:
${REPLY}
: the CPU architecture of the current machine.
Example usage:
system::getArchitecture
local architecture="${REPLY}"
⚡ system::getEnvVars
Get the list of all the environment variables. In pure bash, no need for env or printenv.
Returns:
${REPLY_ARRAY[@]}
: An array with the list of all the environment variables.
Example usage:
system::getEnvVars
for var in "${REPLY_ARRAY[@]}"; do
printf '%s=%s\n' "${var}" "${!var}"
done
⚡ system::getOs
Returns the name of the current OS.
Returns:
${REPLY}
: the name of the current OS: “darwin”, “linux” or “windows”.
Example usage:
system::getOs
local osName="${REPLY}"
⚡ system::isDarwin
Check if the current OS is macOS.
Returns:
$?
- 0 if the current OS is macOS
- 1 otherwise.
Example usage:
if system::isDarwin; then
printf 'The current OS is macOS.'
fi
⚡ system::isLinux
Check if the current OS is Linux.
Returns:
$?
- 0 if the current OS is Linux
- 1 otherwise.
Example usage:
if system::isLinux; then
printf 'The current OS is Linux.'
fi
⚡ system::isRoot
Check if the script is running as root.
Returns:
$?
- 0 if the script is running as root
- 1 otherwise.
Example usage:
if system::isRoot; then
printf 'The script is running as root.'
fi
⚡ system::isWindows
Check if the current OS is Windows.
Returns:
$?
- 0 if the current OS is Windows
- 1 otherwise.
Example usage:
if system::isWindows; then
printf 'The current OS is Windows.'
fi
⚡ terminal::clearBox
Clear a “box” in the terminal. Will return the cursor at the current position at the end (using GLOBAL_CURSOR_LINE and GLOBAL_CURSOR_COLUMN).
Inputs:
${top}
as int:(optional) the top position of the box
(defaults to 1)
${left}
as int:(optional) the left position of the box
(defaults to 1)
${width}
as int:(optional) the width of the box
(defaults to “${GLOBAL_COLUMNS}”)
${height}
as int:(optional) the height of the box
(defaults to “${GLOBAL_LINES}”)
Example usage:
terminal::getCursorPosition
terminal::clearBox top=1 left=1 width=10 height=5
⚡ terminal::clearKeyPressed
This function reads all the inputs from the user, effectively discarding them.
Example usage:
terminal::clearKeyPressed
⚡ terminal::createSpace
This function creates empty lines from the current cursor position.
Then it moves back to its original line (at the column 1).
The current cursor line counts, meaning that terminal::createSpace 1
will
not do anything but clear the current line.
This effectively creates a space in the terminal (scroll up if we are at the bottom). It does not create more space than the number of lines in the terminal.
Inputs:
$1
: number of lines as int:the number of lines to create
Example usage:
terminal::createSpace 5
⚡ terminal::getBestAutocompleteBox
This function returns the best position and size for an autocomplete box that would open at the given position.
- The box will be placed below the current position if possible, but can be placed above if there is not enough space below.
- The box will be placed on the same column as the current position if possible, but can be placed on the left side if there is not enough space on the right to display the full width of the box.
- The box will have the desired height and width if possible, but will be reduced if there is not enough space in the terminal.
- The box will not be placed on the same line as the current position if notOnCurrentLine is set to true. Otherwise it can use the current position line.
Inputs:
${top}
as int:(optional) the current line of the cursor (1 based)
(defaults to 1)
${left}
as int:(optional) the current column of the cursor (1 based)
(defaults to 1)
${desiredHeight}
as int:(optional) the desired height of the box
(defaults to “${GLOBAL_LINES}”)
${desiredWidth}
as int:(optional) the desired width of the box
(defaults to “${GLOBAL_COLUMNS}”)
${maxHeight}
as int:(optional) the maximum height of the box
(defaults to “${GLOBAL_LINES}”)
${forceBelow}
as bool:(optional) force the box to be below the current position
(defaults to false)
${notOnCurrentLine}
as bool:(optional) the box will not be placed on the same line as the current position
(defaults to true)
${terminalHeight}
as int:(optional) the height of the terminal
(defaults to “${GLOBAL_LINES}”)
${terminalWidth}
as int:(optional) the width of the terminal
(defaults to “${GLOBAL_COLUMNS}”)
Returns:
${REPLY}
: the top position of the box (1 based)${REPLY2}
: the left position of the box (1 based)${REPLY3}
: the width of the box${REPLY4}
: the height of the box
Example usage:
terminal::getBestAutocompleteBox top=1 left=1 desiredHeight=10 desiredWidth=5
⚡ terminal::getCursorPosition
Get the current cursor position.
Returns:
GLOBAL_CURSOR_LINE
: the line numberGLOBAL_CURSOR_COLUMN
: the column number
Example usage:
terminal::getCursorPosition
⚡ terminal::getTerminalSize
This function exports the terminal size.
Returns:
GLOBAL_COLUMNS
: The number of columns in the terminal.GLOBAL_LINES
: The number of lines in the terminal.
Example usage:
terminal::getTerminalSize
printf '%s\n' "The terminal has ⌜${GLOBAL_COLUMNS}⌝ columns and ⌜${GLOBAL_LINES}⌝ lines."
⚡ terminal::rebindKeymap
Rebinds all special keys to call a given callback function. See @terminal::testWaitForKeyPress for an implementation example.
This allows to use the -e
option with the read command and receive events for special key press.
This function should be called before using terminal::waitForKeyPress.
You can call terminal::restoreBindings
to restore the default bindings. However, this is not
necessary as the bindings are local to the script.
Inputs:
$1
: callback function as string:The function name to call when a special key is pressed.
⚡ terminal::rerouteLogs
Reroute the logs to a temporary file.
The logs will be displayed when calling terminal::restoreLogs
Example usage:
terminal::rerouteLogs
⚡ terminal::restoreBindings
Reset the key bindings to the default ones.
To be called after terminal::rebindKeymap
.
Example usage:
terminal::restoreBindings
⚡ terminal::restoreInterruptTrap
Restore the original trap for the interrupt signal (SIGINT). To be called after terminal::setInterruptTrap.
Example usage:
terminal::restoreInterruptTrap
⚡ terminal::restoreLogs
Restore the logs to their original state.
Should be called after terminal::rerouteLogs
and at the end of an interactive session.
Example usage:
terminal::restoreLogs
⚡ terminal::restoreSettings
Restore the terminal options to their original state.
Should be called after terminal::setRawMode
.
Example usage:
terminal::restoreSettings
Note that the bash read builtin will restore stty state as it was before entering. So you want to call this after all read has been finished (particularly, you want to kill any background process that is reading inputs before trying to restore these settings).
⚡ terminal::setRawMode
Put the terminal in “raw” mode.
Set options to enable a satisfying and consistent behavior for the GNU readline library.
Call terminal::restoreSettings
to restore the original settings.
Example usage:
terminal::setRawMode
⚡ terminal::switchBackFromFullScreen
Call this function to switch back from the full screen mode.
- This function will restore the terminal state and show the cursor.
- It will also restore the key echoing.
Example usage:
terminal::switchBackFromFullScreen
⚡ terminal::switchToFullScreen
Call this function to start an interactive session in full screen mode. This function will switch to the alternate screen, hide the cursor and clear the screen.
You should call terminal::switchBackFromFullScreen at the end of the interactive session.
Example usage:
terminal::switchToFullScreen
⚡ terminal::testWaitForChar
Wait for the user to send a character to stdin (i.e. wait for a key press) and prints the character that bash reads.
Useful to test the terminal::waitForChar
function and see the char sequence we
get when pressing a key in a given terminal.
See @terminal::waitForChar for more information.
Example usage:
terminal::testWaitForChar
⚡ terminal::waitForChar
Wait for a user input (single char). You can pass additional parameters to the read command (e.g. to wait for a set amount of time).
It uses the read builtin command. This will not detect all key combinations. The output will depend on the terminal used and the character sequences it sends on each key press.
Some special keys are translated into more readable strings:
UP, DOWN, RIGHT, LEFT, BACKSPACE, DEL, PAGE_UP, PAGE_DOWN, HOME, END, ESC, F1, ALT+?.
However, this is not at all exhaustive and will depend on the terminal used.
Use terminal::waitForKeyPress
if you need to listen to special keys.
This simple implementation does not rely on GNU readline and does not require terminal options
to be set using terminal::setRawMode
.
Inputs:
$@
: read parameters as any:additional parameters to pass to the read command
Returns:
$?
:- 0 if a char was retrieved
- 1 otherwise
LAST_KEY_PRESSED
: the last char (key) retrieved.
Example usage:
terminal::waitForChar
terminal::waitForChar -t 0.1
https://en.wikipedia.org/wiki/ANSI_escape_code#Terminal_input_sequences
⚡ terminal::waitForKeyPress
Wait for a key press (single key). You can pass additional parameters to the read command (e.g. to wait for a set amount of time).
It uses the read builtin command with the option -e
to use readline behind the scene.
This means we can detect more key combinations but all keys needs to be bound first…
Special keys (CTRL+, ALT+, F1-F12, arrows, etc.) are intercepted using binding.
You must call terminal::rebindKeymap
and terminal::setRawMode
before using this function.
You should use tui::start
instead of using this function directly.
Inputs:
$@
: read parameters as any:additional parameters to pass to the read command
Returns:
$?
:- 0 if a key was pressed
- 1 otherwise
LAST_KEY_PRESSED
: the key pressed.
Example usage:
terminal::waitForKeyPress
terminal::waitForKeyPress -t 0.1
There are issues when using readline in bash:
- if the cursor is at the end of the screen, it will make the screen scroll even when nothing is read… Make sure to not position the cursor at the end of the screen.
- When read is done, it will print a new line in stderr. So we redirect stderr to null. This means that if you print something to stderr in a readline bound function, you will see nothing As a workaround, do this in your callback function:
exec 2>&"${GLOBAL_FD_LOG}"
- Not all key combinations can be bound, like SHIFT+ENTER. This is inherent to the way terminals work, they send a sequence of characters when a key is pressed and this sequence is read by readline/bash. For advanced key combinations, you will need to use a terminal that allows to remap such keys and send a specific sequence of characters that you can bind in bash.
⚡ test::exec
Call this function to execute a command and write the command and its output to the report file.
The command can fail, in which case the returned exit code is written to the report file.
However, the command must not call exit
(in which case, use test::exit).
Inputs:
$@
: command as string:The command to execute.
Example usage:
test::exec echo "Hello, world!"
⚡ test::exit
Call this function to execute a command that can call exit
and write the command and its output to the report file.
The command is executed in a subshell to catch the exit.
Inputs:
$@
: command as string:The command to execute.
Example usage:
test::exit exit 3
⚡ test::fail
Call this function to log a message and exit with the status 142, which indicates to the self test command that the test failed and that we know the reason (it is a bad implementation of the test itself).
Inputs:
$@
: message as string:The message to log.
Example usage:
test::fail "This is a failure message with a clear reason."
⚡ test::flush
Call this function to flush the standard and error outputs to the report file. They will be added as code blocks in the report file (one for the standard output, one for the standard error).
Example usage:
test::flush
⚡ test::flushStderr
Call this function to flush the standard error to the report file. It will be added as a code block in the report file.
Inputs:
${blockTitle}
as string:(optional) Add a ’title’ to the code block (
**title**:
before the code block).(defaults to “”)
Example usage:
test::flushStderr
⚡ test::flushStdout
Call this function to flush the standard output to the report file. It will be added as a code block in the report file.
Inputs:
${blockTitle}
as string:(optional) Add a ’title’ to the code block (
**title**:
before the code block).(defaults to “”)
Example usage:
test::flushStdout
⚡ test::func
Call this function to test a function that returns a value using the valet conventions (REPLY, REPLY2, REPLY_ARRAY, etc…).
It will write the command and its output to the report file. It will also print the REPLY values.
Inputs:
$@
: command as string:The command to execute (function and its arguments).
Example usage:
test::func myFunction
⚡ test::log
Call this function to log a message during a test. This log will only show in case of a script error or when the debug log level is enabled when running the tests.
Inputs:
$@
: messages as string:The messages to log.
Example usage:
test::log "This is a log message."
⚡ test::markdown
Call this function to add some markdown in the report file.
Inputs:
$@
: markdown as string:The markdown to add in the report file.
Example usage:
test::markdown "> This is a **quote**."
⚡ test::printReplyVars
This function can be called to print the REPLY values, e.g. REPLY, REPLY2, REPLY_ARRAY… They will each be printed in a code block in the report file.
Example usage:
test::printReplyVars
⚡ test::printVars
This function can be called to print the global variables in the report file. They will printed in a code block in the report file.
Inputs:
$@
: variables as string:The variables to print.
Example usage:
test::printVars myVar
⚡ test::prompt
Call this function to print a ‘prompt’ (markdown that looks like a prompt) in the report file.
Inputs:
$@
: command as string:The command to print as a prompt.
Example usage:
test::prompt "echo 'Hello, world!'"
⚡ test::resetReplyVars
Resets the value of each REPLY variable.
Example usage:
test::resetReplyVars
⚡ test::scrubOutput
This function can be defined to modify the flushed text (both stdout and stderr) before adding it to the report.
Scrubbers are required when we need to convert non-deterministic text to something stable so that tests are reproducible.
The text to transform is in the global variable GLOBAL_TEST_OUTPUT_CONTENT
.
You can also use GLOBAL_TEST_FD_NUMBER
to know which file descriptor is being flushed (1 for stdout, 2 for stderr).
Returns:
GLOBAL_TEST_OUTPUT_CONTENT
: The modified text.
You can define this function directly in the test script, or in a test hook if you need it to be available for multiple tests. Note however that this function can be called very often, so it should be optimized.
⚡ test::scrubReplyVars
This function can be defined to modify the REPLY variables before printing them in the report.
Scrubbers are required when we need to convert non-deterministic text to something stable so that tests are reproducible.
You can define this function directly in the test script, or in a test hook if you need it to be available for multiple tests. Note however that this function can be called very often, so it should be optimized.
⚡ test::setTerminalInputs
Replaces the functions terminal::waitForChar
and terminal::waitForKeyPress
by custom functions
that return keys defined as an input of this function.
Inputs:
$@
: keys as string:The keys to return when
terminal::waitForChar
orterminal::waitForKeyPress
are called. Keys are consumed in the order they are provided.
Example usage:
test::setTerminalInputs "a" "b" "c"
⚡ test::title
Call this function to add an H3 title in the report file.
Inputs:
$1
: title as string:The title of the test.
Example usage:
test::title "Testing something"
⚡ time::convertMicrosecondsToHuman
Convert microseconds to human readable format.
Inputs:
$1
: microseconds as int:the microseconds to convert
${format}
as string:(optional) the format to use
Usable formats:
- %HH: hours
- %MM: minutes
- %SS: seconds
- %LL: milliseconds
- %h: hours without leading zero
- %m: minutes without leading zero
- %s: seconds without leading zero
- %l: milliseconds without leading zero
- %u: microseconds without leading zero
- %M: total minutes
- %S: total seconds
- %L: total milliseconds
- %U: total microseconds
(defaults to “%HH:%MM:%SS”)
Returns:
${REPLY}
: the human readable format
Example usage:
time::convertMicrosecondsToHuman 123456789
time::convertMicrosecondsToHuman 123456789 format="%HH:%MM:%SS"
echo "${REPLY}"
⚡ time::convertMicrosecondsToSeconds
Convert a microseconds integer to seconds float. e.g. 1234567 → 1.234567
Inputs:
$1
: microseconds as int:the microseconds to convert
${precision}
as string:(optional) The precision to get (number of digits after the dot).
(defaults to 6)
Returns:
${REPLY}
: The seconds (float number).
Example usage:
time::convertMicrosecondsToSeconds 1234567
time::convertMicrosecondsToSeconds 1234567 precision=3
echo "${REPLY}"
⚡ time::getDate
Get the current date in the given format.
Inputs:
${format}
as string:(optional) the format (see printf) of the date to return
(defaults to “%(%F_%Hh%Mm%Ss)T”)
Returns:
${REPLY}
: the current date in the given format.
Example usage:
time::getDate
local date="${REPLY}"
time::getDate format="'%(%Hh%Mm%Ss)T'"
This function avoid to call $(date) in a subshell (date is a an external executable).
⚡ time::getProgramElapsedMicroseconds
Get the elapsed time in µs since the program started.
Returns:
${REPLY}
: the elapsed time in µs since the program started.
Example usage:
time::getProgramElapsedMicroseconds
echo "${REPLY}"
time::convertMicrosecondsToHuman "${REPLY}"
echo "Human time: ${REPLY}"
We split the computation in seconds and milliseconds to avoid overflow on 32-bit systems. The 10# forces the base 10 conversion to avoid issues with leading zeros. Fun fact: this function will fail in 2038 on 32-bit systems because the number of seconds will overflow.
⚡ time::getTimerMicroseconds
Get the time elapsed since the call of time::startTimer
.
Inputs:
${logElapsedTime}
as bool:(optional) Wether or not to log the elapsed time.
(defaults to false)
${format}
as string:(optional) The format to use if we log the elapsed time. See
time::convertMicrosecondsToHuman
for the format.(defaults to “%S.%LLs”).
Returns:
${REPLY}
: the elapsed time in microseconds.
Example usage:
time::startTimer
time::getTimerMicroseconds logElapsedTime=true
echo "Total microseconds: ${REPLY}"
⚡ time::startTimer
Start a timer. You can then call time::getTimerMicroseconds
to get the elapsed time.
Example usage:
time::startTimer
time::getTimerMicroseconds
⚡ version::bump
This function allows to bump a semantic version formatted like: major.minor.patch-prerelease+build
Inputs:
$1
: version as string:the version to bump
$2
: level as string:the level to bump (major, minor, patch)
${keepPreRelease}
as bool:(optional) keep the prerelease and build strings
(defaults to false)
Returns:
${REPLY}
: the new version string
Example usage:
version::bump "1.2.3-prerelease+build" "major" keepPreRelease=true
version::bump "1.2.3-prerelease+build" "major"
local newVersion="${REPLY}"
⚡ version::compare
This function allows to compare two semantic versions formatted like: major.minor.patch-prerelease+build
Inputs:
$1
: version1 as string:the first version to compare
$2
: version2 as string:the second version to compare
Returns:
${REPLY}
:- 0 if the versions are equal,
- 1 if version1 is greater,
- -1 if version2 is greater
Example usage:
version::compare "2.3.4-prerelease+build" "1.2.3-prerelease+build"
local comparison="${REPLY}"
The prerelease and build are ignored in the comparison.
⚡ windows::addToPath
Add the given path to the PATH environment variable on Windows (current user only).
Will also export the PATH variable in the current bash.
Inputs:
$1
: path as string:the path to add to the PATH environment variable. The path can be in unix format, it will be converted to windows format.
${prepend}
as bool:(optional) True to prepend the path to the PATH, false to append it.
(defaults to false)
Example usage:
windows::addToPath "/path/to/bin"
windows::addToPath "/path/to/bin" prepend=true
This function is only available on Windows, it uses
powershell
to directly modify the registry.
⚡ windows::convertPathFromUnix
Convert a unix path to a Windows path.
Inputs:
$1
: path as string:the path to convert
Returns:
${REPLY}
: The Windows path.
Example usage:
windows::convertPathFromUnix "/path/to/file"
Handles paths starting with
/mnt/x/
or/x/
in pure bash, handles other msys2 paths usingcygpath
.
⚡ windows::convertPathToUnix
Convert a Windows path to a unix path.
Inputs:
$1
: path as string:the path to convert
Returns:
${REPLY}
: The unix path.
Example usage:
windows::convertPathToUnix "C:\path\to\file"
Handles paths starting with
X:\
.
⚡ windows::createLink
Create a soft or hard link (original ← link).
Reminder:
- A soft (symbolic) link is a new file that contains a reference to another file or directory in the form of an absolute or relative path.
- A hard link is a directory entry that associates a new pathname with an existing file (inode + data block) on a file system.
Inputs:
$1
: linked path as string:the path to link to (the original file)
$2
: link path as string:the path where to create the link
${hardlink}
as boolean:(optional) True to create a hard link, false to create a symbolic link
(defaults to false)
${force}
as boolean:(optional) True to overwrite the link or file if it already exists. Otherwise, the function will fail on an existing link.
(defaults to false)
Example usage:
windows::createLink "/path/to/link" "/path/to/linked"
windows::createLink "/path/to/link" "/path/to/linked" hardlink=true force=true
On Windows, the function uses
powershell
(and optionally ls to check the existing link). If you have the windows “developer mode” enabled + MSYS=winsymlinks:nativestrict, then it uses the ln command.
⚡ windows::createTempDirectory
Create a temporary directory on Windows and return the path both for Windows and Unix.
This is useful for creating temporary directories that can be used in both Windows and Unix.
Returns:
${REPLY}
: The Windows path.${REPLY2}
: The Unix path.
Example usage:
windows::createTempDirectory
Directories created this way are automatically cleaned up by the fs::cleanTempFiles function when valet ends.
⚡ windows::createTempFile
Create a temporary file on Windows and return the path both for Windows and Unix.
This is useful for creating temporary files that can be used in both Windows and Unix.
Returns:
${REPLY}
: The Windows path.${REPLY2}
: The Unix path.
Example usage:
windows::createTempFile
Files created this way are automatically cleaned up by the fs::cleanTempFiles function when valet ends.
⚡ windows::endPs1Batch
This function will run all the commands that were batched with windows::startPs1Batch
.
Returns:
${REPLY_CODE}
:- 0 if the command was successful
- 1 otherwise.
${REPLY}
: The content of stdout.${REPLY2}
: The content of stderr.
Example usage:
windows::startPs1Batch
windows::runPs1 "Write-Host \"Hello\""
windows::runPs1 "Write-Host \"World\""
windows::endPs1Batch
⚡ windows::getEnvVar
Get the value of an environment variable for the current user on Windows.
Inputs:
$1
: variable name as string:the name of the environment variable to get.
Returns:
${REPLY}
: the value of the environment variable.
Example usage:
windows::getEnvVar "MY_VAR"
echo "${REPLY}"
⚡ windows::runPs1
Runs a PowerShell command. This is mostly useful on Windows.
Inputs:
$1
: command as string:the command to run.
${runAsAdmin}
as bool:(optional) Wether to run the command as administrator.
(defaults to false).
${noFail}
as bool:(optional) A boolean to indicate if the function should call core::fail (exit) in case the execution fails. If true and the execution fails, the script will exit.
(defaults to false)
Returns:
${REPLY_CODE}
:- 0 if the command was successful
- 1 otherwise.
${REPLY}
: The content of stdout.${REPLY2}
: The content of stderr.
Example usage:
windows::runPs1 "Write-Host \"Press any key:\"; Write-Host -Object ('The key that was pressed was: {0}' -f [System.Console]::ReadKey().Key.ToString());"
windows::runPs1 "Write-Host \"Hello\"" runAsAdmin=true noFail=true
⚡ windows::setEnvVar
Set an environment variable for the current user on Windows.
Inputs:
$1
: variable name as string:The name of the environment variable to set.
$2
: variable value as string:The value of the environment variable to set. An empty string will unset the variable.
Example usage:
windows::setEnvVar "MY_VAR" "my_value"
This function is only available on Windows, it uses
powershell
to directly modify the registry.
⚡ windows::startPs1Batch
After running this function, all commands that should be executed by
windows::runPs1
will be added to a batch that will only be played
when windows::endPs1Batch
is called.
This is a convenient way to run multiple commands in a single PowerShell session. It makes up for the fact that running a new PowerShell session for each command is slow.
Example usage:
windows::startPs1Batch
windows::runPs1 "Write-Host \"Hello\""
windows::runPs1 "Write-Host \"World\""
windows::endPs1Batch
Documentation generated for the version 0.30.1455 (2025-08-18).