diff --git a/tconfpy.3 b/tconfpy.3 index 629a221..9fe9d7b 100644 --- a/tconfpy.3 +++ b/tconfpy.3 @@ -894,9 +894,17 @@ Variable names may not contain whitespace. .IP \(bu 4 -Variable names may not begin with \'$\'. The one exception +Variable names may not begin with the \'$\' character. The one exception to this is when you are referencing the value of an environment -variable. +variable. References to environment variables begin with \'$\': + +.nf + # A reference to an environment variable is legal + x = [$TERM] + + # Attempting to create a new variable starting with \'$\' is illegal + $MYVAR = something +.fi .IP \(bu 4 Variable names cannot have the \'#\' character anywhere in them @@ -1114,7 +1122,7 @@ variable assignment .B and reference is "relative" to the namespace. What this really means is -that \*(TC sticks the namspace plus a period in front of every +that \*(TC sticks the namspace plus a \'.\' in front of every variable assigned or referenced. It does this automatically and invisibly, so \'Brand\' is turned into \'MyCar.Brand\' and so on. You can actually check this by loading the example above into a test @@ -1131,16 +1139,14 @@ table. You're likely scratching your head wondering why on earth this -feature present in \*(TC. There are, in fact, several reasons for it: +feature present in \*(TC. There are several good reasons for it: .IP \(bu 4 - It reduces typing repetetive information throughout the configuration file. In turn, this reduces the likelyhood of a typographical or spelling error. .IP \(bu 4 - It helps visibly organize the configuration file. A namespace makes it clear which variables are related to each other somehow. This is no big deal in small configurations, but \*(TC was written with the idea @@ -1148,7 +1154,6 @@ even tens of thousands of entries. .IP \(bu 4 - It simplifies the application programmer's job. Say I want to write a program that extracts all the information about your car from the configuration file, but I don't know ahead of time how many things you @@ -1161,7 +1166,6 @@ .B and the program does not have to be rewritten. .IP \(bu 4 - It helps enforce correct configuration files. By default, you can introduce new namespaces into the configuration file any time you like. However, as described in the previous section on the @@ -1172,30 +1176,30 @@ namespaces you can enter to reference or create variables. -.SS Lexical Namespace Specifics +.SS Rules For Using Lexical Namespace Creating and using lexical namespaces is fairly straightforward, but there are a few restrictions and rules: .IP \(bu 4 - -The default initial namespace is the empty string, "". In this one case, -\*(TC does nothing to variables assigned or referenced. That's -why our early examples of how to assign a value to a variable and -then reference those value in the previous section worked. -When the namespace is "", nothing is done to the variable names. -The namespace, "", is also called the "root namespace." +The default initial namespace is the empty string, "". In this one +case, \*(TC does nothing to variables assigned or referenced. That's +why our early examples in the previous section worked. When we +assigned a value to a variable and then referenced that variable +value, we did so while in the so-called "root" namespace, "". When +the namespace is "", nothing is done to the variable names Bear in mind that the programmer can change this default namespace to -something other than "" before the configuration file is parsed. If -they do this, they would be well advised to let their users know this -fact. +something other than "" before the configuration file is ever +processed. If they do this, they would be well advised to let their +users know this fact. .IP \(bu 4 There two ways to change to a new namespace: .nf [NewNameSpace] # Must appear on a line by itself or with a comment only +OR NAMESPACE = NewNamespace .fi @@ -1204,38 +1208,109 @@ .nf [] +OR NAMESPACE = .fi -So, why are there two ways to do the same thing? +So, why are there two ways to do the same thing? The first way is the more +common, and the more readable way to do it. It appears on a line by itself and +makes it clear that the namespace is being changed. However, because variable +references cannot be "nested", you can only use strings of text here. + +Suppose you want to change the namespace in a way that depends on the +value of another variable. For instance: + +.nf + LOCATION = Timbuktu + NAMESPACE = [LOCATION]-East +.fi + +In other words, the second form of a namespace change allows you to +employ the \*(TC string substitution and variable referencing +features. Bear in mind that \*(TC is case-sensitive so this +will not work as you expect: + +.nf + Namespace = something +.fi + +This just set the value of the variable \'Namespace\' to +\'something\' and has nothing whatsoever to do with lexical +namespaces. + +This all works, by the way, because \'NAMESPACE\' is +nothing more than (yet) another variable in the symbol table. \*(TC +just understands that variable to be special - it treats it as the +repository of the current lexical namespace. +.IP \(bu 4 + +Whichever method you use to change it, +.B the new namespace cannot begin with \'$\'. +Both of the following will cause an error: + +.nf + [$FOO] +OR + x = $FOO + NAMESPACE = [x] +.fi +.IP \(bu 4 +By default, all variable assignments and references are +.B relative to the currently active namespace: -In other words, \*(TC always prepends the current namespace (plus a -separating period) to any variable assignment or reference it finds in -a configuration. The one exception is when the namespace is "", in -which case \*(TC does not add anything to the variable names. +.nf + [MyNameSpace] -By default, the initial namespace is always "", but you can change this -as desired. Note, however, that the programmer can change this default -initial namespace if they wish. Also there is a programming option -(\'AllowNewNamespaces\', described in the previous section) which can limit -you to using only the namespaces the programmer has pre-defined. i.e., You -will not be able to create -.B new -namespaces of your own invention. + foo = 123 # Creates a variable called \'MyNameSpace.foo\' + x = bar # Means: \'MyNameSpace.x = MyNameSpace.bar\' +.fi -You can change to a new namespace anytime within the configuration file -a number of ways: +.IP \(bu 4 +If you want to set or reference a variable in a namespace different +than the current namespace, you must use a so-called "absolute" +variable name. You do this by "escaping" the variable name. To escape the +name, begin it with a \'.\' and then use the +.B full name (including namespace) +of that variable. (This is called the "fully qualified variable +name".) For example: +.nf + [NS1] # Switch to the namespace \'NS1\' + foo = 14 # Creates \'NS1.foo\' -So how do you access variables in a namespace different than the one -you are in currently? + [NS2] # Switch to the \'NS2\' namespace + foo = [.NS1.foo] # Sets \'NS2.foo = 14\' +.fi +There is another clever way to do this without using the escape +character. \*(TC has no understanding whatsoever of what a +lexical namespace actually is. It does nothing more than +"glue" the current namespace to any variable names and references +in your configuration file. Internally, all variables are +named +.B relative to the root namespace. +This means that you can use the fully qualified variable name +without any escape character any time you are in the root +namespace: -What's the point of all this namespace business anyway? +.nf + [NS1] # Switch to the namespace \'NS1\' + foo = 14 # Creates \'NS1.foo\' + + [] # Switch to the root namespace + foo = [NS1.foo] # Sets \'foo = 14\' - no escape needed +.fi + +.IP \(bu 4 +\*(TC keeps track of every new namespace you create and returns that +list to the calling program to use as it wishes. (See the section +above entitled, +.B The Initial Symbol Table And Lexical Namespaces +for details.) .SS Pre-Defined Variables