Skip to content

Commit b823665

Browse files
authored
Merge pull request #739 from python-cmd2/presentation_stuff
Presentation stuff
2 parents 346589e + 29eeef6 commit b823665

16 files changed

+457
-173
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
* Fixed bug where multiline commands were having leading and ending spaces stripped. This would mess up quoted
66
strings that crossed multiple lines.
77
* Fixed a bug when appending to the clipboard where contents were in reverse order
8+
* Fixed issue where run_pyscript failed if the script's filename had 2 or more consecutive spaces
9+
* Fixed issue where completer function of disabled command would still run
810
* Enhancements
911
* Greatly simplified using argparse-based tab completion. The new interface is a complete overhaul that breaks
1012
the previous way of specifying completion and choices functions. See header of [argparse_custom.py](https://github.com/python-cmd2/cmd2/blob/master/cmd2/argparse_custom.py)

CONTRIBUTING.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -192,7 +192,7 @@ $ git push origin [name_of_your_new_branch]
192192

193193

194194
### Setting up for cmd2 development
195-
For doing cmd2 development, it is recommended you create a virutal environment using Conda or Virtualenv and install the
195+
For doing cmd2 development, it is recommended you create a virtual environment using Conda or Virtualenv and install the
196196
package from the source.
197197

198198
#### Create a new environment for cmd2 using Pipenv
@@ -234,7 +234,7 @@ pyenv versions
234234
# Install python version defined
235235
pyenv install 3.6.3
236236
```
237-
With the Python version installed, you can set the virutalenv properly.
237+
With the Python version installed, you can set the virtualenv properly.
238238

239239
```sh
240240
$ cd ~/src/cmd2

cmd2/cmd2.py

Lines changed: 146 additions & 81 deletions
Large diffs are not rendered by default.

cmd2/parsing.py

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -359,15 +359,13 @@ def is_valid_command(self, word: str) -> Tuple[bool, str]:
359359
errmsg = ''
360360
return valid, errmsg
361361

362-
def tokenize(self, line: str, expand: bool = True) -> List[str]:
362+
def tokenize(self, line: str, *, expand: bool = True) -> List[str]:
363363
"""
364364
Lex a string into a list of tokens. Shortcuts and aliases are expanded and comments are removed
365365
366366
:param line: the command line being lexed
367367
:param expand: If True, then aliases and shortcuts will be expanded.
368-
Set this to False if no expansion should occur because the command name is already known.
369-
Otherwise the command could be expanded if it matched an alias name. This is for cases where
370-
a do_* method was called manually (e.g do_help('alias').
368+
Set this to False if the command token should not be altered. Defaults to True.
371369
:return: A list of tokens
372370
:raises ValueError if there are unclosed quotation marks.
373371
"""
@@ -387,18 +385,16 @@ def tokenize(self, line: str, expand: bool = True) -> List[str]:
387385
tokens = self._split_on_punctuation(tokens)
388386
return tokens
389387

390-
def parse(self, line: str, expand: bool = True) -> Statement:
388+
def parse(self, line: str, *, expand: bool = True) -> Statement:
391389
"""
392390
Tokenize the input and parse it into a Statement object, stripping
393391
comments, expanding aliases and shortcuts, and extracting output
394392
redirection directives.
395393
396394
:param line: the command line being parsed
397395
:param expand: If True, then aliases and shortcuts will be expanded.
398-
Set this to False if no expansion should occur because the command name is already known.
399-
Otherwise the command could be expanded if it matched an alias name. This is for cases where
400-
a do_* method was called manually (e.g do_help('alias').
401-
:return: A parsed Statement
396+
Set this to False if the command token should not be altered. Defaults to True.
397+
:return: the created Statement
402398
:raises ValueError if there are unclosed quotation marks
403399
"""
404400

@@ -414,7 +410,7 @@ def parse(self, line: str, expand: bool = True) -> Statement:
414410
arg_list = []
415411

416412
# lex the input into a list of tokens
417-
tokens = self.tokenize(line, expand)
413+
tokens = self.tokenize(line, expand=expand)
418414

419415
# of the valid terminators, find the first one to occur in the input
420416
terminator_pos = len(tokens) + 1
@@ -533,11 +529,10 @@ def parse(self, line: str, expand: bool = True) -> Statement:
533529
suffix=suffix,
534530
pipe_to=pipe_to,
535531
output=output,
536-
output_to=output_to,
537-
)
532+
output_to=output_to)
538533
return statement
539534

540-
def parse_command_only(self, rawinput: str) -> Statement:
535+
def parse_command_only(self, rawinput: str, *, expand: bool = True) -> Statement:
541536
"""Partially parse input into a Statement object.
542537
543538
The command is identified, and shortcuts and aliases are expanded.
@@ -560,9 +555,17 @@ def parse_command_only(self, rawinput: str) -> Statement:
560555
Different from parse(), this method does not remove redundant whitespace
561556
within args. However, it does ensure args has no leading or trailing
562557
whitespace.
558+
559+
:param rawinput: the command line as entered by the user
560+
:param expand: If True, then aliases and shortcuts will be expanded.
561+
Set this to False if the command token should not be altered. Defaults to True.
562+
:return: the created Statement
563563
"""
564+
line = rawinput
565+
564566
# expand shortcuts and aliases
565-
line = self._expand(rawinput)
567+
if expand:
568+
line = self._expand(rawinput)
566569

567570
command = ''
568571
args = ''
@@ -591,8 +594,7 @@ def parse_command_only(self, rawinput: str) -> Statement:
591594
statement = Statement(args,
592595
raw=rawinput,
593596
command=command,
594-
multiline_command=multiline_command,
595-
)
597+
multiline_command=multiline_command)
596598
return statement
597599

598600
def get_command_arg_list(self, command_name: str, to_parse: Union[Statement, str],

cmd2/utils.py

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,8 @@ def is_quoted(arg: str) -> bool:
2525
return len(arg) > 1 and arg[0] == arg[-1] and arg[0] in constants.QUOTES
2626

2727

28-
def quote_string_if_needed(arg: str) -> str:
29-
""" Quotes a string if it contains spaces and isn't already quoted """
30-
if is_quoted(arg) or ' ' not in arg:
31-
return arg
32-
28+
def quote_string(arg: str) -> str:
29+
"""Quote a string"""
3330
if '"' in arg:
3431
quote = "'"
3532
else:
@@ -38,8 +35,16 @@ def quote_string_if_needed(arg: str) -> str:
3835
return quote + arg + quote
3936

4037

38+
def quote_string_if_needed(arg: str) -> str:
39+
"""Quote a string if it contains spaces and isn't already quoted"""
40+
if is_quoted(arg) or ' ' not in arg:
41+
return arg
42+
43+
return quote_string(arg)
44+
45+
4146
def strip_quotes(arg: str) -> str:
42-
""" Strip outer quotes from a string.
47+
"""Strip outer quotes from a string.
4348
4449
Applies to both single and double quotes.
4550

examples/migrating.py

100644100755
File mode changed.

examples/unicode_commands.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
#!/usr/bin/env python
2+
# coding=utf-8
3+
"""A simple example demonstrating support for unicode command names.
4+
"""
5+
import math
6+
import cmd2
7+
8+
9+
class UnicodeApp(cmd2.Cmd):
10+
"""Example cmd2 application with unicode command names."""
11+
12+
def __init__(self):
13+
super().__init__()
14+
self.intro = 'Welcome the Unicode example app. Note the full Unicode support: 😇 💩'
15+
16+
def do_𝛑print(self, _):
17+
"""This command prints 𝛑 to 5 decimal places."""
18+
self.poutput("𝛑 = {0:.6}".format(math.pi))
19+
20+
def do_你好(self, arg):
21+
"""This command says hello in Chinese (Mandarin)."""
22+
self.poutput("你好 " + arg)
23+
24+
25+
if __name__ == '__main__':
26+
app = UnicodeApp()
27+
app.cmdloop()

tests/pyscript/recursive.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
#!/usr/bin/env python
2+
# coding=utf-8
3+
# flake8: noqa F821
4+
"""
5+
Example demonstrating that calling run_pyscript recursively inside another Python script isn't allowed
6+
"""
7+
import os
8+
9+
app.cmd_echo = True
10+
my_dir = (os.path.dirname(os.path.realpath(sys.argv[0])))
11+
app('run_pyscript {}'.format(os.path.join(my_dir, 'stop.py')))

tests/pyscript/run.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
# flake8: noqa F821
2+
import os
3+
4+
app.cmd_echo = True
5+
my_dir = (os.path.dirname(os.path.realpath(sys.argv[0])))
6+
run(os.path.join(my_dir, 'to_run.py'))

tests/pyscript/to_run.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
# flake8: noqa F821
2+
print("I have been run")

tests/scripts/recursive.py

Lines changed: 0 additions & 8 deletions
This file was deleted.

0 commit comments

Comments
 (0)