def _trg_from_pos(self, buf, pos, implicit=True, DEBUG=False, ac=None, styleClassifier=None): # DEBUG = True # not using 'logging' system, because want to be fast if DEBUG: print "\n----- %s _trg_from_pos(pos=%r, implicit=%r) -----" % (self.lang, pos, implicit) try: if pos == 0: return None if ac is None: ac = AccessorCache(buf.accessor, pos, fetchsize=50) else: ac.resetToPosition(pos) # Ensure this variable is initialized as False, it is used by UDL # for checking if the css style is inside of a html tag, example: # <p style="mycss: value;" /> # When it's found that it is such a case, this value is set True ac.is_html_style_attribute = False last_pos, last_char, last_style = ac.getPrevPosCharStyle() if DEBUG: print " _trg_from_pos:: last_pos: %s" % last_pos print " last_char: %r" % last_char print " last_style: %s" % last_style # All we want to know with sass is if we're in the white-space on # of after the start of a line. If yes, don't trigger, because # the user might want to just type more spaces. if styleClassifier.is_default(last_style): if DEBUG: print " _trg_from_pos:: Default style: %d, ch: %r" % (last_style, last_char) if last_char == "\n": # SASS: we don't want to put up a box until we start typing # something. if DEBUG: print "Found \\n at current pos, don't trigger." return None min_pos = max(0, pos - 200) while last_pos > min_pos: last_pos, last_char, last_style = ac.getPrevPosCharStyle() if styleClassifier.is_default(last_style): if last_char == "\n": return None else: break # Fallback and do SCSS/Less/CSS triggering. # TODO: Support ":color blue" colon-first notation. # TODO: After ",\n", offer tag-names if the above line starts with a tab. # Otherwise, indent the same level, and then offer tag-names. return _NestedCSSLangIntel._trg_from_pos( self, buf, pos, implicit=implicit, DEBUG=DEBUG, ac=None, styleClassifier=styleClassifier ) except IndexError: pass
def _trg_from_pos(self, buf, pos, implicit=True, DEBUG=False, ac=None, styleClassifier=None): # DEBUG = True # not using 'logging' system, because want to be fast if DEBUG: print "\n----- %s _trg_from_pos(pos=%r, implicit=%r) -----"\ % (self.lang, pos, implicit) try: if pos == 0: return None if ac is None: ac = AccessorCache(buf.accessor, pos, fetchsize=50) else: ac.resetToPosition(pos) # Ensure this variable is initialized as False, it is used by UDL # for checking if the css style is inside of a html tag, example: # <p style="mycss: value;" /> # When it's found that it is such a case, this value is set True ac.is_html_style_attribute = False last_pos, last_char, last_style = ac.getPrevPosCharStyle() if DEBUG: print " _trg_from_pos:: last_pos: %s" % last_pos print " last_char: %r" % last_char print " last_style: %s" % last_style # All we want to know with sass is if we're in the white-space on # of after the start of a line. If yes, don't trigger, because # the user might want to just type more spaces. if styleClassifier.is_default(last_style): if DEBUG: print " _trg_from_pos:: Default style: %d, ch: %r" % (last_style, last_char) if last_char == '\n': # SASS: we don't want to put up a box until we start typing # something. if DEBUG: print "Found \\n at current pos, don't trigger." return None min_pos = max(0, pos - 200) while last_pos > min_pos: last_pos, last_char, last_style = ac.getPrevPosCharStyle() if styleClassifier.is_default(last_style): if last_char == '\n': return None else: break # Fallback and do SCSS/Less/CSS triggering. # TODO: Support ":color blue" colon-first notation. # TODO: After ",\n", offer tag-names if the above line starts with a tab. # Otherwise, indent the same level, and then offer tag-names. return _NestedCSSLangIntel._trg_from_pos(self, buf, pos, implicit=implicit, DEBUG=DEBUG, ac=None, styleClassifier=styleClassifier) except IndexError: pass
def preceding_trg_from_pos(self, buf, pos, curr_pos): DEBUG = False # not using 'logging' system, because want to be fast #DEBUG = True # not using 'logging' system, because want to be fast if DEBUG: print "\npreceding_trg_from_pos -- pos: %d, curr_pos: %d" % ( pos, curr_pos, ) if isinstance(buf, UDLBuffer): styleClassifier = UDLCSSStyleClassifier else: styleClassifier = StraightCSSStyleClassifier ac = AccessorCache(buf.accessor, curr_pos+1, fetchsize=50) currTrg = self._trg_from_pos(buf, (curr_pos == pos) and pos or pos+1, implicit=False, DEBUG=DEBUG, ac=ac, styleClassifier=styleClassifier) if DEBUG: print " currTrg: %r" % (currTrg, ) # If we're not looking for a previous trigger, or else the current # trigger position is for a calltip, then do not look any further. if (pos == curr_pos) or (currTrg and currTrg.form == TRG_FORM_CALLTIP): return currTrg # Else, work our way backwards from pos. ac.resetToPosition(pos+1) p, ch, style = ac.getPrevPosCharStyle() if DEBUG: print " preceding_trg_from_pos: p: %r, ch: %r, style: %r" % (p, ch, style) min_p = max(0, p - 200) ignore_styles = styleClassifier.comment_styles + \ styleClassifier.string_styles + \ styleClassifier.number_styles while p > min_p and styleClassifier.is_css_style(style): p, ch, style = ac.getPrecedingPosCharStyle(style, ignore_styles=ignore_styles, max_look_back=100) if DEBUG: print " preceding_trg_from_pos: Trying preceding p: %r, ch: %r, style: %r" % (p, ch, style) if ch and (_isident(ch) or ch in ":( \t"): trg = self._trg_from_pos(buf, p+1, implicit=False, DEBUG=DEBUG, ac=ac, styleClassifier=styleClassifier) if trg is not None: if DEBUG: print "trg: %r" % (trg, ) if currTrg is not None: if currTrg.type != trg.type: if DEBUG: print " Next trigger is a different type, ending search" return None elif currTrg.form != trg.form: return trg elif DEBUG: print " Found same trigger again, continuing " \ "looking for a different trigger" else: return trg return None
def test_basics(self): content = "This is my test buffer\r\nSecond line\r\nThird line\r\n" styles = "1111011011011110111111 2 21111110001111 2 21111101111 2 2".replace(" ", "") ta = _TestAccessor(content, list(map(int, styles))) pos = len(content) - 2 ac = AccessorCache(ta, pos) #ac._debug = True for i in range(2): assert(ac.getPrevPosCharStyle() == (pos-1, "e", 1)) assert(ac.getPrecedingPosCharStyle(1) == (pos-5, " ", 0)) assert(ac.getPrecedingPosCharStyle(0) == (pos-6, "d", 1)) assert(ac.getPrecedingPosCharStyle(1) == (pos-11, "\n", 2)) assert(ac.getPrecedingPosCharStyle() == (pos-13, "e", 1)) assert(ac.getTextBackWithStyle(1) == (pos-16, "line")) assert(ac.getPrevPosCharStyle() == (pos-17, " ", 0)) assert(ac.getPrecedingPosCharStyle(0) == (pos-20, "d", 1)) if i == 0: ac.resetToPosition(pos) assert(ac.getCurrentPosCharStyle() == (pos-20, "d", 1)) #print pos #print ac.getSucceedingPosCharStyle() assert(ac.getNextPosCharStyle() == (pos-19, " ", 0)) assert(ac.getSucceedingPosCharStyle() == (pos-16, "l", 1)) assert(ac.getTextForwardWithStyle(1) == (pos-13, "line")) assert(ac.getNextPosCharStyle() == (pos-12, "\r", 2)) assert(ac.getNextPosCharStyle() == (pos-11, "\n", 2)) assert(ac.getSucceedingPosCharStyle(2) == (pos-10, "T", 1)) assert(ac.getSucceedingPosCharStyle() == (pos-5, " ", 0)) assert(ac.getSucceedingPosCharStyle() == (pos-4, "l", 1)) assert(ac.getSucceedingPosCharStyle() == (pos, "\r", 2)) assert(ac.getNextPosCharStyle() == (pos+1, "\n", 2)) # Bug: http://bugs.activestate.com/show_bug.cgi?id=64227 # Ensure text_range uses correct parameters in boundary situations ac.resetToPosition(3) assert(ac.getTextBackWithStyle(1)[1] == "This") ac.resetToPosition(len(content) - 2) assert(ac.getTextForwardWithStyle(2)[1] == "\r\n")
def test_basics(self): content = "This is my test buffer\r\nSecond line\r\nThird line\r\n" styles = "1111011011011110111111 2 21111110001111 2 21111101111 2 2".replace(" ", "") ta = _TestAccessor(content, map(int, styles)) pos = len(content) - 2 ac = AccessorCache(ta, pos) #ac._debug = True for i in range(2): assert(ac.getPrevPosCharStyle() == (pos-1, "e", 1)) assert(ac.getPrecedingPosCharStyle(1) == (pos-5, " ", 0)) assert(ac.getPrecedingPosCharStyle(0) == (pos-6, "d", 1)) assert(ac.getPrecedingPosCharStyle(1) == (pos-11, "\n", 2)) assert(ac.getPrecedingPosCharStyle() == (pos-13, "e", 1)) assert(ac.getTextBackWithStyle(1) == (pos-16, "line")) assert(ac.getPrevPosCharStyle() == (pos-17, " ", 0)) assert(ac.getPrecedingPosCharStyle(0) == (pos-20, "d", 1)) if i == 0: ac.resetToPosition(pos) assert(ac.getCurrentPosCharStyle() == (pos-20, "d", 1)) #print pos #print ac.getSucceedingPosCharStyle() assert(ac.getNextPosCharStyle() == (pos-19, " ", 0)) assert(ac.getSucceedingPosCharStyle() == (pos-16, "l", 1)) assert(ac.getTextForwardWithStyle(1) == (pos-13, "line")) assert(ac.getNextPosCharStyle() == (pos-12, "\r", 2)) assert(ac.getNextPosCharStyle() == (pos-11, "\n", 2)) assert(ac.getSucceedingPosCharStyle(2) == (pos-10, "T", 1)) assert(ac.getSucceedingPosCharStyle() == (pos-5, " ", 0)) assert(ac.getSucceedingPosCharStyle() == (pos-4, "l", 1)) assert(ac.getSucceedingPosCharStyle() == (pos, "\r", 2)) assert(ac.getNextPosCharStyle() == (pos+1, "\n", 2)) # Bug: http://bugs.activestate.com/show_bug.cgi?id=64227 # Ensure text_range uses correct parameters in boundary situations ac.resetToPosition(3) assert(ac.getTextBackWithStyle(1)[1] == "This") ac.resetToPosition(len(content) - 2) assert(ac.getTextForwardWithStyle(2)[1] == "\r\n")
def _trg_from_pos(self, buf, pos, implicit=True, DEBUG=False, ac=None, styleClassifier=None): #DEBUG = True # not using 'logging' system, because want to be fast if DEBUG: print "\n----- %s _trg_from_pos(pos=%r, implicit=%r) -----"\ % (self.lang, pos, implicit) try: if pos == 0: return None if ac is None: ac = AccessorCache(buf.accessor, pos, fetchsize=50) else: ac.resetToPosition(pos) # Ensure this variable is initialized as False, it is used by UDL # for checking if the css style is inside of a html tag, example: # <p style="mycss: value;" /> # When it's found that it is such a case, this value is set True ac.is_html_style_attribute = False last_pos, last_char, last_style = ac.getPrevPosCharStyle() if DEBUG: print " _trg_from_pos:: last_pos: %s" % last_pos print " last_char: %r" % last_char print " last_style: %s" % last_style # The easy ones are triggering after any of '#.[: '. # For speed, let's get the common ' ' out of the way. The only # trigger on space is 'complete-property-values'. if styleClassifier.is_default(last_style): if DEBUG: print " _trg_from_pos:: Default style: %d, ch: %r" % (last_style, last_char) # Move backwards resolving ambiguity, default on "property-values" min_pos = max(0, pos - 200) while last_pos > min_pos: last_pos, last_char, last_style = ac.getPrevPosCharStyle() if styleClassifier.is_operator(last_style, ac) or styleClassifier.is_value(last_style, ac): if DEBUG: print " _trg_from_pos: space => property-values" return Trigger("CSS", TRG_FORM_CPLN, "property-values", pos, implicit) elif styleClassifier.is_tag(last_style, ac): # Now we need to move further back to see which # region we're in. if DEBUG: print " _trg_from_pos: space => tag-names" return self._get_property_name_trigger_check_context(ac, styleClassifier, pos, implicit) elif styleClassifier.is_identifier(last_style, ac): if DEBUG: print " _trg_from_pos: space => property-names" return Trigger(self.lang, TRG_FORM_CPLN, "tag-or-property-names", pos, implicit) if DEBUG: print " _trg_from_pos: couldn't resolve space, settling on property-names" return Trigger("CSS", TRG_FORM_CPLN, "property-values", pos, implicit) elif styleClassifier.is_operator(last_style, ac): # anchors if DEBUG: print " _trg_from_pos:: OPERATOR style" if last_char == '#': return Trigger("CSS", TRG_FORM_CPLN, "anchors", pos, implicit) elif last_char == ':': try: p, ch, style = ac.getPrevPosCharStyle(ignore_styles=styleClassifier.ignore_styles) if DEBUG: print " _trg_from_pos:: Looking at p: %d, ch: %r, style: %d" % (p, ch, style) except IndexError: style = None if DEBUG: print " _trg_from_pos:: style: %r" % (style) if style and styleClassifier.is_directive(style, ac): # TODO: variables (e.g. "@myvar") are recognized as directives. # There should be no triggers for variable names. return None if style is None or \ not styleClassifier.is_identifier(style, ac): #if style is None or \ # not styleClassifier.is_css_style(style) or \ # styleClassifier.is_class(style, ac): # complete for pseudo-class-names return Trigger("CSS", TRG_FORM_CPLN, "pseudo-class-names", pos, implicit) else: #if styleClassifier.is_identifier(style, ac): # calltip for property-values return Trigger("CSS", TRG_FORM_CALLTIP, "property-values", pos, implicit) # class-names elif last_char == '.': return Trigger("CSS", TRG_FORM_CPLN, "class-names", pos, implicit) # at-rule elif last_char == '@': if self.lang != 'Less': return Trigger("CSS", TRG_FORM_CPLN, "at-rule", pos, implicit) else: # If '@' starts the line, it is an at-rule. Otherwise it # is a Less variable. start = buf.accessor.line_start_pos_from_pos(pos) if not buf.accessor.text_range(start, last_pos).strip(): return Trigger("CSS", TRG_FORM_CPLN, "at-rule", pos, implicit) else: return Trigger(self.lang, TRG_FORM_CPLN, "variable", pos, implicit) # Not quite like CSS: don't handle </ # tag-names elif styleClassifier.is_tag(last_style, ac): # We trigger on tag names of specified length >= 1 char if DEBUG: print " _trg_from_pos:: TAG style" p, ch, style = last_pos, last_char, last_style try: while p >= 0: if DEBUG: print " _trg_from_pos:: Looking at p: %d, ch: %r, style: %d" % (p, ch, style) if not isident(ch): p += 1 break elif style != last_style: if DEBUG: print " _trg_from_pos:: Current style is not a tag: %d" % (style) return None p, ch, style = ac.getPrevPosCharStyle() except IndexError: p = 0 return self._get_property_name_trigger_check_context(ac, styleClassifier, p, implicit) elif styleClassifier.is_identifier(last_style, ac): if DEBUG: print " _trg_from_pos:: IDENTIFIER style" # SCSS variables (not beginning on the start of a line). if last_char == '$' and self.lang == "SCSS": start = buf.accessor.line_start_pos_from_pos(pos) if buf.accessor.text_range(start, last_pos).strip(): return Trigger(self.lang, TRG_FORM_CPLN, "variable", pos, implicit) # property-names #print "here", accessor.text_range(0, pos) # We trigger on identifier names with any length >= 1 char pos = last_pos while pos >= 0: pos, ch, style = ac.getPrevPosCharStyle() if not isident(ch): break elif style != last_style: return None return self._get_property_name_trigger_check_context(ac, styleClassifier, pos + 1, implicit) elif styleClassifier.is_value(last_style, ac): p, ch, style = ac.getPrevPosCharStyle(ignore_styles=styleClassifier.comment_styles) if DEBUG: print " _trg_from_pos:: VALUE style" print " _trg_from_pos:: p: %s" % p print " _trg_from_pos:: ch: %r" % ch print " _trg_from_pos:: style: %s" % style ac.dump() # Implicit triggering only happens on a whitespace character # after any one of these ":,%) " characters # Note: last_char can be a value style yet also be whitespace # in straight CSS. if last_char in WHITESPACE: return Trigger("CSS", TRG_FORM_CPLN, "property-values", last_pos+1, implicit) elif ch in WHITESPACE or ch in ":,%)": # Check to ensure this is not a pseudo-class! Bug: # http://bugs.activestate.com/show_bug.cgi?id=71073 if ch == ":": # Last style must be an identifier then! pp, pch, pstyle = ac.getPrevPosCharStyle( ignore_styles=styleClassifier.ignore_styles) if DEBUG: print "pp: %d, pch: %r, pstyle: %d" % (pp, pch, pstyle) if not styleClassifier.is_identifier(pstyle, ac): # This is likely a pseudo-class definition then, # no trigger here. if DEBUG: print "pseudo-class style found, no trigger." return None return Trigger("CSS", TRG_FORM_CPLN, "property-values", p+1, implicit) # For explicit, we can also be inside a property already if not implicit and isident(ch): # If there is already part of a value there, we need to move # the trigger point "p" to the start of the value. while isident(ch): p, ch, style = ac.getPrevPosCharStyle() return Trigger("CSS", TRG_FORM_CPLN, "property-values", p+1, implicit) return None elif DEBUG: print " _trg_from_pos:: Unexpected style: %d, ch: %r" % (last_style, last_char) # XXX "at-property-names" - Might be used later #elif last_style == SCE_CSS_DIRECTIVE: # # property-names # # We trigger on identifier names with length == 3 # #print "here", accessor.text_range(0, pos) # if pos >= 4 and accessor.char_at_pos(pos - 4) == ' ' and \ # self._is_ident_of_length(accessor, pos, length=3): # # We are good for completion # if DEBUG: # print "Got a trigger for 'at-property-names'" # return Trigger("CSS", TRG_FORM_CPLN, "at-property-names", # pos-3, implicit) except IndexError: # Wen't out of range of buffer before we found anything useful pass if DEBUG: print "----- CSS trg_from_pos() -----" return None
def _trg_from_pos(self, buf, pos, implicit=True, DEBUG=False, ac=None, styleClassifier=None): #DEBUG = True # not using 'logging' system, because want to be fast if DEBUG: print "\n----- %s _trg_from_pos(pos=%r, implicit=%r) -----"\ % (self.lang, pos, implicit) try: if pos == 0: return None if ac is None: ac = AccessorCache(buf.accessor, pos, fetchsize=50) else: ac.resetToPosition(pos) # Ensure this variable is initialized as False, it is used by UDL # for checking if the css style is inside of a html tag, example: # <p style="mycss: value;" /> # When it's found that it is such a case, this value is set True ac.is_html_style_attribute = False last_pos, last_char, last_style = ac.getPrevPosCharStyle() if DEBUG: print " _trg_from_pos:: last_pos: %s" % last_pos print " last_char: %r" % last_char print " last_style: %s" % last_style # The easy ones are triggering after any of '#.[: '. # For speed, let's get the common ' ' out of the way. The only # trigger on space is 'complete-property-values'. if styleClassifier.is_default(last_style): if DEBUG: print " _trg_from_pos:: Default style: %d, ch: %r" % (last_style, last_char) # Move backwards resolving ambiguity, default on "property-values" min_pos = max(0, pos - 200) while last_pos > min_pos: last_pos, last_char, last_style = ac.getPrevPosCharStyle() if styleClassifier.is_operator(last_style, ac) or styleClassifier.is_value(last_style, ac): if DEBUG: print " _trg_from_pos: space => property-values" return Trigger("CSS", TRG_FORM_CPLN, "property-values", pos, implicit, extra={"ac": ac}) elif styleClassifier.is_tag(last_style, ac): # Now we need to move further back to see which # region we're in. if DEBUG: print " _trg_from_pos: space => tag-names" return self._get_property_name_trigger_check_context(ac, styleClassifier, pos, implicit) elif styleClassifier.is_identifier(last_style, ac): if DEBUG: print " _trg_from_pos: space => property-names" return Trigger(self.lang, TRG_FORM_CPLN, "tag-or-property-names", pos, implicit, extra={"ac": ac}) if DEBUG: print " _trg_from_pos: couldn't resolve space, settling on property-names" return Trigger("CSS", TRG_FORM_CPLN, "property-values", pos, implicit, extra={"ac": ac}) elif styleClassifier.is_operator(last_style, ac): # anchors if DEBUG: print " _trg_from_pos:: OPERATOR style" if last_char == '#': return Trigger("CSS", TRG_FORM_CPLN, "anchors", pos, implicit, extra={"ac": ac}) elif last_char == ':': try: p, ch, style = ac.getPrevPosCharStyle(ignore_styles=styleClassifier.ignore_styles) if DEBUG: print " _trg_from_pos:: Looking at p: %d, ch: %r, style: %d" % (p, ch, style) except IndexError: style = None if DEBUG: print " _trg_from_pos:: style: %r" % (style) if style is None or \ not styleClassifier.is_identifier(style, ac): #if style is None or \ # not styleClassifier.is_css_style(style) or \ # styleClassifier.is_class(style, ac): # complete for pseudo-class-names return Trigger("CSS", TRG_FORM_CPLN, "pseudo-class-names", pos, implicit, extra={"ac": ac}) else: #if styleClassifier.is_identifier(style, ac): # calltip for property-values return Trigger("CSS", TRG_FORM_CALLTIP, "property-values", pos, implicit, extra={"ac": ac}) # class-names elif last_char == '.': return Trigger("CSS", TRG_FORM_CPLN, "class-names", pos, implicit, extra={"ac": ac}) # at-rule elif last_char == '@': #p, ch, style = ac.getPrevPosCharStyle(ignore_styles=styleClassifier.comment_styles) # XXX - Should check not beyond first rule set # - Should check not within a rule block. return Trigger("CSS", TRG_FORM_CPLN, "at-rule", pos, implicit, extra={"ac": ac}) # Not quite like CSS: don't handle </ # tag-names elif styleClassifier.is_tag(last_style, ac): # We trigger on tag names of specified length >= 1 char if DEBUG: print " _trg_from_pos:: TAG style" p, ch, style = last_pos, last_char, last_style try: while p >= 0: if DEBUG: print " _trg_from_pos:: Looking at p: %d, ch: %r, style: %d" % (p, ch, style) if not isident(ch): p += 1 break elif style != last_style: if DEBUG: print " _trg_from_pos:: Current style is not a tag: %d" % (style) return None p, ch, style = ac.getPrevPosCharStyle() except IndexError: p = 0 return self._get_property_name_trigger_check_context(ac, styleClassifier, p, implicit) elif styleClassifier.is_identifier(last_style, ac): if DEBUG: print " _trg_from_pos:: IDENTIFIER style" # property-names #print "here", accessor.text_range(0, pos) # We trigger on identifier names with any length >= 1 char pos = last_pos while pos >= 0: pos, ch, style = ac.getPrevPosCharStyle() if not isident(ch): break elif style != last_style: return None return self._get_property_name_trigger_check_context(ac, styleClassifier, pos + 1, implicit) elif styleClassifier.is_value(last_style, ac): p, ch, style = ac.getPrevPosCharStyle(ignore_styles=styleClassifier.comment_styles) if DEBUG: print " _trg_from_pos:: VALUE style" print " _trg_from_pos:: p: %s" % p print " _trg_from_pos:: ch: %r" % ch print " _trg_from_pos:: style: %s" % style ac.dump() # Implicit triggering only happens on a whitespace character # after any one of these ":,%) " characters # Note: last_char can be a value style yet also be whitespace # in straight CSS. if last_char in WHITESPACE: return Trigger("CSS", TRG_FORM_CPLN, "property-values", last_pos+1, implicit, extra={"ac": ac}) elif ch in WHITESPACE or ch in ":,%)": # Check to ensure this is not a pseudo-class! Bug: # http://bugs.activestate.com/show_bug.cgi?id=71073 if ch == ":": # Last style must be an identifier then! pp, pch, pstyle = ac.getPrevPosCharStyle( ignore_styles=styleClassifier.ignore_styles) if DEBUG: print "pp: %d, pch: %r, pstyle: %d" % (pp, pch, pstyle) if not styleClassifier.is_identifier(pstyle, ac): # This is likely a pseudo-class definition then, # no trigger here. if DEBUG: print "pseudo-class style found, no trigger." return None return Trigger("CSS", TRG_FORM_CPLN, "property-values", p+1, implicit, extra={"ac": ac}) # For explicit, we can also be inside a property already if not implicit and isident(ch): # If there is already part of a value there, we need to move # the trigger point "p" to the start of the value. while isident(ch): p, ch, style = ac.getPrevPosCharStyle() return Trigger("CSS", TRG_FORM_CPLN, "property-values", p+1, implicit, extra={"ac": ac}) return None elif DEBUG: print " _trg_from_pos:: Unexpected style: %d, ch: %r" % (last_style, last_char) # XXX "at-property-names" - Might be used later #elif last_style == SCE_CSS_DIRECTIVE: # # property-names # # We trigger on identifier names with length == 3 # #print "here", accessor.text_range(0, pos) # if pos >= 4 and accessor.char_at_pos(pos - 4) == ' ' and \ # self._is_ident_of_length(accessor, pos, length=3): # # We are good for completion # if DEBUG: # print "Got a trigger for 'at-property-names'" # return Trigger("CSS", TRG_FORM_CPLN, "at-property-names", # pos-3, implicit, extra={"ac": ac}) except IndexError: # Wen't out of range of buffer before we found anything useful pass if DEBUG: print "----- CSS trg_from_pos() -----" return None
def _trg_from_pos(self, buf, pos, implicit=True, DEBUG=False, ac=None, styleClassifier=None): #DEBUG = True # not using 'logging' system, because want to be fast if DEBUG: print "\n----- CSS _trg_from_pos(pos=%r, implicit=%r) -----"\ % (pos, implicit) try: if pos == 0: return None if ac is None: ac = AccessorCache(buf.accessor, pos, fetchsize=50) else: ac.resetToPosition(pos) # Ensure this variable is initialized as False, it is used by UDL # for checking if the css style is inside of a html tag, example: # <p style="mycss: value;" /> # When it's found that it is such a case, this value is set True ac.is_html_style_attribute = False last_pos, last_char, last_style = ac.getPrevPosCharStyle() if DEBUG: print " _trg_from_pos:: last_pos: %s" % last_pos print " last_char: %r" % last_char print " last_style: %s" % last_style # The easy ones are triggering after any of '#.[: '. # For speed, let's get the common ' ' out of the way. The only # trigger on space is 'complete-property-values'. if styleClassifier.is_default(last_style): if DEBUG: print " _trg_from_pos:: Default style: %d, ch: %r" % (last_style, last_char) # This may not even be a property-value, but at this stage we # don't care, as it will get worked out later in the # asynchronous call async_eval_at_trg(). return Trigger("CSS", TRG_FORM_CPLN, "property-values", pos, implicit, extra={"ac": ac}) elif styleClassifier.is_operator(last_style, ac): # anchors if DEBUG: print " _trg_from_pos:: OPERATOR style" if last_char == '#': return Trigger("CSS", TRG_FORM_CPLN, "anchors", pos, implicit, extra={"ac": ac}) elif last_char == ':': try: p, ch, style = ac.getPrevPosCharStyle(ignore_styles=styleClassifier.ignore_styles) if DEBUG: print " _trg_from_pos:: Looking at p: %d, ch: %r, style: %d" % (p, ch, style) except IndexError: style = None if DEBUG: print " _trg_from_pos:: style: %r" % (style) if style is None or \ not styleClassifier.is_identifier(style, ac): #if style is None or \ # not styleClassifier.is_css_style(style) or \ # styleClassifier.is_class(style, ac): # complete for pseudo-class-names return Trigger("CSS", TRG_FORM_CPLN, "pseudo-class-names", pos, implicit, extra={"ac": ac}) else: #if styleClassifier.is_identifier(style, ac): # calltip for property-values return Trigger("CSS", TRG_FORM_CALLTIP, "property-values", pos, implicit, extra={"ac": ac}) # class-names elif last_char == '.': return Trigger("CSS", TRG_FORM_CPLN, "class-names", pos, implicit, extra={"ac": ac}) # at-rule elif last_char == '@': #p, ch, style = ac.getPrevPosCharStyle(ignore_styles=styleClassifier.comment_styles) # XXX - Should check not beyond first rule set # - Should check not within a rule block. return Trigger("CSS", TRG_FORM_CPLN, "at-rule", pos, implicit, extra={"ac": ac}) elif last_char == '/': try: p, ch, style = ac.getPrevPosCharStyle() except IndexError: pass else: if ch == "<": # Looks like start of closing '</style>' # tag. While typing this the styling will # still be in the CSS range. return Trigger(buf.m_lang, TRG_FORM_CPLN, "end-tag", pos, implicit) # tag-names elif styleClassifier.is_tag(last_style, ac): # We trigger on tag names of specified length >= 1 char if DEBUG: print " _trg_from_pos:: TAG style" p, ch, style = last_pos, last_char, last_style try: while p >= 0: if DEBUG: print " _trg_from_pos:: Looking at p: %d, ch: %r, style: %d" % (p, ch, style) if not _isident(ch): p += 1 break elif style != last_style: if DEBUG: print " _trg_from_pos:: Current style is not a tag: %d" % (style) return None p, ch, style = ac.getPrevPosCharStyle() except IndexError: p = 0 return Trigger("CSS", TRG_FORM_CPLN, "tag-names", p, implicit, extra={"ac": ac}) elif styleClassifier.is_identifier(last_style, ac): if DEBUG: print " _trg_from_pos:: IDENTIFIER style" # property-names #print "here", accessor.text_range(0, pos) # We trigger on identifier names with any length >= 1 char pos = last_pos while pos >= 0: pos, ch, style = ac.getPrevPosCharStyle() if not _isident(ch): break elif style != last_style: return None return Trigger("CSS", TRG_FORM_CPLN, "property-names", pos+1, implicit, extra={"ac": ac}) elif styleClassifier.is_value(last_style, ac): p, ch, style = ac.getPrevPosCharStyle(ignore_styles=styleClassifier.comment_styles) if DEBUG: print " _trg_from_pos:: VALUE style" print " _trg_from_pos:: p: %s" % p print " _trg_from_pos:: ch: %r" % ch print " _trg_from_pos:: style: %s" % style ac.dump() # Implicit triggering only happens on a whitespace character # after any one of these ":,%) " characters # Note: last_char can be a value style yet also be whitespace # in straight CSS. if last_char in WHITESPACE: return Trigger("CSS", TRG_FORM_CPLN, "property-values", last_pos+1, implicit, extra={"ac": ac}) elif ch in WHITESPACE or ch in ":,%)": # Check to ensure this is not a pseudo-class! Bug: # http://bugs.activestate.com/show_bug.cgi?id=71073 if ch == ":": # Last style must be an identifier then! pp, pch, pstyle = ac.getPrevPosCharStyle( ignore_styles=styleClassifier.ignore_styles) if DEBUG: print "pp: %d, pch: %r, pstyle: %d" % (pp, pch, pstyle) if not styleClassifier.is_identifier(pstyle, ac): # This is likely a pseudo-class definition then, # no trigger here. if DEBUG: print "pseudo-class style found, no trigger." return None return Trigger("CSS", TRG_FORM_CPLN, "property-values", p+1, implicit, extra={"ac": ac}) # For explicit, we can also be inside a property already if not implicit and _isident(ch): # If there is already part of a value there, we need to move # the trigger point "p" to the start of the value. while _isident(ch): p, ch, style = ac.getPrevPosCharStyle() return Trigger("CSS", TRG_FORM_CPLN, "property-values", p+1, implicit, extra={"ac": ac}) return None elif styleClassifier.is_default(last_style): if DEBUG: print " _trg_from_pos:: Default style: %d, ch: %r" % (last_style, last_char) p, ch, style = ac.getPrecedingPosCharStyle(last_style) while style in styleClassifier.identifier_styles: p, ch, style = ac.getPrecedingPosCharStyle(style) if styleClassifier.is_operator(style) and ch in ":,)": return Trigger("CSS", TRG_FORM_CPLN, "property-values", p+1, implicit, extra={"ac": ac}) elif DEBUG: print " _trg_from_pos:: Unknown style: %d, ch: %r" % (last_style, last_char) # XXX "at-property-names" - Might be used later #elif last_style == SCE_CSS_DIRECTIVE: # # property-names # # We trigger on identifier names with length == 3 # #print "here", accessor.text_range(0, pos) # if pos >= 4 and accessor.char_at_pos(pos - 4) == ' ' and \ # self._is_ident_of_length(accessor, pos, length=3): # # We are good for completion # if DEBUG: # print "Got a trigger for 'at-property-names'" # return Trigger("CSS", TRG_FORM_CPLN, "at-property-names", # pos-3, implicit, extra={"ac": ac}) except IndexError: # Wen't out of range of buffer before we found anything useful pass if DEBUG: print "----- CSS trg_from_pos() -----" return None