@@ -5701,19 +5701,15 @@ fn test_ls_hyperlink() {
57015701
57025702 let result = scene. ucmd ( ) . arg ( "--hyperlink" ) . succeeds ( ) ;
57035703 assert ! ( result. stdout_str( ) . contains( "\x1b ]8;;file://" ) ) ;
5704- assert ! (
5705- result
5706- . stdout_str( )
5707- . contains( & format!( "{path}{separator}{file}\x07 {file}\x1b ]8;;\x07 " ) )
5708- ) ;
5704+ assert ! ( result. stdout_str( ) . contains( & format!(
5705+ "{path}{separator}{file}\x1b \\ {file}\x1b ]8;;\x1b \\ "
5706+ ) ) ) ;
57095707
57105708 let result = scene. ucmd ( ) . arg ( "--hyperlink=always" ) . succeeds ( ) ;
57115709 assert ! ( result. stdout_str( ) . contains( "\x1b ]8;;file://" ) ) ;
5712- assert ! (
5713- result
5714- . stdout_str( )
5715- . contains( & format!( "{path}{separator}{file}\x07 {file}\x1b ]8;;\x07 " ) )
5716- ) ;
5710+ assert ! ( result. stdout_str( ) . contains( & format!(
5711+ "{path}{separator}{file}\x1b \\ {file}\x1b ]8;;\x1b \\ "
5712+ ) ) ) ;
57175713
57185714 for argument in [
57195715 "--hyperlink=never" ,
@@ -5748,23 +5744,23 @@ fn test_ls_hyperlink_encode_link() {
57485744 assert ! (
57495745 result
57505746 . stdout_str( )
5751- . contains( "back%5cslash\x07 back \\ slash\x1b ]8;;\x07 " )
5747+ . contains( "back%5cslash\x1b \\ back \\ slash\x1b ]8;;\x1b \\ " )
57525748 ) ;
57535749 assert ! (
57545750 result
57555751 . stdout_str( )
5756- . contains( "ques%3ftion\x07 ques ?tion\x1b ]8;;\x07 " )
5752+ . contains( "ques%3ftion\x1b \\ ques ?tion\x1b ]8;;\x1b \\ " )
57575753 ) ;
57585754 }
57595755 assert ! (
57605756 result
57615757 . stdout_str( )
5762- . contains( "encoded%253Fquestion\x07 encoded %3Fquestion\x1b ]8;;\x07 " )
5758+ . contains( "encoded%253Fquestion\x1b \\ encoded %3Fquestion\x1b ]8;;\x1b \\ " )
57635759 ) ;
57645760 assert ! (
57655761 result
57665762 . stdout_str( )
5767- . contains( "sp%20ace\x07 sp ace\x1b ]8;;\x07 " )
5763+ . contains( "sp%20ace\x1b \\ sp ace\x1b ]8;;\x1b \\ " )
57685764 ) ;
57695765}
57705766// spell-checker: enable
@@ -5796,7 +5792,9 @@ fn test_ls_hyperlink_dirs() {
57965792 . lines( )
57975793 . next( )
57985794 . unwrap( )
5799- . contains( & format!( "{path}{separator}{dir_a}\x07 {dir_a}\x1b ]8;;\x07 :" ) )
5795+ . contains( & format!(
5796+ "{path}{separator}{dir_a}\x1b \\ {dir_a}\x1b ]8;;\x1b \\ :"
5797+ ) )
58005798 ) ;
58015799 assert_eq ! ( result. stdout_str( ) . lines( ) . nth( 1 ) . unwrap( ) , "" ) ;
58025800 assert ! (
@@ -5805,7 +5803,9 @@ fn test_ls_hyperlink_dirs() {
58055803 . lines( )
58065804 . nth( 2 )
58075805 . unwrap( )
5808- . contains( & format!( "{path}{separator}{dir_b}\x07 {dir_b}\x1b ]8;;\x07 :" ) )
5806+ . contains( & format!(
5807+ "{path}{separator}{dir_b}\x1b \\ {dir_b}\x1b ]8;;\x1b \\ :"
5808+ ) )
58095809 ) ;
58105810}
58115811
@@ -5837,21 +5837,89 @@ fn test_ls_hyperlink_recursive_dirs() {
58375837 let mut lines = result. stdout_str ( ) . lines ( ) ;
58385838 assert_hyperlink ! (
58395839 lines. next( ) ,
5840- & format!( "{path}{separator}{dir_a}\x07 {dir_a}\x1b ]8;;\x07 :" )
5840+ & format!( "{path}{separator}{dir_a}\x1b \\ {dir_a}\x1b ]8;;\x1b \\ :" )
58415841 ) ;
58425842 assert_hyperlink ! (
58435843 lines. next( ) ,
5844- & format!( "{path}{separator}{dir_a}{separator}{dir_b}\x07 {dir_b}\x1b ]8;;\x07 " )
5844+ & format!( "{path}{separator}{dir_a}{separator}{dir_b}\x1b \\ {dir_b}\x1b ]8;;\x1b \\ " )
58455845 ) ;
58465846 assert ! ( matches!( lines. next( ) , Some ( l) if l. is_empty( ) ) ) ;
58475847 assert_hyperlink ! (
58485848 lines. next( ) ,
58495849 & format!(
5850- "{path}{separator}{dir_a}{separator}{dir_b}\x07 {dir_a}{separator}{dir_b}\x1b ]8;;\x07 :"
5850+ "{path}{separator}{dir_a}{separator}{dir_b}\x1b \\ {dir_a}{separator}{dir_b}\x1b ]8;;\x1b \\ :"
58515851 )
58525852 ) ;
58535853}
58545854
5855+ #[ test]
5856+ fn test_ls_hyperlink_symlink_target_handling ( ) {
5857+ let scene = TestScenario :: new ( util_name ! ( ) ) ;
5858+ let at = & scene. fixtures ;
5859+
5860+ at. mkdir ( "target_dir" ) ;
5861+ at. touch ( "target_file.txt" ) ;
5862+ at. symlink_file ( "target_file.txt" , "link_to_file" ) ;
5863+ at. symlink_dir ( "target_dir" , "link_to_dir" ) ;
5864+ at. symlink_file ( "nonexistent" , "link_to_missing" ) ;
5865+
5866+ let result = scene
5867+ . ucmd ( )
5868+ . args ( & [ "-l" , "--hyperlink" , "--color" ] )
5869+ . succeeds ( ) ;
5870+ let output = result. stdout_str ( ) ;
5871+
5872+ assert ! ( output. contains( "\x1b ]8;;file://" ) ) ;
5873+ assert ! ( !output. contains( "\x07 " ) ) ;
5874+ assert ! ( output. contains( "\x1b \\ " ) ) ;
5875+
5876+ let file_link_line = output
5877+ . lines ( )
5878+ . find ( |line| line. contains ( "link_to_file" ) )
5879+ . unwrap ( ) ;
5880+ assert ! ( file_link_line. contains( " -> " ) ) ;
5881+ let target_part = file_link_line. split ( " -> " ) . nth ( 1 ) . unwrap ( ) ;
5882+ assert ! ( !target_part. contains( "\x1b [" ) ) ;
5883+ assert ! ( !target_part. ends_with( "\x1b [K" ) ) ;
5884+
5885+ let dir_link_line = output
5886+ . lines ( )
5887+ . find ( |line| line. contains ( "link_to_dir" ) )
5888+ . unwrap ( ) ;
5889+ assert ! ( dir_link_line. contains( " -> " ) ) ;
5890+ let target_part = dir_link_line. split ( " -> " ) . nth ( 1 ) . unwrap ( ) ;
5891+ assert ! ( target_part. contains( "\x1b [" ) ) ;
5892+
5893+ let missing_link_line = output
5894+ . lines ( )
5895+ . find ( |line| line. contains ( "link_to_missing" ) )
5896+ . unwrap ( ) ;
5897+ assert ! ( missing_link_line. contains( " -> " ) ) ;
5898+ let missing_target_part = missing_link_line. split ( " -> " ) . nth ( 1 ) . unwrap ( ) ;
5899+ assert ! ( missing_target_part. contains( "\x1b [" ) ) ;
5900+ }
5901+
5902+ #[ test]
5903+ fn test_ls_hyperlink_utf8_encoding ( ) {
5904+ let scene = TestScenario :: new ( util_name ! ( ) ) ;
5905+ let at = & scene. fixtures ;
5906+
5907+ at. touch ( "café.txt" ) ;
5908+ at. touch ( "file:with:colons.txt" ) ;
5909+ at. touch ( "file with spaces.txt" ) ;
5910+
5911+ let result = scene. ucmd ( ) . args ( & [ "--hyperlink" ] ) . succeeds ( ) ;
5912+ let output = result. stdout_str ( ) ;
5913+
5914+ assert ! ( output. contains( "caf%c3%a9.txt" ) ) ;
5915+ assert ! ( output. contains( "file%3awith%3acolons.txt" ) ) ;
5916+ assert ! ( output. contains( "file%20with%20spaces.txt" ) ) ;
5917+
5918+ let hyperlink_count = output. matches ( "\x1b ]8;;file://" ) . count ( ) ;
5919+ let terminator_count = output. matches ( "\x1b \\ " ) . count ( ) ;
5920+ assert_eq ! ( terminator_count, hyperlink_count * 2 ) ;
5921+ }
5922+
58555923#[ test]
58565924fn test_ls_color_do_not_reset ( ) {
58575925 let scene: TestScenario = TestScenario :: new ( util_name ! ( ) ) ;
0 commit comments