@@ -179,6 +179,7 @@ impl MainWindow {
179179 fn activate_from_ipc ( & self ) {
180180 self . frame . show ( true ) ;
181181 self . frame . iconize ( false ) ;
182+ self . frame . request_user_attention ( UserAttentionFlag :: Info ) ;
182183 self . frame . raise ( ) ;
183184 self . doc_manager . lock ( ) . unwrap ( ) . restore_focus ( ) ;
184185 }
@@ -1184,14 +1185,37 @@ impl MainWindow {
11841185}
11851186
11861187fn ensure_parser_ready_for_path ( frame : & Frame , path : & Path , config : & Rc < Mutex < ConfigManager > > ) -> bool {
1187- let extension = path . extension ( ) . and_then ( |ext| ext . to_str ( ) ) . unwrap_or_default ( ) ;
1188- if extension. is_empty ( ) || parser_supports_extension ( extension) {
1188+ let extension = parser_extension_for_path ( path ) ;
1189+ if extension. is_empty ( ) || parser_supports_extension ( & extension) {
11891190 return true ;
11901191 }
11911192 let cfg = config. lock ( ) . unwrap ( ) ;
11921193 ensure_parser_for_unknown_file ( frame, path, & cfg)
11931194}
11941195
1196+ fn parser_extension_for_path ( path : & Path ) -> String {
1197+ let from_path =
1198+ path. extension ( ) . and_then ( |ext| ext. to_str ( ) ) . map ( clean_extension_token) . unwrap_or_default ( ) . to_string ( ) ;
1199+ if !from_path. is_empty ( ) {
1200+ return from_path;
1201+ }
1202+ // Fallback for odd IPC/CLI strings that may contain trailing quotes or whitespace.
1203+ let raw = path. to_string_lossy ( ) ;
1204+ let cleaned = raw. trim ( ) . trim_matches ( [ '"' , '\'' , '\0' ] ) ;
1205+ let candidate = cleaned
1206+ . rsplit_once ( [ '/' , '\\' ] )
1207+ . map_or ( cleaned, |( _, file_name) | file_name)
1208+ . rsplit_once ( '.' )
1209+ . map_or ( "" , |( _, ext) | ext)
1210+ . trim ( ) ;
1211+ clean_extension_token ( candidate)
1212+ }
1213+
1214+ fn clean_extension_token ( raw : & str ) -> String {
1215+ let trimmed = raw. trim ( ) . trim_matches ( [ '"' , '\'' , '\0' ] ) ;
1216+ trimmed. chars ( ) . take_while ( |c| c. is_ascii_alphanumeric ( ) ) . collect ( )
1217+ }
1218+
11951219fn ensure_parser_for_unknown_file ( parent : & Frame , path : & Path , config : & ConfigManager ) -> bool {
11961220 let path_str = path. to_string_lossy ( ) ;
11971221 let saved_format = config. get_document_format ( & path_str) ;
@@ -1250,3 +1274,33 @@ fn update_title_from_manager(frame: &Frame, dm: &DocumentManager) {
12501274 frame. set_status_text ( & status_text, 0 ) ;
12511275 }
12521276}
1277+
1278+ #[ cfg( test) ]
1279+ mod tests {
1280+ use std:: path:: Path ;
1281+
1282+ use super :: parser_extension_for_path;
1283+
1284+ #[ test]
1285+ fn parser_extension_for_path_handles_normal_paths ( ) {
1286+ assert_eq ! ( parser_extension_for_path( Path :: new( "book.epub" ) ) , "epub" ) ;
1287+ assert_eq ! ( parser_extension_for_path( Path :: new( "C:\\ docs\\ book.PDF" ) ) , "PDF" ) ;
1288+ }
1289+
1290+ #[ test]
1291+ fn parser_extension_for_path_strips_quotes_and_whitespace ( ) {
1292+ assert_eq ! ( parser_extension_for_path( Path :: new( " \" book.epub\" " ) ) , "epub" ) ;
1293+ assert_eq ! ( parser_extension_for_path( Path :: new( "'book.txt'" ) ) , "txt" ) ;
1294+ }
1295+
1296+ #[ test]
1297+ fn parser_extension_for_path_returns_empty_for_no_extension ( ) {
1298+ assert_eq ! ( parser_extension_for_path( Path :: new( "README" ) ) , "" ) ;
1299+ }
1300+
1301+ #[ test]
1302+ fn parser_extension_for_path_handles_ipc_artifacts ( ) {
1303+ assert_eq ! ( parser_extension_for_path( Path :: new( "book.epub\u{0} " ) ) , "epub" ) ;
1304+ assert_eq ! ( parser_extension_for_path( Path :: new( " \" book.epub\u{0} \" " ) ) , "epub" ) ;
1305+ }
1306+ }
0 commit comments