-
Notifications
You must be signed in to change notification settings - Fork 3
/
Docs.txt
183 lines (139 loc) · 7.44 KB
/
Docs.txt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
bashTheObjects
==============
This project is designed to bring OOP to standard bash in way that is
simple. It came about because I wanted to develop a custom linux-installer
for another project and text-based installers are dead, writing my own GUI
would take way too long, and RedHat's installer is way too complicated and
does some things I don't like. So, I decided on a web-based installer. This
has some nice side-effects, such as being able to install to headless systems.
The next question, was what to write it in.
There are plenty of languages around, and thats the problem. I didn't
want people to have to learn some new language to be able to expand and modify
the installer. The obvious solution was plain bash, but maintaining a bash
script over time is incredibly painful. What if bash had OOP?
Enter bashTheObjects!
Calling Methods
===============
First, your main code should source the library file, oop.lib.sh
Then you can import classes with "import". This isn't actually
required as "new" will import classes automatically, but if you want
access to other static methods before calling new, or need to run
other code in your class file at a certain time, import will do it.
import <classname>
Construction:
new <classname> <varname> [<args>]
Ex: new HtmlPage main title: "Cgi Test"
This creates the variable you pass it as an instance and calls the class
constructor. The constructor can get the name of the variable as $varname.
Instance Methods:
varname.method [<args>]
Ex: main.add style: globalStyle content: mainDiv
Like in typical bash, the return value will be numeric. To return some
other variable, print it and call the method like this:
$(varname.method <args>)
Arguments:
Arguments are prefixed with an argument name followed by a colon. You
name your arguments when you pass them. This means that arguments can be in
nearly any order. Your arguments will be placed in local variables of the
same name as the argument. Argument names end with a colon and the space after
the colon is required so that quoted strings function properly.
You can have the an argument be unnamed if you wish. The variable will
be named "value" when it is passed to the method. You can also pass arrays of
values by using an argument called "all". Instance methods have a variable,
"vars", which is a list of all argument variables. The "vars" array can be looped
through. This lets your code manage multiple styles of invocations based on
the arguments it sees.
For example:
main.add all: div1 div2 div3
and I could also do
main.add div4
This last example passes div4 in the variable, "value".
Creating Classes
================
CLASS DEFINITION
A class begins with the "class" keyword followed by the class name.
You should then list the variables and public functions of the class.
public <funcname> makes a public method
inst var <varname> an attribute of an instance
static var <varname> a class variable, shared by all instances
const var <varname> the same as static, but changes aren't saved
You can also specify a default value after any variable and this value is
used to initialize the variable. The word "var" means a generic bash-style
variable. You can place one of your own classnames here or "Array" or "Hash"
to use more complex variables (this feature is still not working).
METHOD DEFINITIONS
You now list all your private and public methods. This is done just as a
normal bash function with a name of class::function. Inside each function,
your arguments, SELF, and CLASS are defined for you. You call private methods
directly as class::function. Beware that this should only be done from inside
another method that you could call with the dot operation described above. If
you absolutely need to call a method from outside the class (static methods),
then use the "callMethod" function. You pass it the SELF variable, then the
classname, then function name, then any arguments. For example:
callMethod '' MyClass MyFunction var1: value var2: value2
... and MyClass::MyFunction will get called, and variables are set
and restored. Obviously, if you use instance variables, you'll need
a valid SELF instead of the placeholder shown.
The constructor has the format classname::classname
GETTERS/SETTERS
You can do this really easy with really short functions. In fact, you can
make your variables public, like this ...
Class::set() { :; }
Class::get() { println ${!value}; }
Make sure those functions are "public" and then you can call them with
varname.set attr1: "value" attr2: "value2" attr3: "My value"
And if the parameter has the same name as an attribute (var) it will be set
Likewise,
$(varname.get attr1)
will return the value of attr1.
Utility Functions
=================
print a safer version of echo. This version has no terminating newline
println as above, with a newline
output like print, but directly to the tty. Use this in a method when
you want to prompt the user, but stdout is captured as a return
value and stderr may be logged to a file.
debug x debug takes the debug level to associate the message with and the
message string. You can set the DEBUG variable to determine how
verbose the output is, or set DEBUG to a filename for everything!
assert Simple asserts. Kills the program if the given value isn't true
typeof returns an object's class
kindof tests if a class is in the inheritance tree
classhas test if a class has a function (like implements, but for class)
fn_exists See if a function exists (fully qualified)
implements tests if a particular method is implemented
new constructor - see above
destroy destroy varname will clean up a variable and call your "ondestroy"
set_instance
use this (no arguments) in your constructor to create a simple
singleton. You'll need a class static called "instance".
return_instance
you call this from a qualified function (class::function) to which
you pass the name of a variable to set (like with new). The new
variable will be set from the static "instance" with all the
blessings of a full-fledged object. See HtmlPage for an example.
import imports a class. The path for classes can be set with CLASSPATH
subclass put this and the name of the class you want to inherit from to
subclass. This is done with the Style and Icon classes as
subclasses of Link.
See the examples for more information.
ARRAYS
======
Both arrays and bash associative arrays are supported via the Array and Hash
built-in classes. Beware the horrible hack that makes this works means that
local variables are copied around, so its not only slow as hell, but using
large arrays will totally kill performace.
Additionally, treat arrays as 1-based. Element 0 is being skipped, so for now
just remember to treat array size ... ${#Array[@]} ... as a loop index (loop
while counter is under this value) and subtract 1 to get a size.
BUGS
====
I bet there are tons of bugs in this, and they may not ever get fixed. I've
decided that this is simply too scarey to maintain. As a proof-of-concept it
has proven that OOP is *possible* in bash, but not desireable. The project
this was going to be used for has been put on hold, and I'll likely go ahead
and write the language I wanted for the project. It will be easier to learn
a new language than work with the idiosyncrosies of bashtheObjects. I keep
this around so that people can play with it and learn a couple of cool shell
tricks.
Email questions/comments to Evan Langlois <[email protected]>