'XML trigger types:
xml-complete-tags-and-namespaces    <|
xml-complete-ns-tags                <x:|
xml-complete-tag-attrs              <x:foo |
xml-complete-ns-tag-attrs           <x:foo y:|
xml-complete-attr-enum-values       <x:foo y:bar="|
xml-complete-end-tag                <x ...>...</|
xml-complete-well-known-ns          <x xmlns:|
xml-gt-bang                         <!|
Not yet implemented:
xml-complete-well-known-ns-value    <x xmlns:x="|
xml-complete-prolog                 <?xml |
xml-complete-doctype                <!DOCTYPE |'

def trg_from_pos(self, buf, pos, implicit=True, DEBUG=False):

    if isinstance(buf, UDLBuffer):
        styles = udl_styles
    else:
        styles = pure_styles
    if DEBUG:
        print ('\n-----    UDL    %s    trg_from_pos(pos=%r,    implicit=%r)    -----' % (self.lang, pos, implicit))
    if (pos == 0):
        return None
    accessor = buf.accessor
    buf_length = accessor.length()
    last_pos = (pos - 1)
    last_char = accessor.char_at_pos(last_pos)
    last_style = accessor.style_at_pos(last_pos)
    if DEBUG:
        print ('        last_pos:    %s' % last_pos)
        print ('        last_char:    %r' % last_char)
        print ('        last_style:    %r    %s' % (last_style, buf.style_names_from_style_num(last_style)))
    if (((last_char == '<') and (last_style in styles[STYLE_DEFAULT])) or (last_style == styles[STYLE_START_TAG])):
        return Trigger(self.lang, TRG_FORM_CPLN, 'tags-and-namespaces', pos, implicit)
    elif ((last_char == '/') and (last_style == styles[STYLE_END_TAG])):
        return Trigger(self.lang, TRG_FORM_CPLN, 'end-tag', pos, implicit)
    elif (last_char == ':'):
        if (last_style in (styles[STYLE_TAG_NAME], styles[STYLE_ATTR_NAME])):
            current_word = accessor.text_range(*accessor.contiguous_style_range_from_pos(last_pos))
            if (current_word.count(':') != 1):
                return None
            if ((current_word == 'xmlns:') and (last_style == styles[STYLE_ATTR_NAME])):
                return Trigger(self.lang, TRG_FORM_CPLN, 'well-known-ns', pos, implicit)
            if (last_style == styles[STYLE_TAG_NAME]):
                return Trigger(self.lang, TRG_FORM_CPLN, 'ns-tags', pos, implicit)
            else:
                return Trigger(self.lang, TRG_FORM_CPLN, 'ns-tags-attrs', pos, implicit)
    elif ((last_char == '!') and (pos >= 2)):
        last_last_char = accessor.char_at_pos((pos - 2))
        last_last_style = accessor.style_at_pos((pos - 2))
        if ((last_last_char == '<') and (last_last_style in styles[STYLE_DEFAULT])):
            return Trigger(self.lang, TRG_FORM_CPLN, 'gt-bang', pos, implicit)
    elif ((last_char in ('    ', ' DCTB ', '\n')) and (last_style == styles[STYLE_TAG_SPACE])):
        have_trg = False
        while (last_pos > 0):
            last_pos -= 1
            last_style = accessor.style_at_pos(last_pos)
            if (last_style in (styles[STYLE_TAG_SPACE], styles[STYLE_DEFAULT])):
                pass
            elif (last_style in styles[STYLE_STRING]):
                have_trg = True
                break
            elif (last_style == styles[STYLE_TAG_NAME]):
                while (last_pos > 0):
                    last_pos -= 1
                    last_style = accessor.style_at_pos(last_pos)
                    if (last_style == styles[STYLE_TAG_NAME]):
                        pass
                    elif (last_style == styles[STYLE_START_TAG]):
                        have_trg = True
                        break
                    else:
                        break
                break
            else:
                return None
        if have_trg:
            return Trigger(self.lang, TRG_FORM_CPLN, 'tag-attrs', pos, implicit)
        else:
            return None
    elif ((last_char in ("'", '"')) and (last_style in styles[STYLE_STRING]) and (pos >= 5)):
        prev_style = accessor.style_at_pos((pos - 2))
        if (prev_style == last_style):
            return None
        else:
            return Trigger(self.lang, TRG_FORM_CPLN, 'attr-enum-values', pos, implicit)
    return None
