diff options
| author | Todd Leonhardt <todd.leonhardt@gmail.com> | 2019-03-04 22:16:10 -0500 |
|---|---|---|
| committer | Todd Leonhardt <todd.leonhardt@gmail.com> | 2019-03-04 22:16:10 -0500 |
| commit | b4e7cc7cb2de1bd78d65a250caab91dc6cd90221 (patch) | |
| tree | e7c62918c696a105b6ab8ce6b7c3322006d1c566 /cmd2 | |
| parent | 123ac08169078cd8d232ae39102534782ac7fd87 (diff) | |
| parent | eb86c739187583a7afdd56e0a9fcf0da212562f1 (diff) | |
| download | cmd2-git-b4e7cc7cb2de1bd78d65a250caab91dc6cd90221.tar.gz | |
Merge master into with_argument_list and resolved conflicts
Diffstat (limited to 'cmd2')
| -rw-r--r-- | cmd2/cmd2.py | 6 | ||||
| -rw-r--r-- | cmd2/constants.py | 1 | ||||
| -rw-r--r-- | cmd2/parsing.py | 54 |
3 files changed, 14 insertions, 47 deletions
diff --git a/cmd2/cmd2.py b/cmd2/cmd2.py index 1167e529..1bfeba1d 100644 --- a/cmd2/cmd2.py +++ b/cmd2/cmd2.py @@ -160,7 +160,7 @@ def parse_quoted_string(string: str, preserve_quotes: bool) -> List[str]: lexed_arglist = string else: # Use shlex to split the command line into a list of arguments based on shell rules - lexed_arglist = shlex.split(string, posix=False) + lexed_arglist = shlex.split(string, comments=False, posix=False) if not preserve_quotes: lexed_arglist = [utils.strip_quotes(arg) for arg in lexed_arglist] @@ -766,7 +766,7 @@ class Cmd(cmd.Cmd): while True: try: # Use non-POSIX parsing to keep the quotes around the tokens - initial_tokens = shlex.split(tmp_line[:tmp_endidx], posix=False) + initial_tokens = shlex.split(tmp_line[:tmp_endidx], comments=False, posix=False) # If the cursor is at an empty token outside of a quoted string, # then that is the token being completed. Add it to the list. @@ -2288,7 +2288,7 @@ class Cmd(cmd.Cmd): " would for the actual command the alias resolves to.\n" "\n" "Examples:\n" - " alias ls !ls -lF\n" + " alias create ls !ls -lF\n" " alias create show_log !cat \"log file.txt\"\n" " alias create save_results print_results \">\" out.txt\n") diff --git a/cmd2/constants.py b/cmd2/constants.py index 3c133b70..3e35a542 100644 --- a/cmd2/constants.py +++ b/cmd2/constants.py @@ -12,6 +12,7 @@ REDIRECTION_OUTPUT = '>' REDIRECTION_APPEND = '>>' REDIRECTION_CHARS = [REDIRECTION_PIPE, REDIRECTION_OUTPUT] REDIRECTION_TOKENS = [REDIRECTION_PIPE, REDIRECTION_OUTPUT, REDIRECTION_APPEND] +COMMENT_CHAR = '#' # Regular expression to match ANSI escape codes ANSI_ESCAPE_RE = re.compile(r'\x1b[^m]*m') diff --git a/cmd2/parsing.py b/cmd2/parsing.py index d4f82ac9..bd3a6900 100644 --- a/cmd2/parsing.py +++ b/cmd2/parsing.py @@ -236,33 +236,6 @@ class StatementParser: else: self.shortcuts = shortcuts - # this regular expression matches C-style comments and quoted - # strings, i.e. stuff between single or double quote marks - # it's used with _comment_replacer() to strip out the C-style - # comments, while leaving C-style comments that are inside either - # double or single quotes. - # - # this big regular expression can be broken down into 3 regular - # expressions that are OR'ed together with a pipe character - # - # /\*.*\*/ Matches C-style comments (i.e. /* comment */) - # does not match unclosed comments. - # \'(?:\\.|[^\\\'])*\' Matches a single quoted string, allowing - # for embedded backslash escaped single quote - # marks. - # "(?:\\.|[^\\"])*" Matches a double quoted string, allowing - # for embedded backslash escaped double quote - # marks. - # - # by way of reminder the (?:...) regular expression syntax is just - # a non-capturing version of regular parenthesis. We need the non- - # capturing syntax because _comment_replacer() looks at match - # groups - self.comment_pattern = re.compile( - r'/\*.*\*/|\'(?:\\.|[^\\\'])*\'|"(?:\\.|[^\\"])*"', - re.DOTALL | re.MULTILINE - ) - # commands have to be a word, so make a regular expression # that matches the first word in the line. This regex has three # parts: @@ -315,6 +288,9 @@ class StatementParser: if not word: return False, 'cannot be an empty string' + if word.startswith(constants.COMMENT_CHAR): + return False, 'cannot start with the comment character' + for (shortcut, _) in self.shortcuts: if word.startswith(shortcut): # Build an error string with all shortcuts listed @@ -338,24 +314,23 @@ class StatementParser: def tokenize(self, line: str) -> List[str]: """Lex a string into a list of tokens. - Comments are removed, and shortcuts and aliases are expanded. + shortcuts and aliases are expanded and comments are removed Raises ValueError if there are unclosed quotation marks. """ - # strip C-style comments - # shlex will handle the python/shell style comments for us - line = re.sub(self.comment_pattern, self._comment_replacer, line) - # expand shortcuts and aliases line = self._expand(line) + # check if this line is a comment + if line.strip().startswith(constants.COMMENT_CHAR): + return [] + # split on whitespace - lexer = shlex.shlex(line, posix=False) - lexer.whitespace_split = True + tokens = shlex.split(line, comments=False, posix=False) # custom lexing - tokens = self._split_on_punctuation(list(lexer)) + tokens = self._split_on_punctuation(tokens) return tokens def parse(self, line: str) -> Statement: @@ -610,15 +585,6 @@ class StatementParser: return command, args - @staticmethod - def _comment_replacer(match): - matched_string = match.group(0) - if matched_string.startswith('/'): - # the matched string was a comment, so remove it - return '' - # the matched string was a quoted string, return the match - return matched_string - def _split_on_punctuation(self, tokens: List[str]) -> List[str]: """Further splits tokens from a command line using punctuation characters |
