Skip to content

dante19031999/bashspark

Repository files navigation

BashSpark

Documentation

BashSpark is a powerful C++ library that provides a command-line tool to execute custom commands seamlessly.

Key Features

  • Bash Inspiration: While BashSpark draws inspiration from the Bash shell, it introduces unique features and behaviors tailored for enhanced usability.
  • Custom Command Execution: Users can easily define and execute their own commands, allowing for flexible scripting and automation.
  • Rich Functionality: The library supports various command types and execution options, accommodating diverse user needs.

BashSpark caters to developers seeking a robust and flexible tool for command execution in C++. It's familiar syntax makes it easier for the user to get started with it.

Key Features:

  • Supports Bash-style syntax:
    • ${VARIABLE_NAME}
    • ${!VARIABLE_NAME}
    • $(command)
    • function function_name {...}
    • Does not recognize semicolons/endls generated by the expansion. Expression $cmd where cmd="echo -n 1; echo -n 2" will output 1; echo -n 2, not 12.

Unique Capabilities:

  • Interprets escaped characters, such as \n (newline) and \t (tab).
  • Supports Unicode code points with the following formats:
    • \x for ascii
    • \u for UTF-16
    • \U for UTF-32
  • Returns shell_status::SHELL_ERROR_BAD_ENCODING for invalid code points.

Different behaviour

  • Does not require space around '(', '[', '{', '}', ']' and ')'.
  • Characters '(', '[', '{', '}', ']' and ')' are always interpreted.
    • Example: "echo }" works in bash, but not in BashSpark, although "echo \}" works in both.
    • Example: "((echo d))" does not work in bash, but works in BashSpark (since they are always interpreted, the spaces are not necessary)
  • Supports empty commands. Syntax like ";;;" is valid (three times empty, whom returns 0).
  • Does not support improved test "[[...]]"
  • Normal test supports operators "||" and "&&"
  • Normal test supports parentheses "(...)"
  • Does not support arithmetic with (()), the user may use command math
  • Does not support syntax: variable=value, use commands setenv and setvar.
  • Does not support syntax: function_name(){...}
  • Does not support syntax: function_name <args>, use command fcall function_name <args>

Command management

Commands are instantiations of class bs::command that are added to the shell. This command management method allow the programmer to strictly control the allowed behaviors, preventing security holes. This enhances the safety and reliability of command execution, ensuring that only authorized commands are executed and that errors are handled gracefully.

** About the shell depth **

The shell parser has a limit to the parsing depth. This is to prevent the program to run out of stack. The user is free to modify the constant std::size_t bs::shell::MAX_DEPTH and rebuild the project with the appropriate compiler flags if needed. The default value of this constant is 16, which was determined enough for general purpose scripts.

Increases the depth:

  • Parsing subblocks like "(...)" and "{...}"
  • Parsing subcommands like "$(...)"
  • Command eval (starts a brand-new shell with new depth in parsing).
  • Keywords like "if", "elif", "for", "while", "until". It increases the session shell depth. Custom commands using subshells should increase the session shell depth.

Does not increase the depth:

  • Parsing variables like "${...}"
  • Parsing tests like "[...]"
  • Keywords like "then", "fi", "else", "do", "done"

** Known Issues **

The implementation, as is, is ATTEMPTS to prevent SIGSEGV. The shell execution does not throw any exceptions except std::bad_alloc or exceptions derived from the streams provided by the programmer. All errors that may occur by default are listed on bs::shell_status and the shell will notify of them throw stderr + error code of last command. This includes shell syntax errors and shell depth limit errors.

Other issues:

  • Shell arguments are limited up to 19 digits, limited by the std::uint64_t range.

Index

  1. License
  2. Instructions
  3. SHELL Usage explanation
  4. API Usage explanation

License

This file is part of BashSpark.

Copyright (C) 2025 Dante Doménech Martínez

This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program. If not, see https://www.gnu.org/licenses/

Instructions

Using in cmake

To use this project in your own, the simplest method is to integrate it via CMake.

Step-by-step instructions

Add the following lines to your CMakeLists.txt file:

# Include FetchContent
include(FetchContent)

# Fetch the repository
FetchContent_Declare(
        bashspark
        GIT_REPOSITORY https://github.com/dante19031999/bashspark.git
        GIT_TAG master
)
FetchContent_MakeAvailable(bashspark)

# Define your library
add_library(foo ...)

# Link your library with BashSpark
target_link_libraries(foo PRIVATE BashSpark::BashSpark)

Available Alias Options

You can choose from several aliases depending on your needs:

  • BashSpark::ABashSpark: static library.
  • BashSpark::FBashSpark: static library of the project with position-independent code.
  • BashSpark::SBashSpark: dynamic library.
  • BashSpark::BashSpark default library (dynamic library).

Generating the documentation

This project includes comprehensive documentation detailing its functionality and operations.

To generate the documentation, follow these steps:

  1. The CMake configuration file includes a dedicated "doc" target.
  2. Executing this target will generate the Doxygen documentation in ${PROJECT_DIR}/docs.
  3. The primary access point for the documentation is the HTML file located at ${PROJECT_DIR}/docs/html/index.html.

The library Doxygen Awesome is used in order to improve the documentation aesthetics.

Building the project

The cmake file contains various predefined targets to build the project

  • doc: Generates documentation (see Generating the documentation).
  • deb: Generate .deb file of the library at ${PROJECT_DIR}/build/bashspark_1.0_amd64.deb.
  • rpm: Generate .rmp file of the library at ${PROJECT_DIR}/build/bashspark_1.0_amd64.rpm (for the time being unavailable).
  • headers Generates a zip file containing the library headers at ${PROJECT_DIR}/build/BashSpark.zip.
  • abashspark: Generates a static library of the project.
  • fbashspark: Generates a static library of the project with position-independent code.
  • sbashspark: Generates a dynamic library of the project.
  • tbashspark: Generates the test executable of the project.

Exposes targets:

  • BashSpark::ABashSpark: static library.
  • BashSpark::FBashSpark: static library of the project with position-independent code.
  • BashSpark::SBashSpark: dynamic library.
  • BashSpark::BashSpark default library (dynamic library).
  • Property BASHPARK_HEADER_DIR with the include path.

Note, if command debuild is missing, use:

sudo apt install devscripts

Install cmake:

Linux Distribution Command
Debian-based sudo apt install -y cmake
Red Hat-based sudo yum install -y cmake
Fedora sudo dnf install -y cmake
Arch Linux sudo pacman -S --noconfirm cmake
Windows https://cmake.org/download/
MAC OS X brew install cmake

Installation

The installation is separated in three steps:

  1. Configure cmake
  2. Unpacking the headers
  3. Building the library
  4. Copying the library

Configure cmake

First is to set the project directory. This simplifies the execution of the further commands.

Assuming that the bash working directory is in the project directory it would be:

BASH_SPARK="$(realpath .)"

The following step is to configure cmake. This processes the CMakeLists.txt and prepares cmake for the build.

It is achieved with the following command:

mkdir -p ${BASH_SPARK}/cmake-build && cd ${BASH_SPARK}/cmake-build && cmake ..

Unpacking the headers

On posix system the library headers are stored at /usr/include. Therefore, the headers need to be copied there.

Generate the headers:

cd ${BASH_SPARK}/cmake-build && make headers

Extract the headers:

tar -xzf ${BASH_SPARK}/build/BashSpark.tar.gz -C ${BASH_SPARK}/build --strip-components=1 "./BashSpark"

Move headers to /usr/include:

sudo mv ${BASH_SPARK}/build/BashSpark /usr/include/BashSpark

Windows users: On windows extract the file ${BASH_SPARK}/build/BashSpark.tar.gz where appropriate.

Build the library

Choose a version of the library to build. If unsure choose sbashspark.

  • abashspark: Generates a static library of the project.
  • fbashspark: Generates a static library of the project with position-independent code.
  • sbashspark: Generates a dynamic library of the project.

Respective commands:

Library abashspark:

cd ${BASH_SPARK}/cmake-build && make abashspark

Library fbashspark:

cd ${BASH_SPARK}/cmake-build && make fbashspark

Library sbashspark:

cd ${BASH_SPARK}/cmake-build && make sbashspark

Copying the library

On posix system the library headers are stored at /usr/lib. Therefore, the headers need to be copied there.

Create the directory for the library:

sudo mkdir -p /usr/lib/BashSpark

Move the libraries:

Library abashspark:

sudo mv ${BASH_SPARK}/build/libabashspark.a /usr/lib/BashSpark/libabashspark.a

Library fbashspark:

sudo mv ${BASH_SPARK}/build/libfbashspark.a /usr/lib/BashSpark/libfbashspark.a

Library sbashspark:

sudo mv ${BASH_SPARK}/build/libsbashspark.so /usr/lib/BashSpark/libsbashspark.so

SHELL Usage Explanation

This section explains the syntax and usage of some special shell commands.

Command echo

The echo command writes its parameters to stdout exactly as provided. If the -n option is used as the first parameter, no newline is printed at the end of the output.

Examples:

Command Output
echo "Hello World!" Hello World!\n
echo -n "Hello World!" Hello World!

Command getenv

The getenv command retrieves the value of an environment variable.
If the variable does not exist, it returns an empty string "".

Requires one argument: a valid environment variable name (like those in Bash).

Error Code Meaning
bs::shell_status::SHELL_CMD_ERROR_GETENV_PARAM_NUMBER Wrong number of parameters provided
bs::shell_status::SHELL_CMD_ERROR_GETENV_VARIABLE_NAME_INVALID Provided variable name is invalid

Example: getenv USER

Command setenv

The setenv command sets the value of an environment variable or creates it if it does not exist.
Requires two arguments: a valid environment variable name (like those in Bash) and a value.

Error Code Meaning
bs::shell_status::SHELL_CMD_ERROR_SETENV_PARAM_NUMBER Wrong number of parameters provided
bs::shell_status::SHELL_CMD_ERROR_SETENV_VARIABLE_NAME_INVALID Provided variable name is invalid

Example:

setenv SHELL "BashSpark"

Command getvar

The getvar command retrieves the value of a local variable.
If the variable does not exist, it returns an empty string "".

Requires one argument: a valid variable name (like those in Bash).

Error Code Meaning
bs::shell_status::SHELL_CMD_ERROR_GETVAR_PARAM_NUMBER Wrong number of parameters provided
bs::shell_status::SHELL_CMD_ERROR_GETVAR_VARIABLE_NAME_INVALID Provided variable name is invalid

Example:

getvar variable

Command setvar

The setvar command sets the value of a local variable or creates it if it does not exist.
Requires two arguments: a valid variable name (like those in Bash) and a value.

Error Code Meaning
bs::shell_status::SHELL_CMD_ERROR_SETVAR_PARAM_NUMBER Wrong number of parameters provided
bs::shell_status::SHELL_CMD_ERROR_SETVAR_VARIABLE_NAME_INVALID Provided variable name is invalid

Example: setvar variable "value"

Command seq

The seq command creates a sequence of integers.
The sequence can be growing or shrinking.

Takes 3 integer parameters: start, step, end.

  • The step parameter is optional and defaults to 1 or -1 depending on the sequence direction.
  • The sequence must extend over a closed set of values (logic error if violated).
  • Integer parameters are limited to 18 digits (64-bit signed integers).
Error Code Meaning
bs::shell_status::SHELL_CMD_ERROR_SEQ_PARAM_NUMBER Wrong number of parameters
bs::shell_status::SHELL_CMD_ERROR_SEQ_INVALID_INT_FORMAT Parameter is not a valid integer
bs::shell_status::SHELL_CMD_ERROR_SEQ_INT_OUT_OF_BOUNDS Parameter exceeds 64-bit integer limits
bs::shell_status::SHELL_CMD_ERROR_SEQ_ITERATION_LOGIC Step and range do not allow a valid sequence

Examples:

Command Output
seq 1 5 1 2 3 4 5
seq 1 2 5 1 3 5
seq 5 -2 1 5 3 1
seq 5 1 5 4 3 2 1
echo -n $(seq 1 5) 1 2 3 4 5

Command math

The math command performs simple integer arithmetic.
It takes mathematical expressions as parameters, broken down into independent tokens.

Supports:

  • Operators: +, -, *, /, ^, **, ×, ÷
  • Integer numbers within the range of 64-bit signed integers
  • Parentheses: ( ) (including nested parentheses)
  • Negative powers partially: { x != 0 } ^ { y < 0 } = 0
  • Functions:
    • factorial(x)
    • sum(variable; start; end; step; expression) — sums expression over the sequence of variable, e.g., count = sum(x;1;1;100;1)
    • product(variable; start; end; step; expression) — multiplies expression over the sequence of variable, e.g., factorial = product(x;1;1;100;x)
    • Note: a variable inside sum/product hides the same variable from the outside scope
    • Variable names must be valid shell variable names

Possible errors:

Error Code Meaning
bs::shell_status::SHELL_CMD_ERROR_MATH_NOT_AN_INTEGER Value is not an integer
bs::shell_status::SHELL_CMD_ERROR_MATH_OVERFLOW Integer overflow
bs::shell_status::SHELL_CMD_ERROR_MATH_UNDERFLOW Integer underflow
bs::shell_status::SHELL_CMD_ERROR_MATH_DIV_BY_ZERO Division by zero
bs::shell_status::SHELL_CMD_ERROR_MATH_POW_0_EXP_0 0^0 power is undefined
bs::shell_status::SHELL_CMD_ERROR_MATH_FACTORIAL_NEGATIVE Factorial of negative number
bs::shell_status::SHELL_CMD_ERROR_MATH_MALFORMED_EXPRESSION Expression is malformed
bs::shell_status::SHELL_CMD_ERROR_MATH_MAX_DEPTH_REACHED Maximum recursion depth reached (512)
bs::shell_status::SHELL_CMD_ERROR_MATH_INVALID_VARIABLE_NAME Invalid variable name in function
bs::shell_status::SHELL_CMD_ERROR_MATH_SEQ_ITERATION_LOGIC Sequence logic error in sequence function

Examples:

Command Output
math + 1 1
math - 1 -1
math +1 1
math -1 -1
math 3 + 4 7
math 3 * 4 12
math 12 / 4 3
math 12 % 5 2
math 2 ^ 3 8
math 2 ** 3 8
math 2 ** - 3 0
math 2 + 2 * 2 + 2 ^ 2 + 2 * 2 + 2 16
math 42 ^ 0 + 1 ^ 42 + 0 ^ 42 2
math \( 2 + 2 \) * \( 2 + 2 \) ^ \( 2 + 2 \) * \( 2 + 2 \) 4096
math $(echo "( 2 + 2 ) * ( 2 + 2 ) ^ ( 2 + 2 ) * ( 2 + 2 )") 4096
math \( \( 2 + 2 \) * \( 2 + 2 \) \) ^ \( \( 1 + 2 \) * \( 1 + 2 \) \) 68719476736
math factorial \( 5 \) 120
math product \( x , 1 , 1 , 5 , x \) 120
math sum \( x , 1 , 1 , 5 , x \) 15
echo $( math sign \( - 42 \) ) $( math sign \( 0 \) ) $( math sign \( + 42 \) ) -1 0 1
math abs \( - 42 \) 42
math abs \( + 42 \) 42
setvar i $(math i + 1) ``

Command test

The test command performs simple tests.
It takes test expressions as parameters, broken down into independent tokens.

Capabilities:

  • Operators or: -o, ||
  • Operators and: -a, &&
  • Comparison operators: ==, -eq, >, -gt, <, -lt, >=, -ge, <=, -le Note that comparison operators will apply numeric comparison if both arguments are numbers or <=> on std::string if they aren't.
  • Operator =: use a = b, checks if a matches b. Uses C++ regex, not bash regex.
  • Parentheses: ( ) (and nested parentheses).

Possible status codes outputs:

Status Description
bs::shell_status::SHELL_SUCCESS Test passed
bs::shell_status::SHELL_CMD_TEST_FALSE Test failed
bs::shell_status::SHELL_CMD_ERROR_TEST_UNCLOSED_PARENTHESIS Opened parenthesis not closed
bs::shell_status::SHELL_CMD_ERROR_TEST_MALFORMED_EXPRESSION Malformed expression
bs::shell_status::SHELL_CMD_ERROR_TEST_MALFORMED_REGEX Malformed regex

Examples:

Command Meaning Result
test -z "" Is the string empty? true
test -n "d" Is the string non-empty? true
test 7 -eq 0007 Numeric equality (leading zeros allowed) true
test 7 != 42 Numeric inequality true
test abc != 42 String inequality true
test 7 -gt 6 Numeric greater-than true
test b > a Lexicographic greater-than true
test 6 -le 7 Numeric ≤ comparison true
test 'hello' =~ '^h.*o$' Regex match true
test 'abc' =~ '^[0-9]+$' Regex check: digits only? false
test 'test@example.com' =~ '^[^@]+@[^@]+\\.[^@]+$' Email-like pattern true

Command fcall

The fcall command calls functions. The first parameter is the function name. The other parameters are the function parameters.

Example:

function echon {
    echo -n $@
}

fcall echon Hello World!

Output: Hello World!

Script examples

This section displays some simple example scripts. Allows to better grasp the shell syntax.

Hello world:

echo -n 'Hello, World!'"

Output: Hello, World!\n

While loop:

setvar count 1
while [ $count <= 5 ];
do
    echo \"Count: $count\"; setvar count $(math $count + 1); 
done

Output:

Count: 1
Count: 2
Count: 3
Count: 4
Count: 5

Until loop:

setvar count 1
until [ $count > 5 ];
do
    echo \"Count: $count\"; setvar count $(math $count + 1); 
done

Output:

Count: 1
Count: 2
Count: 3
Count: 4
Count: 5

Loop for:

for i in $(seq 1 5);
do
    echo -n $i;
done

Output: 12345

Function:

function greet {
    echo \"Ave $1\"
}

fcall greet Cesar

Output: Ave Cesar\n

Count function arguments:

function count_args { 
    echo -n $#
} 

fcall count_args $(seq 1 5)

Output: 5

Function with if-else block:

function oddeven {
    if [ $(math $1 % 2) == 0 ];
    then
        echo \"$1 is even\"
    else
        echo \"$1 is odd\"
    fi
}

fcall oddeven

Output:

42 is even
11 is odd

Function that displays it's arguments:

function show_args {
    if [ $# > 1 ];
    then
        for i in $(seq 1 $#);
        do
            echo \"arg $i: \\u201C${!i}\\u201D\";
        done
    else
        echo 'No arguments';
    fi 
}

fcall show_args
fcall show_args $(seq 1 5)

Output:

No arguments
arg 1: “1”
arg 2: “2”
arg 3: “3”
arg 4: “4”
arg 5: “5”

API Usage explanation

This section provides detailed instructions on how to utilize the BashSpark library effectively. It covers essential operations such as creating a shell instance, initializing a shell session, executing commands, and developing custom commands.

By following these guidelines, developers can manage command execution securely and efficiently while avoiding common pitfalls. The examples included showcase practical implementations, helping users to grasp each concept through hands-on coding snippets. Whether you are new to the library or seeking to enhance your command structures, this section serves as a comprehensive guide for operational success.

Create a shell instance

The first step to run commands is to create a shell. This class is named bs::shell. This class manages the available commands.

This command management method allow the programmer to strictly control the allowed behaviors, preventing security holes. This enhances the safety and reliability of command execution, ensuring that only authorized commands are executed and that errors are handled gracefully.

It is possible to obtain the default shell using method std::unique_ptr<bs::shell> bs::shell::make_default_shell(). The user may also use the default constructor bs::shell() to create a custom shell.

The class shell session may have the following methods overridden to change behavior (such as internationalization):

  • void shell::msg_error_command_not_found(shell_session &, const std::string &) const: error message on command not found.
  • void shell::msg_error_syntax_error(const shell_session &, const shell_exception &) const: error message on syntax error.

Example on obtaining the default session:

std::unique_ptr<bs::shell> pShell = bs::shell::make_default_shell();

Example on building the default session:

std::unique_ptr<shell> shell::make_default_shell() {
    auto pShell = std::make_unique<shell>();
    pShell->set_command<command_echo>();
    pShell->set_command<command_eval>();
    pShell->set_command<command_getenv>();
    pShell->set_command<command_getvar>();
    pShell->set_command<command_setenv>();
    pShell->set_command<command_setvar>();
    pShell->set_command<command_seq>();
    pShell->set_command<command_test>();
    pShell->set_command<command_math>();
    pShell->set_command<command_fcall>();
    return pShell;
}

Create a shell session

In order to execute shell commands a shell session is needed. This class is named bs::shell_session. The class bs::shell_session contains the streams (stdin, stdout, stderr), the environment variables, the function arguments, the local variables, the last exit status code and the shell depth. See the documentation on bs::shell_session for more details.

A bs::shell_session is constructed as shell_session(const shell *pShell, std::istream &oStdIn, std::ostream &oStdOut, std::ostream &oStdErr).

The class bs::shell_session may be extended in order to add custom information to the session. If a custom command uses the custom session, on method bs::command::run(const std::span<const std::string> &, shell_session &) const, it will be necessary to use auto pCustomSession = dynamic_cast<shell_session_custom*>(&oSession) in order to acquire it.

Example of shell session directly linked to terminal:

// Generate shell
std::unique_ptr<bs::shell> pShell = bs::shell::make_default_shell();
// Instantiare session
bs::shell_session oSession(
    pShell.get(), // Owning shell
    std::cin, // stdin
    std::cout, // stdout
    std::cerr // stderr
);

Run a command

Running a command requires instantiating the sell session and using the methods shell_status shell::run(std::istream &oCommand,shell_session &oSession);, shell_status run(const std::string &sCommand, shell_session &oSession); or shell_status run(const std::string_view &sCommand, shell_session &oSession);.

Example of hello world:

bs::shell_status run_helloworld() {
    // Generate shell
    std::unique_ptr<bs::shell> pShell = bs::shell::make_default_shell();
    // Instantiare session
    bs::shell_session oSession(
        pShell.get(), // Owning shell
        std::cin, // stdin
        std::cout, // stdout
        std::cerr // stderr
    );
    // Run command
    return bs::shell::run("echo -n 'Hello world!'"sv, oSession);
}

Create a custom command

Creating a custom command requires implementing the bs::command interface.

The custom command class has to override the method bs::command::run(const std::span<const std::string> &, shell_session &) const. On success, the run method must return bs::shell_status::SHELL_SUCCESS. On failure, the run method must return return bs::make_user_code(USER_ERROR_CODE) where USER_ERROR_CODE is an unsigned int.

It is recommended to define supplementary functions to print the error messages. Such functions would have a prototype like: print_error(std::ostream& oStderr) const.

Use the function bs::shell::set_command(std::unique_ptr<command> &&) to add the custom commands. The helper template template<typename CommandT, typename... Args> void bs::shell::set_command(Args &&...) may also be useful.

If the custom command uses a custom session, on method bs::command::run(const std::span<const std::string> &, shell_session &) const, it will be necessary to use auto pCustomSession = dynamic_cast<shell_session_custom*>(&oSession) in order to acquire it.

If the custom command calls subshells, to prevent SIGSEGV by stack overflow it is recommended to check the shell depth. Custom commands should not modify this depth lightly.

Example:

/**
 * @class command_helloworld
 * @brief Prints "Hellow world!" on stdout.
 * Syntax: helloworld
 */
class command_helloworld : public bs::command {
public:
    /**
     * @brief Constructs the command
     *
     * Instantiates bs::command with the command name
     */
    command_helloworld()
        : bs::command("helloworld") {
    }

public:
    /**
     * @brief Prints "Hellow world!" on stdout
     *
     * If the argument number is different from 0 then msg_error_param_number is called.
     *
     * @param vArgs Command arguments
     * @param oSession Shell session
     * @return Status code
     */
    shell_status run(const std::span<const std::string> &vArgs, shell_session &oSession) const override {
        // Check there are 0 arguments
        if (!vArgs.empty()) {
            // Call error printing functon
            this->msg_error_param_number(
                oSession.err(), // stderr
                vArgs.size() // Argument number
            );
            // Return error code 1 (make user code)
            return bs::make_user_code(1);
        }
        // Print "Hello World! on stdout
        oSession.out() << "Hello World!";
        // Return sucess code
        return bs::shell_status::SHELL_SUCCESS;
    }

    /**
     * @brief Print an error if the wrong number of arguments is provided.
     * @param oStdErr Stream to print error message.
     * @param nArgs Number of provided arguments.
     */
    virtual void msg_error_param_number(std::ostream &oStdErr, const std::size_t nArgs) const {
        // Print error message
        oStdErr << "helloworld: takes 0 parameters, but received " << nArgs << "." << std::endl;
        // The user may implement more complex behaviour such as internationalization
    }
};

Example of adding it to a shell instance:

auto pShell1 = bs::shell::make_default_shell();
pShell1->set_command<command_helloworld>();
auto pShell2 = bs::shell::make_default_shell();
auto pCommand = std::make_unique<command_helloworld>();
pShell2->set_command(std::move(pCommand));

Example of shell depth check:

// Increase depth
if (!oSession.increase_shell_depth()) {
    this->msg_error_max_depth_reached(oSession.err());
    return shell_status::SHELL_ERROR_MAX_DEPTH_REACHED;
}

// Run command here

// Decrease depth
oSession.decrease_shell_depth();

About

BashSpark is a powerful C++ library that provides a command-line tool to execute custom commands seamlessly.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published