(2014-09-08) The Big Reveal

So it's pretty obvious from my last post that I'm working on a pesudo class module for bashlib.

Currently it's going really well, I wont ever be able to get the full range of class abilities in Bash, what I have can be used in a rudementary way. My previous example wasn't amazing, so here's a better one:

#!/bin/bash
source ~/bin/bashlib/bashlib.sh
bashlib.load "class"

User__construct () {
	this : name="No_Name"
	this : dob="1970-01-01"
	this : phone="11111111111"
	this : notes="N/A"
}

User_GetInfo () {
	echo "User  --" $( this . )
	echo "Name:     " $( this - name )
	echo "DOB:      " $( this - dob )
	echo "Phone:    " $( this - phone )
	echo "Notes:    " $( this - notes )
}

USERS=( "bob"		"jim"		"sarah"		"jane"		"joe"		"noname" )
NAMES=( "Wight, Bob"	"Bishop, Jim"	"Amis, Sarah"	"Smith, Jane"	"Blogs, Joe" )
DATES=( "1972-11-18"	"1975-08-23"	"1979-02-05"	"1968-04-22" )
PHONE=( "01189434321"	"01189693219"	"01189679234" )

for (( i=0; i < ${#USERS[@]}; i++ )); do
	class.new User "${USERS[${i}]}" { name="${NAMES[${i}]}" dob="${DATES[${i}]}" phone="${PHONE[${i}]}" }
done

This takes the information from NAMES/DATES/PHONE arrays and puts them in to classes based on the USERS array. So, you could easily do:

bob : GetInfo
jim : GetInfo
sarah : GetInfo
jane : GetInfo
joe : GetInfo
noname : GetInfo

Which would then print out the details provided by the previous arrays. The good thing about this class function, is that the CLASS__construct function runs initially. Which means that you can set default variables, instead of relying on the class.new function filling them all in. This is apparent with the users "jane" "joe" and "noname", which have an increasing amount of data ommited from their arrays. Rather than just being blank though, they will take the defaults set in User__construct. With a simple tweak to the for loop above, we can print the information out:

for (( i=0; i < ${#USERS[@]}; i++ )); do
	class.new User "${USERS[${i}]}" { name="${NAMES[${i}]}" dob="${DATES[${i}]}" phone="${PHONE[${i}]}" }
	${USERS[${i}]} : GetInfo
	(( i != ${#USERS[@]} - 1 )) && echo "=========="
done

This will give the results:

% bash class.test.sh
User  -- bob
Name:    Wight, Bob
DOB:     1972-11-18
Phone:   01189434321
Notes:   N/A
==========
User  -- jim
Name:    Bishop, Jim
DOB:     1975-08-23
Phone:   01189693219
Notes:   N/A
==========
User  -- sarah
Name:    Amis, Sarah
DOB:     1979-02-05
Phone:   01189679234
Notes:   N/A
==========
User  -- jane
Name:    Smith, Jane
DOB:     1968-04-22
Phone:   11111111111
Notes:   N/A
==========
User  -- joe
Name:    Blogs, Joe
DOB:     1970-01-01
Phone:   11111111111
Notes:   N/A
==========
User  -- noname
Name:    No_Name
DOB:     1970-01-01
Phone:   11111111111
Notes:   N/A

As I progress with the implimentation, I'll do my best to explain in more detail. But hopefully that gives you some idea of what to expect.

One of the key features of this new class system is the contextual "this" function. It's incredibly difficult to actually return the true name of a function in bash. The FUNCNAME array *might* contain it, if it's called in the right way. But a more surefire way is to simply pass the custom FUNC_NAME variable around (without the user needing to). This allows for a pretty powerful set of commands that you can run by calling "this" instead of needing to use specific names.

In the above example we use 3 of the 4 currently avaliable commands:

this .			# . Displays the name of the current class
this : variable=value	# : Sets variables
this - variable		# : Prints a variable value
this @ FunctionName	# @ runs a self named function (eg MyClass_FunctionName)

This allows you to set variables, run other functions all from within a class function and without needing outside help to determine which class it should affect.

The above would be similar to itterating over this (still in a class setting):

sName="joe"
echo ${sName}				# . Equivilant
${sName} : variable=value		# : Equivilant
${sName} : variable			# - Equivilant
this @ FunctionName			# @ runs a self named function (eg MyClass_FunctionName)

While for a single set, that works fine; if you need two users, Joe and Jane, you would need to type a second set of calls. And then for three, four, five etc.


On a similar note, 1.5.3 should be avaliable now and 1.6.0 should be coming in the next few days (I'm still trying to make sure bugs have been ironed out with the class system).

Update: change log for 1.5.3:

1.5.2b -> 1.5.3
+Moved modules from lib/ to modules/
+Added README
+Added CHANGELOG
+Added offical and extension module notation
+Changed how bashlib.version works (it now calls itself with the -v switch)