This is a framework to bring bash to a next level.
Check out the examples »
Project status
·
Report Bug
·
Contribute code
Bash++ is a new way to bring bash to a next level. This framework introduces new functionalities to bash. Some of this functionalities are:
Errors
Bash++ is designed so that people could build more complex apps creating better products. Note that this project is for people with experience with bash (not much, just simple understandings and how things usually work).
When you run bash++
with bash, the application breaks. This is why you need to add #!/usr/bash
to the start of the script (see instructions here).
Bash haves it’s own module system, so you will have a bash++ folder in your /usr/libs
directory (just so that you know).
To use bash++
you will (obviously) need to install it. To install it, clone the repo by running the following command:
git clone https://github.com/mauro-balades/bash-plusplus
After cloning the repository, cd
into that directory. Once you are in the directory called bash++
. Run the following command to proceed with the installation.
Note that you need to run it as root.
sudo make install
When you have installed it, you will see a new directory (usually in /usr/lib/bash++
). This directory is where all of bash’s built-in libraries will be stored.
This is something that comes up really often, I’ve found that Oil Shell main FAQ covers this topic thoroughly:
Be sure to check out Oil in more detail if you can, it’s a very impressive project.
We all need to start somewhere, in this section you will se on how to use every functionality in bash++.
To get started, create a bash script (or an existing one). Add the following shebang at the start of the file so that bash can know what file you use.
#!/bin/bash
After you have added the shebang, chmod the main script with:
chmod +x [SCRIPT_NAME].sh
Then, you can just simply run the script as:
./[SCRIPT_NAME].sh
NOTE: Replace [SCRIPT_NAME]
with your main bash script.
To bootstrap your script you will need to source the Import script in your libs folder.
. "${BASHPP_LIBS}/Import.sh" # Source bash++
NOTE: Only do this step once (aka in the main script). and you will need to put in at the top of the file.
Humans need help to learn something new, that is why in this section all bash++ functionalities will be explained with an example.
Normal bash developers will use .
or source
to ‘import’ a bash script. Professional Bash++ developers will use the import function.
The Import function will let you choose more variation of sourcing methods that some developers will kill to have that. Apart from it giving more functionality it also creates new (or experienced) bash users a better syntax reading.
The following code is the function declaration for import
:
# ImportService::Import (import)
#
# Usage:
# import MyFile
# import System # Builtin module
# import github:mauro-balades/bash-plusplus
# import https://example.com/script.sh
# import script1 script2 ...
#
# Description:
# This function is used to import your bash script.
# The function is a replacement for "source" since
# it contains more functionality and it makes the
# code prettier
#
# Arguments:
# [...any] scripts: Bash scripts to be imported
ImportService::Import() {
...
}
As you can see from the function declaration, import can be used in different ways such as:
Description:
Usage:
import MyFile
import github:mauro-balades/bash-plusplus/...
raw.githubusercontent.com
domain.github:
import https://example.com/my/bash/script.sh
curl
curl
does not exists, it will try with wget
import myfile1 myfile2 myfile3
import MyFile
example at the top. (each file is checked if it is a github URL a normal URL)NOTE: It adds the script to an array of imported files. If you get an error saying that a file has already been sourced, remove that file from the import function since it already exists.
Bash++ also exports some extra features from the import API.
alias import="ImportService::Import"
# Overrides
alias .="ImportService::SimpleImport"
alias source="ImportService::SimpleImport"
# Extending the API
alias import.url="ImportService::ImportUrl"
alias import.github="ImportService::ImportGitHub"
alias import.simple="ImportService::SimpleImport" # Same as source and .
# Utility functions
alias import.exists="ImportService::Exists"
alias import.nexists="ImportService::NExists"
alias import.addm="ImportService::AddModule"
.
and source
overridden with the ImportService.SimpleImport (import.simple)
function. import.simple
is basically the same as import
except it does not support multiple files.import.url
and import.github
are the functions used in import
except for the import.github
function you don’t need the github:
prefix. ( It does not support multiple files ).import.exists
and import.nexists
this function returns a 1
if a module exists in the sourced files
array. nexists
returns 0
if it exists.import.addm
. This function takes a string as a parameter and adds that module to the array.
import
Feel free to check out the src/Import.sh
file to see each function declaration (it’s description, arguments and usage).
Classes are the main purpose of this project. To create a class, you will need to import a built-in module called Classes
# BOOTSTRAP ALREADY DONE ABOVE (IMAGINE)
import Classes
To define a class, it is like defining a normal variable except you have “attributes” inside it.
# BOOTSTRAP ALREADY DONE ABOVE (IMAGINE)
import Classes
MyClass=(
function __new__ # When class is initiated
function __delete__ # At the end of the script this is called
function hello
function hi = MyClass::different_function # If you call the function "hi", it will actually call MyClass::different_function
declare name
) # Class called "MyClass"
Great, you have successfully declared a class (joke). To add functionality, how about declaring what the function will do. By the way, functions __new__
and __delete__
are completely optional.
# BOOTSTRAP ALREADY DONE ABOVE (IMAGINE)
import Classes
MyClass=(
function __new__ # When class is initiated
function __delete__ # At the end of the script this is called
function hello
function hi = MyClass::different_function # If you call the function "hi", it will actually call MyClass::different_function
declare name
) # Class called "MyClass"
MyClass::__new__() {
# Get the "self" value
# Explained in the paragraph bellow.
local self=$1
shift
echo "class has inited"
# Set name to the first argument we get
# NOTE that name is declared above
# with the declare keyword
#
# "$1" was the self argument
# but now, we shifter so that function
# can hav arguments like a normal function
$self.name= "$1"
}
MyClass::__delete__() {
echo "Good Bye!"
}
MyClass::hello() {
local self=$1
shift
NAME=$($self.name)
echo "Hello, $NAME"
}
# Called with the "hi" function
MyClass::different_function() {
local self=$1
shift
echo "Hi, $($self.name)"
}
the self argument
. This argument is used for people to access class’ variables. An example has been done above with the variable name
. This argument is the first argument, so you can access it in $1
declare
keyword (you can declare an array using -a
as an argument).To change a variable’s value, a function has been declared which is the following:
$self.[VARIABLE_NAME]= "[VALUE]"
Note that the =
sign is not separated from the function name.
__new__
function. (and same with all functions)To create a new instance of a class, you will use the new
function. In the new function, you need to add a class name, a new variable in which it is going to be created with that name and arguments that can be passed to the __new__
function.
Example (with context of the last example above):
# | Class name | Arguments passed to __new__ (can be infinite)
new MyClass my_class Rob
# ^ ^ new var to create with class instance
When you have created a new instance of a class, a variable is made so that you can access this functions and variables.
example:
$my_class.hello # arguments separated by spaces
and to access class’ variables:
VAR=$($my_class.name)
To import enviromental variables, you will need to include the dotenv module.
import dotenv
This will give you acces to the load_dotenv
function. This functions has 1 optional parameter. That paramenter is the name of your .env
file.
load_dotenv
# or
load_dotenv "path/to/.env"
# ================================ BASH ++ ================================
#
# ...............................................
# @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
# @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
# @@@@@@@@@.(@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
# @@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
# @@@@@@@@@ #@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
# @@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@ @@@ @@
# @@@@@@@@@@@@@ ,@@@@@@@@@@@@@@@@@@@@ @ @@@@@@
# @@@@@@@@@@. @@@@@@@@@@@@@@@@@@@@@@@@@ @@@ @@
# @@@@@@@@ .@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
# @@@@@@@@ @@@@@@@@ #@@@@@@@@@@@@@
# @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
# @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
# @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
# @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
# @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
# @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@&
#
# Copyright <Mauro Baladés> 2021
# Bash++ Is under the license of "GNU GENERAL PUBLIC LICENSE
# =========================================================================