@@ -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 > {
@@ -88,40 +95,85 @@ fn find(path: &Path) -> Option<PathBuf> {
8895
8996fn parse ( file : & Path ) -> Option < PyVenvCfg > {
9097 let contents = fs:: read_to_string ( file) . ok ( ) ?;
98+ let mut version: Option < String > = None ;
99+ let mut version_major: Option < u64 > = None ;
100+ let mut version_minor: Option < u64 > = None ;
101+ let mut prompt: Option < String > = None ;
102+
91103 for line in contents. lines ( ) {
92- if !line. contains ( "version" ) {
93- continue ;
104+ if version. is_none ( ) {
105+ if let Some ( ( ver, major, minor) ) = parse_version ( line, & VERSION ) {
106+ version = Some ( ver) ;
107+ version_major = Some ( major) ;
108+ version_minor = Some ( minor) ;
109+ continue ;
110+ }
111+ if let Some ( ( ver, major, minor) ) = parse_version ( line, & VERSION_INFO ) {
112+ version = Some ( ver) ;
113+ version_major = Some ( major) ;
114+ version_minor = Some ( minor) ;
115+ continue ;
116+ }
94117 }
95- if let Some ( cfg) = parse_version ( line, & VERSION ) {
96- return Some ( cfg) ;
118+ if prompt. is_none ( ) {
119+ if let Some ( p) = parse_prompt ( line) {
120+ prompt = Some ( p) ;
121+ }
97122 }
98- if let Some ( cfg ) = parse_version ( line , & VERSION_INFO ) {
99- return Some ( cfg ) ;
123+ if version . is_some ( ) && prompt . is_some ( ) {
124+ break ;
100125 }
101126 }
102- None
127+
128+ match ( version, version_major, version_minor) {
129+ ( Some ( ver) , Some ( major) , Some ( minor) ) => Some ( PyVenvCfg :: new ( ver, major, minor, prompt) ) ,
130+ _ => None ,
131+ }
103132}
104133
105- fn parse_version ( line : & str , regex : & Regex ) -> Option < PyVenvCfg > {
134+ fn parse_version ( line : & str , regex : & Regex ) -> Option < ( String , u64 , u64 ) > {
106135 if let Some ( captures) = regex. captures ( line) {
107136 if let Some ( value) = captures. get ( 1 ) {
108137 let version = value. as_str ( ) ;
109- let parts: Vec < & str > = version. splitn ( 3 , "." ) . take ( 2 ) . collect ( ) ;
110- // .expect() below is OK because the version regex
111- // guarantees there are at least two digits.
112- let version_major = parts[ 0 ]
113- . parse ( )
114- . expect ( "python major version to be an integer" ) ;
115- let version_minor = parts[ 1 ]
116- . parse ( )
117- . expect ( "python minor version to be an integer" ) ;
118- return Some ( PyVenvCfg :: new (
119- version. to_string ( ) ,
120- version_major,
121- version_minor,
122- ) ) ;
138+ let parts: Vec < & str > = version. split ( '.' ) . collect ( ) ;
139+ if parts. len ( ) >= 2 {
140+ let version_major = parts[ 0 ]
141+ . parse ( )
142+ . expect ( "python major version to be an integer" ) ;
143+ let version_minor = parts[ 1 ]
144+ . parse ( )
145+ . expect ( "python minor version to be an integer" ) ;
146+ return Some ( ( version. to_string ( ) , version_major, version_minor) ) ;
147+ }
123148 }
124149 }
150+ None
151+ }
125152
153+ fn parse_prompt ( line : & str ) -> Option < String > {
154+ let trimmed = line. trim ( ) ;
155+ if trimmed. starts_with ( "prompt" ) {
156+ if let Some ( eq_idx) = trimmed. find ( '=' ) {
157+ // let value = trimmed[eq_idx + 1..].trim();
158+ let mut name = trimmed[ eq_idx + 1 ..] . trim ( ) . to_string ( ) ;
159+ // Strip any leading or trailing single or double quotes
160+ if name. starts_with ( '"' ) {
161+ name = name. trim_start_matches ( '"' ) . to_string ( ) ;
162+ }
163+ if name. ends_with ( '"' ) {
164+ name = name. trim_end_matches ( '"' ) . to_string ( ) ;
165+ }
166+ // Strip any leading or trailing single or double quotes
167+ if name. starts_with ( '\'' ) {
168+ name = name. trim_start_matches ( '\'' ) . to_string ( ) ;
169+ }
170+ if name. ends_with ( '\'' ) {
171+ name = name. trim_end_matches ( '\'' ) . to_string ( ) ;
172+ }
173+ if !name. is_empty ( ) {
174+ return Some ( name) ;
175+ }
176+ }
177+ }
126178 None
127179}
0 commit comments