Shell Namespaces – Understanding Shell Namespaces

shell

Is there a way to source a shell script into a namespace, preferably a bash shell script but I would look into other shells if they had this feature and bash didn't.

What I mean by that is, e.g., something like "prefix all defined symbols with something so that they don't collide with already defined symbols (variable names, function names, aliases)" or any other facility that prevents name collisions.

If there's a solution where I can namespace at source time (NodeJS style), that would be the best.

Example code:

$ echo 'hi(){ echo Hello, world; }' > english.sh
$ echo 'hi(){ echo Ahoj, světe; }' > czech.sh
$ . english.sh
$ hi
 #=> Hello, world
$ . czech.sh #bash doesn't even warn me that `hi` is being overwritten here
$ hi
 #=> Ahoj, světe
#Can't use the English hi now
#And sourcing the appropriate file before each invocation wouldn't be very efficient 

Best Answer

From man ksh on a system with a ksh93 installed...

  • Name Spaces
    • Commands and functions that are executed as part of the list of a namespace command that modify variables or create new ones, create a new variable whose name is the name of the name space as given by identifier preceded by .. When a variable whose name is name is referenced, it is first searched for using .identifier.name.
    • Similarly, a function defined by a command in the namespace list is created using the name space name preceded by a ..
    • When the list of a namespace command contains a namespace command, the names of variables and functions that are created consist of the variable or function name preceded by the list of identifiers each preceded by .. Outside of a name space, a variable or function created inside a name space can be referenced by preceding it with the name space name.
    • By default, variables staring with .sh are in the sh name space.

And, to demonstrate, here is the concept applied to a namespace provided by default for every regular shell variable assigned in a ksh93 shell. In the following example I will define a discipline function that will act as the assigned .get method for the $PS1 shell variable. Every shell variable basically gets its own namespace with, at least, the default get, set, append, and unset methods. After defining the following function, any time the variable $PS1 is referenced in the shell, the output of date will be drawn at the top of the screen...

function PS1.get {
    printf "\0337\33[H\33[K%s\0338" "${ date; }"
}

(Also note the lack of the () subshell in the above command substitution)

Technically, namespaces and disciplines are not exactly the same thing (because disciplines can be defined to apply either globally or locally to a particular namespace), but they are both part and parcel to the conceptualization of shell data types which is fundamental to ksh93.

To address your particular examples:

echo 'function hi { echo Ahoj, světe\!;  }' >  czech.ksh
echo 'function hi { echo Hello, World\!; }' >english.ksh
namespace english { . ./english.ksh; }
namespace czech   { . ./czech.ksh;   }
.english.hi; .czech.hi

Hello, World!
Ahoj, světe!

...or...

for ns in czech english
do  ".$ns.hi"
done

Ahoj, světe!
Hello, World!