11def _initialize ():
22 import platform
33 import sys
4- from enum import Enum
54
65 if sys .platform != "win32" :
76 import readline
87
9- original_ps1 = ">>> "
10- is_wsl = "microsoft-standard-WSL" in platform .release ()
8+ # Override regex to support OSC codes
9+ if sys .version_info >= (3 , 13 ):
10+ import re
11+
12+ import _pyrepl .utils
13+
14+ _pyrepl .utils .ANSI_ESCAPE_SEQUENCE = re .compile (
15+ r"\x1b(?:\[[ -@]*[A-~]|\][^\x1b\x07]*(?:\x07|\x1b\\))"
16+ )
1117
18+ original_ps1 = ">>> "
1219 # PYTHONSTARTUP executes this file's code inside the user's __main__
1320 # namespace, so PS1.__str__'s globals are the user's globals. If the
1421 # user later shadows a name we rely on at prompt-render time (e.g.
@@ -23,36 +30,54 @@ def _initialize():
2330 _bool = bool
2431 _str = str
2532
26- class ShellIntegrationSequence (str , Enum ):
27- SOH = "\001 "
28- STX = "\002 "
29- COMMAND_EXECUTED = "\x1b ]633;C\x07 "
30- COMMAND_LINE = "\x1b ]633;E;"
31- COMMAND_FINISHED = "\x1b ]633;D;"
32- PROMPT_STARTED = "\x1b ]633;A\x07 "
33- COMMAND_START = "\x1b ]633;B\x07 "
34- TERMINATOR = "\x07 "
35-
36- def __str__ (self ):
37- return self .value
33+ # https://code.visualstudio.com/docs/terminal/shell-integration#_supported-escape-sequences
34+ class ShellIntegrationSequence :
35+ soh = "\001 "
36+ stx = "\002 "
37+ template = "\x1b ]633;{}\x07 "
38+
39+ # Before the prompt (>>>) is displayed
40+ @classmethod
41+ def prompt_start (cls ) -> str :
42+ return cls .template .format ("A" )
43+
44+ # After the prompt (>>>) is displayed
45+ @classmethod
46+ def prompt_end (cls ) -> str :
47+ return cls .template .format ("B" )
48+
49+ # After the user has typed a command but before it is executed
50+ @classmethod
51+ def pre_execution (cls ) -> str :
52+ return cls .template .format ("C" )
53+
54+ @classmethod
55+ def execution_finished (cls , exit_code : int ) -> str :
56+ """Mark execution as finished with its exit code."""
57+ return cls .template .format (f"D;{ exit_code } " )
58+
59+ @classmethod
60+ def command_line (cls , command : object ) -> str :
61+ """Explicitly set the command line interpreted by the shell."""
62+ return cls .template .format (f"E;{ command } " )
3863
3964 class REPLHooks :
4065 def __init__ (self ):
4166 self .global_exit = None
42- self .failure_flag = False
67+ self .last_failure_flag = False
4368 self .original_excepthook = sys .excepthook
4469 self .original_displayhook = sys .displayhook
4570 sys .excepthook = self .vscode_excepthook
4671 sys .displayhook = self .vscode_displayhook
4772
4873 def vscode_displayhook (self , value ):
4974 if value is None :
50- self .failure_flag = False
75+ self .last_failure_flag = False
5176 self .original_displayhook (value )
5277
5378 def vscode_excepthook (self , type_ , value , traceback ):
5479 self .global_exit = value
55- self .failure_flag = True
80+ self .last_failure_flag = True
5681 self .original_excepthook (type_ , value , traceback )
5782
5883 def get_last_command ():
@@ -67,43 +92,40 @@ class PS1:
6792
6893 # str will get called for every prompt with exit code to show success/failure
6994 def __str__ (self ):
70- exit_code = _int (_bool (self .hooks .failure_flag ))
71- self .hooks .failure_flag = False
95+ last_exit_code = _int (_bool (self .hooks .last_failure_flag ))
96+ self .hooks .last_failure_flag = False
7297 # Guide following official VS Code doc for shell integration sequence:
7398 result = ""
7499 # For non-windows allow recent_command history.
100+ # fmt: off
75101 if sys .platform != "win32" :
76- result = "{soh}{command_executed}{command_line}{command_finished}{prompt_started}{stx}{prompt}{soh}{command_start}{stx}" .format (
77- soh = ShellIntegrationSequence .SOH ,
78- stx = ShellIntegrationSequence .STX ,
79- command_executed = ShellIntegrationSequence .COMMAND_EXECUTED ,
80- command_line = ShellIntegrationSequence .COMMAND_LINE
81- + _str (get_last_command ())
82- + ShellIntegrationSequence .TERMINATOR ,
83- command_finished = ShellIntegrationSequence .COMMAND_FINISHED
84- + _str (exit_code )
85- + ShellIntegrationSequence .TERMINATOR ,
86- prompt_started = ShellIntegrationSequence .PROMPT_STARTED ,
102+ result = "{soh}{pre_execution}{command_line}{execution_finished}{prompt_start}{stx}{prompt}{soh}{prompt_end}{stx}" .format ( # noqa: UP032
103+ soh = ShellIntegrationSequence .soh ,
104+ pre_execution = ShellIntegrationSequence .pre_execution (),
105+ command_line = ShellIntegrationSequence .command_line (get_last_command ()),
106+ execution_finished = ShellIntegrationSequence .execution_finished (last_exit_code ),
107+ prompt_start = ShellIntegrationSequence .prompt_start (),
108+ stx = ShellIntegrationSequence .stx ,
87109 prompt = original_ps1 ,
88- command_start = ShellIntegrationSequence .COMMAND_START ,
110+ prompt_end = ShellIntegrationSequence .prompt_end () ,
89111 )
90112 else :
91- result = "{command_finished}{prompt_started}{prompt}{command_start}{command_executed}" .format (
92- command_finished = ShellIntegrationSequence .COMMAND_FINISHED
93- + _str (exit_code )
94- + ShellIntegrationSequence .TERMINATOR ,
95- prompt_started = ShellIntegrationSequence .PROMPT_STARTED ,
113+ result = "{execution_finished}{prompt_start}{prompt}{prompt_end}{pre_execution}" .format ( # noqa: UP032
114+ execution_finished = ShellIntegrationSequence .execution_finished (last_exit_code ),
115+ prompt_start = ShellIntegrationSequence .prompt_start (),
96116 prompt = original_ps1 ,
97- command_start = ShellIntegrationSequence .COMMAND_START ,
98- command_executed = ShellIntegrationSequence .COMMAND_EXECUTED ,
117+ prompt_end = ShellIntegrationSequence .prompt_end () ,
118+ pre_execution = ShellIntegrationSequence .pre_execution () ,
99119 )
120+ # fmt: on
100121
101122 return result
102123
103124 def __repr__ (self ):
104125 return "<Custom PS1 for VS Code Python Shell Integration>"
105126
106- if sys .platform != "win32" and (not is_wsl ):
127+ is_wsl = "microsoft-standard-WSL" in platform .release ()
128+ if not is_wsl and (sys .platform != "win32" or sys .version_info >= (3 , 13 )):
107129 sys .ps1 = PS1 ()
108130
109131 ctrl_key = "Cmd" if sys .platform == "darwin" else "Ctrl"
0 commit comments