示例#1
0
    def __init__(self, admin_cli):
        # remove stdout stream encoding while in 'shell' mode, becuase this breaks readline
        # (autocompletion and shell history). In 'shell' mode the stdout
        # is encoded just for time necessary for command execution see precmd a postcmd

        sys.stdout = stdout_origin
        self.stdout_with_codec = encode_stream(sys.stdout, "utf-8")

        self.completion_matches = None
        Cmd.__init__(self)
        self.admin_cli = admin_cli
        self.completion = Completion(self.admin_cli)
        try:
            Config()
            self.prompt = Config.parser.get('shell', 'prompt') + ' '
        except (ConfigFileError, ConfigParser.Error):
            self.prompt = 'katello> '

        try:
            # don't split on hyphens during tab completion (important for completing parameters)
            newdelims = readline.get_completer_delims()
            newdelims = re.sub('-', '', newdelims)
            readline.set_completer_delims(newdelims)

            if (Config.parser.get('shell', 'nohistory').lower() != 'true'):
                self.__init_history()
        except ConfigParser.Error:
            pass
        self.__init_commands()
示例#2
0
文件: shell.py 项目: bcrochet/katello
    def __init__(self, admin_cli):
        # remove stdout stream encoding while in 'shell' mode, becuase this breaks readline
        # (autocompletion and shell history). In 'shell' mode the stdout
        # is encoded just for time necessary for command execution see precmd a postcmd

        sys.stdout = stdout_origin
        self.stdout_with_codec = encode_stream(sys.stdout, "utf-8")

        self.completion_matches = None
        Cmd.__init__(self)
        self.admin_cli = admin_cli
        self.completion = Completion(self.admin_cli)
        try:
            Config()
            self.prompt = Config.parser.get('shell', 'prompt') + ' '
        except (ConfigFileError, ConfigParser.Error):
            self.prompt = 'katello> '

        try:
            # don't split on hyphens during tab completion (important for completing parameters)
            newdelims = readline.get_completer_delims()
            newdelims = re.sub('-', '', newdelims)
            readline.set_completer_delims(newdelims)

            if (Config.parser.get('shell', 'nohistory').lower() != 'true'):
                self.__init_history()
        except ConfigParser.Error:
            pass
        self.__init_commands()
示例#3
0
文件: shell.py 项目: bcrochet/katello
class KatelloShell(Cmd):

    # maximum length of history file
    HISTORY_LENGTH = 1024
    BUILTIN_COMMANDS = ("help", "quit", "exit")

    cmdqueue = []
    completekey = 'tab'
    stdout = sys.stdout

    # do nothing on an empty line
    emptyline = lambda self: None

    # pylint: disable=R0201
    @property
    def history_file(self):
        conf_dir = Config.USER_DIR
        try:
            if not os.path.isdir(conf_dir):
                os.mkdir(conf_dir, 0700)
        except OSError:
            logging.error('Could not create directory %s', conf_dir)
        return os.path.join(conf_dir, 'history')


    def __init__(self, admin_cli):
        # remove stdout stream encoding while in 'shell' mode, becuase this breaks readline
        # (autocompletion and shell history). In 'shell' mode the stdout
        # is encoded just for time necessary for command execution see precmd a postcmd

        sys.stdout = stdout_origin
        self.stdout_with_codec = encode_stream(sys.stdout, "utf-8")

        self.completion_matches = None
        Cmd.__init__(self)
        self.admin_cli = admin_cli
        self.completion = Completion(self.admin_cli)
        try:
            Config()
            self.prompt = Config.parser.get('shell', 'prompt') + ' '
        except (ConfigFileError, ConfigParser.Error):
            self.prompt = 'katello> '

        try:
            # don't split on hyphens during tab completion (important for completing parameters)
            newdelims = readline.get_completer_delims()
            newdelims = re.sub('-', '', newdelims)
            readline.set_completer_delims(newdelims)

            if (Config.parser.get('shell', 'nohistory').lower() != 'true'):
                self.__init_history()
        except ConfigParser.Error:
            pass
        self.__init_commands()


    def __init_history(self):
        try:
            readline.read_history_file(self.history_file)
            readline.set_history_length(self.HISTORY_LENGTH)
            # always write the history file on exit
            atexit.register(readline.write_history_file, self.history_file)
        except IOError:
            logging.error('Could not read history file')


    def __init_commands(self):
        # add commans to shell to avoid unknown syntax errors
        for cmd in self.admin_cli.get_command_names():
            setattr(self, "do_"+cmd, self.admin_cli.main)
        # add builtin commands into cli command - needed for correct completion
        for name in self.BUILTIN_COMMANDS:
            self.admin_cli.add_command(name, Command())
        # set exit aliases
        setattr(self, "do_quit", self.do_exit)
        setattr(self, "do_EOF", self.do_exit)
        setattr(self, "do_eof", self.do_exit)


    # pylint: disable=W0613
    def do_exit(self, args):
        self.__remove_last_history_item()
        sys.exit(0)


    def do_help(self, str_args):
        self.admin_cli.main("--help")


    def precmd(self, line):
        # turn on wrapper for encoding stdout
        sys.stdout = self.stdout_with_codec
        # preprocess the line
        line = line.strip()
        line = self.__history_preprocess(line)
        return line


    def postcmd(self, stop, line):
        # turn off wrapper for encoding stdout
        sys.stdout = stdout_origin
        # always stay in the command loop (we call sys.exit from exit commands)
        return False


    def __history_preprocess(self, line):
        # history search commands start with !
        if not line.startswith('!'):
            return line

        command = line.split()[0]
        if re.match('^!$', command):
            # single ! repeats last command
            new_line = self.__history_try_repeat_nth(-1)
        elif re.match('^!-?[0-9]+$', command):
            # !<int> repeats n-th command from history
            # negative numbers can be used for reversed indexing
            new_line = self.__history_try_repeat_nth(command[1:])
        else:
            # !<string> searches for last command starting with the string
            # and repeats it
            new_line = self.__history_try_search(command[1:])

        # remove the '!*' line from the history
        if new_line:
            self.__replace_last_history_item(new_line)
            print new_line
            return new_line
        return line

    @classmethod
    def __history_try_repeat_nth(cls, n):
        try:
            n = int(n)
            if n < 0:
                n = readline.get_current_history_length()+n
            return readline.get_history_item(n)
        except IOError:
            logging.warning('Could not read history file')
            return ''

    @classmethod
    def __history_try_search(cls, text):
        history_range = range(readline.get_current_history_length(), 1, -1)
        for i in history_range:
            item = readline.get_history_item(i)
            if item.startswith(text):
                return item
        return ''


    def parseline(self, line):
        """
        Parses a line to command and arguments.
        For our uses we copy name of the command to arguments so that
        the man command knows what subcommands to run.
        """
        cmd, arg, line = Cmd.parseline(self, line)
        if (cmd in self.admin_cli.get_command_names()) and (arg != None):
            arg = cmd + " " + arg
        return cmd, arg, line


    def complete(self, text, state):
        """
        Return the next possible completion for 'text'.
        """
        if state == 0:
            line = readline.get_line_buffer()
            self.completion_matches = self.completion.complete(line)

        try:
            return self.completion_matches[state]
        except IndexError:
            return None


    @classmethod
    def __remove_last_history_item(cls):
        last = readline.get_current_history_length() - 1
        if last >= 0:
            readline.remove_history_item(last)


    def __replace_last_history_item(self, replace_with):
        self.__remove_last_history_item()
        readline.add_history(replace_with)
示例#4
0
class KatelloShell(Cmd):

    # maximum length of history file
    HISTORY_LENGTH = 1024
    BUILTIN_COMMANDS = ("help", "quit", "exit")

    cmdqueue = []
    completekey = 'tab'
    stdout = sys.stdout

    # do nothing on an empty line
    emptyline = lambda self: None

    # pylint: disable=R0201
    @property
    def history_file(self):
        conf_dir = Config.USER_DIR
        try:
            if not os.path.isdir(conf_dir):
                os.mkdir(conf_dir, 0700)
        except OSError:
            logging.error('Could not create directory %s', conf_dir)
        return os.path.join(conf_dir, 'history')

    def __init__(self, admin_cli):
        # remove stdout stream encoding while in 'shell' mode, becuase this breaks readline
        # (autocompletion and shell history). In 'shell' mode the stdout
        # is encoded just for time necessary for command execution see precmd a postcmd

        sys.stdout = stdout_origin
        self.stdout_with_codec = encode_stream(sys.stdout, "utf-8")

        self.completion_matches = None
        Cmd.__init__(self)
        self.admin_cli = admin_cli
        self.completion = Completion(self.admin_cli)
        try:
            Config()
            self.prompt = Config.parser.get('shell', 'prompt') + ' '
        except (ConfigFileError, ConfigParser.Error):
            self.prompt = 'katello> '

        try:
            # don't split on hyphens during tab completion (important for completing parameters)
            newdelims = readline.get_completer_delims()
            newdelims = re.sub('-', '', newdelims)
            readline.set_completer_delims(newdelims)

            if (Config.parser.get('shell', 'nohistory').lower() != 'true'):
                self.__init_history()
        except ConfigParser.Error:
            pass
        self.__init_commands()

    def __init_history(self):
        try:
            readline.read_history_file(self.history_file)
            readline.set_history_length(self.HISTORY_LENGTH)
            # always write the history file on exit
            atexit.register(readline.write_history_file, self.history_file)
        except IOError:
            logging.error('Could not read history file')

    def __init_commands(self):
        # add commans to shell to avoid unknown syntax errors
        for cmd in self.admin_cli.get_command_names():
            setattr(self, "do_" + cmd, self.admin_cli.main)
        # add builtin commands into cli command - needed for correct completion
        for name in self.BUILTIN_COMMANDS:
            self.admin_cli.add_command(name, Command())
        # set exit aliases
        setattr(self, "do_quit", self.do_exit)
        setattr(self, "do_EOF", self.do_exit)
        setattr(self, "do_eof", self.do_exit)

    # pylint: disable=W0613
    def do_exit(self, args):
        self.__remove_last_history_item()
        sys.exit(0)

    def do_help(self, str_args):
        self.admin_cli.main("--help")

    def precmd(self, line):
        # turn on wrapper for encoding stdout
        sys.stdout = self.stdout_with_codec
        # preprocess the line
        line = line.strip()
        line = self.__history_preprocess(line)
        return line

    def postcmd(self, stop, line):
        # turn off wrapper for encoding stdout
        sys.stdout = stdout_origin
        # always stay in the command loop (we call sys.exit from exit commands)
        return False

    def __history_preprocess(self, line):
        # history search commands start with !
        if not line.startswith('!'):
            return line

        command = line.split()[0]
        if re.match('^!$', command):
            # single ! repeats last command
            new_line = self.__history_try_repeat_nth(-1)
        elif re.match('^!-?[0-9]+$', command):
            # !<int> repeats n-th command from history
            # negative numbers can be used for reversed indexing
            new_line = self.__history_try_repeat_nth(command[1:])
        else:
            # !<string> searches for last command starting with the string
            # and repeats it
            new_line = self.__history_try_search(command[1:])

        # remove the '!*' line from the history
        if new_line:
            self.__replace_last_history_item(new_line)
            print new_line
            return new_line
        return line

    @classmethod
    def __history_try_repeat_nth(cls, n):
        try:
            n = int(n)
            if n < 0:
                n = readline.get_current_history_length() + n
            return readline.get_history_item(n)
        except IOError:
            logging.warning('Could not read history file')
            return ''

    @classmethod
    def __history_try_search(cls, text):
        history_range = range(readline.get_current_history_length(), 1, -1)
        for i in history_range:
            item = readline.get_history_item(i)
            if item.startswith(text):
                return item
        return ''

    def parseline(self, line):
        """
        Parses a line to command and arguments.
        For our uses we copy name of the command to arguments so that
        the man command knows what subcommands to run.
        """
        cmd, arg, line = Cmd.parseline(self, line)
        if (cmd in self.admin_cli.get_command_names()) and (arg != None):
            arg = cmd + " " + arg
        return cmd, arg, line

    def complete(self, text, state):
        """
        Return the next possible completion for 'text'.
        """
        if state == 0:
            line = readline.get_line_buffer()
            self.completion_matches = self.completion.complete(line)

        try:
            return self.completion_matches[state]
        except IndexError:
            return None

    @classmethod
    def __remove_last_history_item(cls):
        last = readline.get_current_history_length() - 1
        if last >= 0:
            readline.remove_history_item(last)

    def __replace_last_history_item(self, replace_with):
        self.__remove_last_history_item()
        readline.add_history(replace_with)