Skip to content

Commit 0763d8b

Browse files
committed
Dynamically switch completion style based on result count
- Added max_column_completion_items setting (default 7) to configure the threshold. - Updated Cmd.complete to switch between CompleteStyle.COLUMN and CompleteStyle.MULTI_COLUMN. - Added test case to verify the behavior.
1 parent e51078e commit 0763d8b

File tree

2 files changed

+73
-0
lines changed

2 files changed

+73
-0
lines changed

cmd2/cmd2.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -428,6 +428,10 @@ def _(event: Any) -> None: # pragma: no cover
428428
# not include the description value of the CompletionItems.
429429
self.max_completion_items: int = 50
430430

431+
# The maximum number of completion results to display in a single column (CompleteStyle.COLUMN).
432+
# If the number of results exceeds this, CompleteStyle.MULTI_COLUMN will be used.
433+
self.max_column_completion_items: int = 7
434+
431435
# A dictionary mapping settable names to their Settable instance
432436
self._settables: dict[str, Settable] = {}
433437
self._always_prefix_settables: bool = False
@@ -1219,6 +1223,11 @@ def allow_style_type(value: str) -> ru.AllowStyle:
12191223
self.add_settable(
12201224
Settable('max_completion_items', int, "Maximum number of CompletionItems to display during tab completion", self)
12211225
)
1226+
self.add_settable(
1227+
Settable(
1228+
'max_column_completion_items', int, "Maximum number of completion results to display in a single column", self
1229+
)
1230+
)
12221231
self.add_settable(Settable('quiet', bool, "Don't print nonessential feedback", self))
12231232
self.add_settable(Settable('scripts_add_to_history', bool, 'Scripts and pyscripts add commands to history', self))
12241233
self.add_settable(Settable('timing', bool, "Report execution times", self))
@@ -2500,6 +2509,12 @@ def complete(
25002509
self.display_matches.sort(key=self.default_sort_key)
25012510
self.matches_sorted = True
25022511

2512+
# Swap between COLUMN and MULTI_COLUMN style based on the number of matches
2513+
if len(self.completion_matches) > self.max_column_completion_items:
2514+
self.session.complete_style = CompleteStyle.MULTI_COLUMN
2515+
else:
2516+
self.session.complete_style = CompleteStyle.COLUMN
2517+
25032518
try:
25042519
return self.completion_matches[state]
25052520
except IndexError:
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
import pytest
2+
from prompt_toolkit.shortcuts import CompleteStyle
3+
4+
import cmd2
5+
6+
7+
class AutoStyleApp(cmd2.Cmd):
8+
def __init__(self):
9+
super().__init__()
10+
11+
def do_foo(self, args):
12+
pass
13+
14+
def complete_foo(self, text, line, begidx, endidx):
15+
# Return 10 items
16+
return [f'item{i}' for i in range(10) if f'item{i}'.startswith(text)]
17+
18+
def do_bar(self, args):
19+
pass
20+
21+
def complete_bar(self, text, line, begidx, endidx):
22+
# Return 5 items
23+
return [f'item{i}' for i in range(5) if f'item{i}'.startswith(text)]
24+
25+
26+
@pytest.fixture
27+
def app():
28+
return AutoStyleApp()
29+
30+
31+
def test_dynamic_complete_style(app):
32+
# Default max_column_completion_items is 7
33+
assert app.max_column_completion_items == 7
34+
35+
# Complete 'foo' which has 10 items (> 7)
36+
# text='item', state=0, line='foo item', begidx=4, endidx=8
37+
app.complete('item', 0, 'foo item', 4, 8)
38+
assert app.session.complete_style == CompleteStyle.MULTI_COLUMN
39+
40+
# Complete 'bar' which has 5 items (<= 7)
41+
app.complete('item', 0, 'bar item', 4, 8)
42+
assert app.session.complete_style == CompleteStyle.COLUMN
43+
44+
45+
def test_dynamic_complete_style_custom_limit(app):
46+
# Change limit to 3
47+
app.max_column_completion_items = 3
48+
49+
# Complete 'bar' which has 5 items (> 3)
50+
app.complete('item', 0, 'bar item', 4, 8)
51+
assert app.session.complete_style == CompleteStyle.MULTI_COLUMN
52+
53+
# Change limit to 15
54+
app.max_column_completion_items = 15
55+
56+
# Complete 'foo' which has 10 items (<= 15)
57+
app.complete('item', 0, 'foo item', 4, 8)
58+
assert app.session.complete_style == CompleteStyle.COLUMN

0 commit comments

Comments
 (0)