22
33import click
44import sys
5- from prompt_toolkit import PromptSession
65from prompt_toolkit .history import InMemoryHistory
76
87from ._completer import ClickCompleter
98from .exceptions import ClickExit # type: ignore[attr-defined]
109from .exceptions import CommandLineParserError , ExitReplException , InvalidGroupFormat
1110from .utils import _execute_internal_and_sys_cmds
11+ from .core import ReplContext
12+ from .globals_ import ISATTY , get_current_repl_ctx
1213
1314
1415__all__ = ["bootstrap_prompt" , "register_repl" , "repl" ]
@@ -73,8 +74,6 @@ def repl(
7374 f"an optional argument '{ param .name } ' in REPL mode"
7475 )
7576
76- isatty = sys .stdin .isatty ()
77-
7877 # Delete the REPL command from those available, as we don't want to allow
7978 # nesting REPLs (note: pass `None` to `pop` as we don't want to error if
8079 # REPL command already not present for some reason).
@@ -90,58 +89,67 @@ def repl(
9089
9190 original_command = available_commands .pop (repl_command_name , None )
9291
93- if isatty :
94- prompt_kwargs = bootstrap_prompt (group , prompt_kwargs , group_ctx )
95- session = PromptSession (** prompt_kwargs )
92+ repl_ctx = ReplContext (
93+ group_ctx ,
94+ bootstrap_prompt (group , prompt_kwargs , group_ctx ),
95+ get_current_repl_ctx (silent = True ),
96+ )
9697
97- def get_command ():
98- return session .prompt ()
98+ if ISATTY :
99+ # If stdin is a TTY, prompt the user for input using PromptSession.
100+ def get_command () -> str :
101+ return repl_ctx .session .prompt () # type: ignore
99102
100103 else :
101- get_command = sys .stdin .readline
102-
103- while True :
104- try :
105- command = get_command ()
106- except KeyboardInterrupt :
107- continue
108- except EOFError :
109- break
110-
111- if not command :
112- if isatty :
104+ # If stdin is not a TTY, read input from stdin directly.
105+ def get_command () -> str :
106+ inp = sys .stdin .readline ().strip ()
107+ repl_ctx ._history .append (inp )
108+ return inp
109+
110+ with repl_ctx :
111+ while True :
112+ try :
113+ command = get_command ()
114+ except KeyboardInterrupt :
113115 continue
114- else :
116+ except EOFError :
115117 break
116118
117- try :
118- args = _execute_internal_and_sys_cmds (
119- command , allow_internal_commands , allow_system_commands
120- )
121- if args is None :
122- continue
119+ if not command :
120+ if ISATTY :
121+ continue
122+ else :
123+ break
123124
124- except CommandLineParserError :
125- continue
125+ try :
126+ args = _execute_internal_and_sys_cmds (
127+ command , allow_internal_commands , allow_system_commands
128+ )
129+ if args is None :
130+ continue
126131
127- except ExitReplException :
128- break
132+ except CommandLineParserError :
133+ continue
134+
135+ except ExitReplException :
136+ break
129137
130- try :
131- # The group command will dispatch based on args.
132- old_protected_args = group_ctx .protected_args
133138 try :
134- group_ctx .protected_args = args
135- group .invoke (group_ctx )
136- finally :
137- group_ctx .protected_args = old_protected_args
138- except click .ClickException as e :
139- e .show ()
140- except (ClickExit , SystemExit ):
141- pass
142-
143- except ExitReplException :
144- break
139+ # The group command will dispatch based on args.
140+ old_protected_args = group_ctx .protected_args
141+ try :
142+ group_ctx .protected_args = args
143+ group .invoke (group_ctx )
144+ finally :
145+ group_ctx .protected_args = old_protected_args
146+ except click .ClickException as e :
147+ e .show ()
148+ except (ClickExit , SystemExit ):
149+ pass
150+
151+ except ExitReplException :
152+ break
145153
146154 if original_command is not None :
147155 available_commands [repl_command_name ] = original_command
0 commit comments