First commit!

This commit is contained in:
Ad5001 2021-12-28 00:44:16 +01:00
commit 573d2da85e
Signed by: Ad5001
GPG Key ID: EF45F9C6AFE20160
5 changed files with 175 additions and 0 deletions

55
README.md Normal file
View File

@ -0,0 +1,55 @@
# BashOOP
This idea was inspired from https://stackoverflow.com/a/40981277 in order to be adapted into making a proper OOP with constructors, properties and namespace system for bash.
## Reference:
- .shn: **SH**ell **N**amespace
- .shc: **SH**ell **C**lass
## Example syntax:
### Declaring objects.
`script.sh`:
This is the main script which will use our objects.
```bash
. $OOP_ROOT/oop.sh # Import library.
importNamespace Example.shn
Example.Object t "Test"
```
`Example.shn`:
This file declares our namespace and all the objects within it.
```bash
# Namespace declaration.
namespace Example
# If namespace is set to null (no argument), then the object will be declared globally.
# Otherwise, the object will be declared within the namespace.
# Object declaration, from class name to file name.
class Object "Object.shc"
```
`Object.shc`:
This file will contain the object code.
```bash
# Property declaration
property Object.name
# Optional constructor.
Object.constructor() {
Object.name = $1
}
# Example function
Object.print() {
echo "Example OOP from $($this.name)!"
}
```

7
example/Example.shn Normal file
View File

@ -0,0 +1,7 @@
# Namespace declaration.
namespace Example
# If namespace is set to null (no argument), then the object will be declared globally.
# Otherwise, the object will be declared within the namespace.
# Object declaration, from class name to file name.
class Object "Object.shc"

12
example/Object.shc Normal file
View File

@ -0,0 +1,12 @@
# Property declaration
property Object.name
# Optional constructor.
Object.constructor() {
Object.name = $1
}
# Example function
Object.print() {
echo "Example OOP from $(this.name)!"
}

16
example/script.sh Normal file
View File

@ -0,0 +1,16 @@
#!/bin/bash
OOP_ROOT=..
. $OOP_ROOT/oop.sh # Import library.
importNamespace Example.shn
Example.Object t1 "Test"
Example.Object t2 "Example"
t1.print
t2.print
t1.name = "New name"
t1.print

85
oop.sh Normal file
View File

@ -0,0 +1,85 @@
#!/bin/bash
# This file contains all functions required to create a namespace.
# Internal variables are marked with a beginning underscore, like in most other languages.
# Signatures are a list of arguments.. Those within <> are mandatory, the ones within [] are optional.
_namespace=""
_namespacePath=""
# Namespace declaration.
# Signature: ([string namespaceName])
namespace() {
_namespace=$1;
}
# Imports a namespace into the current shell.
# Signature: (<string namespaceFile>)
importNamespace() {
namespaceFile=$1
# Save the path in order to get the absolute path of the file.
_namespacePath=$(realpath $(dirname $namespaceFile))
. $namespaceFile
}
# Creates an object instance.
# Signature: (<string type>, <string associatedFile>, <string variableName>, [string[] constructorArguments])
_createObject() {
type=$1
associatedFile=$2
varName=$3
constructorArguments=${@:4}
# Declare dummy constructor.
eval "$varName.constructor() { :; }"
# Create property array.
eval "declare -Ag _${varName}_properties"
# Imports the file and replace all "<Type>." with the variable name.
. <(sed s/this\\./$varName./g <(sed s/$type\\./$varName./g $associatedFile))
# Call the constructor
eval "$varName.constructor $constructorArguments"
}
# Object creation.
# Signature: (<string type>, <string associatedFile>)
class() {
type=$1 # Type of the object as declared within the file.
associatedFile=$2
objFullName=$type # Type of the object referenced elsewhere
if [ "$_namespace" != "" ]; then
objFullName="${_namespace}.$type"
fi
if [ ${associatedFile::1} != "/" ]; then # Relative path, we save only the absolute path
associatedFile="$_namespacePath/$associatedFile"
fi
# Declares a new function for object initialisation.
eval "$objFullName() { _createObject $type $associatedFile \$@; }"
}
# Associated function for properties
# Signature: (<string variableName>, <string propertyName>, [string operator, string value])
_accessProperty() {
varName=$1
prop=$2
if [ "$3" == "=" ]; then
eval "_${varName}_properties[$prop]='${@:4}'"
else
eval "echo \${_${varName}_properties[$prop]}"
fi
}
# Declares a property.
# Signature: (<string propertyFullName>)
property() {
propertyFullName=$1
# Split the name by ".". First element is variable name,
# second is property name.
propertyNames=($(echo $propertyFullName | tr "." "\n"))
varName=${propertyNames[0]}
prop=${propertyNames[1]}
# Default value
eval "_${varName}_properties[$prop]=''"
# Property alias
eval "$propertyFullName() { _accessProperty $varName $prop \$@; }"
}