def create_grammar(): return compile( """ (\s* (?P<operator1>[a-z]+) \s+ (?P<var1>[0-9.]+) \s+ (?P<var2>[0-9.]+) \s*) | (\s* (?P<operator2>[a-z]+) \s+ (?P<var1>[0-9.]+) \s*) """ )
def create_ipython_grammar(): """ Return compiled IPython grammar. """ return compile( r""" \s* ( (?P<percent>%)( (?P<magic>pycat|run|loadpy|load) \s+ (?P<py_filename>[^\s]+) | (?P<magic>cat) \s+ (?P<filename>[^\s]+) | (?P<magic>pushd|cd|ls) \s+ (?P<directory>[^\s]+) | (?P<magic>pdb) \s+ (?P<pdb_arg>[^\s]+) | (?P<magic>autocall) \s+ (?P<autocall_arg>[^\s]+) | (?P<magic>time|timeit|prun) \s+ (?P<python>.+) | (?P<magic>psource|pfile|pinfo|pinfo2) \s+ (?P<python>.+) | (?P<magic>system) \s+ (?P<system>.+) | (?P<magic>unalias) \s+ (?P<alias_name>.+) | (?P<magic>[^\s]+) .* | ) .* | !(?P<system>.+) | (?![%!]) (?P<python>.+) ) \s* """ )
def create_grammar(): return compile(""" ((?P<op_mac>mac) \s* (?P<op_main>login) \s+) | ((?P<op_mac>mac) \s* (?P<op_main>instance) \s+ (?P<op_instance>[list|create|update|destroy|ssh|facts|log|lifespan]+) \s+ (?P<op_parameter>("[^"]*"|[^"]+)(\s+|$)) \s+) | ((?P<op_mac>mac) \s* (?P<op_main>configuration) \s+ (?P<op_configuration>[list|search]+) \s+ (?P<op_parameter>("[^"]*"|[^"]+)(\s+|$)) \s+) | ((?P<op_mac>mac) \s* (?P<op_main>infrastructure) \s+ (?P<op_infrastructure>[macfile|list|items|destroy|update|lifespan|sshkey]+) \s+ (?P<op_parameter>("[^"]*"|[^"]+)(\s+|$)) \s+) """)
def create_grammar(): """ Grammar :return: """ return compile(r""" (\s* (?P<operator>[a-z]+) (\s+ (?P<var>[0-9.]+) )*) """)
def create_grammar(): return compile(""" (\s* repos \s (?P<repocmd>tag|untag) \s (?P<repokey>[\w/\-\._]*) \s (?P<tagkey>[\w/\-\._]*)(,(?P<tagkey>[\w/\-\._]*))* | repos \s (?P<repocmd>links) \s (?P<tagkey>[\w/\-\._]*)(,(?P<tagkey>[\w/\-\._]*))* | repos \s (?P<repocmd>add|show|remove|edit|rename) \s (?P<repokey>[\w/\-\._]*) | tags \s (?P<tagcmd>add|show|remove|edit|rename) \s (?P<tagkey>[\w/\-\._]*) ) """)
def create_pdb_grammar(pdb_commands): """ Create a compiled grammar for this list of PDB commands. (Note: this is an expensive function. Call only when `pdb_commands` changes.) """ pdb_commands_re = '|'.join(map(re.escape, pdb_commands)) def create_grammar(recursive=True): return r""" \s* ( (?P<pdb_command>p|pp|whatis) \s+ (?P<python_code>.*) | (?P<pdb_command>enable) \s+ (?P<disabled_breakpoint>.*) | (?P<pdb_command>disable) \s+ (?P<enabled_breakpoint>.*) | (?P<pdb_command>condition) \s+ [0-9]+ \s+ (?P<python_code>.*) | (?P<pdb_command>ignore) \s+ (?P<breakpoint>[0-9]+) \s+ [0-9]+ | (?P<pdb_command>commands) \s+ (?P<breakpoint>[0-9]+) | (?P<pdb_command>alias) \s+ [^\s]+ \s+ """ + ( create_grammar(False) if recursive else '.+') + """ (?P<pdb_command>unalias) \s+ (?P<alias_name>.*) | (?P<pdb_command>h|help) \s+ (?P<pdb_command>.*) | (?P<pdb_command>display) \s+ (?P<python_code>.*) | # For the break command, do autocompletion on file and function names. # After the comma, do completion on python code. (?P<pdb_command>break|b|tbreak) \s+ ( # Break on a <function> (?P<python_function>[^\s:]+) | # Break on a <file>:<lineno> (?P<python_file>(?![0-9])[^\s:]+):[^\s]+ | # Break on a <lineno> [0-9]+ ) \s* (, \s* (?P<python_code>.*))? | # Known PDB commands (autocompletion & highlighting of all commands) (?P<pdb_command>""" + pdb_commands_re + """) (\s+ .*)? | # Starting with exclamation mark -> always Python code. !(?P<python_code>.*) | # When the input is no valid PDB command, we consider it Python code. # (We use negative lookahead to be sure it doesn't start with a pdb # command or an exclamation mark.) # (?P<python_code>(?!(""" + pdb_commands_re + """)(\s+|$))(?!\!).*) | (?P<python_code_highlight_only>(?!(""" + pdb_commands_re + """)(\s+|$))(?!\!).*) | ) \s* """ return compile(create_grammar())
def __init__(self): # Compile grammar. g = compile( r""" # First we have an executable. (?P<executable>[^\s]+) # Ignore literals in between. ( \s+ ("[^"]*" | '[^']*' | [^'"]+ ) )* \s+ # Filename as parameters. ( (?P<filename>[^\s]+) | "(?P<double_quoted_filename>[^\s]+)" | '(?P<single_quoted_filename>[^\s]+)' ) """, escape_funcs={ 'double_quoted_filename': (lambda string: string.replace('"', '\\"')), 'single_quoted_filename': (lambda string: string.replace("'", "\\'")), }, unescape_funcs={ 'double_quoted_filename': (lambda string: string.replace('\\"', '"') ), # XXX: not enterily correct. 'single_quoted_filename': (lambda string: string.replace("\\'", "'")), }) # Create GrammarCompleter super(SystemCompleter, self).__init__( g, { 'executable': PathCompleter( only_directories=False, min_input_len=1, get_paths=lambda: os.environ.get('PATH', '').split( os.pathsep), file_filter=lambda name: os.access(name, os.X_OK), expanduser=True), 'filename': PathCompleter(only_directories=False, expanduser=True), 'double_quoted_filename': PathCompleter(only_directories=False, expanduser=True), 'single_quoted_filename': PathCompleter(only_directories=False, expanduser=True), })
def create_pdb_grammar(pdb_commands): """ Create a compiled grammar for this list of PDB commands. (Note: this is an expensive function. Call only when `pdb_commands` changes.) """ pdb_commands_re = '|'.join(map(re.escape, pdb_commands)) def create_grammar(recursive=True): return r""" \s* ( (?P<pdb_command>p|pp|whatis) \s+ (?P<python_code>.*) | (?P<pdb_command>enable) \s+ (?P<disabled_breakpoint>.*) | (?P<pdb_command>disable) \s+ (?P<enabled_breakpoint>.*) | (?P<pdb_command>condition) \s+ [0-9]+ \s+ (?P<python_code>.*) | (?P<pdb_command>ignore) \s+ (?P<breakpoint>[0-9]+) \s+ [0-9]+ | (?P<pdb_command>commands) \s+ (?P<breakpoint>[0-9]+) | (?P<pdb_command>alias) \s+ [^\s]+ \s+ """ + (create_grammar(False) if recursive else '.+') + """ (?P<pdb_command>unalias) \s+ (?P<alias_name>.*) | (?P<pdb_command>h|help) \s+ (?P<pdb_command>.*) | (?P<pdb_command>display) \s+ (?P<python_code>.*) | # For the break command, do autocompletion on file and function names. # After the comma, do completion on python code. (?P<pdb_command>break|b|tbreak) \s+ ( # Break on a <function> (?P<python_function>[^\s:]+) | # Break on a <file>:<lineno> (?P<python_file>(?![0-9])[^\s:]+):[^\s]+ | # Break on a <lineno> [0-9]+ ) \s* (, \s* (?P<python_code>.*))? | # Known PDB commands (autocompletion & highlighting of all commands) (?P<pdb_command>""" + pdb_commands_re + """) (\s+ .*)? | # Starting with exclamation mark -> always Python code. !(?P<python_code>.*) | # When the input is no valid PDB command, we consider it Python code. # (We use negative lookahead to be sure it doesn't start with a pdb # command or an exclamation mark.) # (?P<python_code>(?!(""" + pdb_commands_re + """)(\s+|$))(?!\!).*) | (?P<python_code_highlight_only>(?!(""" + pdb_commands_re + """)(\s+|$))(?!\!).*) | ) \s* """ return compile(create_grammar())
def __init__(self) -> None: # Compile grammar. g = compile( r""" # First we have an executable. (?P<executable>[^\s]+) # Ignore literals in between. ( \s+ ("[^"]*" | '[^']*' | [^'"]+ ) )* \s+ # Filename as parameters. ( (?P<filename>[^\s]+) | "(?P<double_quoted_filename>[^\s]+)" | '(?P<single_quoted_filename>[^\s]+)' ) """, escape_funcs={ "double_quoted_filename": (lambda string: string.replace('"', '\\"')), "single_quoted_filename": (lambda string: string.replace("'", "\\'")), }, unescape_funcs={ "double_quoted_filename": (lambda string: string.replace('\\"', '"') ), # XXX: not entirely correct. "single_quoted_filename": (lambda string: string.replace("\\'", "'")), }, ) # Create GrammarCompleter super().__init__( g, { "executable": ExecutableCompleter(), "filename": PathCompleter(only_directories=False, expanduser=True), "double_quoted_filename": PathCompleter(only_directories=False, expanduser=True), "single_quoted_filename": PathCompleter(only_directories=False, expanduser=True), }, )
def create_grammar(): return compile(""" (\s*(?P<command>list) (\s+ (?P<accountName>[\w0-9]+))? \s*) | (\s*(?P<command>remove) \s+ (?P<accountName>[\w0-9]+) (\s+(?P<force>-f))? \s*) | (\s*(?P<command>update) \s+ (?P<accountName>[\w0-9\.]+) \s+ (?P<updateOption>name|username|password|remark) (\s+(?P<force>-f))? \s*) | (\s*(?P<command>search) \s+ (?P<keyword>[\w0-9]+) \s*) | (\s*(?P<command>password) (\s+ (?P<path>~?[\w0-9\./_-]+))? \s*) | (\s*(?P<command>switch) \s+ (?P<path>~?[\w0-9\./_-]+) \s*) | (\s*(?P<command>where) \s*) | (\s*(?P<command>exit) \s*) | (\s*(?P<command>create) \s*) | (\s*(?P<command>help) \s*) """)
def get_command_grammar(command): """ :param command: command name in upper case. This command must be raw user input, otherwise can't match in lexer, cause this command to be invalid; """ syntax_name = command2syntax[command.upper()] syntax = NEW_GRAMMAR.get(syntax_name) # TODO this should be deleted if syntax is None: return command_grammar syntax = syntax.replace(r"xxin", command.replace(r" ", r"\s+")) logger.info(f"syxtax: {syntax}") return compile(syntax)
def __init__(self): # Compile grammar. g = compile( r""" # First we have an executable. (?P<executable>[^\s]+) # Ignore literals in between. ( \s+ ("[^"]*" | '[^']*' | [^'"]+ ) )* \s+ # Filename as parameters. ( (?P<filename>[^\s]+) | "(?P<double_quoted_filename>[^\s]+)" | '(?P<single_quoted_filename>[^\s]+)' ) """, escape_funcs={ 'double_quoted_filename': (lambda string: string.replace('"', '\\"')), 'single_quoted_filename': (lambda string: string.replace("'", "\\'")), }, unescape_funcs={ 'double_quoted_filename': (lambda string: string.replace('\\"', '"')), # XXX: not enterily correct. 'single_quoted_filename': (lambda string: string.replace("\\'", "'")), }) # Create GrammarCompleter super(SystemCompleter, self).__init__( g, { 'executable': PathCompleter(only_directories=False, min_input_len=1, get_paths=lambda: os.environ.get('PATH', '').split(os.pathsep), file_filter=lambda name: os.access(name, os.X_OK), expanduser=True), 'filename': PathCompleter(only_directories=False, expanduser=True), 'double_quoted_filename': PathCompleter(only_directories=False, expanduser=True), 'single_quoted_filename': PathCompleter(only_directories=False, expanduser=True), })
def compile_and_patch(session): start_time = time.time() logger.debug("[compile] start compile grammer...") redis_grammar = compile(REDIS_COMMANDS) end_time = time.time() logger.debug(f"[compile] Compile finished! Cost: {end_time - start_time}") # get lexer lexer = get_lexer(group2commands.keys(), redis_grammar) # get completer completer = get_completer(group2commands, redis_grammar) session.completer = completer session.lexer = lexer logger.debug("[compile] Patch finished!") config.compiling = COMPILING_JUST_FINISH time.sleep(1) config.compiling = COMPILING_DONE
def __init__(self): # Compile grammar. g = compile( r""" # First we have an executable. (?P<executable>[^\s]+) # Ignore literals in between. ( \s+ ("[^"]*" | '[^']*' | [^'"]+ ) )* \s+ # Filename as parameters. ( (?P<filename>[^\s]+) | "(?P<double_quoted_filename>[^\s]+)" | '(?P<single_quoted_filename>[^\s]+)' ) """, escape_funcs={ "double_quoted_filename": (lambda string: string.replace('"', '\\"')), "single_quoted_filename": (lambda string: string.replace("'", "\\'")), }, unescape_funcs={ "double_quoted_filename": (lambda string: string.replace('\\"', '"')), # XXX: not enterily correct. "single_quoted_filename": (lambda string: string.replace("\\'", "'")), }, ) # Create GrammarCompleter super(SystemCompleter, self).__init__( g, { "executable": ExecutableCompleter(), "filename": PathCompleter(only_directories=False, expanduser=True), "double_quoted_filename": PathCompleter(only_directories=False, expanduser=True), "single_quoted_filename": PathCompleter(only_directories=False, expanduser=True), }, )
def __init__(self): # Compile grammar. g = compile( r""" # First we have an executable. (?P<executable>[^\s]+) # Ignore literals in between. ( \s+ ("[^"]*" | '[^']*' | [^'"]+ ) )* \s+ # Secondary grammar ( /(?P<smodifier>[^\s]+) | (?P<filename>[^\s]+) | -(?P<hmodifier>[^\s]+) | "(?P<double_quoted_filename>[^\s]+)" | '(?P<single_quoted_filename>[^\s]+)' ) """, escape_funcs={ 'double_quoted_filename': (lambda string: string.replace('"', '\\"')), 'single_quoted_filename': (lambda string: string.replace("'", "\\'")), }, unescape_funcs={ 'double_quoted_filename': (lambda string: string.replace('\\"', '"')), # XXX: not enterily correct. 'single_quoted_filename': (lambda string: string.replace("\\'", "'")), }) # Create GrammarCompleter super(SystemCompleter, self).__init__( g, { 'executable': WordCompleter(master_dict.primary, meta_dict=master_dict.primary), 'hmodifier': WordCompleter(master_dict.secondary_h), 'smodifier': WordCompleter(master_dict.secondary_s), 'filename': PathCompleter(only_directories=False, expanduser=True), 'double_quoted_filename': PathCompleter(only_directories=False, expanduser=True), 'single_quoted_filename': PathCompleter(only_directories=False, expanduser=True), })
def get_command_grammar(command): """ :param command: command name in upper case. This command must be raw user input, otherwise can't match in lexer, cause this command to be invalid; """ syntax_name = command2syntax[command.upper()] syntax = NEW_GRAMMAR.get(syntax_name) # If a command is not supported yet, (e.g. command from latest version added # by Redis recently, or command from third Redis module.) return a defualt # grammar, so the lexer and completion won't be activated. if syntax is None: return command_grammar # prepend command token for this syntax command_allow_multi_spaces = command.replace(r" ", r"\s+") syntax = fr"\s* (?P<command>{command_allow_multi_spaces}) " + syntax # allow user input pipeline to redirect to shell, like `get json | jq .` syntax += pipeline logger.info(f"syxtax: {syntax}") return compile(syntax)
COMMAND_GRAMMAR = compile(r""" # Allow leading colons and whitespace. (They are ignored.) :* \s* ( # Commands accepting a location. (?P<command>%(commands_taking_locations)s)(?P<force>!?) \s+ (?P<location>[^\s]+) | # Commands accepting a buffer. (?P<command>b|buffer)(?P<force>!?) \s+ (?P<buffer_name>[^\s]+) | # Jump to line numbers. (?P<go_to_line>\d+) | # Set operation (?P<command>set) \s+ (?P<set_option>[^\s=]+) (=(?P<set_value>[^\s]+))? | # Colorscheme command (?P<command>colorscheme) \s+ (?P<colorscheme>[^\s]+) | # Shell command !(?P<shell_command>.*) | # Any other normal command. (?P<command>[^\s!]+)(?P<force>!?) | # Accept the empty input as well. (Ignores everything.) #(?P<command>colorscheme.+) (?P<colorscheme>[^\s]+) | ) # Allow trailing space. \s* """ % { 'commands_taking_locations': '|'.join(get_commands_taking_locations()), })
def grammar(): grams = getClientGrams() + getNewClientGrams() return compile("".join(grams))
def _create_grammar(): patterns = map(_build_pattern, [ (command, operand_pattern) for (command, (_, operand_pattern, _)) in COMMANDS.items()]) patterns = '|'.join(patterns) return compiler.compile(patterns)
def grammar(): utilGrams = getUtilGrams() nodeGrams = getNodeGrams() clientGrams = getClientGrams() grams = getAllGrams(utilGrams, nodeGrams, clientGrams) return compile("".join(grams))
def create_grammar(): return compile(""" (\s* (?P<operator1>[a-z]+) \s+ (?P<var1>[0-9.]+) \s+ (?P<var2>[0-9.]+) \s*) | (\s* (?P<operator2>[a-z]+) \s+ (?P<var1>[0-9.]+) \s*) """)
'status': functions.package_status, }, 'hardware': { 'add': functions.add_hardware, 'remove': functions.remove_hardware, 'reset': functions.reset_hardware, } } GRAMMAR = compiler.compile(r''' (\s* (?P<group>product) \s+ (?P<product>[a-z]+) \s+ (?P<arg>.+?) \s*) | (\s* (?P<group>product) \s+ (?P<product>[a-z]+) \s*) | (\s* (?P<group>hardware) \s+ (?P<hardware>[a-z]+) \s+ (?P<arg>.+?) \s*) | (\s* (?P<group>hardware) \s+ (?P<hardware>[a-z]+) \s*) | (\s* (?P<group>package) \s+ (?P<package>[a-z-]+) \s+ (?P<arg>.+?) \s*) | (\s* (?P<group>package) \s+ (?P<package>[a-z-]+) \s*) | (\s* (?P<command>[a-z]+) \s*) | (\s* (?P<command>[a-z]+) \s+ (?P<arg>.+?) \s*) | ''') class UHURepl: """The main class for UpdateHub REPL.""" completer = GrammarCompleter( GRAMMAR, { 'command': WordCompleter(COMMANDS), 'group': WordCompleter(GROUPS),
def __init__(self, looper, tmpdir, nodeReg, cliNodeReg, debug=False, logFileName=None): self.curClientPort = None logging.root.addHandler(CliHandler(self.out)) self.looper = looper self.tmpdir = tmpdir self.nodeReg = nodeReg self.cliNodeReg = cliNodeReg # Used to store created clients self.clients = {} # clientId -> Client # To store the created requests self.requests = {} # To store the nodes created self.nodes = {} self.cliCmds = {'status', 'new'} self.nodeCmds = self.cliCmds | {'keyshare'} self.helpablesCommands = self.cliCmds | self.nodeCmds self.simpleCmds = {'status', 'exit', 'quit', 'license'} self.commands = {'list', 'help'} | self.simpleCmds self.cliActions = {'send', 'show'} self.commands.update(self.cliCmds) self.commands.update(self.nodeCmds) self.node_or_cli = ['node', 'client'] self.nodeNames = list(self.nodeReg.keys()) + ["all"] self.debug = debug self.plugins = [] ''' examples: status new node Alpha new node all new client Joe client Joe send <msg> client Joe show 1 ''' def re(seq): return '(' + '|'.join(seq) + ')' grams = [ "(\s* (?P<simple>{}) \s*) |".format(re(self.simpleCmds)), "(\s* (?P<client_command>{}) \s+ (?P<node_or_cli>clients?) \s+ (?P<client_name>[a-zA-Z0-9]+) \s*) |".format(re(self.cliCmds)), "(\s* (?P<node_command>{}) \s+ (?P<node_or_cli>nodes?) \s+ (?P<node_name>[a-zA-Z0-9]+)\s*) |".format(re(self.nodeCmds)), "(\s* (?P<client>client) \s+ (?P<client_name>[a-zA-Z0-9]+) \s+ (?P<cli_action>send) \s+ (?P<msg>\{\s*\".*\}) \s*) |", "(\s* (?P<client>client) \s+ (?P<client_name>[a-zA-Z0-9]+) \s+ (?P<cli_action>show) \s+ (?P<req_id>[0-9]+) \s*) |", "(\s* (?P<load_plugins>load\s+plugins\s+from) \s+ (?P<plugin_dir>[a-zA-Z0-9-{}]+) \s*) |".format(os.path.sep), "(\s* (?P<load>load) \s+ (?P<file_name>[.a-zA-z0-9{}]+) \s*) |".format(os.path.sep), "(\s* (?P<command>help) (\s+ (?P<helpable>[a-zA-Z0-9]+) )? (\s+ (?P<node_or_cli>{}) )?\s*) |".format(re(self.node_or_cli)), "(\s* (?P<command>list) \s*)".format(re(self.commands)) ] self.grammar = compile("".join(grams)) lexer = GrammarLexer(self.grammar, lexers={ 'node_command': SimpleLexer(Token.Keyword), 'command': SimpleLexer(Token.Keyword), 'helpable': SimpleLexer(Token.Keyword), 'load_plugins': SimpleLexer(Token.Keyword), 'load': SimpleLexer(Token.Keyword), 'node_or_cli': SimpleLexer(Token.Keyword), 'arg1': SimpleLexer(Token.Name), 'node_name': SimpleLexer(Token.Name), 'more_nodes': SimpleLexer(Token.Name), 'simple': SimpleLexer(Token.Keyword), 'client_command': SimpleLexer(Token.Keyword), }) self.clientWC = WordCompleter([]) completer = GrammarCompleter(self.grammar, { 'node_command': WordCompleter(self.nodeCmds), 'client_command': WordCompleter(self.cliCmds), 'client': WordCompleter(['client']), 'command': WordCompleter(self.commands), 'node_or_cli': WordCompleter(self.node_or_cli), 'node_name': WordCompleter(self.nodeNames), 'more_nodes': WordCompleter(self.nodeNames), 'helpable': WordCompleter(self.helpablesCommands), 'load_plugins': WordCompleter(['load plugins from']), 'client_name': self.clientWC, 'cli_action': WordCompleter(self.cliActions), 'simple': WordCompleter(self.simpleCmds) }) self.style = PygmentsStyle.from_defaults({ Token.Operator: '#33aa33 bold', Token.Number: '#aa3333 bold', Token.Name: '#ffff00 bold', Token.Heading: 'bold', Token.TrailingInput: 'bg:#662222 #ffffff', Token.BoldGreen: '#33aa33 bold', Token.BoldOrange: '#ff4f2f bold', Token.BoldBlue: '#095cab bold'}) self.functionMappings = self.createFunctionMappings() self.voidMsg = "<none>" # Create an asyncio `EventLoop` object. This is a wrapper around the # asyncio loop that can be passed into prompt_toolkit. eventloop = create_asyncio_eventloop(looper.loop) pers_hist = FileHistory('.plenum-cli-history') # Create interface. app = create_prompt_application('plenum> ', lexer=lexer, completer=completer, style=self.style, history=pers_hist) self.cli = CommandLineInterface( application=app, eventloop=eventloop, output=CustomOutput.from_pty(sys.__stdout__, true_color=True)) # Patch stdout in something that will always print *above* the prompt # when something is written to stdout. sys.stdout = self.cli.stdout_proxy() setupLogging(TRACE_LOG_LEVEL, Console.Wordage.mute, filename=logFileName) self.logger = getlogger("cli") self.print("\nplenum-CLI (c) 2016 Evernym, Inc.") self.print("Node registry loaded.") self.print("None of these are created or running yet.") self.showNodeRegistry() self.print("Type 'help' for more information.")
def __init__(self): # Compile grammar. g = compile( r""" git(\.exe)? (\s+h|\s+help)? \s+ (?P<git_command>[^\s]+) \s+ ( (?P<filename>[^\s]+) | "(?P<double_quoted_filename>[^\s]+)" ) | svn(\.exe)? \s+ (?P<svn_command>[^\s]+) \s+ ( (?P<filename>[^\s]+) | "(?P<double_quoted_filename>[^\s]+)" ) | start \s+ ("[^"]+"\s+)? # First we have an executable. ( (?P<executable>[^\s]+) | "(?P<double_quoted_executable>[^\s]+)" ) # Ignore literals in between. ( \s+ ("[^"]*" | '[^']*' | [^'"]+ ) )* \s+ # Filename as parameters. ( (?P<filename>[^\s]+) | "(?P<double_quoted_filename>[^\s]+)" ) | ;? # a semicolon get a start command # First we have an executable. ( (?P<executable>[^\s]+) | "(?P<double_quoted_executable>[^\s]+)" ) # Ignore texts between .* \s+ # Filename as parameters. ( (?P<filename>[^\s]+) | "(?P<double_quoted_filename>[^\s]+)" ) """, escape_funcs={ 'double_quoted_filename': (lambda string: string.replace('"', '\\"')), 'double_quoted_executable': (lambda string: string.replace('"', '\\"')), }, unescape_funcs={ # XXX: not enterily correct. 'double_quoted_filename': (lambda string: string.replace('\\"', '"')), 'double_quoted_executable': (lambda string: string.replace('\\"', '"')), }) # Create GrammarCompleter super(CmdExCompleter, self).__init__( g, { 'executable': ExecutableCompleter(), 'double_quoted_executable': ExecutableCompleter(), 'filename': PathCompleter(only_directories=False, expanduser=True), 'double_quoted_filename': PathCompleter(only_directories=False, expanduser=True), 'git_command': GitCmdCompeter(), 'svn_command': SvnCmdCompleter(), })
def initializeGrammar(self): self.utilGrams[-1] += " |" self.nodeGrams[-1] += " |" self.grams = self.utilGrams + self.nodeGrams + self.clientGrams self.grammar = compile("".join(self.grams))
COMMAND_GRAMMAR = compile( r""" # Allow leading colons and whitespace. (They are ignored.) :* \s* ( # Commands accepting a filename. (?P<command>%(commands_taking_filenames)s) \s+ (?P<filename>[^\s]+) | # Commands accepting a buffer. (?P<command>b|buffer) \s+ (?P<buffer_name>[^\s]+) | # Jump to line numbers. (?P<go_to_line>\d+) | # Set operation (?P<command>set) \s+ (?P<set_option>[^\s=]+) (=(?P<set_value>[^\s]+))? | # Colorscheme command (?P<command>colorscheme) \s+ (?P<colorscheme>[^\s]+) | # Shell command !(?P<shell_command>.*) | # Any command. (For command completions.) (?P<command>[^\s]+) | # Accept the empty input as well. (Ignores everything.) #(?P<command>colorscheme.+) (?P<colorscheme>[^\s]+) | ) # Allow trailing space. \s* """ % { 'commands_taking_filenames': '|'.join(get_commands_taking_filenames()), })
import pexpect import pytest import redis from iredis.redis_grammar import REDIS_COMMANDS from iredis.client import Client from prompt_toolkit.contrib.regular_languages.compiler import compile TIMEOUT = 3 redis_grammar = compile(REDIS_COMMANDS) @pytest.fixture def judge_command(): def judge_command_func(command, expect): m = redis_grammar.match(command) # not match if not expect: assert m is None return variables = m.variables() for expect_token, expect_value in expect.items(): all_variables = variables.getall(expect_token) if len(all_variables) > 1: assert sorted(all_variables) == sorted(expect_value) else: assert variables.get(expect_token) == expect_value return judge_command_func
OVERFLOW = fr"(?P<overflow>{c('overflow')})" OVERFLOW_OPTION = fr"(?P<overflow_option>{c('overflow_option')})" KEEPTTL = fr"(?P<keepttl>{c('keepttl')})" GRAPHEVENT = fr"(?P<graphevent>{c('graphevent')})" VERSION = fr"(?P<version>{c('version')})" SECTION = fr"(?P<section>{c('section')})" SCHEDULE = fr"(?P<schedule>{c('schedule')})" REDIRECT_CONST = fr"(?P<redirect_const>{c('redirect_const')})" PREFIX_CONST = fr"(?P<prefix_const>{c('prefix_const')})" BCAST_CONST = fr"(?P<bcast_const>{c('bcast_const')})" OPTIN_CONST = fr"(?P<optin_const>{c('optin_const')})" OPTOUT_CONST = fr"(?P<optout_const>{c('optout_const')})" NOLOOP_CONST = fr"(?P<noloop_const>{c('noloop_const')})" command_grammar = compile(COMMAND) # Here are the core grammars, those are tokens after ``command``. # E.g. SET command's syntax is "SET key value" # Then it's grammar here is r"\s+ key \s+ value \s*", we needn't add `command` # here because every syntaxes starts with `command` so we will prepend `command` # in get_command_grammar function. NEW_GRAMMAR = { "command_key": fr"\s+ {KEY} \s*", "command_pattern": fr"\s+ {PATTERN} \s*", "command_georadiusbymember": fr""" \s+ {KEY} \s+ {MEMBER} \s+ {FLOAT} \s+ {DISTUNIT} (\s+ {GEOCHOICE})* (\s+ {COUNT_CONST} \s+ {COUNT})? (\s+ {ORDER})?
COMMAND_GRAMMAR = compile( r""" # Allow leading colons and whitespace. (They are ignored.) :* \s* ( # Substitute command ((?P<range_start>\d+)(,(?P<range_end>\d+))?)? (?P<command>s|substitute) \s* / (?P<search>[^/]*) ( / (?P<replace>[^/]*) (?P<flags> /(g)? )? )? | # Commands accepting a location. (?P<command>%(commands_taking_locations)s)(?P<force>!?) \s+ (?P<location>[^\s]+) | # Commands accepting a buffer. (?P<command>b|buffer)(?P<force>!?) \s+ (?P<buffer_name>[^\s]+) | # Jump to line numbers. (?P<go_to_line>\d+) | # Set operation (?P<command>set) \s+ (?P<set_option>[^\s=]+) (=(?P<set_value>[^\s]+))? | # Colorscheme command (?P<command>colorscheme) \s+ (?P<colorscheme>[^\s]+) | # Shell command !(?P<shell_command>.*) | # Any other normal command. (?P<command>[^\s!]+)(?P<force>!?) | # Accept the empty input as well. (Ignores everything.) #(?P<command>colorscheme.+) (?P<colorscheme>[^\s]+) | ) # Allow trailing space. \s* """ % { 'commands_taking_locations': '|'.join(get_commands_taking_locations()), })
def __init__(self, config, db, scanner): """class object initialization""" self.log = Log(name='shell') self.config = config self.db = db self.scan = scanner self.parser = Parser() self.collors = ( '#000000', '#800000', '#008000', '#808000', '#000080', '#800080', '#008080', '#c0c0c0', '#808080', '#ff0000', '#00ff00', '#ffff00', '#0000ff', '#ff00ff', '#00ffff', '#ffffff', '#000000', '#00005f', '#000087', '#0000af', '#0000d7', '#0000ff', '#005f00', '#005f5f', '#005f87', '#005faf', '#005fd7', '#005fff', '#008700', '#00875f', '#008787', '#0087af', '#0087d7', '#0087ff', '#00af00', '#00af5f', '#00af87', '#00afaf', '#00afd7', '#00afff', '#00d700', '#00d75f', '#00d787', '#00d7af', '#00d7d7', '#00d7ff', '#00ff00', '#00ff5f', '#00ff87', '#00ffaf', '#00ffd7', '#00ffff', '#5f0000', '#5f005f', '#5f5fd7', '#5faf5f', '#5f0087', '#5f00af', '#5f00d7', '#5f00ff', '#5f5f00', '#5f5f5f', '#5f5f87', '#5f5faf', '#5f5fff', '#5f8700', '#5f875f', '#5f8787', '#5f87af', '#5f87d7', '#5f87ff', '#5faf00', '#5faf87', '#5fafaf', '#5fafd7', '#5fafff', '#5fd700', '#5fd75f', '#5fd787', '#5fd7af', '#5fd7ff', '#5fff00', '#5fff5f', '#5fff87', '#5fffaf', '#5fffd7', '#5fffff', '#870000', '#870087', '#8700af', '#8700d7', '#8700ff', '#875f00', '#875f5f', '#875f87', '#875faf', '#875fff', '#878700', '#87875f', '#878787', '#8787af', '#8787d7', '#8787ff', '#87af00', '#87af87', '#87afaf', '#87afd7', '#87afff', '#87d700', '#87d75f', '#87d787', '#87d7af', '#87d7ff', '#87ff00', '#87ff5f', '#87ff87', '#87ffaf', '#87ffd7', '#87ffff', '#af0000', '#af0087', '#af00af', '#af00d7', '#af00ff', '#af5f00', '#af5f5f', '#af5f87', '#af5faf', '#af5fff', '#af8700', '#af875f', '#af8787', '#af87af', '#af87d7', '#af87ff', '#afaf00', '#afaf87', '#afafaf', '#afafd7', '#afafff', '#afd700', '#afd75f', '#afd787', '#afd7af', '#afd7ff', '#afff00', '#afff5f', '#afff87', '#afffaf', '#afffd7', '#afffff', '#d70000', '#d70087', '#d700af', '#d700d7', '#d700ff', '#d75f00', '#d75f5f', '#d75f87', '#d75faf', '#d75fff', '#d78700', '#d7875f', '#d78787', '#d787af', '#d787d7', '#d787ff', '#d7af00', '#d7af87', '#d7afaf', '#d7afd7', '#d7afff', '#d7d700', '#d7d75f', '#d7d787', '#d7d7af', '#d7d7ff', '#d7ff00', '#d7ff5f', '#d7ff87', '#d7ffaf', '#d7ffd7', '#d7ffff', '#ff0000', '#ff0087', '#ff00af', '#ff00d7', '#ff00ff', '#ff5f00', '#ff5f5f', '#ff5f87', '#ff5faf', '#ff5fff', '#ff8700', '#ff875f', '#ff8787', '#ff87af', '#ff87d7', '#ff87ff', '#ffaf00', '#ffaf87', '#ffafaf', '#ffafd7', '#ffafff', '#ffd700', '#ffd75f', '#ffd787', '#ffd7af', '#ffd7ff', '#ffff00', '#ffff5f', '#ffff87', '#ffffaf', '#ffffd7', '#ffffff', '#080808', '#1c1c1c', '#262626', '#303030', '#3a3a3a', '#444444', '#4e4e4e', '#585858', '#626262', '#767676', '#808080', '#8a8a8a', '#949494', '#9e9e9e', '#a8a8a8', '#b2b2b2', '#bcbcbc', '#d0d0d0', '#dadada', '#e4e4e4', '#eeeeee', '#5fd7d7', '#87005f', '#875fd7', '#875fd7', '#87af5f', '#87d7d7', '#af005f', '#af5fd7', '#afaf5f', '#afd7d7', '#d7005f', '#d75fd7', '#d7af5f', '#d7d7d7', '#ff005f', '#ff5fd7', '#ffaf5f', '#ffd7d7', '#121212', '#6c6c6c', '#c6c6c6', ) self.commands = { 'set': self.config.get_all_start_config_key(), 'show': { 'config': 'print curent config (takes param)', 'host': 'print host table (takes param)', 'port': 'print port table', 'task': 'print running tasks', 'log': 'print the last n lines of the log file' }, 'sync': { 'config': 'synchronizes the configuration file' }, 'run': self.get_scanner_methods(self.scan), 'workspase': self.get_all_workspase(), 'flush': {}, 'kill': {}, 'help': {}, 'exit': {} } self.c_function = { 'set': self.f_set, 'show': self.f_show, 'sync': self.f_sync, 'run': self.f_run, 'workspase': self.f_workspase, 'flush': self.f_flush, 'kill': self.f_kill, 'help': self.f_help, 'exit': self.f_exit } self.grammar = compile(""" (\s* (?P<command>[a-z]+) \s*) | (\s* (?P<command>[a-z]+) \s+ (?P<operator>[A-Za-z0-9_-]+) \s*) | (\s* (?P<command>[a-z]+) \s+ (?P<operator>[A-Za-z0-9_-]+) \s+ (?P<parameter>[A-Za-z0-9.,-_/+*]+) \s*) """) self.style = Style.from_dict({ 'command': '#216f21 bold', 'operator': '#6f216f bold', 'parameter': '#ff0000 bold', 'trailing-input': 'bg:#662222 #ffffff', 'bottom-toolbar': '#6f216f bg:#ffffff', # Logo. 'bear': random.choice(self.collors), 'text': random.choice(self.collors), # User input (default text). '': '#ff0066', # Prompt. 'prompt_for_input': '#6f216f', }) self.lexer = GrammarLexer(self.grammar, lexers={ 'command': SimpleLexer('class:command'), 'operator': SimpleLexer('class:operator'), 'parameter': SimpleLexer('class:parameter') }) self.completer = GCompleter(self.commands) self.history_path = Path( os.path.abspath( os.path.join(os.path.dirname(__file__), '../.history'))) self.history = FileHistory(self.history_path) version_str = ''.join(['v', gummy.__version__, ' ']) self.logo = HTML(f''' <text> </text><bear> _ _ </bear> <text> _____ _ _ __ __ __ ____ __</text><bear> (c).-.(c) </bear> <text> / ____| | | | \/ | \/ \ \ / /</text><bear> / ._. \ </bear> <text> | | __| | | | \ / | \ / |\ \_/ / </text><bear> __\( Y )/__ </bear> <text> | | |_ | | | | |\/| | |\/| | \ / </text><bear> (_.-/'-'\-._)</bear> <text> | |__| | |__| | | | | | | | | | </text><bear> || </bear><text>G</text><bear> || </bear> <text> \_____|\____/|_| |_|_| |_| |_| </text><bear> _.' `-' '._ </bear> <text> </text><bear> (.-./`-'\.-.)</bear> <text>{version_str:>38}</text><bear> `-' `-'</bear> ''') self.prompt_str = [('class:prompt_for_input', '>>> ')] self.counter = 0 self.sync_config_stat = 0