def testEscapeXmlRemovesInvalidControlCharacters(self): for char in xml_tools.INVALID_CONTROL_CHARACTERS: xmlStr = u"%s\u2026" % chr(char) self.assertEquals(xml_tools.escape_xml(xmlStr), u"\u2026") xmlStr = "%shi" % chr(char) self.assertEquals(xml_tools.escape_xml(xmlStr), "hi") return xmlStr
def testEscapeXmlRemovesInvalidControlCharacters( self ): for char in xml_tools.INVALID_CONTROL_CHARACTERS: xmlStr = u"%s\u2026" % chr( char ) self.assertEquals( xml_tools.escape_xml(xmlStr), u"\u2026" ) xmlStr = "%shi" % chr( char ) self.assertEquals( xml_tools.escape_xml(xmlStr), "hi" ) return xmlStr
def __newCreateLines(self, quasimode): """ LONGTERM TODO: Document this. """ lines = [] suggestionList = quasimode.getSuggestionList() description = smart_quote(suggestionList.getDescription()) description = escape_xml(description) didyoumean_hint = suggestionList.getDidyoumeanHint() if didyoumean_hint: didyoumean_hint = escape_xml(didyoumean_hint) suggestions = suggestionList.getSuggestions() activeIndex = suggestionList.getActiveIndex() lines.append(layoutXmlLine( xml_data=self.LINE_XML % description, styles=retrieveDescriptionStyles(), scale=DESCRIPTION_SCALE, )) text = suggestions[0].toXml() if len(text) == 0: text = escape_xml(suggestions[0].getSource()) # Highlight traling space in the input area if needed if text.endswith(" ") and TRAILING_SPACE_STRING: text = text[:-1] + \ u"<endspace>%s</endspace>" % TRAILING_SPACE_STRING lines.append(layoutXmlLine( xml_data=self.LINE_XML % text, styles=retrieveAutocompleteStyles(active=(activeIndex == 0)), scale=AUTOCOMPLETE_SCALE, )) if didyoumean_hint: hint_text = config.DIDYOUMEAN_HINT_TEXT % didyoumean_hint else: hint_text = "" lines.append(layoutXmlLine( xml_data=self.LINE_XML % hint_text, styles=retrieveDidyoumeanHintStyles(), scale=DIDYOUMEANHINT_SCALE, )) for index in range(1, len(suggestions)): lines.append(layoutXmlLine( xml_data=self.LINE_XML % suggestions[index].toXml(), styles=retrieveSuggestionStyles(active=(activeIndex == index)), scale=SUGGESTION_SCALE, )) return lines
def run(self, seldict=None): if seldict is None: seldict = self._selection.get() text = seldict.get("text", "").strip() evalSuccessful = False append = False if text.endswith("="): text = text[:-1].strip() append = True if not text: self._displayMessage("<p>No code to evaluate!</p>") else: try: code = compile(text, "<selected text>", "eval") result = eval(code, {"__builtins__": None}, {}) evalSuccessful = True except Exception as e: self._displayMessage("<p>Error: %s</p>" % xml_tools.escape_xml(str(e))) if evalSuccessful: resulttext = str(repr(result)) if append: newtext = "%s = %s" % (text, resulttext) else: newtext = resulttext self._selection.set({"text": newtext})
def draw(self): if not self.__isDirty: return self.__isDirty = False suggestions = self.getSuggestions() if not suggestions: self.hide() return #styles = layout.retrieveParameterSuggestionStyles() #styles.update('document', margin_top = '0.0pt') DOCUMENT_XML = "<document>%s</document>" LINE_XML = "<line>%s</line>" ACTIVE_LINE_XML = "<line><alt>%s</alt></line>" lines_xml = [] active = self.getActiveIndex() for i, line in enumerate(suggestions): lines_xml.append( (ACTIVE_LINE_XML if i == active else LINE_XML) % escape_xml(line) ) xml_data = DOCUMENT_XML % "".join(lines_xml) lines = layout.layoutXmlLine( xml_data=xml_data, styles=self.styles, scale=layout.PARAMETERSUGGESTION_SCALE, ) self.__window.draw(lines, active)
def __showBadCommandMsg(self, userText): """ Displays an error message telling the user that userText does not match any command. Also, if there are any reasonable commands that were similar but not matching, offers those to the user as suggestions. """ # Generate a caption for the message with a couple suggestions # for command names similar to the user's text caption = self.__commandSuggestionCaption(escape_xml(userText)) badCmd = userText.lower() badCmd = escape_xml(badCmd) # Create and display a primary message. text = config.BAD_COMMAND_MSG text = text % (badCmd, caption) messages.displayMessage(text)
def __showBadCommandMsg( self, userText ): """ Displays an error message telling the user that userText does not match any command. Also, if there are any reasonable commands that were similar but not matching, offers those to the user as suggestions. """ # Generate a caption for the message with a couple suggestions # for command names similar to the user's text caption = self.__commandSuggestionCaption( escape_xml( userText ) ) badCmd = userText.lower() badCmd = escape_xml( badCmd ) # Create and display a primary message. text = config.BAD_COMMAND_MSG text = text % ( badCmd, caption ) messages.displayMessage( text )
def __newCreateLines(self, quasimode): """ LONGTERM TODO: Document this. """ lines = [] suggestionList = quasimode.getSuggestionList() description = suggestionList.getDescription() description = escape_xml(description) suggestions = suggestionList.getSuggestions() activeIndex = suggestionList.getActiveIndex() lines.append( layoutXmlLine( xml_data=self.LINE_XML % description, styles=retrieveDescriptionStyles(), scale=DESCRIPTION_SCALE, )) if len(suggestions[0].toXml()) == 0: text = suggestions[0].getSource() text = escape_xml(text) else: text = suggestions[0].toXml() lines.append( layoutXmlLine( xml_data=self.LINE_XML % text, styles=retrieveAutocompleteStyles(active=(activeIndex == 0)), scale=AUTOCOMPLETE_SCALE, )) for index in range(1, len(suggestions)): isActive = (activeIndex == index) lines.append( layoutXmlLine( xml_data=self.LINE_XML % suggestions[index].toXml(), styles=retrieveSuggestionStyles(active=isActive), scale=SUGGESTION_SCALE, )) return lines
def __newCreateLines( self, quasimode ): """ LONGTERM TODO: Document this. """ lines = [] suggestionList = quasimode.getSuggestionList() description = suggestionList.getDescription() description = escape_xml( description ) suggestions = suggestionList.getSuggestions() activeIndex = suggestionList.getActiveIndex() lines.append( layoutXmlLine( xml_data = self.LINE_XML % description, styles = retrieveDescriptionStyles(), scale = DESCRIPTION_SCALE, ) ) text = suggestions[0].toXml() if len(text) == 0: text = escape_xml( suggestions[0].getSource() ) # Highlight traling space in the input area if needed if text.endswith(" ") and TRAILING_SPACE_STRING: text = text[:-1] + u"<endspace>%s</endspace>" % TRAILING_SPACE_STRING lines.append( layoutXmlLine( xml_data = self.LINE_XML % text, styles = retrieveAutocompleteStyles( active = (activeIndex==0) ), scale = AUTOCOMPLETE_SCALE, ) ) for index in range( 1, len(suggestions) ): isActive = (activeIndex==index) lines.append( layoutXmlLine( xml_data = self.LINE_XML % suggestions[index].toXml(), styles = retrieveSuggestionStyles( active = isActive ), scale = SUGGESTION_SCALE, ) ) return lines
def __newCreateLines( self, quasimode ): """ LONGTERM TODO: Document this. """ lines = [] suggestionList = quasimode.getSuggestionList() description = suggestionList.getDescription() description = escape_xml( description ) suggestions = suggestionList.getSuggestions() activeIndex = suggestionList.getActiveIndex() lines.append( layoutXmlLine( xml_data = self.LINE_XML % description, styles = retrieveDescriptionStyles(), scale = DESCRIPTION_SCALE, ) ) if len(suggestions[0].toXml()) == 0: text = suggestions[0].getSource() text = escape_xml( text ) else: text = suggestions[0].toXml() lines.append( layoutXmlLine( xml_data = self.LINE_XML % text, styles = retrieveAutocompleteStyles( active = (activeIndex==0) ), scale = AUTOCOMPLETE_SCALE, ) ) for index in range( 1, len(suggestions) ): isActive = (activeIndex==index) lines.append( layoutXmlLine( xml_data = self.LINE_XML % suggestions[index].toXml(), styles = retrieveSuggestionStyles( active = isActive ), scale = SUGGESTION_SCALE, ) ) return lines
def layoutMessageXml(xmlMarkup, width, size, height, ellipsify="false", raiseLayoutExceptions=False): """ Lays out the xmlMarkup in a block that is width wide. if raiseLayoutExceptions is False, then this function will suppress any exceptions raised when parsing xmlMarkup and replace it with a message that tells the end-user that the message was broken, providing the end-user with as much of the original message as possible. If raiseLayoutExceptions is True, however, any exceptions raised will be passed through to the caller. """ maxLines = int(height / (size * LINE_SPACING)) _styles.update( "document", width="%fpt" % width, line_height="%spt" % int(size * LINE_SPACING), max_lines=maxLines, font_size="%spt" % size, ellipsify=ellipsify, ) try: document = xmltextlayout.xmlMarkupToDocument(xmlMarkup, _styles, _tagAliases) except MaxLinesExceededError: pass except Exception as e: if raiseLayoutExceptions: raise logging.warn("Could not layout message text %s; got error %s" % (xmlMarkup, e)) document = xmltextlayout.xmlMarkupToDocument( "<document><p>%s</p>%s</document>" % (escape_xml(xmlMarkup.strip()), "<caption>from a broken message</caption>"), _styles, _tagAliases) return document
def layoutMessageXml( xmlMarkup, width, size, height, ellipsify="false", raiseLayoutExceptions=False ): """ Lays out the xmlMarkup in a block that is width wide. if raiseLayoutExceptions is False, then this function will suppress any exceptions raised when parsing xmlMarkup and replace it with a message that tells the end-user that the message was broken, providing the end-user with as much of the original message as possible. If raiseLayoutExceptions is True, however, any exceptions raised will be passed through to the caller. """ maxLines = int( height / (size*LINE_SPACING) ) _styles.update( "document", width = "%fpt" % width, line_height = "%spt" % int(size*LINE_SPACING), max_lines = maxLines, font_size = "%spt" % size, ellipsify = ellipsify, ) try: document = xmltextlayout.xmlMarkupToDocument( xmlMarkup, _styles, _tagAliases ) except MaxLinesExceededError: pass except Exception, e: if raiseLayoutExceptions: raise logging.warn( "Could not layout message text %s; got error %s" % ( xmlMarkup, e ) ) document = xmltextlayout.xmlMarkupToDocument( "<document><p>%s</p>%s</document>" % ( escape_xml( xmlMarkup.strip() ), "<caption>from a broken message</caption>" ), _styles, _tagAliases )
def __commandSuggestionCaption(self, userText): """ Creates and returns a caption suggesting one or two commands that are similar to userText. """ # Retrieve one or two command name suggestions. suggestions = self.__cmdManager.retrieveSuggestions(userText) # FIXME: It seems that this will never get any matches if suggestions: cmds = [s.toText() for s in suggestions] ratioBestMatch = string_ratio_best_match(userText.lower(), cmds) caption = config.ONE_SUGG_CAPTION caption = caption % escape_xml(ratioBestMatch) else: # There were no suggestions; so we don't want a caption. caption = "" return caption
def run(self, seldict=None): if seldict is None: seldict = self._selection.get() text = seldict.get("text", u"").strip() evalSuccessful = False append = False if text.endswith("="): text = text[:-1].strip() append = True if not text: self._displayMessage("<p>No code to evaluate!</p>") else: try: code = compile(text, "<selected text>", "eval") result = eval(code, {"__builtins__": None}, {}) evalSuccessful = True except Exception, e: self._displayMessage("<p>Error: %s</p>" % xml_tools.escape_xml(str(e)))
def __transform(self): if self.__start is not None: #s = escape_xml(self.__suggestion) xmlText = "%s<ins>%s</ins>%s<ins>%s</ins>" % (escape_xml( self.__suggestion[ :self.__prefix_end]), escape_xml( self.__suggestion[ self.__prefix_end:self.__prefix_end + self.__start]), escape_xml( self.__suggestion[ self.__prefix_end + self.__start:self.__prefix_end + self.__end]), escape_xml( self.__suggestion[ self.__prefix_end + self.__end:])) if self.__suggestedPrefix and xmlText.startswith( self.__suggestedPrefix): xmlText = "<prefix>%s</prefix>%s" % (escape_xml( self.__suggestedPrefix), xmlText[len(self.__suggestedPrefix):]) # Finally, add help text, if it exists. if self.__helpText is not None: xmlText = "%s<help>%s</help>" % (xmlText, escape_xml(self.__helpText)) self.__xml = xmlText return else: pass # We are going to "use up" both the source string and the # suggestion unusedSource = self.__source[:] unusedSuggestion = self.__suggestion[:] # The xml representation xmlText = "" # The "to the next word" completion. completion = "" # If we cannot match an initial substring of unusedSource, # then we are going to peel off characters one-by-one into # this variable. These characters have been lost in the # suggestion, and will cause "insertions" to instead be # "alterations". unmatchedChars = "" # BEGIN SOURCE-STRING LOOP # Each iteration of this loop should reduce the length of # unusedSource, and this loop ends when unusedSource is empty. while len(unusedSource) > 0: # Save a copy of unusedSource, so we know if it changes. oldUnusedSource = unusedSource[:] # Loop from the full length of unusedSource down to one # character for i in range(len(unusedSource), 0, -1): # The initial substring we are trying to locate. target = unusedSource[:i] # BEGIN TARGET-FOUND CONDITION if target in unusedSuggestion: # Search normally from begining index = unusedSuggestion.find(target) # Search on word boundaries. This is different from \b in # that it considers also the underscore character as a word # boundary. m = re.match( r".*[^0-9a-zA-Z](%s)" % re.escape(target), unusedSuggestion, re.I) if m and m.groups() and m.start(1) > index: # Prefer word boundary match index = m.start(1) # index, m.start(1) if index > 0: if len(unmatchedChars) > 0: # There were unused characters in the # source, and there were characters in the # unused suggestion before the target, so # the next "inserted" portion of the # suggestion becomes an "alteration" # instead. xml_format = "<alt>%s</alt>" else: xml_format = "<ins>%s</ins>" xmlText += xml_format % escape_xml( unusedSuggestion[:index] ) # NOTE: Do not add inserted characters to the # 'next word' completion. # Whether or not there were characters between # the start of the unused suggestion and "here", # any unmatched chars are now defunct. unmatchedChars = "" xmlText += escape_xml(target) completion += target unusedSuggestion = unusedSuggestion[index + len(target):] unusedSource = unusedSource[i:] # The target was found and unusedSource was # modified; we exit the for-loop (to be entered # again if unusedSource is still nonempty). break # END TARGET-FOUND CONDITION # Either unusedSource is smaller, or it is the same as # oldUnusedSource. If it is the same as old unusedSource, # then there was no match of a beginning substring, so we # remove the first character and store it as an "unused # character", which will become part of an "altered # substring", if there is a match to a later substring. if unusedSource == oldUnusedSource: unmatchedChars += unusedSource[0] unusedSource = unusedSource[1:] assert len(unusedSource) < len(oldUnusedSource), \ "Potential infinite loop condition; failed to reduce"\ " the length of the unused portion of the source string"\ " in toXml()" # END SOURCE-STRING LOOP # The source-string loop above only guarantees to use up the # source string; there may be an unused portion of the # suggestion left. We append it to the xml string as an # insertion (or alteration, if appropriate). if len(unusedSuggestion) > 0: if len(unmatchedChars) > 0: xml_format = "<alt>%s</alt>" else: xml_format = "<ins>%s</ins>" unusedXml = escape_xml(unusedSuggestion) xmlText += xml_format % unusedXml completion += unusedSuggestion.split(" ")[0] if " " in unusedSuggestion: completion += " " # Finally, add the help text, if it exists. if self.__helpText is not None: xmlText += "<help>%s</help>" % self.__helpText if self.__suggestedPrefix and xmlText.startswith( self.__suggestedPrefix): xmlText = "<prefix>%s</prefix>%s" % (escape_xml( self.__suggestedPrefix), xmlText[len(self.__suggestedPrefix):]) self.__xml = xmlText
def __transform( self ): if self.__start is not None: #s = escape_xml(self.__suggestion) xmlText = "%s<ins>%s</ins>%s<ins>%s</ins>" % ( escape_xml(self.__suggestion[:self.__prefix_end]), escape_xml(self.__suggestion[self.__prefix_end:self.__prefix_end+self.__start]), escape_xml(self.__suggestion[self.__prefix_end+self.__start:self.__prefix_end+self.__end]), escape_xml(self.__suggestion[self.__prefix_end+self.__end:]) ) if self.__suggestedPrefix and xmlText.startswith(self.__suggestedPrefix): xmlText = "<prefix>%s</prefix>%s" % (escape_xml(self.__suggestedPrefix), xmlText[len(self.__suggestedPrefix):]) # Finally, add help text, if it exists. if self.__helpText is not None: xmlText = "%s<help>%s</help>" % (xmlText, escape_xml(self.__helpText)) self.__xml = xmlText return else: pass # We are going to "use up" both the source string and the # suggestion unusedSource = self.__source[:] unusedSuggestion = self.__suggestion[:] # The xml representation xmlText = "" # The "to the next word" completion. completion = "" # If we cannot match an initial substring of unusedSource, # then we are going to peel off characters one-by-one into # this variable. These characters have been lost in the # suggestion, and will cause "insertions" to instead be # "alterations". unmatchedChars = "" # BEGIN SOURCE-STRING LOOP # Each iteration of this loop should reduce the length of # unusedSource, and this loop ends when unusedSource is empty. while len(unusedSource) > 0: # Save a copy of unusedSource, so we know if it changes. oldUnusedSource = unusedSource[:] # Loop from the full length of unusedSource down to one # character for i in range( len(unusedSource), 0, -1 ): # The initial substring we are trying to locate. target = unusedSource[:i] # BEGIN TARGET-FOUND CONDITION if target in unusedSuggestion: # Search normally from begining index = unusedSuggestion.find( target ) # Search on word boundaries. This is different from \b in # that it considers also the underscore character as a word boundary. m = re.match(r".*[^0-9a-zA-Z](%s)" % re.escape(target), unusedSuggestion, re.I) if m and m.groups() and m.start(1) > index: # Prefer word boundary match index = m.start(1) # index, m.start(1) if index > 0: if len(unmatchedChars) > 0: # There were unused characters in the # source, and there were characters in the # unused suggestion before the target, so # the next "inserted" portion of the # suggestion becomes an "alteration" # instead. xmlFormat = "<alt>%s</alt>" else: xmlFormat = "<ins>%s</ins>" xmlText += xmlFormat % escape_xml( unusedSuggestion[:index] ) # NOTE: Do not add inserted characters to the # 'next word' completion. # Whether or not there were characters between # the start of the unused suggestion and "here", # any unmatched chars are now defunct. unmatchedChars = "" xmlText += escape_xml( target ) completion += target unusedSuggestion = unusedSuggestion[index+len(target):] unusedSource = unusedSource[i:] # The target was found and unusedSource was # modified; we exit the for-loop (to be entered # again if unusedSource is still nonempty). break # END TARGET-FOUND CONDITION # Either unusedSource is smaller, or it is the same as # oldUnusedSource. If it is the same as old unusedSource, # then there was no match of a beginning substring, so we # remove the first character and store it as an "unused # character", which will become part of an "altered # substring", if there is a match to a later substring. if unusedSource == oldUnusedSource: unmatchedChars += unusedSource[0] unusedSource = unusedSource[1:] assert len( unusedSource ) < len( oldUnusedSource ), \ "Potential infinite loop condition; failed to reduce"\ " the length of the unused portion of the source string"\ " in toXml()" # END SOURCE-STRING LOOP # The source-string loop above only guarantees to use up the # source string; there may be an unused portion of the # suggestion left. We append it to the xml string as an # insertion (or alteration, if appropriate). if len( unusedSuggestion ) > 0: if len( unmatchedChars ) > 0: format = "<alt>%s</alt>" else: format = "<ins>%s</ins>" unusedXml = escape_xml( unusedSuggestion ) xmlText += format % unusedXml completion += unusedSuggestion.split(" ")[0] if " " in unusedSuggestion: completion += " " # Finally, add the help text, if it exists. if self.__helpText != None: xmlText += "<help>%s</help>" % self.__helpText if self.__suggestedPrefix and xmlText.startswith(self.__suggestedPrefix): xmlText = "<prefix>%s</prefix>%s" % (escape_xml(self.__suggestedPrefix), xmlText[len(self.__suggestedPrefix):]) self.__xml = xmlText