Skip to content

Commit e018bbd

Browse files
committed
Removed the expensive imports from cmd2/__init__.py
Added some shared definitions to cmd2/__init__.py -> maybe there's a better place for these? Figured out how to trick bash into showing argument hints. It's a bit weird. Updated all of the tests and examples to import cmd2 resources from their new location without the automatic imports in cmd2/__init__.py For #369
1 parent 4193ef0 commit e018bbd

26 files changed

+128
-87
lines changed

cmd2/__init__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
#
22
# -*- coding: utf-8 -*-
33
#
4-
from .cmd2 import __version__, Cmd, set_posix_shlex, set_strip_quotes, AddSubmenu, CmdResult, categorize
5-
from .cmd2 import with_argument_list, with_argparser, with_argparser_and_unknown_args, with_category
4+
# from .cmd2 import __version__, Cmd, set_posix_shlex, set_strip_quotes, AddSubmenu, CmdResult, categorize
5+
# from .cmd2 import with_argument_list, with_argparser, with_argparser_and_unknown_args, with_category
66

77
# Used for tab completion and word breaks. Do not change.
88
QUOTES = ['"', "'"]

cmd2/argcomplete_bridge.py

Lines changed: 37 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@
22
"""Hijack the ArgComplete's bash completion handler to return AutoCompleter results"""
33

44
import argcomplete
5+
from contextlib import redirect_stdout
56
import copy
7+
from io import StringIO
68
import os
79
import shlex
810
import sys
@@ -162,7 +164,13 @@ def __call__(self, argument_parser, completer=None, always_complete_options=True
162164
comp_point = int(os.environ["COMP_POINT"])
163165

164166
comp_line = argcomplete.ensure_str(comp_line)
165-
### SWAPPED FOR AUTOCOMPLETER
167+
168+
##############################
169+
# SWAPPED FOR AUTOCOMPLETER
170+
#
171+
# Replaced with our own tokenizer function
172+
##############################
173+
166174
# cword_prequote, cword_prefix, cword_suffix, comp_words, last_wordbreak_pos = split_line(comp_line, comp_point)
167175
tokens, _, begidx, endidx = tokens_for_completion(comp_line, comp_point)
168176

@@ -172,7 +180,11 @@ def __call__(self, argument_parser, completer=None, always_complete_options=True
172180
# 2: python <script> [args]
173181
# 3: python -m <module> [args]
174182
start = int(os.environ["_ARGCOMPLETE"]) - 1
175-
### SWAPPED FOR AUTOCOMPLETER
183+
##############################
184+
# SWAPPED FOR AUTOCOMPLETER
185+
#
186+
# Applying the same token dropping to our tokens
187+
##############################
176188
# comp_words = comp_words[start:]
177189
tokens = tokens[start:]
178190

@@ -183,11 +195,20 @@ def __call__(self, argument_parser, completer=None, always_complete_options=True
183195
# "\nSUFFIX: {!r}".format(cword_suffix),
184196
# "\nWORDS:", comp_words)
185197

186-
### SWAPPED FOR AUTOCOMPLETER
198+
##############################
199+
# SWAPPED FOR AUTOCOMPLETER
200+
#
201+
# Replaced with our own completion function and customizing the returned values
202+
##############################
187203
# completions = self._get_completions(comp_words, cword_prefix, cword_prequote, last_wordbreak_pos)
188-
completions = completer.complete_command(tokens, tokens[-1], comp_line, begidx, endidx)
189204

190-
if completions is not None:
205+
# capture stdout from the autocompleter
206+
result = StringIO()
207+
with redirect_stdout(result):
208+
completions = completer.complete_command(tokens, tokens[-1], comp_line, begidx, endidx)
209+
outstr = result.getvalue()
210+
211+
if completions:
191212
# If any completion has a space in it, then quote all completions
192213
# this improves the user experience so they don't nede to go back and add a quote
193214
if ' ' in ''.join(completions):
@@ -196,6 +217,17 @@ def __call__(self, argument_parser, completer=None, always_complete_options=True
196217
argcomplete.debug("\nReturning completions:", completions)
197218

198219
output_stream.write(ifs.join(completions).encode(argcomplete.sys_encoding))
220+
elif outstr:
221+
# if there are no completions, but we got something from stdout, try to print help
222+
223+
# trick the bash completion into thinking there are 2 completions that are unlikely
224+
# to ever match.
225+
outstr = outstr.replace('\n', ' ').replace('\t', ' ').replace(' ', ' ').strip()
226+
# generate a filler entry that should always sort first
227+
filler = ' {0:><{width}}'.format('', width=len(outstr))
228+
outstr = ifs.join([filler, outstr])
229+
230+
output_stream.write(outstr.encode(argcomplete.sys_encoding))
199231
else:
200232
# if completions is None we assume we don't know how to handle it so let bash
201233
# go forward with normal filesystem completion

examples/alias_startup.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,10 @@
66
"""
77
import argparse
88

9-
import cmd2
9+
from cmd2 import cmd2
1010
import pyparsing
1111

12-
from cmd2 import with_argument_list, with_argparser, with_argparser_and_unknown_args
12+
from cmd2.cmd2 import with_argument_list, with_argparser, with_argparser_and_unknown_args
1313

1414

1515
class AliasAndStartup(cmd2.Cmd):

examples/arg_print.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,8 @@
1111
"""
1212
import argparse
1313

14-
import cmd2
15-
import pyparsing
16-
17-
from cmd2 import with_argument_list, with_argparser, with_argparser_and_unknown_args
14+
from cmd2 import cmd2
15+
from cmd2.cmd2 import with_argument_list, with_argparser, with_argparser_and_unknown_args
1816

1917

2018
class ArgumentAndOptionPrinter(cmd2.Cmd):

examples/argparse_example.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
import argparse
1515
import sys
1616

17-
from cmd2 import Cmd, with_argparser, with_argument_list
17+
from cmd2.cmd2 import Cmd, with_argparser, with_argument_list
1818

1919

2020
class CmdLineApp(Cmd):

examples/environment.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
A sample application for cmd2 demonstrating customized environment parameters
55
"""
66

7-
from cmd2 import Cmd
7+
from cmd2.cmd2 import Cmd
88

99

1010
class EnvironmentApp(Cmd):

examples/event_loops.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
77
This opens up the possibility of registering cmd2 input with event loops, like asyncio, without occupying the main loop.
88
"""
9-
import cmd2
9+
from cmd2 import cmd2
1010

1111

1212
class Cmd2EventBased(cmd2.Cmd):

examples/example.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
import random
1515
import argparse
1616

17-
from cmd2 import Cmd, with_argparser
17+
from cmd2.cmd2 import Cmd, with_argparser
1818

1919

2020
class CmdLineApp(Cmd):

examples/help_categories.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
A sample application for tagging categories on commands.
55
"""
66

7-
from cmd2 import Cmd, categorize, __version__, with_argparser, with_category
7+
from cmd2.cmd2 import Cmd, categorize, __version__, with_argparser, with_category
88
import argparse
99

1010

examples/paged_output.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33
"""A simple example demonstrating the using paged output via the ppaged() method.
44
"""
55

6-
import cmd2
7-
from cmd2 import with_argument_list
6+
from cmd2 import cmd2
7+
from cmd2.cmd2 import with_argument_list
88

99

1010
class PagedOutput(cmd2.Cmd):

0 commit comments

Comments
 (0)