Skip to content

Commit 1306eeb

Browse files
authored
Merge pull request #374 from python-cmd2/constants
Move constants and utility functions into separate files.
2 parents a934373 + bed0b6b commit 1306eeb

File tree

3 files changed

+43
-32
lines changed

3 files changed

+43
-32
lines changed

cmd2/cmd2.py

Lines changed: 18 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,9 @@
4949
import pyparsing
5050
import pyperclip
5151

52+
from . import constants
53+
from . import utils
54+
5255
# Set up readline
5356
from .rl_utils import rl_force_redisplay, readline, rl_type, RlType
5457
from .argparse_completer import AutoCompleter, ACArgumentParser
@@ -134,10 +137,6 @@ def __subclasshook__(cls, C):
134137
# Strip outer quotes for convenience if POSIX_SHLEX = False
135138
STRIP_QUOTES_FOR_NON_POSIX = True
136139

137-
# Used for tab completion and word breaks. Do not change.
138-
QUOTES = ['"', "'"]
139-
REDIRECTION_CHARS = ['|', '<', '>']
140-
141140
# optional attribute, when tagged on a function, allows cmd2 to categorize commands
142141
HELP_CATEGORY = 'help_category'
143142
HELP_SUMMARY = 'help_summary'
@@ -398,19 +397,6 @@ class EmptyStatement(Exception):
398397
pass
399398

400399

401-
# Regular expression to match ANSI escape codes
402-
ANSI_ESCAPE_RE = re.compile(r'\x1b[^m]*m')
403-
404-
405-
def strip_ansi(text: str) -> str:
406-
"""Strip ANSI escape codes from a string.
407-
408-
:param text: string which may contain ANSI escape codes
409-
:return: the same string with any ANSI escape codes removed
410-
"""
411-
return ANSI_ESCAPE_RE.sub('', text)
412-
413-
414400
def _pop_readline_history(clear_history: bool=True) -> List[str]:
415401
"""Returns a copy of readline's history and optionally clears it (default)"""
416402
# noinspection PyArgumentList
@@ -855,7 +841,7 @@ def visible_prompt(self):
855841
856842
:return: str - prompt stripped of any ANSI escape codes
857843
"""
858-
return strip_ansi(self.prompt)
844+
return utils.strip_ansi(self.prompt)
859845

860846
def _finalize_app_parameters(self):
861847
self.commentGrammars.ignore(pyparsing.quotedString).setParseAction(lambda x: '')
@@ -1021,7 +1007,7 @@ def tokens_for_completion(self, line, begidx, endidx):
10211007
Both items are None
10221008
"""
10231009
unclosed_quote = ''
1024-
quotes_to_try = copy.copy(QUOTES)
1010+
quotes_to_try = copy.copy(constants.QUOTES)
10251011

10261012
tmp_line = line[:endidx]
10271013
tmp_endidx = endidx
@@ -1064,7 +1050,7 @@ def tokens_for_completion(self, line, begidx, endidx):
10641050
for cur_initial_token in initial_tokens:
10651051

10661052
# Save tokens up to 1 character in length or quoted tokens. No need to parse these.
1067-
if len(cur_initial_token) <= 1 or cur_initial_token[0] in QUOTES:
1053+
if len(cur_initial_token) <= 1 or cur_initial_token[0] in constants.QUOTES:
10681054
raw_tokens.append(cur_initial_token)
10691055
continue
10701056

@@ -1076,10 +1062,10 @@ def tokens_for_completion(self, line, begidx, endidx):
10761062
cur_raw_token = ''
10771063

10781064
while True:
1079-
if cur_char not in REDIRECTION_CHARS:
1065+
if cur_char not in constants.REDIRECTION_CHARS:
10801066

10811067
# Keep appending to cur_raw_token until we hit a redirect char
1082-
while cur_char not in REDIRECTION_CHARS:
1068+
while cur_char not in constants.REDIRECTION_CHARS:
10831069
cur_raw_token += cur_char
10841070
cur_index += 1
10851071
if cur_index < len(cur_initial_token):
@@ -1485,7 +1471,7 @@ def _redirect_complete(self, text, line, begidx, endidx, compfunc):
14851471
if len(raw_tokens) > 1:
14861472

14871473
# Build a list of all redirection tokens
1488-
all_redirects = REDIRECTION_CHARS + ['>>']
1474+
all_redirects = constants.REDIRECTION_CHARS + ['>>']
14891475

14901476
# Check if there are redirection strings prior to the token being completed
14911477
seen_pipe = False
@@ -1695,7 +1681,7 @@ def complete(self, text, state):
16951681
raw_completion_token = raw_tokens[-1]
16961682

16971683
# Check if the token being completed has an opening quote
1698-
if raw_completion_token and raw_completion_token[0] in QUOTES:
1684+
if raw_completion_token and raw_completion_token[0] in constants.QUOTES:
16991685

17001686
# Since the token is still being completed, we know the opening quote is unclosed
17011687
unclosed_quote = raw_completion_token[0]
@@ -2391,11 +2377,11 @@ def _cmdloop(self):
23912377
readline.set_completer(self.complete)
23922378

23932379
# Break words on whitespace and quotes when tab completing
2394-
completer_delims = " \t\n" + ''.join(QUOTES)
2380+
completer_delims = " \t\n" + ''.join(constants.QUOTES)
23952381

23962382
if self.allow_redirection:
23972383
# If redirection is allowed, then break words on those characters too
2398-
completer_delims += ''.join(REDIRECTION_CHARS)
2384+
completer_delims += ''.join(constants.REDIRECTION_CHARS)
23992385

24002386
readline.set_completer_delims(completer_delims)
24012387

@@ -2840,13 +2826,13 @@ def do_shell(self, command):
28402826
# Check if the token is quoted. Since shlex.split() passed, there isn't
28412827
# an unclosed quote, so we only need to check the first character.
28422828
first_char = tokens[index][0]
2843-
if first_char in QUOTES:
2829+
if first_char in constants.QUOTES:
28442830
tokens[index] = strip_quotes(tokens[index])
28452831

28462832
tokens[index] = os.path.expanduser(tokens[index])
28472833

28482834
# Restore the quotes
2849-
if first_char in QUOTES:
2835+
if first_char in constants.QUOTES:
28502836
tokens[index] = first_char + tokens[index] + first_char
28512837

28522838
expanded_command = ' '.join(tokens)
@@ -3713,13 +3699,13 @@ def runTest(self): # was testall
37133699
def _test_transcript(self, fname, transcript):
37143700
line_num = 0
37153701
finished = False
3716-
line = strip_ansi(next(transcript))
3702+
line = utils.strip_ansi(next(transcript))
37173703
line_num += 1
37183704
while not finished:
37193705
# Scroll forward to where actual commands begin
37203706
while not line.startswith(self.cmdapp.visible_prompt):
37213707
try:
3722-
line = strip_ansi(next(transcript))
3708+
line = utils.strip_ansi(next(transcript))
37233709
except StopIteration:
37243710
finished = True
37253711
break
@@ -3743,13 +3729,13 @@ def _test_transcript(self, fname, transcript):
37433729
self.cmdapp.onecmd_plus_hooks(command)
37443730
result = self.cmdapp.stdout.read()
37453731
# Read the expected result from transcript
3746-
if strip_ansi(line).startswith(self.cmdapp.visible_prompt):
3732+
if utils.strip_ansi(line).startswith(self.cmdapp.visible_prompt):
37473733
message = '\nFile {}, line {}\nCommand was:\n{}\nExpected: (nothing)\nGot:\n{}\n'.format(
37483734
fname, line_num, command, result)
37493735
self.assert_(not (result.strip()), message)
37503736
continue
37513737
expected = []
3752-
while not strip_ansi(line).startswith(self.cmdapp.visible_prompt):
3738+
while not utils.strip_ansi(line).startswith(self.cmdapp.visible_prompt):
37533739
expected.append(line)
37543740
try:
37553741
line = next(transcript)

cmd2/constants.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
#
2+
# coding=utf-8
3+
"""Constants and definitions"""
4+
5+
import re
6+
7+
# Used for command parsing, tab completion and word breaks. Do not change.
8+
QUOTES = ['"', "'"]
9+
REDIRECTION_CHARS = ['|', '<', '>']
10+
11+
# Regular expression to match ANSI escape codes
12+
ANSI_ESCAPE_RE = re.compile(r'\x1b[^m]*m')

cmd2/utils.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#
2+
# coding=utf-8
3+
"""Shared utility functions"""
4+
5+
from . import constants
6+
7+
def strip_ansi(text: str) -> str:
8+
"""Strip ANSI escape codes from a string.
9+
10+
:param text: string which may contain ANSI escape codes
11+
:return: the same string with any ANSI escape codes removed
12+
"""
13+
return constants.ANSI_ESCAPE_RE.sub('', text)

0 commit comments

Comments
 (0)