import tab, point

class ShTabber(tab.TokenStackTabber):
    close_tags = {'}': '{',
                  ')': '(',
                  ']': '[',
                  'done': 'do',
                  'fi': 'then',
                  'esac': 'case'}

    def stack_append_const(self, c):
        self.stack_append((c, self.tab_stack[-1][1] + 4))
    def stack_append_unique_const(self, c):
        if self.tab_stack[-1][0] != c:
            self.stack_append((c, self.tab_stack[-1][1] + 4))
    def stack_pop_const(self, *c_args):
        if self.tab_stack[-1][0] in c_args:
            self.stack_pop()
    def stack_pop_all_const(self, *c_args):
        while self.tab_stack[-1][0] in c_args:
            self.stack_pop()

    def handle_token(self, prev_token, token, next_token, y=None):
        buffer = self.mode.window.buffer
        name = token.name
        s = token.string

        if next_token is None and name != "continuation":
            self.stack_pop_all_const(self, "continued")

        if name == 'reserved' or name == "keyword" or name == "delimiter":
            if s == ")" and self.tab_stack[-1][0] == "case":
                pass
            elif s == "then" or s == "do" or s == "(" or s == "[" or s == "case" or s == "{":
                if next_token is None:
                    self.stack_append((s, self.tab_stack[-1][1] + 4))
                else:
                    p = buffer.get_offset_point(next_token.start)
                    self.stack_append((s, p.x))
            elif s == "else":
                assert self.tab_stack[-1][0] == "then", "bbbsssxxx: %s" % self.tab_stack[-1][0]
                d = self.tab_stack[-1][1] - self.tab_stack[-2][1]
                self.line_depth -= d
            elif s in self.close_tags:
                if self.tab_stack[-1][0] == self.close_tags[s]:
                    self.stack_pop()
                    if prev_token is None:
                        self.line_depth = self.tab_stack[-1][1]
                elif self.errors is False:
                    err = "tag mismatch, line %d: expected %r, got %r" % \
                          (self.y, self.tab_stack[-1][0], s)
                    self.mode.window.application.set_error(err)
                    self.errors = True
        elif name == "continuation":
            self.stack_append_unique_const("continued")