Ejemplo n.º 1
0
 def draw_statusbars(self, top_row=0, bottom_row=-1, topbar=None, bottombar=None,
                     bottombar_help=True, scr=None):
     self.add_string(top_row, topbar if topbar else self.statusbars.topbar, scr=scr)
     bottombar = bottombar if bottombar else self.statusbars.bottombar
     if bottombar_help:
         if bottombar_help is True:
             bottombar_help = self.help_hstr
         bottombar += ' ' * (self.cols - len(remove_formatting(bottombar)) -
                             len(remove_formatting(bottombar_help))) + bottombar_help
     self.add_string(self.rows + bottom_row, bottombar, scr=scr)
Ejemplo n.º 2
0
 def render(self,
            screen,
            row,
            active=False,
            focused=False,
            col=0,
            width=None,
            **kwargs):
     util.safe_curs_set(util.Curser.INVISIBLE
                        )  # Make cursor invisible when text field is active
     fmt = self.build_fmt_string(focused, active)
     self.fmt_keys['msg'] = self.txt
     if self.fill_width:
         self.fmt_keys['msg'] = ''
         string_len = len(remove_formatting(fmt % self.fmt_keys))
         fill_len = width - string_len - (len(self.txt) - 1)
         self.fmt_keys['msg'] = self.txt * fill_len
     string = fmt % self.fmt_keys
     self.parent.add_string(row,
                            string,
                            scr=screen,
                            col=col,
                            pad=False,
                            trim=False)
     return 1
Ejemplo n.º 3
0
 def render(self, screen, row, active=False, focused=False, col=0, width=None, **kwargs):
     util.safe_curs_set(util.Curser.INVISIBLE)  # Make cursor invisible when text field is active
     fmt = self.build_fmt_string(focused, active)
     self.fmt_keys['msg'] = self.txt
     if self.fill_width:
         self.fmt_keys['msg'] = ''
         string_len = len(remove_formatting(fmt % self.fmt_keys))
         fill_len = width - string_len - (len(self.txt) - 1)
         self.fmt_keys['msg'] = self.txt * fill_len
     string = fmt % self.fmt_keys
     self.parent.add_string(row, string, scr=screen, col=col, pad=False, trim=False)
     return 1
Ejemplo n.º 4
0
def complete_line(line, possible_matches):
    """Find the common prefix of possible matches.

    Proritizing matching-case elements.
    """

    if not possible_matches:
        return line

    line = line.replace(r'\ ', ' ')

    matches1 = []
    matches2 = []

    for match in possible_matches:
        match = remove_formatting(match)
        match = match.replace(r'\ ', ' ')
        m1, m2 = '', ''
        for i, c in enumerate(line):
            if m1 and m2:
                break
            if not m1 and c != line[i]:
                m1 = line[:i]
            if not m2 and c.lower() != line[i].lower():
                m2 = line[:i]
        if not m1:
            matches1.append(match)
        elif not m2:
            matches2.append(match)

    possible_matches = matches1 + matches2

    maxlen = 9001

    for match in possible_matches[1:]:
        for i, c in enumerate(match):
            try:
                if c.lower() != possible_matches[0][i].lower():
                    maxlen = min(maxlen, i)
                    break
            except IndexError:
                maxlen = min(maxlen, i)
                break

    return possible_matches[0][:maxlen].replace(' ', r'\ ')
Ejemplo n.º 5
0
def complete_line(line, possible_matches):
    'Find the common prefix of possible matches, proritizing matching-case elements'

    if not possible_matches:
        return line

    line = line.replace(r'\ ', ' ')

    matches1 = []
    matches2 = []

    for match in possible_matches:
        match = remove_formatting(match)
        match = match.replace(r'\ ', ' ')
        m1, m2 = '', ''
        for i, c in enumerate(line):
            if m1 and m2:
                break
            if not m1 and c != line[i]:
                m1 = line[:i]
            if not m2 and c.lower() != line[i].lower():
                m2 = line[:i]
        if not m1:
            matches1.append(match)
        elif not m2:
            matches2.append(match)

    possible_matches = matches1 + matches2

    maxlen = 9001

    for match in possible_matches[1:]:
        for i, c in enumerate(match):
            try:
                if c.lower() != possible_matches[0][i].lower():
                    maxlen = min(maxlen, i)
                    break
            except IndexError:
                maxlen = min(maxlen, i)
                break

    return possible_matches[0][:maxlen].replace(' ', r'\ ')
Ejemplo n.º 6
0
    def tab_completer(self, line, cursor, hits):
        """
        Called when the user hits 'tab' and will autocomplete or show options.
        If a command is already supplied in the line, this function will call the
        complete method of the command.

        :param line: str, the current input string
        :param cursor: int, the cursor position in the line
        :param second_hit: bool, if this is the second time in a row the tab key
            has been pressed

        :returns: 2-tuple (string, cursor position)

        """
        # First check to see if there is no space, this will mean that it's a
        # command that needs to be completed.

        # We don't want to split by escaped spaces
        def split(string):
            return re.split(r'(?<!\\) ', string)

        if ' ' not in line:
            possible_matches = []
            # Iterate through the commands looking for ones that startwith the
            # line.
            for cmd in self.console._commands:
                if cmd.startswith(line):
                    possible_matches.append(cmd)

            line_prefix = ''
        else:
            cmd = split(line)[0]
            if cmd in self.console._commands:
                # Call the command's complete method to get 'er done
                possible_matches = self.console._commands[cmd].complete(split(line)[-1])
                line_prefix = ' '.join(split(line)[:-1]) + ' '
            else:
                # This is a bogus command
                return (line, cursor)

        # No matches, so just return what we got passed
        if len(possible_matches) == 0:
            return (line, cursor)
        # If we only have 1 possible match, then just modify the line and
        # return it, else we need to print out the matches without modifying
        # the line.
        elif len(possible_matches) == 1:
            # Do not append space after directory names
            new_line = line_prefix + possible_matches[0]
            if not new_line.endswith('/') and not new_line.endswith(r'\\'):
                new_line += ' '
            # We only want to print eventual colors or other control characters, not return them
            new_line = remove_formatting(new_line)
            return (new_line, len(new_line))
        else:
            if hits == 1:
                p = ' '.join(split(line)[:-1])

                try:
                    l_arg = split(line)[-1]
                except IndexError:
                    l_arg = ''

                new_line = ' '.join(
                    [p, complete_line(l_arg, possible_matches)]
                ).lstrip()

                if len(remove_formatting(new_line)) > len(line):
                    line = new_line
                    cursor = len(line)
            elif hits >= 2:
                max_list = self.console_config['cmdline']['torrents_per_tab_press']
                match_count = len(possible_matches)
                listed = (hits - 2) * max_list
                pages = (match_count - 1) // max_list + 1
                left = match_count - listed
                if hits == 2:
                    self.write(' ')

                    if match_count >= 4:
                        self.write('{!green!}Autocompletion matches:')
                # Only list some of the matching torrents as there can be hundreds of them
                if self.console_config['cmdline']['third_tab_lists_all']:
                    if hits == 2 and left > max_list:
                        for i in range(listed, listed + max_list):
                            match = possible_matches[i]
                            self.write(match.replace(r'\ ', ' '))
                        self.write(
                            '{!error!}And %i more. Press <tab> to list them'
                            % (left - max_list)
                        )
                    else:
                        self.tab_count = 0
                        for match in possible_matches[listed:]:
                            self.write(match.replace(r'\ ', ' '))
                else:
                    if left > max_list:
                        for i in range(listed, listed + max_list):
                            match = possible_matches[i]
                            self.write(match.replace(r'\ ', ' '))
                        self.write(
                            '{!error!}And %i more (%i/%i). Press <tab> to view more'
                            % (left - max_list, hits - 1, pages)
                        )
                    else:
                        self.tab_count = 0
                        for match in possible_matches[listed:]:
                            self.write(match.replace(r'\ ', ' '))
                        if hits > 2:
                            self.write(
                                '{!green!}Finished listing %i torrents (%i/%i)'
                                % (match_count, hits - 1, pages)
                            )

            # We only want to print eventual colors or other control characters, not return them
            line = remove_formatting(line)
            cursor = len(line)
            return (line, cursor)
Ejemplo n.º 7
0
    def __init__(self, stdscr, encoding=None):
        # Get a handle to the main console
        self.console = component.get('ConsoleUI')
        Commander.__init__(self, self.console._commands, interactive=True)

        self.batch_write = False

        # A list of strings to be displayed based on the offset (scroll)
        self.lines = []
        # The offset to display lines
        self.display_lines_offset = 0

        # Holds the user input and is cleared on 'enter'
        self.input = ''
        self.input_incomplete = ''

        # Keep track of where the cursor is
        self.input_cursor = 0
        # Keep a history of inputs
        self.input_history = []
        self.input_history_index = 0

        # Keep track of double- and multi-tabs
        self.tab_count = 0

        self.console_config = component.get('TorrentList').config

        # To avoid having to truncate the file every time we're writing
        # or doing it on exit(and therefore relying on an error-less
        # or in other words clean exit, we're going to have two files
        # that we swap around based on length
        config_dir = deluge.configmanager.get_config_dir()
        self.history_file = [
            os.path.join(config_dir, 'cmd_line.hist1'),
            os.path.join(config_dir, 'cmd_line.hist2'),
        ]
        self._hf_lines = [0, 0]
        if self.console_config['cmdline']['save_command_history']:
            try:
                with open(self.history_file[0], 'r', encoding='utf8') as _file:
                    lines1 = _file.read().splitlines()
                self._hf_lines[0] = len(lines1)
            except IOError:
                lines1 = []
                self._hf_lines[0] = 0

            try:
                with open(self.history_file[1], 'r', encoding='utf8') as _file:
                    lines2 = _file.read().splitlines()
                self._hf_lines[1] = len(lines2)
            except IOError:
                lines2 = []
                self._hf_lines[1] = 0

            # The non-full file is the active one
            if self._hf_lines[0] > self._hf_lines[1]:
                self.lines = lines1 + lines2
            else:
                self.lines = lines2 + lines1

            if len(self.lines) > MAX_HISTFILE_SIZE:
                self.lines = self.lines[-MAX_HISTFILE_SIZE:]

            # Instead of having additional input history file, we can
            # simply scan for lines beginning with ">>> "
            for i, line in enumerate(self.lines):
                line = remove_formatting(line)
                if line.startswith('>>> '):
                    console_input = line[4:]
                    if self.console_config['cmdline']['ignore_duplicate_lines']:
                        if len(self.input_history) > 0:
                            if self.input_history[-1] != console_input:
                                self.input_history.append(console_input)
                        else:
                            self.input_history.append(console_input)

            self.input_history_index = len(self.input_history)

        # show the cursor
        util.safe_curs_set(util.Curser.VERY_VISIBLE)
        BaseMode.__init__(self, stdscr, encoding, depend=['SessionProxy'])
Ejemplo n.º 8
0
    def __init__(self, stdscr, encoding=None):
        # Get a handle to the main console
        self.console = component.get('ConsoleUI')
        Commander.__init__(self, self.console._commands, interactive=True)

        self.batch_write = False

        # A list of strings to be displayed based on the offset (scroll)
        self.lines = []
        # The offset to display lines
        self.display_lines_offset = 0

        # Holds the user input and is cleared on 'enter'
        self.input = ''
        self.input_incomplete = ''

        # Keep track of where the cursor is
        self.input_cursor = 0
        # Keep a history of inputs
        self.input_history = []
        self.input_history_index = 0

        # Keep track of double- and multi-tabs
        self.tab_count = 0

        self.console_config = component.get('TorrentList').config

        # To avoid having to truncate the file every time we're writing
        # or doing it on exit(and therefore relying on an error-less
        # or in other words clean exit, we're going to have two files
        # that we swap around based on length
        config_dir = deluge.configmanager.get_config_dir()
        self.history_file = [
            os.path.join(config_dir, 'cmd_line.hist1'),
            os.path.join(config_dir, 'cmd_line.hist2')
        ]
        self._hf_lines = [0, 0]
        if self.console_config['cmdline']['save_command_history']:
            try:
                with open(self.history_file[0], 'r', encoding='utf8') as _file:
                    lines1 = _file.read().splitlines()
                self._hf_lines[0] = len(lines1)
            except IOError:
                lines1 = []
                self._hf_lines[0] = 0

            try:
                with open(self.history_file[1], 'r', encoding='utf8') as _file:
                    lines2 = _file.read().splitlines()
                self._hf_lines[1] = len(lines2)
            except IOError:
                lines2 = []
                self._hf_lines[1] = 0

            # The non-full file is the active one
            if self._hf_lines[0] > self._hf_lines[1]:
                self.lines = lines1 + lines2
            else:
                self.lines = lines2 + lines1

            if len(self.lines) > MAX_HISTFILE_SIZE:
                self.lines = self.lines[-MAX_HISTFILE_SIZE:]

            # Instead of having additional input history file, we can
            # simply scan for lines beginning with ">>> "
            for i, line in enumerate(self.lines):
                line = remove_formatting(line)
                if line.startswith('>>> '):
                    console_input = line[4:]
                    if self.console_config['cmdline']['ignore_duplicate_lines']:
                        if len(self.input_history) > 0:
                            if self.input_history[-1] != console_input:
                                self.input_history.append(console_input)
                        else:
                            self.input_history.append(console_input)

            self.input_history_index = len(self.input_history)

        # show the cursor
        util.safe_curs_set(util.Curser.VERY_VISIBLE)
        BaseMode.__init__(self, stdscr, encoding, depend=['SessionProxy'])
Ejemplo n.º 9
0
    def tab_completer(self, line, cursor, hits):
        """
        Called when the user hits 'tab' and will autocomplete or show options.
        If a command is already supplied in the line, this function will call the
        complete method of the command.

        :param line: str, the current input string
        :param cursor: int, the cursor position in the line
        :param second_hit: bool, if this is the second time in a row the tab key
            has been pressed

        :returns: 2-tuple (string, cursor position)

        """
        # First check to see if there is no space, this will mean that it's a
        # command that needs to be completed.

        # We don't want to split by escaped spaces
        def split(string):
            return re.split(r'(?<!\\) ', string)

        if ' ' not in line:
            possible_matches = []
            # Iterate through the commands looking for ones that startwith the
            # line.
            for cmd in self.console._commands:
                if cmd.startswith(line):
                    possible_matches.append(cmd)

            line_prefix = ''
        else:
            cmd = split(line)[0]
            if cmd in self.console._commands:
                # Call the command's complete method to get 'er done
                possible_matches = self.console._commands[cmd].complete(split(line)[-1])
                line_prefix = ' '.join(split(line)[:-1]) + ' '
            else:
                # This is a bogus command
                return (line, cursor)

        # No matches, so just return what we got passed
        if len(possible_matches) == 0:
            return (line, cursor)
        # If we only have 1 possible match, then just modify the line and
        # return it, else we need to print out the matches without modifying
        # the line.
        elif len(possible_matches) == 1:
            # Do not append space after directory names
            new_line = line_prefix + possible_matches[0]
            if not new_line.endswith('/') and not new_line.endswith(r'\\'):
                new_line += ' '
            # We only want to print eventual colors or other control characters, not return them
            new_line = remove_formatting(new_line)
            return (new_line, len(new_line))
        else:
            if hits == 1:
                p = ' '.join(split(line)[:-1])

                try:
                    l_arg = split(line)[-1]
                except IndexError:
                    l_arg = ''

                new_line = ' '.join([p, complete_line(l_arg, possible_matches)]).lstrip()

                if len(remove_formatting(new_line)) > len(line):
                    line = new_line
                    cursor = len(line)
            elif hits >= 2:
                max_list = self.console_config['cmdline']['torrents_per_tab_press']
                match_count = len(possible_matches)
                listed = (hits - 2) * max_list
                pages = (match_count - 1) // max_list + 1
                left = match_count - listed
                if hits == 2:
                    self.write(' ')

                    if match_count >= 4:
                        self.write('{!green!}Autocompletion matches:')
                # Only list some of the matching torrents as there can be hundreds of them
                if self.console_config['cmdline']['third_tab_lists_all']:
                    if hits == 2 and left > max_list:
                        for i in range(listed, listed + max_list):
                            match = possible_matches[i]
                            self.write(match.replace(r'\ ', ' '))
                        self.write('{!error!}And %i more. Press <tab> to list them' % (left - max_list))
                    else:
                        self.tab_count = 0
                        for match in possible_matches[listed:]:
                            self.write(match.replace(r'\ ', ' '))
                else:
                    if left > max_list:
                        for i in range(listed, listed + max_list):
                            match = possible_matches[i]
                            self.write(match.replace(r'\ ', ' '))
                        self.write('{!error!}And %i more (%i/%i). Press <tab> to view more' % (
                            left - max_list, hits - 1, pages))
                    else:
                        self.tab_count = 0
                        for match in possible_matches[listed:]:
                            self.write(match.replace(r'\ ', ' '))
                        if hits > 2:
                            self.write('{!green!}Finished listing %i torrents (%i/%i)' % (match_count, hits - 1, pages))

            # We only want to print eventual colors or other control characters, not return them
            line = remove_formatting(line)
            cursor = len(line)
            return (line, cursor)
Ejemplo n.º 10
0
Archivo: info.py Proyecto: zluca/deluge
 def tlen(string):
     return strwidth(remove_formatting(string))
Ejemplo n.º 11
0
 def tlen(string):
     return strwidth(remove_formatting(string))