@@ -187,14 +187,18 @@ fn is_executable(entry: &fs::DirEntry) -> bool {
187187}
188188
189189fn resolve_dir_path ( dir_path : & str ) -> PathBuf {
190+ // Unescape the directory path to handle spaces and other special characters
191+ let unescaped = unescape_for_completion ( dir_path) ;
192+
190193 if dir_path. starts_with ( '/' ) {
191- PathBuf :: from ( dir_path )
194+ PathBuf :: from ( unescaped )
192195 } else if let Some ( stripped) = dir_path. strip_prefix ( '~' ) {
196+ let unescaped_stripped = unescape_for_completion ( stripped) ;
193197 dirs:: home_dir ( )
194- . map ( |h| h. join ( stripped . strip_prefix ( '/' ) . unwrap_or ( stripped ) ) )
195- . unwrap_or_else ( || PathBuf :: from ( dir_path ) )
198+ . map ( |h| h. join ( unescaped_stripped . strip_prefix ( '/' ) . unwrap_or ( & unescaped_stripped ) ) )
199+ . unwrap_or_else ( || PathBuf :: from ( unescaped ) )
196200 } else {
197- PathBuf :: from ( "." ) . join ( dir_path )
201+ PathBuf :: from ( "." ) . join ( unescaped )
198202 }
199203}
200204
@@ -465,4 +469,50 @@ mod tests {
465469 . unwrap ( ) ;
466470 assert_eq ! ( matches. len( ) , 0 ) ;
467471 }
472+
473+ #[ tokio:: test]
474+ async fn test_complete_files_in_directory_with_spaces ( ) {
475+ let temp_dir = TempDir :: new ( ) . unwrap ( ) ;
476+ let temp_path = temp_dir. path ( ) ;
477+
478+ // Create a directory with a space in its name
479+ fs:: create_dir ( temp_path. join ( "some dir" ) ) . unwrap ( ) ;
480+ fs:: File :: create ( temp_path. join ( "some dir/file1.txt" ) ) . unwrap ( ) ;
481+ fs:: File :: create ( temp_path. join ( "some dir/file2.txt" ) ) . unwrap ( ) ;
482+
483+ let completer = ShellCompleter :: new ( HashSet :: new ( ) ) ;
484+ let history = DefaultHistory :: new ( ) ;
485+
486+ // Test 1: completion of "some\ d" should suggest the directory
487+ let line = format ! ( "cd {}/some\\ d" , temp_path. display( ) ) ;
488+ let pos = line. len ( ) ;
489+ let ( _start, matches) = completer
490+ . complete ( & line, pos, & Context :: new ( & history) )
491+ . unwrap ( ) ;
492+ assert_eq ! ( matches. len( ) , 1 ) ;
493+ assert_eq ! (
494+ matches[ 0 ] . replacement,
495+ format!( "{}/some\\ dir/" , temp_path. display( ) )
496+ ) ;
497+
498+ // Test 2: completion of "some\ dir/f" should suggest both files
499+ let line = format ! ( "cat {}/some\\ dir/f" , temp_path. display( ) ) ;
500+ let pos = line. len ( ) ;
501+ let ( _start, matches) = completer
502+ . complete ( & line, pos, & Context :: new ( & history) )
503+ . unwrap ( ) ;
504+ assert_eq ! ( matches. len( ) , 2 ) ;
505+
506+ // Test 3: completion of "some\ dir/file1" should complete to file1.txt
507+ let line = format ! ( "cat {}/some\\ dir/file1" , temp_path. display( ) ) ;
508+ let pos = line. len ( ) ;
509+ let ( _start, matches) = completer
510+ . complete ( & line, pos, & Context :: new ( & history) )
511+ . unwrap ( ) ;
512+ assert_eq ! ( matches. len( ) , 1 ) ;
513+ assert_eq ! (
514+ matches[ 0 ] . replacement,
515+ format!( "{}/some\\ dir/file1.txt" , temp_path. display( ) )
516+ ) ;
517+ }
468518}
0 commit comments