Skip to content

Commit 95b092b

Browse files
committed
✨ add continuous operation streams in CLI
1 parent 93a43f3 commit 95b092b

6 files changed

Lines changed: 160 additions & 60 deletions

File tree

nb_cli/cli/__init__.py

Lines changed: 31 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
from typing import Optional, cast
33

44
import click
5-
from noneprompt import Choice, ListPrompt, CancelledError
5+
from noneprompt import Choice, ListPrompt, ConfirmPrompt, CancelledError
66

77
from nb_cli import _, __version__
88
from nb_cli.handlers import draw_logo
@@ -16,6 +16,22 @@
1616
from .customize import ClickAliasedCommand as ClickAliasedCommand
1717

1818

19+
@click.command # this command only appears in interactive mode.
20+
@click.pass_context
21+
@run_async
22+
async def exit_(ctx: click.Context):
23+
if await ConfirmPrompt(_("Are you sure to exit NB CLI?"), True).prompt_async(
24+
style=CLI_DEFAULT_STYLE
25+
):
26+
ctx.exit()
27+
28+
29+
@click.command # this command only appears in interactive mode.
30+
def back_():
31+
# nothing to do, just to keep a command to avoid type violation
32+
return
33+
34+
1935
def _set_global_working_dir(
2036
ctx: click.Context, param: click.Option, value: Optional[Path]
2137
):
@@ -93,21 +109,25 @@ async def cli(ctx: click.Context):
93109
sub_cmd,
94110
)
95111
)
112+
_exit_choice = Choice(_("Exit NB CLI."), exit_)
113+
choices.append(_exit_choice)
96114

97115
click.secho(draw_logo(), fg="cyan", bold=True)
98116
click.echo("\n\b")
99117
click.secho(_("Welcome to NoneBot CLI!"), fg="green", bold=True)
100118

101-
# prompt user to choose
102-
try:
103-
result = await ListPrompt(
104-
_("What do you want to do?"), choices=choices
105-
).prompt_async(style=CLI_DEFAULT_STYLE)
106-
except CancelledError:
107-
ctx.exit()
108-
109-
sub_cmd = result.data
110-
await run_sync(ctx.invoke)(sub_cmd)
119+
while True:
120+
# prompt user to choose
121+
try:
122+
result = await ListPrompt(
123+
_("What do you want to do?"), choices=choices
124+
).prompt_async(style=CLI_DEFAULT_STYLE)
125+
except CancelledError:
126+
result = _exit_choice
127+
128+
sub_cmd = result.data
129+
ctx.params["can_back_to_parent"] = True
130+
await run_sync(ctx.invoke)(sub_cmd)
111131

112132

113133
from .commands import (

nb_cli/cli/commands/adapter.py

Lines changed: 25 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,14 @@
77
from nb_cli import _
88
from nb_cli.config import GLOBAL_CONFIG
99
from nb_cli.cli.utils import find_exact_package
10-
from nb_cli.cli import CLI_DEFAULT_STYLE, ClickAliasedGroup, run_sync, run_async
10+
from nb_cli.cli import (
11+
CLI_DEFAULT_STYLE,
12+
ClickAliasedGroup,
13+
back_,
14+
exit_,
15+
run_sync,
16+
run_async,
17+
)
1118
from nb_cli.handlers import (
1219
list_adapters,
1320
create_adapter,
@@ -39,16 +46,25 @@ async def adapter(ctx: click.Context):
3946
sub_cmd,
4047
)
4148
)
49+
if ctx.parent and ctx.parent.params.get("can_back_to_parent", False):
50+
_exit_choice = Choice(_("Back to top level."), back_)
51+
else:
52+
_exit_choice = Choice(_("Exit NB CLI."), exit_)
53+
choices.append(_exit_choice)
4254

43-
try:
44-
result = await ListPrompt(
45-
_("What do you want to do?"), choices=choices
46-
).prompt_async(style=CLI_DEFAULT_STYLE)
47-
except CancelledError:
48-
ctx.exit()
55+
while True:
56+
try:
57+
result = await ListPrompt(
58+
_("What do you want to do?"), choices=choices
59+
).prompt_async(style=CLI_DEFAULT_STYLE)
60+
except CancelledError:
61+
result = _exit_choice
4962

50-
sub_cmd = result.data
51-
await run_sync(ctx.invoke)(sub_cmd)
63+
sub_cmd = result.data
64+
if sub_cmd == back_:
65+
return
66+
ctx.params["can_back_to_parent"] = True
67+
await run_sync(ctx.invoke)(sub_cmd)
5268

5369

5470
@adapter.command(

nb_cli/cli/commands/cache.py

Lines changed: 27 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,14 @@
99
from nb_cli.handlers.data import CACHE_DIR
1010
from nb_cli.cli.utils import humanize_data_size
1111
from nb_cli.handlers import download_module_data
12-
from nb_cli.cli import CLI_DEFAULT_STYLE, ClickAliasedGroup, run_sync, run_async
12+
from nb_cli.cli import (
13+
CLI_DEFAULT_STYLE,
14+
ClickAliasedGroup,
15+
back_,
16+
exit_,
17+
run_sync,
18+
run_async,
19+
)
1320

1421

1522
@click.group(
@@ -35,16 +42,25 @@ async def cache(ctx: click.Context):
3542
sub_cmd,
3643
)
3744
)
38-
39-
try:
40-
result = await ListPrompt(
41-
_("What do you want to do?"), choices=choices
42-
).prompt_async(style=CLI_DEFAULT_STYLE)
43-
except CancelledError:
44-
ctx.exit()
45-
46-
sub_cmd = result.data
47-
await run_sync(ctx.invoke)(sub_cmd)
45+
if ctx.parent and ctx.parent.params.get("can_back_to_parent", False):
46+
_exit_choice = Choice(_("Back to top level."), back_)
47+
else:
48+
_exit_choice = Choice(_("Exit NB CLI."), exit_)
49+
choices.append(_exit_choice)
50+
51+
while True:
52+
try:
53+
result = await ListPrompt(
54+
_("What do you want to do?"), choices=choices
55+
).prompt_async(style=CLI_DEFAULT_STYLE)
56+
except CancelledError:
57+
result = _exit_choice
58+
59+
sub_cmd = result.data
60+
if sub_cmd == back_:
61+
return
62+
ctx.params["can_back_to_parent"] = True
63+
await run_sync(ctx.invoke)(sub_cmd)
4864

4965

5066
def _filesize(

nb_cli/cli/commands/driver.py

Lines changed: 27 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,14 @@
66
from nb_cli import _
77
from nb_cli.config import GLOBAL_CONFIG
88
from nb_cli.cli.utils import find_exact_package
9-
from nb_cli.cli import CLI_DEFAULT_STYLE, ClickAliasedGroup, run_sync, run_async
9+
from nb_cli.cli import (
10+
CLI_DEFAULT_STYLE,
11+
ClickAliasedGroup,
12+
back_,
13+
exit_,
14+
run_sync,
15+
run_async,
16+
)
1017
from nb_cli.handlers import (
1118
list_drivers,
1219
call_pip_update,
@@ -37,16 +44,25 @@ async def driver(ctx: click.Context):
3744
sub_cmd,
3845
)
3946
)
40-
41-
try:
42-
result = await ListPrompt(
43-
_("What do you want to do?"), choices=choices
44-
).prompt_async(style=CLI_DEFAULT_STYLE)
45-
except CancelledError:
46-
ctx.exit()
47-
48-
sub_cmd = result.data
49-
await run_sync(ctx.invoke)(sub_cmd)
47+
if ctx.parent and ctx.parent.params.get("can_back_to_parent", False):
48+
_exit_choice = Choice(_("Back to top level."), back_)
49+
else:
50+
_exit_choice = Choice(_("Exit NB CLI."), exit_)
51+
choices.append(_exit_choice)
52+
53+
while True:
54+
try:
55+
result = await ListPrompt(
56+
_("What do you want to do?"), choices=choices
57+
).prompt_async(style=CLI_DEFAULT_STYLE)
58+
except CancelledError:
59+
result = _exit_choice
60+
61+
sub_cmd = result.data
62+
if sub_cmd == back_:
63+
return
64+
ctx.params["can_back_to_parent"] = True
65+
await run_sync(ctx.invoke)(sub_cmd)
5066

5167

5268
@driver.command(

nb_cli/cli/commands/plugin.py

Lines changed: 25 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,14 @@
77
from nb_cli import _
88
from nb_cli.config import GLOBAL_CONFIG
99
from nb_cli.cli.utils import find_exact_package
10-
from nb_cli.cli import CLI_DEFAULT_STYLE, ClickAliasedGroup, run_sync, run_async
10+
from nb_cli.cli import (
11+
CLI_DEFAULT_STYLE,
12+
ClickAliasedGroup,
13+
back_,
14+
exit_,
15+
run_sync,
16+
run_async,
17+
)
1118
from nb_cli.handlers import (
1219
list_plugins,
1320
create_plugin,
@@ -39,16 +46,25 @@ async def plugin(ctx: click.Context):
3946
sub_cmd,
4047
)
4148
)
49+
if ctx.parent and ctx.parent.params.get("can_back_to_parent", False):
50+
_exit_choice = Choice(_("Back to top level."), back_)
51+
else:
52+
_exit_choice = Choice(_("Exit NB CLI."), exit_)
53+
choices.append(_exit_choice)
4254

43-
try:
44-
result = await ListPrompt(
45-
_("What do you want to do?"), choices=choices
46-
).prompt_async(style=CLI_DEFAULT_STYLE)
47-
except CancelledError:
48-
ctx.exit()
55+
while True:
56+
try:
57+
result = await ListPrompt(
58+
_("What do you want to do?"), choices=choices
59+
).prompt_async(style=CLI_DEFAULT_STYLE)
60+
except CancelledError:
61+
result = _exit_choice
4962

50-
sub_cmd = result.data
51-
await run_sync(ctx.invoke)(sub_cmd)
63+
sub_cmd = result.data
64+
if sub_cmd == back_:
65+
return
66+
ctx.params["can_back_to_parent"] = True
67+
await run_sync(ctx.invoke)(sub_cmd)
5268

5369

5470
@plugin.command(

nb_cli/cli/commands/self.py

Lines changed: 25 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,20 @@
66

77
from nb_cli import _
88
from nb_cli.cli.commands.cache import cache
9-
from nb_cli.cli import CLI_DEFAULT_STYLE, ClickAliasedGroup, run_sync, run_async
109
from nb_cli.handlers import (
1110
call_pip_list,
1211
call_pip_update,
1312
call_pip_install,
1413
call_pip_uninstall,
1514
)
15+
from nb_cli.cli import (
16+
CLI_DEFAULT_STYLE,
17+
ClickAliasedGroup,
18+
back_,
19+
exit_,
20+
run_sync,
21+
run_async,
22+
)
1623

1724

1825
@click.group(
@@ -36,16 +43,25 @@ async def self(ctx: click.Context):
3643
sub_cmd,
3744
)
3845
)
46+
if ctx.parent and ctx.parent.params.get("can_back_to_parent", False):
47+
_exit_choice = Choice(_("Back to top level."), back_)
48+
else:
49+
_exit_choice = Choice(_("Exit NB CLI."), exit_)
50+
choices.append(_exit_choice)
3951

40-
try:
41-
result = await ListPrompt(
42-
_("What do you want to do?"), choices=choices
43-
).prompt_async(style=CLI_DEFAULT_STYLE)
44-
except CancelledError:
45-
ctx.exit()
52+
while True:
53+
try:
54+
result = await ListPrompt(
55+
_("What do you want to do?"), choices=choices
56+
).prompt_async(style=CLI_DEFAULT_STYLE)
57+
except CancelledError:
58+
result = _exit_choice
4659

47-
sub_cmd = result.data
48-
await run_sync(ctx.invoke)(sub_cmd)
60+
sub_cmd = result.data
61+
if sub_cmd == back_:
62+
return
63+
ctx.params["can_back_to_parent"] = True
64+
await run_sync(ctx.invoke)(sub_cmd)
4965

5066

5167
@self.command(

0 commit comments

Comments
 (0)