Modules
In traditional shells such as bash and zsh, code is written in a single file. which can be called as a command later from other scripts. each script runs in its own shell which forces encapsulation per-file.
There is nothing wrong with that given the fact that those are interpreted languages. However, once the file exceeds a given count of lines of code. it becomes hard to read, maintain and extend. That's the time where you start thinking of switching to other languages (which usually is python 😊 ).
Bunster is built on the idea of modules. a module consists of one or more files within a directory.
Each bunster module contains a main script (usually named main.sh
) which is the entry point from which the program will start executing. and declaration files which are all other files in the module that have the .sh
extension.
The main script looks just like any other shell script. However, declaration files (which are all .sh
files in the module) are only allowed to declare functions, you cannot run commands in the global scope.
Creating a module
To create a module, all you need is a single file named main.sh
in current working directory.
Within a directory of your choice, create a file named main.sh
with the given content:
main.sh
echo "Hello World"
Compile this module:
bunster build -o hello
this will build an executable program named hello
in current working directory.
Add more files to this module
within same directory, create another file math.sh
:
math.sh
function calculatePercentage(){
total=$1
x=$2
echo $(( (x * 100) / total ))
}
function calculateAge(){
bith_year=$1
currentYear=$(date +%Y)
echo $(( currentYear - bith_year ))
}
Then update main.sh
to use these functions:
calculatePercentage 1024 30
calculateAge 2003
Compile this module:
bunster build -o hello
Now run the program
./hello
This will output:
2
22
TIP
Each module can have as many declaration scripts as needed.
Custom main script
Sometimes the main script is not named main.sh
. When you compile the program, you can pass the name of the main script as the first argument:
├── foo.sh
├── bar.sh
└── baz.sh
Assuming your main script is foo.sh
, you can compile this module like this:
bunster build foo.sh -o hello
Publishing module as library
Publishing a bunster module is as easy as hosting it in a git repository on your preferred git registry such as github
, gitlab
, bitbucket
or even your own server.
We call bunster modules published for others to use as libraries
. as a library, the module may only contain declaration files. in other words. only functions declaraion are allowed in global scope.
Example library
Create a file named hello.sh
with given content:
function hello {
echo "Hello World ✨"
}
that's it, your module is ready. go ahead an put it on a git repository of your choice. in our case we will put it at: https://github.com/yassinebenaid/hello-bunster
Using external libraries
As described above, bunster libraries are hosted on git repositories. for example, we have previously published a library at https://github.com/yassinebenaid/hello-bunster
.
Now, in your project directory, run the following command:
bunster get github.com/yassinebenaid/hello-bunster@684da09acea05d9351c4c61d4296bc696f729533
this command fetches the library from the repository github.com/yassinebenaid/hello-bunster
at commit 684da09acea05d9351c4c61d4296bc696f729533
. And will update the file bunster.yml
with the content:
require:
github.com/yassinebenaid/hello-bunster: 684da09acea05d9351c4c61d4296bc696f729533
That's it, you can use the functions form the library in your own module :
main.sh
hello
Output:
Hello World ✨
Editing bunster.yml
manually
You can list your dependencies manually in bunster.yml
file. for example:
require:
github.com/foo/bar: 684da09acea05d9351c4c61d4296bc696f729533
gitlab.com/baz/boo: 0ef176a380bb9c2410298c7444c93d62fd915357
bitbucket.com/baz/boo: 086d715616f6ec157fb8f2544aa025883acba649
You can download these modules using the command:
bunster get --missing
Why commit hash as version
Security, yes, commit hash is the most secure way to trust the content of a library. it's not the most readable, beutiful or friendly. but that's not as important as security.
If we were to use semantic versionning, library authors can still edit the release content. and no one can trust what the authors may change.
However, commit hash is unique enough that can never be altered. worst thing that can happen is the commit to be deleted.
At least for now, we will continue to use commit hash as version. I don't have the budget to host a checksum database and allow use of semantic versionning as well.