@@ -22,14 +22,21 @@ pub struct PyVenvCfg {
2222 pub version : String ,
2323 pub version_major : u64 ,
2424 pub version_minor : u64 ,
25+ pub prompt : Option < String > ,
2526}
2627
2728impl PyVenvCfg {
28- fn new ( version : String , version_major : u64 , version_minor : u64 ) -> Self {
29+ fn new (
30+ version : String ,
31+ version_major : u64 ,
32+ version_minor : u64 ,
33+ prompt : Option < String > ,
34+ ) -> Self {
2935 Self {
3036 version,
3137 version_major,
3238 version_minor,
39+ prompt,
3340 }
3441 }
3542 pub fn find ( path : & Path ) -> Option < Self > {
@@ -79,40 +86,85 @@ fn find(path: &Path) -> Option<PathBuf> {
7986
8087fn parse ( file : & Path ) -> Option < PyVenvCfg > {
8188 let contents = fs:: read_to_string ( file) . ok ( ) ?;
89+ let mut version: Option < String > = None ;
90+ let mut version_major: Option < u64 > = None ;
91+ let mut version_minor: Option < u64 > = None ;
92+ let mut prompt: Option < String > = None ;
93+
8294 for line in contents. lines ( ) {
83- if !line. contains ( "version" ) {
84- continue ;
95+ if version. is_none ( ) {
96+ if let Some ( ( ver, major, minor) ) = parse_version ( line, & VERSION ) {
97+ version = Some ( ver) ;
98+ version_major = Some ( major) ;
99+ version_minor = Some ( minor) ;
100+ continue ;
101+ }
102+ if let Some ( ( ver, major, minor) ) = parse_version ( line, & VERSION_INFO ) {
103+ version = Some ( ver) ;
104+ version_major = Some ( major) ;
105+ version_minor = Some ( minor) ;
106+ continue ;
107+ }
85108 }
86- if let Some ( cfg) = parse_version ( line, & VERSION ) {
87- return Some ( cfg) ;
109+ if prompt. is_none ( ) {
110+ if let Some ( p) = parse_prompt ( line) {
111+ prompt = Some ( p) ;
112+ }
88113 }
89- if let Some ( cfg ) = parse_version ( line , & VERSION_INFO ) {
90- return Some ( cfg ) ;
114+ if version . is_some ( ) && prompt . is_some ( ) {
115+ break ;
91116 }
92117 }
93- None
118+
119+ match ( version, version_major, version_minor) {
120+ ( Some ( ver) , Some ( major) , Some ( minor) ) => Some ( PyVenvCfg :: new ( ver, major, minor, prompt) ) ,
121+ _ => None ,
122+ }
94123}
95124
96- fn parse_version ( line : & str , regex : & Regex ) -> Option < PyVenvCfg > {
125+ fn parse_version ( line : & str , regex : & Regex ) -> Option < ( String , u64 , u64 ) > {
97126 if let Some ( captures) = regex. captures ( line) {
98127 if let Some ( value) = captures. get ( 1 ) {
99128 let version = value. as_str ( ) ;
100- let parts: Vec < & str > = version. splitn ( 3 , "." ) . take ( 2 ) . collect ( ) ;
101- // .expect() below is OK because the version regex
102- // guarantees there are at least two digits.
103- let version_major = parts[ 0 ]
104- . parse ( )
105- . expect ( "python major version to be an integer" ) ;
106- let version_minor = parts[ 1 ]
107- . parse ( )
108- . expect ( "python minor version to be an integer" ) ;
109- return Some ( PyVenvCfg :: new (
110- version. to_string ( ) ,
111- version_major,
112- version_minor,
113- ) ) ;
129+ let parts: Vec < & str > = version. split ( '.' ) . collect ( ) ;
130+ if parts. len ( ) >= 2 {
131+ let version_major = parts[ 0 ]
132+ . parse ( )
133+ . expect ( "python major version to be an integer" ) ;
134+ let version_minor = parts[ 1 ]
135+ . parse ( )
136+ . expect ( "python minor version to be an integer" ) ;
137+ return Some ( ( version. to_string ( ) , version_major, version_minor) ) ;
138+ }
114139 }
115140 }
141+ None
142+ }
116143
144+ fn parse_prompt ( line : & str ) -> Option < String > {
145+ let trimmed = line. trim ( ) ;
146+ if trimmed. starts_with ( "prompt" ) {
147+ if let Some ( eq_idx) = trimmed. find ( '=' ) {
148+ // let value = trimmed[eq_idx + 1..].trim();
149+ let mut name = trimmed[ eq_idx + 1 ..] . trim ( ) . to_string ( ) ;
150+ // Strip any leading or trailing single or double quotes
151+ if name. starts_with ( '"' ) {
152+ name = name. trim_start_matches ( '"' ) . to_string ( ) ;
153+ }
154+ if name. ends_with ( '"' ) {
155+ name = name. trim_end_matches ( '"' ) . to_string ( ) ;
156+ }
157+ // Strip any leading or trailing single or double quotes
158+ if name. starts_with ( '\'' ) {
159+ name = name. trim_start_matches ( '\'' ) . to_string ( ) ;
160+ }
161+ if name. ends_with ( '\'' ) {
162+ name = name. trim_end_matches ( '\'' ) . to_string ( ) ;
163+ }
164+ if !name. is_empty ( ) {
165+ return Some ( name) ;
166+ }
167+ }
168+ }
117169 None
118170}
0 commit comments