Example #1
0
    def editText(self, text, jumpIndex=None, highlight=None):
        """Return the text as edited by the user.

        Uses a Tkinter edit box because we don't have a console editor

        Parameters:
            * text      - a Unicode string
            * jumpIndex - an integer: position at which to put the caret
            * highlight - a substring; each occurrence will be highlighted

        """
        try:
            import gui
        except ImportError as e:
            print('Could not load GUI modules: %s' % e)
            return text
        editor = gui.EditBoxWindow()
        return editor.edit(text, jumpIndex=jumpIndex, highlight=highlight)
    def editText(self, text, jumpIndex=None, highlight=None):
        """Return the text as edited by the user.

        Uses a Tkinter edit box because we don't have a console editor

        @param text: the text to be edited
        @type text: unicode
        @param jumpIndex: position at which to put the caret
        @type jumpIndex: int
        @param highlight: each occurrence of this substring will be highlighted
        @type highlight: unicode
        @return: the modified text, or None if the user didn't save the text
            file in his text editor
        @rtype: unicode or None
        """
        try:
            import gui
        except ImportError as e:
            print('Could not load GUI modules: %s' % e)
            return text
        editor = gui.EditBoxWindow()
        return editor.edit(text, jumpIndex=jumpIndex, highlight=highlight)
Example #3
0
class UI:
    def __init__(self):
        pass

    def printColorizedInUnix(self, text, targetStream):
        lastColor = None
        for key, value in unixColors.iteritems():
            text = text.replace('\03{%s}' % key, value)
        # just to be sure, reset the color
        text += unixColors['default']

        targetStream.write(text.encode(config.console_encoding, 'replace'))

    def printColorizedInWindows(self, text, targetStream):
        """
        This only works in Python 2.5 or higher.
        """
        if ctypes_found:
            std_out_handle = ctypes.windll.kernel32.GetStdHandle(-11)
            # Color tags might be cascaded, e.g. because of transliteration.
            # Therefore we need this stack.
            colorStack = []
            tagM = True
            while tagM:
                tagM = colorTagR.search(text)
                if tagM:
                    # print the text up to the tag.
                    targetStream.write(text[:tagM.start()].encode(
                        config.console_encoding, 'replace'))
                    newColor = tagM.group('name')
                    if newColor == 'default':
                        if len(colorStack) > 0:
                            colorStack.pop()
                            if len(colorStack) > 0:
                                lastColor = colorStack[-1]
                            else:
                                lastColor = 'default'
                            ctypes.windll.kernel32.SetConsoleTextAttribute(
                                std_out_handle, windowsColors[lastColor])
                    else:
                        colorStack.append(newColor)
                        # set the new color
                        ctypes.windll.kernel32.SetConsoleTextAttribute(
                            std_out_handle, windowsColors[newColor])
                    text = text[tagM.end():]
            # print the rest of the text
            targetStream.write(text.encode(config.console_encoding, 'replace'))
            # just to be sure, reset the color
            ctypes.windll.kernel32.SetConsoleTextAttribute(
                std_out_handle, windowsColors['default'])
        else:
            # ctypes is only available since Python 2.5, and we won't
            # try to colorize without it. Instead we add *** after the text as a whole
            # if anything needed to be colorized.
            lines = text.split('\n')
            for line in lines:
                line, count = colorTagR.subn('', line)
                if count > 0:
                    line += '***'
                line += '\n'
                targetStream.write(
                    line.encode(config.console_encoding, 'replace'))

    def printColorized(self, text, targetStream):
        if config.colorized_output:
            if sys.platform == 'win32':
                self.printColorizedInWindows(text, targetStream)
            else:
                self.printColorizedInUnix(text, targetStream)
        else:
            targetStream.write(text.encode(config.console_encoding, 'replace'))

    def output(self, text, toStdout=False):
        """
        If a character can't be displayed in the encoding used by the user's
        terminal, it will be replaced with a question mark or by a
        transliteration.
        """
        if config.transliterate:
            # Encode our unicode string in the encoding used by the user's console,
            # and decode it back to unicode. Then we can see which characters
            # can't be represented in the console encoding.
            codecedText = text.encode(config.console_encoding,
                                      'replace').decode(
                                          config.console_encoding)
            transliteratedText = ''
            # Note: A transliteration replacement might be longer than the original
            # character, e.g. ч is transliterated to ch.
            prev = "-"
            for i in xrange(len(codecedText)):
                # work on characters that couldn't be encoded, but not on
                # original question marks.
                if codecedText[i] == '?' and text[i] != u'?':
                    try:
                        transliterated = transliterator.transliterate(
                            text[i], default='?', prev=prev, next=text[i + 1])
                    except IndexError:
                        transliterated = transliterator.transliterate(
                            text[i], default='?', prev=prev, next=' ')
                    # transliteration was successful. The replacement
                    # could consist of multiple letters.
                    # mark the transliterated letters in yellow.
                    transliteratedText += '\03{lightyellow}%s\03{default}' % transliterated
                    transLength = len(transliterated)
                    # memorize if we replaced a single letter by multiple letters.
                    if len(transliterated) > 0:
                        prev = transliterated[-1]
                else:
                    # no need to try to transliterate.
                    transliteratedText += codecedText[i]
                    prev = codecedText[i]
            text = transliteratedText

        if toStdout:
            targetStream = sys.stdout
        else:
            targetStream = sys.stderr
        self.printColorized(text, targetStream)

    def input(self, question, password=False):
        """
        Works like raw_input(), but returns a unicode string instead of ASCII.

        Unlike raw_input, this function automatically adds a space after the
        question.
        """

        # sound the terminal bell to notify the user
        if config.ring_bell:
            sys.stdout.write('\07')
        # TODO: make sure this is logged as well
        self.output(question + ' ')
        if password:
            import getpass
            text = getpass.getpass('')
        else:
            text = raw_input()
        text = unicode(text, config.console_encoding)
        return text

    def inputChoice(self, question, options, hotkeys, default=None):
        options = options[:]  # we don't want to edit the passed parameter
        for i in range(len(options)):
            option = options[i]
            hotkey = hotkeys[i]
            # try to mark a part of the option name as the hotkey
            m = re.search('[%s%s]' % (hotkey.lower(), hotkey.upper()), option)
            if hotkey == default:
                caseHotkey = hotkey.upper()
            else:
                caseHotkey = hotkey
            if m:
                pos = m.start()
                options[i] = '%s[%s]%s' % (option[:pos], caseHotkey,
                                           option[pos + 1:])
            else:
                options[i] = '%s [%s]' % (option, caseHotkey)
        # loop until the user entered a valid choice
        while True:
            prompt = '%s (%s)' % (question, ', '.join(options))
            answer = self.input(prompt)
            if answer.lower() in hotkeys or answer.upper() in hotkeys:
                return answer
            elif default and answer == '':  # empty string entered
                return default

    def editText(self, text, jumpIndex=None, highlight=None):
        """
        Uses a Tkinter edit box because we don't have a console editor

        Parameters:
            * text      - a Unicode string
            * jumpIndex - an integer: position at which to put the caret
            * highlight - a substring; each occurence will be highlighted
        """
        try:
            import gui
        except ImportError, e:
            print 'Could not load GUI modules: %s' % e
            return text
        editor = gui.EditBoxWindow()
        return editor.edit(text, jumpIndex=jumpIndex, highlight=highlight)
Example #4
0
class UI:
    def __init__(self):
        self.stdin = sys.stdin
        self.stdout = sys.stdout
        self.stderr = sys.stderr
        self.encoding = config.console_encoding
        self.transliteration_target = config.transliteration_target

        self.stderr = sys.stderr
        self.stdout = sys.stdout

    def init_handlers(self, root_logger, default_stream='stderr'):
        """Initialize the handlers for user output.

        This method initializes handler(s) for output levels VERBOSE (if
        enabled by config.verbose_output), INFO, STDOUT, WARNING, ERROR,
        and CRITICAL.  STDOUT writes its output to sys.stdout; all the
        others write theirs to sys.stderr.

        """

        if default_stream == 'stdout':
            default_stream = self.stdout
        elif default_stream == 'stderr':
            default_stream = self.stderr

        # default handler for display to terminal
        default_handler = TerminalHandler(self, strm=default_stream)
        if config.verbose_output:
            default_handler.setLevel(VERBOSE)
        else:
            default_handler.setLevel(INFO)
        # this handler ignores levels above INPUT
        default_handler.addFilter(MaxLevelFilter(INPUT))
        default_handler.setFormatter(
            TerminalFormatter(fmt="%(message)s%(newline)s"))
        root_logger.addHandler(default_handler)

        # handler for level STDOUT
        output_handler = TerminalHandler(self, strm=self.stdout)
        output_handler.setLevel(STDOUT)
        output_handler.addFilter(MaxLevelFilter(STDOUT))
        output_handler.setFormatter(
            TerminalFormatter(fmt="%(message)s%(newline)s"))
        root_logger.addHandler(output_handler)

        # handler for levels WARNING and higher
        warning_handler = TerminalHandler(self, strm=self.stderr)
        warning_handler.setLevel(logging.WARNING)
        warning_handler.setFormatter(
            TerminalFormatter(fmt="%(levelname)s: %(message)s%(newline)s"))
        root_logger.addHandler(warning_handler)

    def printNonColorized(self, text, targetStream):
        # We add *** after the text as a whole if anything needed to be colorized.
        lines = text.split('\n')
        for i, line in enumerate(lines):
            if i > 0:
                line = "\n" + line
            line, count = colorTagR.subn('', line)
            if count > 0:
                line += ' ***'
            targetStream.write(line.encode(self.encoding, 'replace'))

    printColorized = printNonColorized

    def _print(self, text, targetStream):
        if config.colorized_output:
            self.printColorized(text, targetStream)
        else:
            self.printNonColorized(text, targetStream)

    def output(self, text, toStdout=False, targetStream=None):
        """
        If a character can't be displayed in the encoding used by the user's
        terminal, it will be replaced with a question mark or by a
        transliteration.
        
        """
        if config.transliterate:
            # Encode our unicode string in the encoding used by the user's
            # console, and decode it back to unicode. Then we can see which
            # characters can't be represented in the console encoding.
            # We need to take min(console_encoding, transliteration_target)
            # the first is what the terminal is capable of
            # the second is how unicode-y the user would like the output
            codecedText = text.encode(self.encoding,
                                      'replace').decode(self.encoding)
            if self.transliteration_target:
                codecedText = codecedText.encode(
                    self.transliteration_target,
                    'replace').decode(self.transliteration_target)
            transliteratedText = ''
            # Note: A transliteration replacement might be longer than the
            # original character, e.g. ч is transliterated to ch.
            prev = "-"
            for i in xrange(len(codecedText)):
                # work on characters that couldn't be encoded, but not on
                # original question marks.
                if codecedText[i] == '?' and text[i] != u'?':
                    try:
                        transliterated = transliterator.transliterate(
                            text[i], default='?', prev=prev, next=text[i + 1])
                    except IndexError:
                        transliterated = transliterator.transliterate(
                            text[i], default='?', prev=prev, next=' ')
                    # transliteration was successful. The replacement
                    # could consist of multiple letters.
                    # mark the transliterated letters in yellow.
                    transliteratedText += '\03{lightyellow}%s\03{default}' \
                                          % transliterated
                    transLength = len(transliterated)
                    # memorize if we replaced a single letter by multiple
                    # letters.
                    if len(transliterated) > 0:
                        prev = transliterated[-1]
                else:
                    # no need to try to transliterate.
                    transliteratedText += codecedText[i]
                    prev = codecedText[i]
            text = transliteratedText

        if not targetStream:
            if toStdout:
                targetStream = self.stdout
            else:
                targetStream = self.stderr

        self._print(text, targetStream)

    def _raw_input(self):
        return raw_input()

    def input(self, question, password=False):
        """
        Ask the user a question and return the answer.

        Works like raw_input(), but returns a unicode string instead of ASCII.

        Unlike raw_input, this function automatically adds a space after the
        question.

        """

        # sound the terminal bell to notify the user
        if config.ring_bell:
            sys.stdout.write('\07')
        # TODO: make sure this is logged as well
        self.output(question + ' ')
        if password:
            import getpass
            text = getpass.getpass('')
        else:
            text = self._raw_input()
        text = unicode(text, self.encoding)
        return text

    def inputChoice(self, question, options, hotkeys, default=None):
        """
        Ask the user a question with a predefined list of acceptable answers.
        """
        options = options[:]  # we don't want to edit the passed parameter
        for i in range(len(options)):
            option = options[i]
            hotkey = hotkeys[i]
            # try to mark a part of the option name as the hotkey
            m = re.search('[%s%s]' % (hotkey.lower(), hotkey.upper()), option)
            if hotkey == default:
                caseHotkey = hotkey.upper()
            else:
                caseHotkey = hotkey
            if m:
                pos = m.start()
                options[i] = '%s[%s]%s' % (option[:pos], caseHotkey,
                                           option[pos + 1:])
            else:
                options[i] = '%s [%s]' % (option, caseHotkey)
        # loop until the user entered a valid choice
        while True:
            prompt = '%s (%s)' % (question, ', '.join(options))
            answer = self.input(prompt)
            if answer.lower() in hotkeys or answer.upper() in hotkeys:
                return answer
            elif default and answer == '':  # empty string entered
                return default

    def editText(self, text, jumpIndex=None, highlight=None):
        """Return the text as edited by the user.

        Uses a Tkinter edit box because we don't have a console editor

        Parameters:
            * text      - a Unicode string
            * jumpIndex - an integer: position at which to put the caret
            * highlight - a substring; each occurence will be highlighted

        """
        try:
            import gui
        except ImportError, e:
            print 'Could not load GUI modules: %s' % e
            return text
        editor = gui.EditBoxWindow()
        return editor.edit(text, jumpIndex=jumpIndex, highlight=highlight)
class UI:
    def __init__(self):
        self.stdin = sys.stdin
        self.stdout = sys.stdout
        self.stderr = sys.stderr
        self.encoding = config.console_encoding
        self.transliteration_target = config.transliteration_target

    def printNonColorized(self, text, targetStream):
        # We add *** after the text as a whole if anything needed to be colorized.
        lines = text.split('\n')
        for line in lines:
            line, count = colorTagR.subn('', line)
            if count > 0:
                line += '***'
            line += '\n'
            targetStream.write(line.encode(self.encoding, 'replace'))

    printColorized = printNonColorized

    def _print(self, text, targetStream):
        if config.colorized_output:
            self.printColorized(text, targetStream)
        else:
            self.printNonColorized(text, targetStream)

    def output(self, text, toStdout=False):
        """
        If a character can't be displayed in the encoding used by the user's
        terminal, it will be replaced with a question mark or by a
        transliteration.
        """
        if config.transliterate:
            # Encode our unicode string in the encoding used by the user's console,
            # and decode it back to unicode. Then we can see which characters
            # can't be represented in the console encoding.
            # We need to take min(console_encoding, transliteration_target)
            # the first is what the terminal is capable of
            # the second is how unicode-y the user would like the output
            codecedText = text.encode(self.encoding,
                                      'replace').decode(self.encoding)
            if self.transliteration_target:
                codecedText = codecedText.encode(
                    self.transliteration_target,
                    'replace').decode(self.transliteration_target)
            transliteratedText = ''
            # Note: A transliteration replacement might be longer than the original
            # character, e.g. ч is transliterated to ch.
            prev = "-"
            for i in xrange(len(codecedText)):
                # work on characters that couldn't be encoded, but not on
                # original question marks.
                if codecedText[i] == '?' and text[i] != u'?':
                    try:
                        transliterated = transliterator.transliterate(
                            text[i], default='?', prev=prev, next=text[i + 1])
                    except IndexError:
                        transliterated = transliterator.transliterate(
                            text[i], default='?', prev=prev, next=' ')
                    # transliteration was successful. The replacement
                    # could consist of multiple letters.
                    # mark the transliterated letters in yellow.
                    transliteratedText += '\03{lightyellow}%s\03{default}' % transliterated
                    transLength = len(transliterated)
                    # memorize if we replaced a single letter by multiple letters.
                    if len(transliterated) > 0:
                        prev = transliterated[-1]
                else:
                    # no need to try to transliterate.
                    transliteratedText += codecedText[i]
                    prev = codecedText[i]
            text = transliteratedText

        if toStdout:
            targetStream = self.stdout
        else:
            targetStream = self.stderr
        self._print(text, targetStream)

    def _raw_input(self):
        return raw_input()

    def input(self, question, password=False):
        """
        Works like raw_input(), but returns a unicode string instead of ASCII.

        Unlike raw_input, this function automatically adds a space after the
        question.
        """

        # sound the terminal bell to notify the user
        if config.ring_bell:
            sys.stdout.write('\07')
        # TODO: make sure this is logged as well
        self.output(question + ' ')
        if password:
            import getpass
            text = getpass.getpass('')
        else:
            text = self._raw_input()
        text = unicode(text, self.encoding)
        return text

    def inputChoice(self, question, options, hotkeys, default=None):
        options = options[:]  # we don't want to edit the passed parameter
        for i in range(len(options)):
            option = options[i]
            hotkey = hotkeys[i]
            # try to mark a part of the option name as the hotkey
            m = re.search('[%s%s]' % (hotkey.lower(), hotkey.upper()), option)
            if hotkey == default:
                caseHotkey = hotkey.upper()
            else:
                caseHotkey = hotkey
            if m:
                pos = m.start()
                options[i] = '%s[%s]%s' % (option[:pos], caseHotkey,
                                           option[pos + 1:])
            else:
                options[i] = '%s [%s]' % (option, caseHotkey)
        # loop until the user entered a valid choice
        while True:
            prompt = '%s (%s)' % (question, ', '.join(options))
            answer = self.input(prompt)
            if answer.lower() in hotkeys or answer.upper() in hotkeys:
                return answer
            elif default and answer == '':  # empty string entered
                return default

    def editText(self, text, jumpIndex=None, highlight=None):
        """
        Uses a Tkinter edit box because we don't have a console editor

        Parameters:
            * text      - a Unicode string
            * jumpIndex - an integer: position at which to put the caret
            * highlight - a substring; each occurence will be highlighted
        """
        try:
            import gui
        except ImportError, e:
            print 'Could not load GUI modules: %s' % e
            return text
        editor = gui.EditBoxWindow()
        return editor.edit(text, jumpIndex=jumpIndex, highlight=highlight)