diff --git a/mo b/mo
index 82c0a7a..89490ef 100755
--- a/mo
+++ b/mo
@@ -24,26 +24,109 @@ mustache-is-function() {
 # Process a chunk of content some number of times.
 #
 # Parameters:
-#     $1: Destination variable name for the modified content
-#     $2: Content to parse and reparse and reparse
-#     $3: Ending tag for the parser
-#     $4-*: Values to insert into the parsed content
+#     $1: Content to parse and reparse and reparse
+#     $2: Tag prefix (context name)
+#     $3-*: Names to insert into the parsed content
 mustache-loop() {
-    local CONTENT DEST_NAME END_TAG MODIFIED_CONTENT
+    local CONTENT CONTEXT CONTEXT_BASE IGNORE
 
-    DEST_NAME=$1
-    CONTENT=$2
-    END_TAG=$3
-    shift 3
+    CONTENT=$1
+    CONTEXT_BASE=$2
+    shift 2
 
-    # This MUST loop at least once or assignment back to ${!DEST_NAME}
-    # will not work.
     while [[ "${#@}" -gt 0 ]]; do
-        mustache-parse MODIFIED_CONTENT "$CONTENT" "$END_TAG" "$1" false
+        mustache-full-tag-name CONTEXT "$CONTEXT_BASE" "$1"
+        mustache-parse IGNORE "$CONTENT" "" "$CONTEXT" false
         shift
     done
+}
 
-    local "$DEST_NAME" && mustache-indirect "$DEST_NAME" "$MODIFIED_CONTENT"
+
+# Return a dotted name based on current context and target name
+#
+# Parameters:
+#     $1: Target variable to store results
+#     $2: Context name
+#     $3: Desired variable name
+mustache-full-tag-name() {
+    if [[ -z "$2" ]]; then
+        local "$1" && mustache-indirect "$1" "$3"
+    else
+        local "$1" && mustache-indirect "$1" "${2}.${3}"
+    fi
+}
+
+
+# Eat content until the right end tag is found.  Returns an array with the
+# following members:
+#     [0] = Content before end tag
+#     [1] = End tag (complete tag)
+#     [2] = Content after end tag
+#
+# Everything using this function uses the "standalone tags" logic.
+#
+# Parameters:
+#     $1: Where to store the array
+#     $2: Content
+#     $3: Name of end tag
+#     $4: If -z, do standalone tag processing before finishing
+mustache-find-end-tag() {
+    local CONTENT SCANNED
+
+    # Find open tags
+    SCANNED=""
+    mustache-split CONTENT "$2" '{{' '}}'
+
+    while [[ "${#CONTENT[@]}" -gt 1 ]]; do
+        mustache-trim-whitespace TAG "${CONTENT[1]}"
+        
+        # Restore CONTENT[1] before we start using it
+        CONTENT[1]='{{'"${CONTENT[1]}"'}}'
+
+        case $TAG in
+            '#'* | '^'*)
+                # Start another block
+                SCANNED="${SCANNED}${CONTENT[0]}${CONTENT[1]}"
+                mustache-trim-whitespace TAG "${TAG:1}"
+                mustache-find-end-tag CONTENT "${CONTENT[2]}" "$TAG" "loop"
+                SCANNED="${SCANNED}${CONTENT[0]}${CONTENT[1]}"
+                CONTENT=${CONTENT[2]}
+                ;;
+
+            '/'*)
+                # End a block - could be ours
+                mustache-trim-whitespace TAG "${TAG:1}"
+                SCANNED="$SCANNED${CONTENT[0]}"
+
+                if [[ "$TAG" == "$3" ]]; then
+                    # Found our end tag
+                    if [[ -z "$4" ]] && mustache-is-standalone STANDALONE_BYTES "$SCANNED" "${CONTENT[2]}" false; then
+                        # This is also a standalone tag - clean up whitespace
+                        STANDALONE_BYTES=( $STANDALONE_BYTES )
+                        SCANNED="${SCANNED:0:${STANDALONE_BYTES[0]}}"
+                        CONTENT[2]="${CONTENT[2]:${STANDALONE_BYTES[1]}}"
+                    fi
+
+                    local "$1" && mustache-indirect-array "$1" "$SCANNED" "${CONTENT[1]}" "${CONTENT[2]}"
+                    return 0
+                fi
+
+                SCANNED="$SCANNED${CONTENT[1]}"
+                CONTENT=${CONTENT[2]}
+                ;;
+
+            *)
+                # Ignore all other tags
+                SCANNED="${SCANNED}${CONTENT[0]}${CONTENT[1]}"
+                CONTENT=${CONTENT[2]}
+                ;;
+        esac
+
+        mustache-split CONTENT "$CONTENT" '{{' '}}'
+    done
+
+    # Did not find our closing tag
+    local "$1" && mustache-indirect-array "$1" "${SCANNED}" "" ""
 }
 
 
@@ -53,12 +136,12 @@ mustache-loop() {
 #     $1: Where to store content left after parsing
 #     $2: Block of text to change
 #     $3: Stop at this closing tag  (eg "/NAME")
-#     $4: Current value (what {{.}} will mean)
+#     $4: Current name (the variable NAME for what {{.}} means)
 #     $5: true when no content before this, false otherwise
 mustache-parse() {
     # Keep naming variables MUSTACHE_* here to not overwrite needed variables
     # used in the string replacements
-    local MUSTACHE_CONTENT MUSTACHE_CURRENT MUSTACHE_END_TAG MUSTACHE_IS_BEGINNING MUSTACHE_TAG
+    local MUSTACHE_BLOCK MUSTACHE_CONTENT MUSTACHE_CURRENT MUSTACHE_END_TAG MUSTACHE_IS_BEGINNING MUSTACHE_TAG
 
     MUSTACHE_END_TAG=$3
     MUSTACHE_CURRENT=$4
@@ -76,26 +159,23 @@ mustache-parse() {
                 # Sets context
                 mustache-standalone-allowed MUSTACHE_CONTENT "${MUSTACHE_CONTENT[@]}" $MUSTACHE_IS_BEGINNING
                 mustache-trim-whitespace MUSTACHE_TAG "${MUSTACHE_TAG:1}"
+                mustache-find-end-tag MUSTACHE_BLOCK "$MUSTACHE_CONTENT" "$MUSTACHE_TAG"
+                mustache-full-tag-name MUSTACHE_TAG "$MUSTACHE_CURRENT" "$MUSTACHE_TAG"
 
                 if mustache-test "$MUSTACHE_TAG"; then
                     # Show / loop / pass through function
                     if mustache-is-function "$MUSTACHE_TAG"; then
-                        # This is slower - need to parse twice to avoid
-                        # subshells.  First, pass content to function but
-                        # the updated MUSTACHE_CONTENT is lost due to subshell.
-                        $MUSTACHE_TAG "$(mustache-parse MUSTACHE_CONTENT "$MUSTACHE_CONTENT" "$MUSTACHE_TAG" "" false)"
-
-                        # Secondly, update MUSTACHE_CONTENT but do not output.
-                        mustache-parse MUSTACHE_CONTENT "$MUSTACHE_CONTENT" "$MUSTACHE_TAG" "" false > /dev/null 2>&1
+                        MUSTACHE_CONTENT=$($MUSTACHE_TAG "${MUSTACHE_BLOCK[0]}")
+                        mustache-parse MUSTACHE_CONTENT "$MUSTACHE_CONTENT" "" "$MUSTACHE_CURRENT" false
+                        MUSTACHE_CONTENT="${MUSTACHE_BLOCK[2]}"
                     elif mustache-is-array "$MUSTACHE_TAG"; then
-                        eval 'mustache-loop MUSTACHE_CONTENT "$MUSTACHE_CONTENT" "$MUSTACHE_TAG" "${'"$MUSTACHE_TAG"'[@]}"'
+                        eval 'mustache-loop "${MUSTACHE_BLOCK[0]}" "$MUSTACHE_TAG" "${!'"$MUSTACHE_TAG"'[@]}"'
                     else
-                        mustache-parse MUSTACHE_CONTENT "$MUSTACHE_CONTENT" "$MUSTACHE_TAG" "$(mustache-show "$MUSTACHE_TAG")" false
+                        mustache-parse MUSTACHE_CONTENT "${MUSTACHE_BLOCK[0]}" "" "$MUSTACHE_CURRENT" false
                     fi
-                else
-                    # Do not show
-                    mustache-parse MUSTACHE_CONTENT "$MUSTACHE_CONTENT" "$MUSTACHE_TAG" false > /dev/null
                 fi
+
+                MUSTACHE_CONTENT="${MUSTACHE_BLOCK[2]}"
                 ;;
 
             '>'*)
@@ -116,31 +196,23 @@ mustache-parse() {
                 ;;
 
             '/'*)
-                # Closing tag - If we hit MUSTACHE_END_TAG, we're done.
+                # Closing tag - If hit in this loop, we simply ignore
+                # Matching tags are found in mustache-find-end-tag
                 mustache-standalone-allowed MUSTACHE_CONTENT "${MUSTACHE_CONTENT[@]}" $MUSTACHE_IS_BEGINNING
-                mustache-trim-whitespace MUSTACHE_TAG "${MUSTACHE_TAG:1}"
-
-                if [[ "$MUSTACHE_TAG" == "$MUSTACHE_END_TAG" ]]; then
-                    # Tag hit - done
-                    local "$1" && mustache-indirect "$1" "$MUSTACHE_CONTENT"
-                    return 0
-                fi
-
-                # If the tag does not match, we ignore this tag
                 ;;
 
             '^'*)
                 # Display section if named thing does not exist
                 mustache-standalone-allowed MUSTACHE_CONTENT "${MUSTACHE_CONTENT[@]}" $MUSTACHE_IS_BEGINNING
                 mustache-trim-whitespace MUSTACHE_TAG "${MUSTACHE_TAG:1}"
+                mustache-find-end-tag MUSTACHE_BLOCK "$MUSTACHE_CONTENT" "$MUSTACHE_TAG"
+                mustache-full-tag-name MUSTACHE_TAG "$MUSTACHE_CURRENT" "$MUSTACHE_TAG"
 
-                if mustache-test "$MUSTACHE_TAG"; then
-                    # Do not show
-                    mustache-parse MUSTACHE_CONTENT "$MUSTACHE_CONTENT" "$MUSTACHE_TAG" "" false > /dev/null 2>&1
-                else
-                    # Show
-                    mustache-parse MUSTACHE_CONTENT "$MUSTACHE_CONTENT" "$MUSTACHE_TAG" "" false
+                if ! mustache-test "$MUSTACHE_TAG"; then
+                    mustache-parse MUSTACHE_CONTENT "${MUSTACHE_BLOCK[0]}" "" "$MUSTACHE_CURRENT" false
                 fi
+
+                MUSTACHE_CONTENT="${MUSTACHE_BLOCK[2]}"
                 ;;
 
             '!'*)
@@ -152,7 +224,7 @@ mustache-parse() {
             .)
                 # Current content (environment variable or function)
                 mustache-standalone-denied MUSTACHE_CONTENT "${MUSTACHE_CONTENT[@]}"
-                echo -n "$MUSTACHE_CURRENT"
+                mustache-show "$MUSTACHE_CURRENT" "$MUSTACHE_CURRENT"
                 ;;
 
             '=')
@@ -168,23 +240,26 @@ mustache-parse() {
                 MUSTACHE_CONTENT="${MUSTACHE_TAG:1}"'}}'"$MUSTACHE_CONTENT"
                 mustache-split MUSTACHE_CONTENT "$MUSTACHE_CONTENT" '}}}'
                 mustache-trim-whitespace MUSTACHE_TAG "${MUSTACHE_CONTENT[0]}"
+                mustache-full-tag-name MUSTACHE_TAG "$MUSTACHE_CURRENT" "$MUSTACHE_TAG"
                 MUSTACHE_CONTENT=${MUSTACHE_CONTENT[1]}
 
                 # Now show the value
-                mustache-show "$MUSTACHE_TAG"
+                mustache-show "$MUSTACHE_TAG" "$MUSTACHE_CURRENT"
                 ;;
 
             '&'*)
                 # Unescaped
                 mustache-standalone-denied MUSTACHE_CONTENT "${MUSTACHE_CONTENT[@]}"
                 mustache-trim-whitespace MUSTACHE_TAG "${MUSTACHE_TAG:1}"
-                mustache-show "$MUSTACHE_TAG"
+                mustache-full-tag-name MUSTACHE_TAG "$MUSTACHE_CURRENT" "$MUSTACHE_TAG"
+                mustache-show "$MUSTACHE_TAG" "$MUSTACHE_CURRENT"
                 ;;
 
             *)
                 # Normal environment variable or function call
                 mustache-standalone-denied MUSTACHE_CONTENT "${MUSTACHE_CONTENT[@]}"
-                mustache-show "$MUSTACHE_TAG"
+                mustache-full-tag-name MUSTACHE_TAG "$MUSTACHE_CURRENT" "$MUSTACHE_TAG"
+                mustache-show "$MUSTACHE_TAG" "$MUSTACHE_CURRENT"
                 ;;
         esac
 
@@ -281,13 +356,27 @@ mustache-standalone-denied() {
 
 # Show an environment variable or the output of a function.
 #
+# Limit/prefix any variables used
+#
 # Parameters:
 #     $1: Name of environment variable or function
+#     $2: Current context
 mustache-show() {
+    local CONTENT MUSTACHE_NAME_PARTS
+
     if mustache-is-function "$1"; then
-        $1
-    else
+        CONTENT=$($1 "")
+        mustache-parse CONTENT "$CONTENT" "" "$2" false
+        return 0
+    fi
+
+    mustache-split MUSTACHE_NAME_PARTS "$1" "."
+    
+    if [[ -z "${MUSTACHE_NAME_PARTS[1]}" ]]; then
         echo -n "${!1}"
+    else
+        # Further subindexes are disallowed
+        eval 'echo -n "${'"${MUSTACHE_NAME_PARTS[0]}"'['"${MUSTACHE_NAME_PARTS[1]%%.*}"']}"'
     fi
 }
 
@@ -300,6 +389,7 @@ mustache-show() {
 #
 # Parameters:
 #     $1: Name of environment variable or function
+#     $2: Current value (our context)
 #
 # Return code:
 #     0 if the name is not empty, 1 otherwise
@@ -330,7 +420,10 @@ mustache-is-array() {
     local MUSTACHE_TEST
 
     MUSTACHE_TEST=$(declare -p "$1" 2>/dev/null) || return 1
-    [[ "${MUSTACHE_TEST:0:10}" == "declare -a" ]] || return 1
+    [[ "${MUSTACHE_TEST:0:10}" == "declare -a" ]] && return 0
+    [[ "${MUSTACHE_TEST:0:10}" == "declare -A" ]] && return 0
+
+    return 1
 }
 
 
diff --git a/tests/array.expected b/tests/array.expected
index aa1dee6..a45557c 100644
--- a/tests/array.expected
+++ b/tests/array.expected
@@ -1,6 +1,3 @@
-
   <b>resque</b>
-
   <b>hub</b>
-
   <b>rip</b>
diff --git a/tests/function.expected b/tests/function.expected
index 67e44a3..a55e97c 100644
--- a/tests/function.expected
+++ b/tests/function.expected
@@ -1,2 +1,2 @@
-<b>
-  Willy is awesome.</b>
+<b>  Willy is awesome.
+</b>
diff --git a/tests/inverted.expected b/tests/inverted.expected
index a3df620..2730fcf 100644
--- a/tests/inverted.expected
+++ b/tests/inverted.expected
@@ -1,3 +1,2 @@
 
-
   No repos :(
diff --git a/tests/mush.expected b/tests/mush.expected
index 3cc885a..1e04ed6 100644
--- a/tests/mush.expected
+++ b/tests/mush.expected
@@ -1,5 +1,4 @@
 
-
 jwerle is male
 apple is red
 tobi is cool
diff --git a/tests/non-false.env b/tests/non-false.env
deleted file mode 100644
index 83105eb..0000000
--- a/tests/non-false.env
+++ /dev/null
@@ -1 +0,0 @@
-person=Jon
diff --git a/tests/non-false.expected b/tests/non-false.expected
deleted file mode 100644
index 23cfca4..0000000
--- a/tests/non-false.expected
+++ /dev/null
@@ -1,2 +0,0 @@
-
-  Hi Jon!
diff --git a/tests/non-false.template b/tests/non-false.template
deleted file mode 100644
index fe0e022..0000000
--- a/tests/non-false.template
+++ /dev/null
@@ -1,3 +0,0 @@
-{{#person}}
-  Hi {{.}}!
-{{/person}}
diff --git a/tests/partial.expected b/tests/partial.expected
index cc95c9b..8d66fc0 100644
--- a/tests/partial.expected
+++ b/tests/partial.expected
@@ -1,3 +1,3 @@
 <h2>Names</h2>
-
   <strong>Tyler</strong>
+
diff --git a/tests/typical.expected b/tests/typical.expected
index 9eeff21..cb51809 100644
--- a/tests/typical.expected
+++ b/tests/typical.expected
@@ -1,4 +1,3 @@
 Hello Chris
 You have just won 10000 dollars!
-
 Well, 6000 dollars, after taxes.