use predicates ::boolean ::PredicateBooleanExt ;
use predicates ::{ prelude ::predicate , str ::PredicateStrExt } ;
use serial_test ::serial ;
use std ::path ::Path ;
use std ::str ::from_utf8 ;
use tempfile ::tempdir ;
#[ cfg(unix) ]
mod unix {
pub use std ::fs ::File ;
pub use std ::io ::{ self , Write } ;
pub use std ::os ::unix ::io ::FromRawFd ;
pub use std ::path ::PathBuf ;
pub use std ::process ::Stdio ;
pub use std ::thread ;
pub use std ::time ::Duration ;
pub use assert_cmd ::assert ::OutputAssertExt ;
pub use nix ::pty ::{ openpty , OpenptyResult } ;
pub use wait_timeout ::ChildExt ;
pub const SAFE_CHILD_PROCESS_CREATION_TIME : Duration = Duration ::from_millis ( 100 ) ;
pub const CHILD_WAIT_TIMEOUT : Duration = Duration ::from_secs ( 15 ) ;
}
#[ cfg(unix) ]
use unix ::* ;
mod utils ;
use utils ::command ::{ bat , bat_with_config } ;
#[ cfg(unix) ]
use utils ::command ::bat_raw_command ;
use utils ::mocked_pagers ;
const EXAMPLES_DIR : & str = "tests/examples" ;
fn get_config ( ) -> & ' static str {
if cfg! ( windows ) {
"bat-windows.conf"
} else {
"bat.conf"
}
}
#[ test ]
fn basic ( ) {
bat ( )
. arg ( "test.txt" )
. assert ( )
. success ( )
. stdout ( "hello world\n" )
. stderr ( "" ) ;
}
#[ test ]
fn stdin ( ) {
bat ( )
. write_stdin ( "foo\nbar\n" )
. assert ( )
. success ( )
. stdout ( "foo\nbar\n" ) ;
}
#[ test ]
fn concatenate ( ) {
bat ( )
. arg ( "test.txt" )
. arg ( "test.txt" )
. assert ( )
. success ( )
. stdout ( "hello world\nhello world\n" ) ;
}
#[ test ]
fn concatenate_stdin ( ) {
bat ( )
. arg ( "test.txt" )
. arg ( "-" )
. arg ( "test.txt" )
. write_stdin ( "stdin\n" )
. assert ( )
. success ( )
. stdout ( "hello world\nstdin\nhello world\n" ) ;
}
#[ test ]
fn concatenate_empty_first ( ) {
bat ( )
. arg ( "empty.txt" )
. arg ( "test.txt" )
. assert ( )
. success ( )
. stdout ( "hello world\n" ) ;
}
#[ test ]
fn concatenate_empty_last ( ) {
bat ( )
. arg ( "test.txt" )
. arg ( "empty.txt" )
. assert ( )
. success ( )
. stdout ( "hello world\n" ) ;
}
#[ test ]
fn concatenate_empty_both ( ) {
bat ( )
. arg ( "empty.txt" )
. arg ( "empty.txt" )
. assert ( )
. success ( )
. stdout ( "" ) ;
}
#[ test ]
fn concatenate_empty_between ( ) {
bat ( )
. arg ( "test.txt" )
. arg ( "empty.txt" )
. arg ( "test.txt" )
. assert ( )
. success ( )
. stdout ( "hello world\nhello world\n" ) ;
}
#[ test ]
fn concatenate_empty_first_and_last ( ) {
bat ( )
. arg ( "empty.txt" )
. arg ( "test.txt" )
. arg ( "empty.txt" )
. assert ( )
. success ( )
. stdout ( "hello world\n" ) ;
}
#[ test ]
fn concatenate_single_line ( ) {
bat ( )
. arg ( "single-line.txt" )
. arg ( "single-line.txt" )
. assert ( )
. success ( )
. stdout ( "Single LineSingle Line" ) ;
}
#[ test ]
fn concatenate_single_line_empty ( ) {
bat ( )
. arg ( "single-line.txt" )
. arg ( "empty.txt" )
. arg ( "single-line.txt" )
. assert ( )
. success ( )
. stdout ( "Single LineSingle Line" ) ;
}
#[ test ]
fn line_numbers ( ) {
bat ( )
. arg ( "multiline.txt" )
. arg ( "--style=numbers" )
. arg ( "--decorations=always" )
. assert ( )
. success ( )
. stdout ( " 1 line 1\n 2 line 2\n 3 line 3\n 4 line 4\n" ) ;
}
#[ test ]
fn line_range_2_3 ( ) {
bat ( )
. arg ( "multiline.txt" )
. arg ( "--line-range=2:3" )
. assert ( )
. success ( )
. stdout ( "line 2\nline 3\n" ) ;
}
#[ test ]
fn line_range_first_two ( ) {
bat ( )
. arg ( "multiline.txt" )
. arg ( "--line-range=:2" )
. assert ( )
. success ( )
. stdout ( "line 1\nline 2\n" ) ;
}
#[ test ]
fn line_range_last_3 ( ) {
bat ( )
. arg ( "multiline.txt" )
. arg ( "--line-range=2:" )
. assert ( )
. success ( )
. stdout ( "line 2\nline 3\nline 4\n" ) ;
}
#[ test ]
fn line_range_multiple ( ) {
bat ( )
. arg ( "multiline.txt" )
. arg ( "--line-range=1:2" )
. arg ( "--line-range=4:4" )
. assert ( )
. success ( )
. stdout ( "line 1\nline 2\nline 4\n" ) ;
}
#[ test ]
fn squeeze_blank ( ) {
bat ( )
. arg ( "empty_lines.txt" )
. arg ( "--squeeze-blank" )
. assert ( )
. success ( )
. stdout ( "line 1\n\nline 5\n\nline 20\nline 21\n\nline 24\n\nline 26\n\nline 30\n" ) ;
}
#[ test ]
fn squeeze_blank_line_numbers ( ) {
bat ( )
. arg ( "empty_lines.txt" )
. arg ( "--squeeze-blank" )
. arg ( "--decorations=always" )
. arg ( "--number" )
. assert ( )
. success ( )
. stdout ( " 1 line 1\n 2 \n 5 line 5\n 6 \n 20 line 20\n 21 line 21\n 22 \n 24 line 24\n 25 \n 26 line 26\n 27 \n 30 line 30\n" ) ;
}
#[ test ]
fn squeeze_limit ( ) {
bat ( )
. arg ( "empty_lines.txt" )
. arg ( "--squeeze-blank" )
. arg ( "--squeeze-limit=2" )
. assert ( )
. success ( )
. stdout ( "line 1\n\n\nline 5\n\n\nline 20\nline 21\n\n\nline 24\n\nline 26\n\n\nline 30\n" ) ;
bat ( )
. arg ( "empty_lines.txt" )
. arg ( "--squeeze-blank" )
. arg ( "--squeeze-limit=5" )
. assert ( )
. success ( )
. stdout ( "line 1\n\n\n\nline 5\n\n\n\n\n\nline 20\nline 21\n\n\nline 24\n\nline 26\n\n\n\nline 30\n" ) ;
}
#[ test ]
fn squeeze_limit_line_numbers ( ) {
bat ( )
. arg ( "empty_lines.txt" )
. arg ( "--squeeze-blank" )
. arg ( "--squeeze-limit=2" )
. arg ( "--decorations=always" )
. arg ( "--number" )
. assert ( )
. success ( )
. stdout ( " 1 line 1\n 2 \n 3 \n 5 line 5\n 6 \n 7 \n 20 line 20\n 21 line 21\n 22 \n 23 \n 24 line 24\n 25 \n 26 line 26\n 27 \n 28 \n 30 line 30\n" ) ;
bat ( )
. arg ( "empty_lines.txt" )
. arg ( "--squeeze-blank" )
. arg ( "--squeeze-limit=5" )
. arg ( "--decorations=always" )
. arg ( "--number" )
. assert ( )
. success ( )
. stdout ( " 1 line 1\n 2 \n 3 \n 4 \n 5 line 5\n 6 \n 7 \n 8 \n 9 \n 10 \n 20 line 20\n 21 line 21\n 22 \n 23 \n 24 line 24\n 25 \n 26 line 26\n 27 \n 28 \n 29 \n 30 line 30\n" ) ;
}
#[ test ]
fn list_themes_with_colors ( ) {
#[ cfg(target_os = " macos " ) ]
let default_theme_chunk = "Monokai Extended Light\x1B[0m (default)" ;
#[ cfg(not(target_os = " macos " )) ]
let default_theme_chunk = "Monokai Extended\x1B[0m (default)" ;
bat ( )
. arg ( "--color=always" )
. arg ( "--list-themes" )
. assert ( )
. success ( )
. stdout ( predicate ::str ::contains ( "DarkNeon" ) . normalize ( ) )
. stdout ( predicate ::str ::contains ( default_theme_chunk ) . normalize ( ) )
. stdout ( predicate ::str ::contains ( "Output the square of a number." ) . normalize ( ) ) ;
}
#[ test ]
fn list_themes_without_colors ( ) {
#[ cfg(target_os = " macos " ) ]
let default_theme_chunk = "Monokai Extended Light (default)" ;
#[ cfg(not(target_os = " macos " )) ]
let default_theme_chunk = "Monokai Extended (default)" ;
bat ( )
. arg ( "--color=never" )
. arg ( "--list-themes" )
. assert ( )
. success ( )
. stdout ( predicate ::str ::contains ( "DarkNeon" ) . normalize ( ) )
. stdout ( predicate ::str ::contains ( default_theme_chunk ) . normalize ( ) ) ;
}
#[ test ]
#[ cfg_attr(any(not(feature = " git " ), target_os = " windows " ), ignore) ]
fn short_help ( ) {
test_help ( "-h" , "../doc/short-help.txt" ) ;
}
#[ test ]
#[ cfg_attr(any(not(feature = " git " ), target_os = " windows " ), ignore) ]
fn long_help ( ) {
test_help ( "--help" , "../doc/long-help.txt" ) ;
}
fn test_help ( arg : & str , expect_file : & str ) {
let assert = bat ( ) . arg ( arg ) . assert ( ) ;
expect_test ::expect_file ! [ expect_file ]
. assert_eq ( & String ::from_utf8_lossy ( & assert . get_output ( ) . stdout ) ) ;
}
#[ cfg(unix) ]
fn setup_temp_file ( content : & [ u8 ] ) -> io ::Result < ( PathBuf , tempfile ::TempDir ) > {
let dir = tempfile ::tempdir ( ) . expect ( "Couldn't create tempdir" ) ;
let path = dir . path ( ) . join ( "temp_file" ) ;
File ::create ( & path ) ? . write_all ( content ) ? ;
Ok ( ( path , dir ) )
}
#[ cfg(unix) ]
#[ test ]
fn basic_io_cycle ( ) -> io ::Result < ( ) > {
let ( filename , dir ) = setup_temp_file ( b" I am not empty " ) ? ;
let file_out = Stdio ::from ( File ::create ( & filename ) ? ) ;
let res = bat_raw_command ( )
. arg ( "test.txt" )
. arg ( & filename )
. stdout ( file_out )
. assert ( ) ;
drop ( dir ) ;
res . failure ( ) ;
Ok ( ( ) )
}
#[ cfg(unix) ]
#[ test ]
fn first_file_cyclic_is_ok ( ) -> io ::Result < ( ) > {
let ( filename , dir ) = setup_temp_file ( b" I am not empty " ) ? ;
let file_out = Stdio ::from ( File ::create ( & filename ) ? ) ;
let res = bat_raw_command ( )
. arg ( & filename )
. arg ( "test.txt" )
. stdout ( file_out )
. assert ( ) ;
drop ( dir ) ;
res . success ( ) ;
Ok ( ( ) )
}
#[ cfg(unix) ]
#[ test ]
fn empty_file_cycle_is_ok ( ) -> io ::Result < ( ) > {
let ( filename , dir ) = setup_temp_file ( b" I am not empty " ) ? ;
let file_out = Stdio ::from ( File ::create ( & filename ) ? ) ;
let res = bat_raw_command ( )
. arg ( "empty.txt" )
. arg ( & filename )
. stdout ( file_out )
. assert ( ) ;
drop ( dir ) ;
res . success ( ) ;
Ok ( ( ) )
}
#[ cfg(unix) ]
#[ test ]
fn stdin_to_stdout_cycle ( ) -> io ::Result < ( ) > {
let ( filename , dir ) = setup_temp_file ( b" I am not empty " ) ? ;
let file_in = Stdio ::from ( File ::open ( & filename ) ? ) ;
let file_out = Stdio ::from ( File ::create ( & filename ) ? ) ;
let res = bat_raw_command ( )
. arg ( "test.txt" )
. arg ( "-" )
. stdin ( file_in )
. stdout ( file_out )
. assert ( ) ;
drop ( dir ) ;
res . failure ( ) ;
Ok ( ( ) )
}
#[ cfg(unix) ]
#[ test ]
fn no_args_doesnt_break ( ) {
// To simulate bat getting started from the shell, a process is created with stdin and stdout
// as the slave end of a pseudo terminal. Although both point to the same "file", bat should
// not exit, because in this case it is safe to read and write to the same fd, which is why
// this test exists.
let OpenptyResult { master , slave } = openpty ( None , None ) . expect ( "Couldn't open pty." ) ;
let mut master = unsafe { File ::from_raw_fd ( master ) } ;
let stdin_file = unsafe { File ::from_raw_fd ( slave ) } ;
let stdout_file = stdin_file . try_clone ( ) . unwrap ( ) ;
let stdin = Stdio ::from ( stdin_file ) ;
let stdout = Stdio ::from ( stdout_file ) ;
let mut child = bat_raw_command ( )
. stdin ( stdin )
. stdout ( stdout )
. spawn ( )
. expect ( "Failed to start." ) ;
// Some time for the child process to start and to make sure, that we can poll the exit status.
// Although this waiting period is not necessary, it is best to keep it in and be absolutely
// sure, that the try_wait does not error later.
thread ::sleep ( SAFE_CHILD_PROCESS_CREATION_TIME ) ;
// The child process should be running and waiting for input,
// therefore no exit status should be available.
let exit_status = child
. try_wait ( )
. expect ( "Error polling exit status, this should never happen." ) ;
assert! ( exit_status . is_none ( ) ) ;
// Write Ctrl-D (end of transmission) to the pty.
master
. write_all ( & [ 0x04 ] )
. expect ( "Couldn't write EOT character to master end." ) ;
let exit_status = child
. wait_timeout ( CHILD_WAIT_TIMEOUT )
. expect ( "Error polling exit status, this should never happen." )
. expect ( "Exit status not set, but the child should have exited already." ) ;
assert! ( exit_status . success ( ) ) ;
}
#[ test ]
fn tabs_numbers ( ) {
bat ( )
. arg ( "tabs.txt" )
. arg ( "--tabs=4" )
. arg ( "--style=numbers" )
. arg ( "--decorations=always" )
. assert ( )
. success ( )
. stdout (
" 1 1 2 3 4
2 1 ?
3 22 ?
4 333 ?
5 4444 ?
6 55555 ?
7 666666 ?
8 7777777 ?
9 88888888 ?
" ,
) ;
}
#[ test ]
fn tabs_passthrough_wrapped ( ) {
bat ( )
. arg ( "tabs.txt" )
. arg ( "--tabs=0" )
. arg ( "--style=plain" )
. arg ( "--decorations=always" )
. assert ( )
. success ( )
. stdout (
" 1 2 3 4
1 ?
22 ?
333 ?
4444 ?
55555 ?
666666 ?
7777777 ?
88888888 ?
" ,
) ;
}
#[ test ]
fn tabs_4_wrapped ( ) {
bat ( )
. arg ( "tabs.txt" )
. arg ( "--tabs=4" )
. arg ( "--style=plain" )
. arg ( "--decorations=always" )
. assert ( )
. success ( )
. stdout (
" 1 2 3 4
1 ?
22 ?
333 ?
4444 ?
55555 ?
666666 ?
7777777 ?
88888888 ?
" ,
) ;
}
#[ test ]
fn tabs_8_wrapped ( ) {
bat ( )
. arg ( "tabs.txt" )
. arg ( "--tabs=8" )
. arg ( "--style=plain" )
. arg ( "--decorations=always" )
. assert ( )
. success ( )
. stdout (
" 1 2 3 4
1 ?
22 ?
333 ?
4444 ?
55555 ?
666666 ?
7777777 ?
88888888 ?
" ,
) ;
}
#[ test ]
fn tabs_passthrough ( ) {
bat ( )
. arg ( "tabs.txt" )
. arg ( "--tabs=0" )
. arg ( "--style=plain" )
. arg ( "--decorations=always" )
. assert ( )
. success ( )
. stdout (
" 1 2 3 4
1 ?
22 ?
333 ?
4444 ?
55555 ?
666666 ?
7777777 ?
88888888 ?
" ,
) ;
}
#[ test ]
fn tabs_4 ( ) {
bat ( )
. arg ( "tabs.txt" )
. arg ( "--tabs=4" )
. arg ( "--style=plain" )
. arg ( "--decorations=always" )
. assert ( )
. success ( )
. stdout (
" 1 2 3 4
1 ?
22 ?
333 ?
4444 ?
55555 ?
666666 ?
7777777 ?
88888888 ?
" ,
) ;
}
#[ test ]
fn tabs_8 ( ) {
bat ( )
. arg ( "tabs.txt" )
. arg ( "--tabs=8" )
. arg ( "--style=plain" )
. arg ( "--decorations=always" )
. assert ( )
. success ( )
. stdout (
" 1 2 3 4
1 ?
22 ?
333 ?
4444 ?
55555 ?
666666 ?
7777777 ?
88888888 ?
" ,
) ;
}
#[ test ]
fn tabs_4_env_overrides_config ( ) {
bat_with_config ( )
. env ( "BAT_CONFIG_PATH" , "bat-tabs.conf" )
. env ( "BAT_TABS" , "4" )
. arg ( "tabs.txt" )
. arg ( "--style=plain" )
. arg ( "--decorations=always" )
. assert ( )
. success ( )
. stdout (
" 1 2 3 4
1 ?
22 ?
333 ?
4444 ?
55555 ?
666666 ?
7777777 ?
88888888 ?
" ,
) ;
}
#[ test ]
fn tabs_4_arg_overrides_env ( ) {
bat_with_config ( )
. env ( "BAT_CONFIG_PATH" , "bat-tabs.conf" )
. env ( "BAT_TABS" , "6" )
. arg ( "tabs.txt" )
. arg ( "--tabs=4" )
. arg ( "--style=plain" )
. arg ( "--decorations=always" )
. assert ( )
. success ( )
. stdout (
" 1 2 3 4
1 ?
22 ?
333 ?
4444 ?
55555 ?
666666 ?
7777777 ?
88888888 ?
" ,
) ;
}
#[ test ]
fn tabs_4_arg_overrides_env_noconfig ( ) {
bat ( )
. env ( "BAT_TABS" , "6" )
. arg ( "tabs.txt" )
. arg ( "--tabs=4" )
. arg ( "--style=plain" )
. arg ( "--decorations=always" )
. assert ( )
. success ( )
. stdout (
" 1 2 3 4
1 ?
22 ?
333 ?
4444 ?
55555 ?
666666 ?
7777777 ?
88888888 ?
" ,
) ;
}
#[ test ]
fn fail_non_existing ( ) {
bat ( ) . arg ( "non-existing-file" ) . assert ( ) . failure ( ) ;
}
#[ test ]
fn fail_directory ( ) {
bat ( ) . arg ( "sub_directory" ) . assert ( ) . failure ( ) ;
}
#[ test ]
fn do_not_exit_directory ( ) {
bat ( )
. arg ( "sub_directory" )
. arg ( "test.txt" )
. assert ( )
. stdout ( "hello world\n" )
. failure ( ) ;
}
#[ test ]
#[ serial ]
fn pager_basic ( ) {
mocked_pagers ::with_mocked_versions_of_more_and_most_in_path ( | | {
bat ( )
. env ( "PAGER" , mocked_pagers ::from ( "echo pager-output" ) )
. arg ( "--paging=always" )
. arg ( "test.txt" )
. assert ( )
. success ( )
. stdout ( predicate ::str ::contains ( "pager-output\n" ) . normalize ( ) ) ;
} ) ;
}
#[ test ]
#[ serial ]
fn pager_basic_arg ( ) {
mocked_pagers ::with_mocked_versions_of_more_and_most_in_path ( | | {
bat ( )
. arg ( format! (
"--pager={}" ,
mocked_pagers ::from ( "echo pager-output" )
) )
. arg ( "--paging=always" )
. arg ( "test.txt" )
. assert ( )
. success ( )
. stdout ( predicate ::str ::contains ( "pager-output\n" ) . normalize ( ) ) ;
} ) ;
}
#[ test ]
#[ serial ]
fn pager_overwrite ( ) {
mocked_pagers ::with_mocked_versions_of_more_and_most_in_path ( | | {
bat ( )
. env ( "PAGER" , mocked_pagers ::from ( "echo other-pager" ) )
. env ( "BAT_PAGER" , mocked_pagers ::from ( "echo pager-output" ) )
. arg ( "--paging=always" )
. arg ( "test.txt" )
. assert ( )
. success ( )
. stdout ( predicate ::str ::contains ( "pager-output\n" ) . normalize ( ) ) ;
} ) ;
}
#[ test ]
fn pager_disable ( ) {
bat ( )
. env ( "PAGER" , "echo other-pager" )
. env ( "BAT_PAGER" , "" )
. arg ( "--paging=always" )
. arg ( "test.txt" )
. assert ( )
. success ( )
. stdout ( predicate ::eq ( "hello world\n" ) . normalize ( ) ) ;
}
#[ test ]
#[ serial ]
fn pager_arg_override_env_withconfig ( ) {
mocked_pagers ::with_mocked_versions_of_more_and_most_in_path ( | | {
bat_with_config ( )
. env ( "BAT_CONFIG_PATH" , get_config ( ) )
. env ( "PAGER" , mocked_pagers ::from ( "echo another-pager" ) )
. env ( "BAT_PAGER" , mocked_pagers ::from ( "echo other-pager" ) )
. arg ( format! (
"--pager={}" ,
mocked_pagers ::from ( "echo pager-output" )
) )
. arg ( "--paging=always" )
. arg ( "test.txt" )
. assert ( )
. success ( )
. stdout ( predicate ::str ::contains ( "pager-output\n" ) . normalize ( ) ) ;
} ) ;
}
#[ test ]
#[ serial ]
fn pager_arg_override_env_noconfig ( ) {
mocked_pagers ::with_mocked_versions_of_more_and_most_in_path ( | | {
bat ( )
. env ( "PAGER" , mocked_pagers ::from ( "echo another-pager" ) )
. env ( "BAT_PAGER" , mocked_pagers ::from ( "echo other-pager" ) )
. arg ( format! (
"--pager={}" ,
mocked_pagers ::from ( "echo pager-output" )
) )
. arg ( "--paging=always" )
. arg ( "test.txt" )
. assert ( )
. success ( )
. stdout ( predicate ::str ::contains ( "pager-output\n" ) . normalize ( ) ) ;
} ) ;
}
#[ test ]
#[ serial ]
fn pager_env_bat_pager_override_config ( ) {
mocked_pagers ::with_mocked_versions_of_more_and_most_in_path ( | | {
bat_with_config ( )
. env ( "BAT_CONFIG_PATH" , get_config ( ) )
. env ( "PAGER" , mocked_pagers ::from ( "echo other-pager" ) )
. env ( "BAT_PAGER" , mocked_pagers ::from ( "echo pager-output" ) )
. arg ( "--paging=always" )
. arg ( "test.txt" )
. assert ( )
. success ( )
. stdout ( predicate ::str ::contains ( "pager-output\n" ) . normalize ( ) ) ;
} ) ;
}
#[ test ]
#[ serial ]
fn pager_env_pager_nooverride_config ( ) {
mocked_pagers ::with_mocked_versions_of_more_and_most_in_path ( | | {
bat_with_config ( )
. env ( "BAT_CONFIG_PATH" , get_config ( ) )
. env ( "PAGER" , mocked_pagers ::from ( "echo other-pager" ) )
. arg ( "--paging=always" )
. arg ( "test.txt" )
. assert ( )
. success ( )
. stdout ( predicate ::str ::contains ( "dummy-pager-from-config\n" ) . normalize ( ) ) ;
} ) ;
}
#[ test ]
fn env_var_pager_value_bat ( ) {
bat ( )
. env ( "PAGER" , "bat" )
. arg ( "--paging=always" )
. arg ( "test.txt" )
. assert ( )
. success ( )
. stdout ( predicate ::eq ( "hello world\n" ) . normalize ( ) ) ;
}
#[ test ]
fn env_var_bat_pager_value_bat ( ) {
bat ( )
. env ( "BAT_PAGER" , "bat" )
. arg ( "--paging=always" )
. arg ( "test.txt" )
. assert ( )
. failure ( )
. stderr ( predicate ::str ::contains ( "bat as a pager is disallowed" ) ) ;
}
#[ test ]
fn pager_value_bat ( ) {
bat ( )
. arg ( "--pager=bat" )
. arg ( "--paging=always" )
. arg ( "test.txt" )
. assert ( )
. failure ( )
. stderr ( predicate ::str ::contains ( "bat as a pager is disallowed" ) ) ;
}
/// We shall use less instead of most if PAGER is used since PAGER
/// is a generic env var
#[ test ]
#[ serial ] // Because of PATH
fn pager_most_from_pager_env_var ( ) {
mocked_pagers ::with_mocked_versions_of_more_and_most_in_path ( | | {
// If the output is not "I am most" then we know 'most' is not used
bat ( )
. env ( "PAGER" , mocked_pagers ::from ( "most" ) )
. arg ( "--paging=always" )
. arg ( "test.txt" )
. assert ( )
. success ( )
. stdout ( predicate ::eq ( "hello world\n" ) . normalize ( ) ) ;
} ) ;
}
/// If the bat-specific BAT_PAGER is used, obey the wish of the user
/// and allow 'most'
#[ test ]
#[ serial ] // Because of PATH
fn pager_most_from_bat_pager_env_var ( ) {
mocked_pagers ::with_mocked_versions_of_more_and_most_in_path ( | | {
bat ( )
. env ( "BAT_PAGER" , mocked_pagers ::from ( "most" ) )
. arg ( "--paging=always" )
. arg ( "test.txt" )
. assert ( )
. success ( )
. stdout ( predicate ::str ::contains ( "I am most" ) ) ;
} ) ;
}
/// Same reasoning with --pager as with BAT_PAGER
#[ test ]
#[ serial ] // Because of PATH
fn pager_most_from_pager_arg ( ) {
mocked_pagers ::with_mocked_versions_of_more_and_most_in_path ( | | {
bat ( )
. arg ( "--paging=always" )
. arg ( format! ( "--pager={}" , mocked_pagers ::from ( "most" ) ) )
. arg ( "test.txt" )
. assert ( )
. success ( )
. stdout ( predicate ::str ::contains ( "I am most" ) ) ;
} ) ;
}
/// Make sure the logic for 'most' applies even if an argument is passed
#[ test ]
#[ serial ] // Because of PATH
fn pager_most_with_arg ( ) {
mocked_pagers ::with_mocked_versions_of_more_and_most_in_path ( | | {
bat ( )
. env ( "PAGER" , format! ( "{} -w" , mocked_pagers ::from ( "most" ) ) )
. arg ( "--paging=always" )
. arg ( "test.txt" )
. assert ( )
. success ( )
. stdout ( predicate ::eq ( "hello world\n" ) . normalize ( ) ) ;
} ) ;
}
/// Sanity check that 'more' is treated like 'most'
#[ test ]
#[ serial ] // Because of PATH
fn pager_more ( ) {
mocked_pagers ::with_mocked_versions_of_more_and_most_in_path ( | | {
bat ( )
. env ( "PAGER" , mocked_pagers ::from ( "more" ) )
. arg ( "--paging=always" )
. arg ( "test.txt" )
. assert ( )
. success ( )
. stdout ( predicate ::eq ( "hello world\n" ) . normalize ( ) ) ;
} ) ;
}
#[ test ]
fn alias_pager_disable ( ) {
bat ( )
. env ( "PAGER" , "echo other-pager" )
. arg ( "-P" )
. arg ( "test.txt" )
. assert ( )
. success ( )
. stdout ( predicate ::eq ( "hello world\n" ) . normalize ( ) ) ;
}
#[ test ]
#[ serial ]
fn alias_pager_disable_long_overrides_short ( ) {
mocked_pagers ::with_mocked_versions_of_more_and_most_in_path ( | | {
bat ( )
. env ( "PAGER" , mocked_pagers ::from ( "echo pager-output" ) )
. arg ( "-P" )
. arg ( "--paging=always" )
. arg ( "test.txt" )
. assert ( )
. success ( )
. stdout ( predicate ::str ::contains ( "pager-output\n" ) . normalize ( ) ) ;
} ) ;
}
#[ test ]
fn disable_pager_if_disable_paging_flag_comes_after_paging ( ) {
bat ( )
. env ( "PAGER" , "echo pager-output" )
. arg ( "--paging=always" )
. arg ( "-P" )
. arg ( "test.txt" )
. assert ( )
. success ( )
. stdout ( predicate ::eq ( "hello world\n" ) . normalize ( ) ) ;
}
#[ test ]
fn disable_pager_if_pp_flag_comes_after_paging ( ) {
bat ( )
. env ( "PAGER" , "echo pager-output" )
. arg ( "--paging=always" )
. arg ( "-pp" )
. arg ( "test.txt" )
. assert ( )
. success ( )
. stdout ( predicate ::eq ( "hello world\n" ) . normalize ( ) ) ;
}
#[ test ]
fn enable_pager_if_disable_paging_flag_comes_before_paging ( ) {
bat ( )
. env ( "PAGER" , "echo pager-output" )
. arg ( "-P" )
. arg ( "--paging=always" )
. arg ( "test.txt" )
. assert ( )
. success ( )
. stdout ( predicate ::eq ( "pager-output\n" ) . normalize ( ) ) ;
}
#[ test ]
fn enable_pager_if_pp_flag_comes_before_paging ( ) {
bat ( )
. env ( "PAGER" , "echo pager-output" )
. arg ( "-pp" )
. arg ( "--paging=always" )
. arg ( "test.txt" )
. assert ( )
. success ( )
. stdout ( predicate ::eq ( "pager-output\n" ) . normalize ( ) ) ;
}
#[ test ]
fn pager_failed_to_parse ( ) {
bat ( )
. env ( "BAT_PAGER" , "mismatched-quotes 'a" )
. arg ( "--paging=always" )
. arg ( "test.txt" )
. assert ( )
. failure ( )
. stderr ( predicate ::str ::contains ( "Could not parse pager command" ) ) ;
}
#[ test ]
#[ serial ]
fn env_var_bat_paging ( ) {
mocked_pagers ::with_mocked_versions_of_more_and_most_in_path ( | | {
bat ( )
. env ( "BAT_PAGER" , mocked_pagers ::from ( "echo pager-output" ) )
. env ( "BAT_PAGING" , "always" )
. arg ( "test.txt" )
. assert ( )
. success ( )
. stdout ( predicate ::str ::contains ( "pager-output\n" ) . normalize ( ) ) ;
} ) ;
}
#[ test ]
fn basic_set_terminal_title ( ) {
bat ( )
. arg ( "--paging=always" )
. arg ( "--set-terminal-title" )
. arg ( "test.txt" )
. assert ( )
. success ( )
. stdout ( "\u{1b}]0;bat: test.txt\x07hello world\n" )
. stderr ( "" ) ;
}
#[ test ]
fn diagnostic_sanity_check ( ) {
bat ( )
. arg ( "--diagnostic" )
. assert ( )
. success ( )
. stdout ( predicate ::str ::contains ( "BAT_PAGER=" ) )
. stderr ( "" ) ;
}
#[ test ]
fn config_location_test ( ) {
bat_with_config ( )
. env ( "BAT_CONFIG_PATH" , "bat.conf" )
. arg ( "--config-file" )
. assert ( )
. success ( )
. stdout ( "bat.conf\n" ) ;
bat_with_config ( )
. env ( "BAT_CONFIG_PATH" , "not-existing.conf" )
. arg ( "--config-file" )
. assert ( )
. success ( )
. stdout ( "not-existing.conf\n" ) ;
}
#[ test ]
fn config_location_when_generating ( ) {
let tmp_dir = tempdir ( ) . expect ( "can create temporary directory" ) ;
let tmp_config_path = tmp_dir . path ( ) . join ( "should-be-created.conf" ) ;
// Create the file with bat
bat_with_config ( )
. env ( "BAT_CONFIG_PATH" , tmp_config_path . to_str ( ) . unwrap ( ) )
. arg ( "--generate-config-file" )
. assert ( )
. success ( )
. stdout (
predicate ::str ::is_match ( "Success! Config file written to .*should-be-created.conf\n" )
. unwrap ( ) ,
) ;
// Now we expect the file to exist. If it exists, we assume contents are correct
assert! ( tmp_config_path . exists ( ) ) ;
}
#[ test ]
fn config_location_from_bat_config_dir_variable ( ) {
bat_with_config ( )
. env ( "BAT_CONFIG_DIR" , "conf/" )
. arg ( "--config-file" )
. assert ( )
. success ( )
. stdout ( predicate ::str ::is_match ( "conf/config\n" ) . unwrap ( ) ) ;
}
#[ test ]
#[ serial ]
fn config_read_arguments_from_file ( ) {
mocked_pagers ::with_mocked_versions_of_more_and_most_in_path ( | | {
bat_with_config ( )
. env ( "BAT_CONFIG_PATH" , get_config ( ) )
. arg ( "test.txt" )
. assert ( )
. success ( )
. stdout ( predicate ::str ::contains ( "dummy-pager-from-config\n" ) . normalize ( ) ) ;
} ) ;
}
#[ cfg(unix) ]
#[ test ]
fn cache_clear ( ) {
let src_dir = "cache_source" ;
let tmp_dir = tempdir ( ) . expect ( "can create temporary directory" ) ;
let themes_filename = "themes.bin" ;
let syntaxes_filename = "syntaxes.bin" ;
let metadata_filename = "metadata.yaml" ;
[ themes_filename , syntaxes_filename , metadata_filename ]
. iter ( )
. map ( | filename | {
let fp = tmp_dir . path ( ) . join ( filename ) ;
let mut file = File ::create ( fp ) . expect ( "can create temporary file" ) ;
writeln! ( file , "dummy content" ) . expect ( "can write to file" ) ;
} )
. count ( ) ;
// Clear the targeted cache
// Include the BAT_CONFIG_PATH and BAT_THEME environment variables to ensure that
// options loaded from a config or the environment are not inserted
// before the cache subcommand, which would break it.
bat_with_config ( )
. current_dir ( Path ::new ( EXAMPLES_DIR ) . join ( src_dir ) )
. env ( "BAT_CONFIG_PATH" , "bat.conf" )
. env ( "BAT_THEME" , "1337" )
. arg ( "cache" )
. arg ( "--clear" )
. arg ( "--source" )
. arg ( "." )
. arg ( "--target" )
. arg ( tmp_dir . path ( ) . to_str ( ) . unwrap ( ) )
. assert ( )
. success ( )
. stdout (
predicate ::str ::is_match (
" Clearing theme set cache .. . okay
Clearing syntax set cache .. . okay
Clearing metadata file .. . okay " ,
)
. unwrap ( ) ,
) ;
// We expect these files to be removed
assert! ( ! tmp_dir . path ( ) . join ( themes_filename ) . exists ( ) ) ;
assert! ( ! tmp_dir . path ( ) . join ( syntaxes_filename ) . exists ( ) ) ;
assert! ( ! tmp_dir . path ( ) . join ( metadata_filename ) . exists ( ) ) ;
}
#[ cfg(unix) ]
#[ test ]
fn cache_build ( ) {
let src_dir = "cache_source" ;
let tmp_dir = tempdir ( ) . expect ( "can create temporary directory" ) ;
let tmp_themes_path = tmp_dir . path ( ) . join ( "themes.bin" ) ;
let tmp_syntaxes_path = tmp_dir . path ( ) . join ( "syntaxes.bin" ) ;
let tmp_acknowledgements_path = tmp_dir . path ( ) . join ( "acknowledgements.bin" ) ;
let tmp_metadata_path = tmp_dir . path ( ) . join ( "metadata.yaml" ) ;
// Build the cache
// Include the BAT_CONFIG_PATH and BAT_THEME environment variables to ensure that
// options loaded from a config or the environment are not inserted
// before the cache subcommand, which would break it.
bat_with_config ( )
. current_dir ( Path ::new ( EXAMPLES_DIR ) . join ( src_dir ) )
. env ( "BAT_CONFIG_PATH" , "bat.conf" )
. env ( "BAT_THEME" , "1337" )
. arg ( "cache" )
. arg ( "--build" )
. arg ( "--blank" )
. arg ( "--source" )
. arg ( "." )
. arg ( "--target" )
. arg ( tmp_dir . path ( ) . to_str ( ) . unwrap ( ) )
. arg ( "--acknowledgements" )
. assert ( )
. success ( )
. stdout (
predicate ::str ::is_match (
" Writing theme set to . * / themes . bin .. . okay
Writing syntax set to . * / syntaxes . bin .. . okay
Writing acknowledgements to . * / acknowledgements . bin .. . okay
Writing metadata to folder . * .. . okay " ,
)
. unwrap ( ) ,
) ;
// Now we expect the files to exist. If they exist, we assume contents are correct
assert! ( tmp_themes_path . exists ( ) ) ;
assert! ( tmp_syntaxes_path . exists ( ) ) ;
assert! ( tmp_acknowledgements_path . exists ( ) ) ;
assert! ( tmp_metadata_path . exists ( ) ) ;
}
#[ test ]
fn utf16 ( ) {
// The output will be converted to UTF-8 with the leading UTF-16
// BOM removed. This behavior is wanted in interactive mode as
// some terminals seem to display the BOM character as a space,
// and it also breaks syntax highlighting.
bat ( )
. arg ( "--plain" )
. arg ( "--decorations=always" )
. arg ( "test_UTF-16LE.txt" )
. assert ( )
. success ( )
. stdout ( "hello world\n" ) ;
}
// Regression test for https://github.com/sharkdp/bat/issues/1922
#[ test ]
fn bom_not_stripped_in_loop_through_mode ( ) {
bat ( )
. arg ( "--plain" )
. arg ( "--decorations=never" )
. arg ( "--color=never" )
. arg ( "test_BOM.txt" )
. assert ( )
. success ( )
. stdout ( "\u{feff}hello world\n" ) ;
}
// Regression test for https://github.com/sharkdp/bat/issues/1922
#[ test ]
fn bom_stripped_when_colored_output ( ) {
bat ( )
. arg ( "--color=always" )
. arg ( "--decorations=never" )
. arg ( "test_BOM.txt" )
. assert ( )
. success ( )
. stdout (
predicate ::str ::is_match ( "\u{1b}\\[38;5;[0-9]{3}mhello world\u{1b}\\[0m\n" ) . unwrap ( ) ,
) ;
}
// Regression test for https://github.com/sharkdp/bat/issues/1922
#[ test ]
fn bom_stripped_when_no_color_and_not_loop_through ( ) {
bat ( )
. arg ( "--color=never" )
. arg ( "--decorations=always" )
. arg ( "--style=numbers,grid,header" )
. arg ( "--terminal-width=80" )
. arg ( "test_BOM.txt" )
. assert ( )
. success ( )
. stdout (
" \
─ ─ ─ ─ ─ ┬ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─
│ File : test_BOM . txt
─ ─ ─ ─ ─ ┼ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─
1 │ hello world
─ ─ ─ ─ ─ ┴ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─
" ,
) ;
}
// Regression test for https://github.com/sharkdp/bat/issues/2541
#[ test ]
fn no_broken_osc_emit_with_line_wrapping ( ) {
bat ( )
. arg ( "--color=always" )
. arg ( "--decorations=never" )
. arg ( "--wrap=character" )
. arg ( "--terminal-width=40" )
. arg ( "regression_tests/issue_2541.txt" )
. assert ( )
. success ( )
. stdout ( predicate ::function ( | s : & str | s . lines ( ) . count ( ) = = 1 ) ) ;
}
#[ test ]
fn can_print_file_named_cache ( ) {
bat_with_config ( )
. arg ( "cache" )
. assert ( )
. success ( )
. stdout ( "test\n" )
. stderr ( "" ) ;
}
#[ test ]
fn can_print_file_named_cache_with_additional_argument ( ) {
bat_with_config ( )
. arg ( "cache" )
. arg ( "test.txt" )
. assert ( )
. success ( )
. stdout ( "test\nhello world\n" )
. stderr ( "" ) ;
}
#[ test ]
fn can_print_file_starting_with_cache ( ) {
bat_with_config ( )
. arg ( "cache.c" )
. assert ( )
. success ( )
. stdout ( "test\n" )
. stderr ( "" ) ;
}
#[ test ]
fn does_not_print_unwanted_file_named_cache ( ) {
bat_with_config ( ) . arg ( "cach" ) . assert ( ) . failure ( ) ;
}
#[ test ]
fn accepts_no_custom_assets_arg ( ) {
// Just make sure --no-custom-assets is considered a valid arg
// Don't bother to actually verify that it works
bat ( )
. arg ( "--no-custom-assets" )
. arg ( "test.txt" )
. assert ( )
. success ( ) ;
}
#[ test ]
fn unicode_wrap ( ) {
bat_with_config ( )
. arg ( "unicode-wrap.txt" )
. arg ( "--style=numbers,snip" )
. arg ( "--decorations=always" )
. arg ( "--terminal-width=40" )
. assert ( )
. success ( )
. stdout (
" 1 ビ タ ミ ン A ビ タ ミ ン D ビ タ ミ ン E ビ
タ ミ ン K ビ タ ミ ン B1 ビ タ ミ ン B2 ナ
イ ア シ ン パ ン ト テ ン 酸 ビ タ ミ ン B6
ビ タ ミ ン B12 葉 酸 ビ オ チ ン ビ タ
ミ ン C
2
3 고 양 이 고 양 이 고 양 이 고 양 이 고 양 이
고 양 이 고 양 이 고 양 이 고 양 이 고 양 이
고 양 이 고 양 이 고 양 이 고 양 이 고 양 이
고 양 이 고 양 이 고 양 이 고 양 이 고 양 이
고 양 이 고 양 이 고 양 이 고 양 이 고 양 이
고 양 이 고 양 이 고 양 이 고 양 이 고 양 이
고 양 이 고 양 이 고 양 이 고 양 이 고 양 이
고 양 이 고 양 이 고 양 이 고 양 이 고 양 이
고 양 이
4
5 1 บ ว ก 2 บ ว ก 3 บ ว ก 4 บ ว ก 5 บ ว ก 6 บ ว ก
7 บ ว ก 8 บ ว ก 9 บ ว ก 10 บ ว ก 11 บ ว ก 12
บ ว ก 13 บ ว ก 14 บ ว ก 15 บ ว ก 16 บ ว ก 17
บ ว ก 18 บ ว ก 19 บ ว ก 20
6
7 Б е л ь г и я Б о л г а р и я Ч е х и я Д а н и я Г е р м а н
и я Э с т о н и я И р л а н д и я Г р е ц и я И с п а н и я
Ф р а н ц и я Х о р в а т и я И т а л и я К и п р Л а т в и я
Л и т в а Л ю к с е м б у р г В е н г р и я М а л ь т а Н и
д е р л а н д ы А в с т р и я П о л ь ш а П о р т у г а л и я
Р у м ы н и я С л о в е н и я С л о в а к и я Ф и н л я н д и я
Ш в е ц и я В е л и к о б р и т а н и я
" ,
) ;
}
#[ test ]
fn snip ( ) {
bat ( )
. arg ( "multiline.txt" )
. arg ( "--style=numbers,snip" )
. arg ( "--decorations=always" )
. arg ( "--line-range=1:2" )
. arg ( "--line-range=4:" )
. arg ( "--terminal-width=80" )
. assert ( )
. success ( )
. stdout (
" 1 line 1
2 line 2
.. . ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ 8 < ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─
4 line 4
" ,
) ;
}
#[ test ]
fn empty_file_leads_to_empty_output_with_grid_enabled ( ) {
bat ( )
. arg ( "empty.txt" )
. arg ( "--style=grid" )
. arg ( "--decorations=always" )
. arg ( "--terminal-width=80" )
. assert ( )
. success ( )
. stdout ( "" ) ;
}
#[ test ]
fn empty_file_leads_to_empty_output_with_rule_enabled ( ) {
bat ( )
. arg ( "empty.txt" )
. arg ( "--style=rule" )
. arg ( "--decorations=always" )
. arg ( "--terminal-width=80" )
. assert ( )
. success ( )
. stdout ( "" ) ;
}
#[ test ]
fn header_basic ( ) {
bat ( )
. arg ( "test.txt" )
. arg ( "--decorations=always" )
. arg ( "--style=header" )
. arg ( "-r=0:0" )
. arg ( "--file-name=foo" )
. assert ( )
. success ( )
. stdout ( "File: foo\n" )
. stderr ( "" ) ;
}
#[ test ]
fn header_full_basic ( ) {
bat ( )
. arg ( "test.txt" )
. arg ( "--decorations=always" )
. arg ( "--style=header-filename,header-filesize" )
. arg ( "-r=0:0" )
. arg ( "--file-name=foo" )
. assert ( )
. success ( )
. stdout ( "File: foo\nSize: 12 B\n" )
. stderr ( "" ) ;
}
#[ test ]
fn header_env_basic ( ) {
bat_with_config ( )
. env ( "BAT_STYLE" , "header-filename,header-filesize" )
. arg ( "test.txt" )
. arg ( "--decorations=always" )
. arg ( "-r=0:0" )
. arg ( "--file-name=foo" )
. assert ( )
. success ( )
. stdout ( "File: foo\nSize: 12 B\n" )
. stderr ( "" ) ;
}
#[ test ]
fn header_arg_overrides_env ( ) {
bat_with_config ( )
. env ( "BAT_STYLE" , "header-filesize" )
. arg ( "test.txt" )
. arg ( "--decorations=always" )
. arg ( "--style=header-filename" )
. arg ( "-r=0:0" )
. arg ( "--file-name=foo" )
. assert ( )
. success ( )
. stdout ( "File: foo\n" )
. stderr ( "" ) ;
}
#[ test ]
fn header_binary ( ) {
bat ( )
. arg ( "test.binary" )
. arg ( "--decorations=always" )
. arg ( "--style=header" )
. arg ( "-r=0:0" )
. arg ( "--file-name=foo" )
. assert ( )
. success ( )
. stdout ( "File: foo <BINARY>\n" )
. stderr ( "" ) ;
}
#[ test ]
fn header_full_binary ( ) {
bat ( )
. arg ( "test.binary" )
. arg ( "--decorations=always" )
. arg ( "--style=header-filename,header-filesize" )
. arg ( "-r=0:0" )
. arg ( "--file-name=foo" )
. assert ( )
. success ( )
. stdout ( "File: foo <BINARY>\nSize: 4 B\n" )
. stderr ( "" ) ;
}
#[ test ]
#[ cfg(not(feature = " git " )) ]
fn header_narrow_terminal ( ) {
bat ( )
. arg ( "--terminal-width=30" )
. arg ( "--decorations=always" )
. arg ( "this-file-path-is-really-long-and-would-have-broken-the-layout-of-the-header.txt" )
. assert ( )
. success ( )
. stdout (
" \
─ ─ ─ ─ ─ ┬ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─
│ File : this - file - path - is
│ - really - long - and - would -
│ have - broken - the - layout -
│ of - the - header . txt
─ ─ ─ ─ ─ ┼ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─
1 │ The header is not broke
│ n
─ ─ ─ ─ ─ ┴ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─
" ,
)
. stderr ( "" ) ;
}
#[ test ]
fn header_very_narrow_terminal ( ) {
bat ( )
. arg ( "--terminal-width=10" )
. arg ( "--decorations=always" )
. arg ( "this-file-path-is-really-long-and-would-have-broken-the-layout-of-the-header.txt" )
. assert ( )
. success ( )
. stdout (
" \
─ ─ ─ ─ ─ ─ ─ ─ ─ ─
File : this
- file - path
- is - really
- long - and -
would - have
- broken - th
e - layout - o
f - the - head
er . txt
─ ─ ─ ─ ─ ─ ─ ─ ─ ─
The header
is not br
oken
─ ─ ─ ─ ─ ─ ─ ─ ─ ─
" ,
)
. stderr ( "" ) ;
}
#[ test ]
#[ cfg(feature = " git " ) ] // Expected output assumes git is enabled
fn header_default ( ) {
bat ( )
. arg ( "--paging=never" )
. arg ( "--color=never" )
. arg ( "--terminal-width=80" )
. arg ( "--wrap=never" )
. arg ( "--decorations=always" )
. arg ( "--style=default" )
. arg ( "single-line.txt" )
. assert ( )
. success ( )
. stdout (
" \
─ ─ ─ ─ ─ ─ ─ ┬ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─
│ File : single - line . txt
─ ─ ─ ─ ─ ─ ─ ┼ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─
1 │ Single Line
─ ─ ─ ─ ─ ─ ─ ┴ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─
" ,
)
. stderr ( "" ) ;
}
#[ test ]
#[ cfg(feature = " git " ) ] // Expected output assumes git is enabled
fn header_default_is_default ( ) {
bat ( )
. arg ( "--paging=never" )
. arg ( "--color=never" )
. arg ( "--terminal-width=80" )
. arg ( "--wrap=never" )
. arg ( "--decorations=always" )
. arg ( "single-line.txt" )
. assert ( )
. success ( )
. stdout (
" \
─ ─ ─ ─ ─ ─ ─ ┬ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─
│ File : single - line . txt
─ ─ ─ ─ ─ ─ ─ ┼ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─
1 │ Single Line
─ ─ ─ ─ ─ ─ ─ ┴ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─
" ,
)
. stderr ( "" ) ;
}
#[ test ]
fn filename_stdin ( ) {
bat ( )
. arg ( "--decorations=always" )
. arg ( "--style=header" )
. arg ( "-r=0:0" )
. arg ( "-" )
. write_stdin ( "stdin\n" )
. arg ( "--file-name=foo" )
. assert ( )
. success ( )
. stdout ( "File: foo\n" )
. stderr ( "" ) ;
}
#[ test ]
fn filename_stdin_binary ( ) {
let vec = vec! [ 0 ; 1 ] ;
bat_with_config ( )
. arg ( "--decorations=always" )
. arg ( "--style=header" )
. write_stdin ( vec )
. arg ( "--file-name=foo" )
. assert ( )
. success ( )
. stdout ( "File: foo <BINARY>\n" )
. stderr ( "" ) ;
}
#[ test ]
fn filename_multiple_ok ( ) {
bat ( )
. arg ( "--decorations=always" )
. arg ( "--style=header" )
. arg ( "-r=0:0" )
. arg ( "test.txt" )
. arg ( "--file-name=foo" )
. arg ( "single-line.txt" )
. arg ( "--file-name=bar" )
. assert ( )
. success ( )
. stdout ( "File: foo\n\nFile: bar\n" )
. stderr ( "" ) ;
}
#[ test ]
fn filename_multiple_err ( ) {
bat ( )
. arg ( "--decorations=always" )
. arg ( "--style=header" )
. arg ( "-r=0:0" )
. arg ( "test.txt" )
. arg ( "--file-name=foo" )
. arg ( "single-line.txt" )
. assert ( )
. failure ( ) ;
}
#[ test ]
fn header_padding ( ) {
bat ( )
. arg ( "--decorations=always" )
. arg ( "--style=header" )
. arg ( "test.txt" )
. arg ( "single-line.txt" )
. assert ( )
. stdout ( "File: test.txt\nhello world\n\nFile: single-line.txt\nSingle Line\n" )
. stderr ( "" ) ;
}
#[ test ]
fn header_full_padding ( ) {
bat ( )
. arg ( "--decorations=always" )
. arg ( "--style=header-filename,header-filesize" )
. arg ( "test.txt" )
. arg ( "single-line.txt" )
. assert ( )
. stdout ( "File: test.txt\nSize: 12 B\nhello world\n\nFile: single-line.txt\nSize: 11 B\nSingle Line\n" )
. stderr ( "" ) ;
}
#[ test ]
fn header_padding_rule ( ) {
bat ( )
. arg ( "--decorations=always" )
. arg ( "--style=header,rule" )
. arg ( "--terminal-width=80" )
. arg ( "test.txt" )
. arg ( "single-line.txt" )
. assert ( )
. stdout (
" File : test . txt
hello world
─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─
File : single - line . txt
Single Line
" ,
)
. stderr ( "" ) ;
}
#[ test ]
fn header_full_padding_rule ( ) {
bat ( )
. arg ( "--decorations=always" )
. arg ( "--style=header-filename,header-filesize,rule" )
. arg ( "--terminal-width=80" )
. arg ( "test.txt" )
. arg ( "single-line.txt" )
. assert ( )
. stdout (
" File : test . txt
Size : 12 B
hello world
─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─
File : single - line . txt
Size : 11 B
Single Line
" ,
)
. stderr ( "" ) ;
}
#[ test ]
fn grid_overrides_rule ( ) {
bat ( )
. arg ( "--decorations=always" )
. arg ( "--style=grid,rule" )
. arg ( "--terminal-width=80" )
. arg ( "test.txt" )
. arg ( "single-line.txt" )
. assert ( )
. stdout (
" \
─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─
hello world
─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─
─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─
Single Line
─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─
" ,
)
. stderr (
"\x1b[33m[bat warning]\x1b[0m: Style 'rule' is a subset of style 'grid', 'rule' will not be visible.\n" ,
) ;
}
#[ cfg(target_os = " linux " ) ]
#[ test ]
fn file_with_invalid_utf8_filename ( ) {
use std ::ffi ::OsStr ;
use std ::fs ::File ;
use std ::io ::Write ;
use std ::os ::unix ::ffi ::OsStrExt ;
let tmp_dir = tempdir ( ) . expect ( "can create temporary directory" ) ;
let file_path = tmp_dir
. path ( )
. join ( OsStr ::from_bytes ( b" test-invalid-utf8- \xC3 (.rs " ) ) ;
{
let mut file = File ::create ( & file_path ) . expect ( "can create temporary file" ) ;
writeln! ( file , "dummy content" ) . expect ( "can write to file" ) ;
}
bat ( )
. arg ( file_path . as_os_str ( ) )
. assert ( )
. success ( )
. stdout ( "dummy content\n" ) ;
}
#[ test ]
fn do_not_panic_regression_tests ( ) {
for filename in & [
"issue_28.md" ,
"issue_190.md" ,
"issue_314.hs" ,
"issue_914.rb" ,
"issue_915.vue" ,
] {
bat ( )
. arg ( "--color=always" )
. arg ( & format! ( "regression_tests/{filename}" ) )
. assert ( )
. success ( ) ;
}
}
#[ test ]
fn do_not_detect_different_syntax_for_stdin_and_files ( ) {
let file = "regression_tests/issue_985.js" ;
let cmd_for_file = bat ( )
. arg ( "--color=always" )
. arg ( "--map-syntax=*.js:Markdown" )
. arg ( & format! ( "--file-name={file}" ) )
. arg ( "--style=plain" )
. arg ( file )
. assert ( )
. success ( ) ;
let cmd_for_stdin = bat ( )
. arg ( "--color=always" )
. arg ( "--map-syntax=*.js:Markdown" )
. arg ( "--style=plain" )
. arg ( & format! ( "--file-name={file}" ) )
. pipe_stdin ( Path ::new ( EXAMPLES_DIR ) . join ( file ) )
. unwrap ( )
. assert ( )
. success ( ) ;
assert_eq! (
from_utf8 ( & cmd_for_file . get_output ( ) . stdout ) . expect ( "output is valid utf-8" ) ,
from_utf8 ( & cmd_for_stdin . get_output ( ) . stdout ) . expect ( "output is valid utf-8" )
) ;
}
#[ test ]
fn no_first_line_fallback_when_mapping_to_invalid_syntax ( ) {
let file = "regression_tests/first_line_fallback.invalid-syntax" ;
bat ( )
. arg ( "--color=always" )
. arg ( "--map-syntax=*.invalid-syntax:InvalidSyntax" )
. arg ( & format! ( "--file-name={file}" ) )
. arg ( "--style=plain" )
. arg ( file )
. assert ( )
. failure ( )
. stderr ( predicate ::str ::contains ( "unknown syntax: 'InvalidSyntax'" ) ) ;
}
#[ test ]
fn show_all_mode ( ) {
bat ( )
. arg ( "--show-all" )
. arg ( "nonprintable.txt" )
. assert ( )
. stdout ( "hello·world␊\n├──┤␍␀␇␈␛" )
. stderr ( "" ) ;
}
#[ test ]
fn show_all_extends_tab_markers_to_next_tabstop ( ) {
bat ( )
. arg ( "tabs.txt" )
. arg ( "--show-all" )
. arg ( "--tabs=4" )
. arg ( "--style=plain" )
. assert ( )
. success ( )
. stdout (
" ├ ─ ─ ┤ 1 ├ ─ ┤ 2 ├ ─ ┤ 3 ├ ─ ┤ 4 ␊
1 ├ ─ ┤ ? ␊
22 ├ ┤ ? ␊
333 ↹ ? ␊
4444 ├ ─ ─ ┤ ? ␊
55555 ├ ─ ┤ ? ␊
666666 ├ ┤ ? ␊
7777777 ↹ ? ␊
88888888 ├ ─ ─ ┤ ? ␊
" ,
) ;
}
#[ test ]
fn show_all_extends_tab_markers_to_next_tabstop_width_8 ( ) {
bat ( )
. arg ( "tabs.txt" )
. arg ( "--show-all" )
. arg ( "--tabs=8" )
. arg ( "--style=plain" )
. assert ( )
. success ( )
. stdout (
" ├ ─ ─ ─ ─ ─ ─ ┤ 1 ├ ─ ─ ─ ─ ─ ┤ 2 ├ ─ ─ ─ ─ ─ ┤ 3 ├ ─ ─ ─ ─ ─ ┤ 4 ␊
1 ├ ─ ─ ─ ─ ─ ┤ ? ␊
22 ├ ─ ─ ─ ─ ┤ ? ␊
333 ├ ─ ─ ─ ┤ ? ␊
4444 ├ ─ ─ ┤ ? ␊
55555 ├ ─ ┤ ? ␊
666666 ├ ┤ ? ␊
7777777 ↹ ? ␊
88888888 ├ ─ ─ ─ ─ ─ ─ ┤ ? ␊
" ,
) ;
}
#[ test ]
fn show_all_with_caret_notation ( ) {
bat ( )
. arg ( "--show-all" )
. arg ( "--nonprintable-notation=caret" )
. arg ( "nonprintable.txt" )
. assert ( )
. stdout ( "hello·world^J\n├──┤^M^@^G^H^[" )
. stderr ( "" ) ;
bat ( )
. arg ( "--show-all" )
. arg ( "--nonprintable-notation=caret" )
. arg ( "control_characters.txt" )
. assert ( )
. stdout ( "^@^A^B^C^D^E^F^G^H├─┤^J\n^K^L^M^N^O^P^Q^R^S^T^U^V^W^X^Y^Z^[^\\^]^^^_^?" )
. stderr ( "" ) ;
}
#[ test ]
fn show_all_with_unicode ( ) {
bat ( )
. arg ( "--show-all" )
. arg ( "--nonprintable-notation=unicode" )
. arg ( "control_characters.txt" )
. assert ( )
. stdout ( "␀␁␂␃␄␅␆␇␈├─┤␊\n␋␌␍␎␏␐␑␒␓␔␕␖␗␘␙␚␛␜␝␞␟␡" )
. stderr ( "" ) ;
}
#[ test ]
fn no_paging_arg ( ) {
bat ( )
. arg ( "--no-paging" )
. arg ( "--color=never" )
. arg ( "--decorations=never" )
. arg ( "single-line.txt" )
. assert ( )
. success ( )
. stdout ( "Single Line" ) ;
}
#[ test ]
fn no_paging_short_arg ( ) {
bat ( )
. arg ( "-P" )
. arg ( "--color=never" )
. arg ( "--decorations=never" )
. arg ( "single-line.txt" )
. assert ( )
. success ( )
. stdout ( "Single Line" ) ;
}
#[ test ]
fn no_pager_arg ( ) {
bat ( )
. arg ( "--no-pager" )
. arg ( "--color=never" )
. arg ( "--decorations=never" )
. arg ( "single-line.txt" )
. assert ( )
. success ( )
. stdout ( "Single Line" ) ;
}
#[ test ]
fn plain_mode_does_not_add_nonexisting_newline ( ) {
bat ( )
. arg ( "--paging=never" )
. arg ( "--color=never" )
. arg ( "--decorations=always" )
. arg ( "--style=plain" )
. arg ( "single-line.txt" )
. assert ( )
. success ( )
. stdout ( "Single Line" ) ;
}
// Regression test for https://github.com/sharkdp/bat/issues/299
#[ test ]
#[ cfg(feature = " git " ) ] // Expected output assumes git is enabled
fn grid_for_file_without_newline ( ) {
bat ( )
. arg ( "--paging=never" )
. arg ( "--color=never" )
. arg ( "--terminal-width=80" )
. arg ( "--wrap=never" )
. arg ( "--decorations=always" )
. arg ( "--style=full" )
. arg ( "single-line.txt" )
. assert ( )
. success ( )
. stdout (
" \
─ ─ ─ ─ ─ ─ ─ ┬ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─
│ File : single - line . txt
│ Size : 11 B
─ ─ ─ ─ ─ ─ ─ ┼ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─
1 │ Single Line
─ ─ ─ ─ ─ ─ ─ ┴ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─
" ,
)
. stderr ( "" ) ;
}
// For ANSI theme, use underscore as a highlighter
#[ test ]
fn ansi_highlight_underline ( ) {
bat ( )
. arg ( "--paging=never" )
. arg ( "--color=never" )
. arg ( "--terminal-width=80" )
. arg ( "--wrap=never" )
. arg ( "--decorations=always" )
. arg ( "--theme=ansi" )
. arg ( "--style=plain" )
. arg ( "--highlight-line=1" )
. write_stdin ( "Ansi Underscore Test\nAnother Line" )
. assert ( )
. success ( )
. stdout ( "\x1B[4mAnsi Underscore Test\n\x1B[24mAnother Line" )
. stderr ( "" ) ;
}
// Ensure that ANSI passthrough is emitted properly for both wrapping and non-wrapping printer.
// See https://github.com/sharkdp/bat/issues/2307 for what common use case this test tests.
#[ test ]
fn ansi_passthrough_emit ( ) {
for wrapping in & [ "never" , "character" ] {
bat ( )
. arg ( "--paging=never" )
. arg ( "--color=never" )
. arg ( "--terminal-width=80" )
. arg ( format! ( "--wrap={wrapping}" ) )
. arg ( "--decorations=always" )
. arg ( "--style=plain" )
. write_stdin ( "\x1B[33mColor\nColor \x1B[m\nPlain\n" )
. assert ( )
. success ( )
. stdout ( "\x1B[33m\x1B[33mColor\n\x1B[33mColor \x1B[m\nPlain\n" )
. stderr ( "" ) ;
}
}
// Ensure that a simple ANSI sequence passthrough is emitted properly on wrapped lines.
// This also helps ensure that escape sequences are counted as part of the visible characters when wrapping.
#[ test ]
fn ansi_sgr_emitted_when_wrapped ( ) {
bat ( )
. arg ( "--paging=never" )
. arg ( "--color=never" )
. arg ( "--terminal-width=20" )
. arg ( "--wrap=character" )
. arg ( "--decorations=always" )
. arg ( "--style=plain" )
. write_stdin ( "\x1B[33mColor...............Also color.\n" )
. assert ( )
. success ( )
. stdout ( "\x1B[33m\x1B[33mColor...............\n\x1B[33mAlso color.\n" )
// FIXME: ~~~~~~~~ should not be emitted twice.
. stderr ( "" ) ;
}
// Ensure that a simple ANSI sequence passthrough is emitted properly on wrapped lines.
// This also helps ensure that escape sequences are counted as part of the visible characters when wrapping.
#[ test ]
fn ansi_hyperlink_emitted_when_wrapped ( ) {
bat ( )
. arg ( "--paging=never" )
. arg ( "--color=never" )
. arg ( "--terminal-width=20" )
. arg ( "--wrap=character" )
. arg ( "--decorations=always" )
. arg ( "--style=plain" )
. write_stdin ( "\x1B]8;;http://example.com/\x1B\\Hyperlinks..........Wrap across lines.\n" )
. assert ( )
. success ( )
. stdout ( "\x1B]8;;http://example.com/\x1B\\\x1B]8;;http://example.com/\x1B\\Hyperlinks..........\x1B]8;;\x1B\\\n\x1B]8;;http://example.com/\x1B\\Wrap across lines.\n" )
// FIXME: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ should not be emitted twice.
. stderr ( "" ) ;
}
// Ensure that multiple ANSI sequence SGR attributes are combined when emitted on wrapped lines.
#[ test ]
fn ansi_sgr_joins_attributes_when_wrapped ( ) {
bat ( )
. arg ( "--paging=never" )
. arg ( "--color=never" )
. arg ( "--terminal-width=20" )
. arg ( "--wrap=character" )
. arg ( "--decorations=always" )
. arg ( "--style=plain" )
. write_stdin ( "\x1B[33mColor. \x1B[1mBold.........Also bold and color.\n" )
. assert ( )
. success ( )
. stdout ( "\x1B[33m\x1B[33mColor. \x1B[1m\x1B[33m\x1B[1mBold.........\n\x1B[33m\x1B[1mAlso bold and color.\n" )
// FIXME: ~~~~~~~~ ~~~~~~~~~~~~~~~ should not be emitted twice.
. stderr ( "" ) ;
}
#[ test ]
fn ignored_suffix_arg ( ) {
bat ( )
. arg ( "-f" )
. arg ( "--theme" )
. arg ( "Monokai Extended" )
. arg ( "-p" )
. arg ( "test.json~" )
. assert ( )
. success ( )
. stdout ( "\u{1b}[38;5;231m{\u{1b}[0m\u{1b}[38;5;208m\"\u{1b}[0m\u{1b}[38;5;208mtest\u{1b}[0m\u{1b}[38;5;208m\"\u{1b}[0m\u{1b}[38;5;231m:\u{1b}[0m\u{1b}[38;5;231m \u{1b}[0m\u{1b}[38;5;186m\"\u{1b}[0m\u{1b}[38;5;186mvalue\u{1b}[0m\u{1b}[38;5;186m\"\u{1b}[0m\u{1b}[38;5;231m}\u{1b}[0m" )
. stderr ( "" ) ;
bat ( )
. arg ( "-f" )
. arg ( "--theme" )
. arg ( "Monokai Extended" )
. arg ( "-p" )
. arg ( "--ignored-suffix=.suffix" )
. arg ( "test.json.suffix" )
. assert ( )
. success ( )
. stdout ( "\u{1b}[38;5;231m{\u{1b}[0m\u{1b}[38;5;208m\"\u{1b}[0m\u{1b}[38;5;208mtest\u{1b}[0m\u{1b}[38;5;208m\"\u{1b}[0m\u{1b}[38;5;231m:\u{1b}[0m\u{1b}[38;5;231m \u{1b}[0m\u{1b}[38;5;186m\"\u{1b}[0m\u{1b}[38;5;186mvalue\u{1b}[0m\u{1b}[38;5;186m\"\u{1b}[0m\u{1b}[38;5;231m}\u{1b}[0m" )
. stderr ( "" ) ;
bat ( )
. arg ( "-f" )
. arg ( "--theme" )
. arg ( "Monokai Extended" )
. arg ( "-p" )
. arg ( "test.json.suffix" )
. assert ( )
. success ( )
. stdout ( "\u{1b}[38;5;231m{\"test\": \"value\"}\u{1b}[0m" )
. stderr ( "" ) ;
}
fn wrapping_test ( wrap_flag : & str , expect_wrap : bool ) {
let expected = match expect_wrap {
true = >
"abcdefghigklmnopqrstuvxyzabcdefghigklmnopqrstuvxyzabcdefghigklmnopqrstuvxyzabcde\nfghigklmnopqrstuvxyz\n" ,
false = >
"abcdefghigklmnopqrstuvxyzabcdefghigklmnopqrstuvxyzabcdefghigklmnopqrstuvxyzabcdefghigklmnopqrstuvxyz\n" ,
} ;
bat ( )
. arg ( wrap_flag )
. arg ( "--style=rule" )
. arg ( "--color=never" )
. arg ( "--decorations=always" )
. arg ( "--terminal-width=80" )
. arg ( "long-single-line.txt" )
. assert ( )
. success ( )
. stdout ( expected . to_owned ( ) )
. stderr ( "" ) ;
}
#[ test ]
fn no_line_wrapping_when_set_to_never ( ) {
wrapping_test ( "--wrap=never" , false ) ;
}
#[ test ]
fn line_wrapping_when_auto ( ) {
wrapping_test ( "--wrap=auto" , true ) ;
}
#[ test ]
fn no_line_wrapping_with_s_flag ( ) {
wrapping_test ( "-S" , false ) ;
}
#[ test ]
fn no_wrapping_with_chop_long_lines ( ) {
wrapping_test ( "--chop-long-lines" , false ) ;
}
#[ test ]
fn theme_arg_overrides_env ( ) {
bat ( )
. env ( "BAT_THEME" , "TwoDark" )
. arg ( "--paging=never" )
. arg ( "--color=never" )
. arg ( "--terminal-width=80" )
. arg ( "--wrap=never" )
. arg ( "--decorations=always" )
. arg ( "--theme=ansi" )
. arg ( "--style=plain" )
. arg ( "--highlight-line=1" )
. write_stdin ( "Ansi Underscore Test\nAnother Line" )
. assert ( )
. success ( )
. stdout ( "\x1B[4mAnsi Underscore Test\n\x1B[24mAnother Line" )
. stderr ( "" ) ;
}
#[ test ]
fn theme_arg_overrides_env_withconfig ( ) {
bat_with_config ( )
. env ( "BAT_CONFIG_PATH" , "bat-theme.conf" )
. env ( "BAT_THEME" , "TwoDark" )
. arg ( "--paging=never" )
. arg ( "--color=never" )
. arg ( "--terminal-width=80" )
. arg ( "--wrap=never" )
. arg ( "--decorations=always" )
. arg ( "--theme=ansi" )
. arg ( "--style=plain" )
. arg ( "--highlight-line=1" )
. write_stdin ( "Ansi Underscore Test\nAnother Line" )
. assert ( )
. success ( )
. stdout ( "\x1B[4mAnsi Underscore Test\n\x1B[24mAnother Line" )
. stderr ( "" ) ;
}
#[ test ]
fn theme_env_overrides_config ( ) {
bat_with_config ( )
. env ( "BAT_CONFIG_PATH" , "bat-theme.conf" )
. env ( "BAT_THEME" , "ansi" )
. arg ( "--paging=never" )
. arg ( "--color=never" )
. arg ( "--terminal-width=80" )
. arg ( "--wrap=never" )
. arg ( "--decorations=always" )
. arg ( "--style=plain" )
. arg ( "--highlight-line=1" )
. write_stdin ( "Ansi Underscore Test\nAnother Line" )
. assert ( )
. success ( )
. stdout ( "\x1B[4mAnsi Underscore Test\n\x1B[24mAnother Line" )
. stderr ( "" ) ;
}
#[ test ]
fn highlighting_is_skipped_on_long_lines ( ) {
let expected = "\u{1b}[38;5;231m{\u{1b}[0m\u{1b}[38;5;208m\"\u{1b}[0m\u{1b}[38;5;208mapi\u{1b}[0m\u{1b}[38;5;208m\"\u{1b}[0m\u{1b}[38;5;231m:\u{1b}[0m\n" . to_owned ( ) +
"\u{1b}" +
r #"[38;5;231m {" ANGLE_instanced_arrays ":{" __compat ":{" mdn_url ":" https ://developer.mozilla.org/docs/Web/API/ANGLE_instanced_arrays","spec_url":"https://www.khronos.org/registry/webgl/extensions/ANGLE_instanced_arrays/","support":{"chrome":{"version_added":"32"},"chrome_android":{"version_added":"32"},"edge":{"version_added":"12"},"firefox":{"version_added":"47"},"firefox_android":{"version_added":true},"ie":{"version_added":"11"},"opera":{"version_added":"19"},"opera_android":{"version_added":"19"},"safari":{"version_added":"8"},"safari_ios":{"version_added":"8"},"samsunginternet_android":{"version_added":"2.0"},"webview_android":{"version_added":"4.4"}},"status":{"experimental":false,"standard_track":true,"deprecated":false}},"drawArraysInstancedANGLE":{"__compat":{"mdn_url":"https://developer.mozilla.org/docs/Web/API/ANGLE_instanced_arrays/drawArraysInstancedANGLE","spec_url":"https://www.khronos.org/registry/webgl/extensions/ANGLE_instanced_arrays/","support":{"chrome":{"version_added":"32"},"chrome_android":{"version_added":"32"},"edge":{"version_added":"12"},"firefox":{"version_added":"47"},"firefox_android":{"version_added":true},"ie":{"version_added":"11"},"opera":{"version_added":"19"},"opera_android":{"version_added":"19"},"safari":{"version_added":"8"},"safari_ios":{"version_added":"8"},"samsunginternet_android":{"version_added":"2.0"},"webview_android":{"version_added":"4.4"}},"status":{"experimental":false,"standard_track":true,"deprecated":false}}},"drawElementsInstancedANGLE":{"__compat":{"mdn_url":"https://developer.mozilla.org/docs/Web/API/ANGLE_instanced_arrays/drawElementsInstancedANGLE","spec_url":"https://www.khronos.org/registry/webgl/extensions/ANGLE_instanced_arrays/","support":{"chrome":{"version_added":"32"},"chrome_android":{"version_added":"32"},"edge":{"version_added":"12"},"firefox":{"version_added":"47"},"firefox_android":{"version_added":true},"ie":{"version_added":"11"},"opera":{"version_added":"19"},"opera_android":{"version_added":"19"},"safari":{"version_added":"8"},"safari_ios":{"version_added":"8"},"samsunginternet_android":{"version_added":"2.0"},"webview_android":{"version_added":"4.4"}},"status":{"experimental":false,"standard_track":true,"deprecated":false}}},"vertexAttribDivisorANGLE":{"__compat":{"mdn_url":"https://developer.mozilla.org/docs/Web/API/ANGLE_instanced_arrays/vertexAttribDivisorANGLE","spec_url":"https://www.khronos.org/registry/webgl/extensions/ANGLE_instanced_arrays/","support":{"chrome":{"version_added":"32"},"chrome_android":{"version_added":"32"},"edge":{"version_added":"12"},"firefox":{"version_added":"47"},"firefox_android":{"version_added":true},"ie":{"version_added":"11"},"opera":{"version_added":"19"},"opera_android":{"version_added":"19"},"safari":{"version_added":"8"},"safari_ios":{"version_added":"8"},"samsunginternet_android":{"version_added":"2.0"},"webview_android":{"version_added":"4.4"}},"status":{"experimental":false,"standard_track":true,"deprecated":false}}}},"AbortController":{"__compat":{"mdn_url":"https://developer.mozilla.org/docs/Web/API/AbortController","spec_url":"https://dom.spec.whatwg.org/#interface-abortcontroller","support":{"chrome":{"version_added":"66"},"chrome_android":{"version_added":"66"},"edge":{"version_added":"16"},"firefox":{"version_added":"57"},"firefox_android":{"version_added":"57"},"ie":{"version_added":false},"nodejs":{"version_added":"15.0.0"},"opera":{"version_added":"53"},"opera_android":{"version_added":"47"},"safari":[{"version_added":"12.1"},{"version_added":"11.1","partial_implementation":true,"notes":"Even though <code>window.AbortController</code> is defined, it doesn't really abort <code>fetch</code> requests. See <a href='https://webkit.org/b/174980'>bug 174980</a>."}],"safari_ios":[{"version_added":"12.2"},{"version_added":"11.3","partial_implementation":true,"notes":"Even though <code>window.AbortController</code> is defined, it doesn't really abort <code>fetch</code> requests. See <a href='https://webkit.org/b/174980'>bug 174980</a>."}],"samsunginternet_android":{"version_added":"9.0"},"webvi
"\u{1b}[0m\n\u{1b}[38;5;231m \u{1b}[0m\u{1b}[38;5;231m{\u{1b}[0m\u{1b}[38;5;208m\"\u{1b}[0m\u{1b}[38;5;208mversion_added\u{1b}[0m\u{1b}[38;5;208m\"\u{1b}[0m\u{1b}[38;5;231m:\u{1b}[0m\u{1b}[38;5;141mfalse\u{1b}[0m\u{1b}[38;5;231m}\u{1b}[0m\n" ;
bat ( )
. arg ( "-f" )
. arg ( "--theme" )
. arg ( "Monokai Extended" )
. arg ( "-p" )
. arg ( "longline.json" )
. assert ( )
. success ( )
. stdout ( expected )
. stderr ( "" ) ;
}
#[ test ]
fn all_global_git_config_locations_syntax_mapping_work ( ) {
let fake_home = Path ::new ( EXAMPLES_DIR ) . join ( "git" ) . canonicalize ( ) . unwrap ( ) ;
let expected = " \ u { 1 b } [ 38 ; 5 ; 231 m [ \ u { 1 b } [ 0 m \ u { 1 b } [ 38 ; 5 ; 149 muser \ u { 1 b } [ 0 m \ u { 1 b } [ 38 ; 5 ; 231 m ] \ u { 1 b } [ 0 m
\ u { 1 b } [ 38 ; 5 ; 231 m \ u { 1 b } [ 0 m \ u { 1 b } [ 38 ; 5 ; 231 memail \ u { 1 b } [ 0 m \ u { 1 b } [ 38 ; 5 ; 231 m \ u { 1 b } [ 0 m \ u { 1 b } [ 38 ; 5 ; 203 m = \ u { 1 b } [ 0 m \ u { 1 b } [ 38 ; 5 ; 231 m \ u { 1 b } [ 0 m \ u { 1 b } [ 38 ; 5 ; 186 mfoo @ bar . net \ u { 1 b } [ 0 m
\ u { 1 b } [ 38 ; 5 ; 231 m \ u { 1 b } [ 0 m \ u { 1 b } [ 38 ; 5 ; 231 mname \ u { 1 b } [ 0 m \ u { 1 b } [ 38 ; 5 ; 231 m \ u { 1 b } [ 0 m \ u { 1 b } [ 38 ; 5 ; 203 m = \ u { 1 b } [ 0 m \ u { 1 b } [ 38 ; 5 ; 231 m \ u { 1 b } [ 0 m \ u { 1 b } [ 38 ; 5 ; 186 mfoobar \ u { 1 b } [ 0 m
" ;
bat ( )
. env ( "XDG_CONFIG_HOME" , fake_home . join ( ".config" ) . as_os_str ( ) )
. arg ( "-f" )
. arg ( "--theme" )
. arg ( "Monokai Extended" )
. arg ( "-p" )
. arg ( "git/.config/git/config" )
. assert ( )
. success ( )
. stdout ( expected )
. stderr ( "" ) ;
bat ( )
. env ( "HOME" , fake_home . as_os_str ( ) )
. arg ( "-f" )
. arg ( "--theme" )
. arg ( "Monokai Extended" )
. arg ( "-p" )
. arg ( "git/.config/git/config" )
. assert ( )
. success ( )
. stdout ( expected )
. stderr ( "" ) ;
bat ( )
. env ( "HOME" , fake_home . as_os_str ( ) )
. arg ( "-f" )
. arg ( "--theme" )
. arg ( "Monokai Extended" )
. arg ( "-p" )
. arg ( "git/.gitconfig" )
. assert ( )
. success ( )
. stdout ( expected )
. stderr ( "" ) ;
}
#[ test ]
fn map_syntax_and_ignored_suffix_work_together ( ) {
bat ( )
. arg ( "-f" )
. arg ( "--theme" )
. arg ( "Monokai Extended" )
. arg ( "-p" )
. arg ( "--ignored-suffix=.suffix" )
. arg ( "--map-syntax=*.demo:JSON" )
. arg ( "test.demo.suffix" )
. assert ( )
. success ( )
. stdout ( "\u{1b}[38;5;231m{\u{1b}[0m\u{1b}[38;5;208m\"\u{1b}[0m\u{1b}[38;5;208mtest\u{1b}[0m\u{1b}[38;5;208m\"\u{1b}[0m\u{1b}[38;5;231m:\u{1b}[0m\u{1b}[38;5;231m \u{1b}[0m\u{1b}[38;5;186m\"\u{1b}[0m\u{1b}[38;5;186mvalue\u{1b}[0m\u{1b}[38;5;186m\"\u{1b}[0m\u{1b}[38;5;231m}\u{1b}[0m" )
. stderr ( "" ) ;
bat ( )
. arg ( "-f" )
. arg ( "--theme" )
. arg ( "Monokai Extended" )
. arg ( "-p" )
. arg ( "--ignored-suffix=.suffix" )
. arg ( "--ignored-suffix=.foo" )
. arg ( "--map-syntax=*.demo:JSON" )
. arg ( "test.demo.foo.suffix" )
. assert ( )
. success ( )
. stdout ( "\u{1b}[38;5;231m{\u{1b}[0m\u{1b}[38;5;208m\"\u{1b}[0m\u{1b}[38;5;208mtest\u{1b}[0m\u{1b}[38;5;208m\"\u{1b}[0m\u{1b}[38;5;231m:\u{1b}[0m\u{1b}[38;5;231m \u{1b}[0m\u{1b}[38;5;186m\"\u{1b}[0m\u{1b}[38;5;186mvalue\u{1b}[0m\u{1b}[38;5;186m\"\u{1b}[0m\u{1b}[38;5;231m}\u{1b}[0m" )
. stderr ( "" ) ;
}
#[ test ]
fn acknowledgements ( ) {
bat ( )
. arg ( "--acknowledgements" )
. assert ( )
. success ( )
. stdout (
// Just some sanity checking that avoids names of persons, except our own Keith Hall :)
predicate ::str ::contains (
"Copyright (c) 2018-2021 bat-developers (https://github.com/sharkdp/bat)." ,
)
. and ( predicate ::str ::contains (
"Copyright (c) 2012-2020 The Sublime CMake authors" ,
) )
. and ( predicate ::str ::contains (
"Copyright 2014-2015 SaltStack Team" ,
) )
. and ( predicate ::str ::contains (
"Copyright (c) 2013-present Dracula Theme" ,
) )
. and ( predicate ::str ::contains (
"## syntaxes/01_Packages/Rust/LICENSE.txt" ,
) )
. and ( predicate ::str ::contains (
"## syntaxes/02_Extra/http-request-response/LICENSE" ,
) )
. and ( predicate ::str ::contains (
"## themes/dracula-sublime/LICENSE" ,
) )
. and ( predicate ::str ::contains ( "Copyright (c) 2017 b123400" ) )
. and ( predicate ::str ::contains ( "Copyright (c) 2021 Keith Hall" ) )
. and ( predicate ::str ::contains ( "Copyright 2014 Clams" ) ) ,
)
. stderr ( "" ) ;
}
#[ cfg(unix) ] // Expected output assumed that tests are run on a Unix-like system
#[ cfg(feature = " lessopen " ) ]
#[ test ]
fn lessopen_file_piped ( ) {
bat ( )
. env ( "LESSOPEN" , "|echo File is %s" )
. arg ( "--lessopen" )
. arg ( "test.txt" )
. assert ( )
. success ( )
. stdout ( "File is test.txt\n" ) ;
}
#[ cfg(unix) ] // Expected output assumed that tests are run on a Unix-like system
#[ cfg(feature = " lessopen " ) ]
#[ test ]
fn lessopen_stdin_piped ( ) {
bat ( )
. env ( "LESSOPEN" , "|cat" )
. arg ( "--lessopen" )
. write_stdin ( "hello world\n" )
. assert ( )
. success ( )
. stdout ( "hello world\n" ) ;
}
#[ cfg(unix) ] // Expected output assumed that tests are run on a Unix-like system
#[ cfg(feature = " lessopen " ) ]
#[ test ]
#[ serial ] // Randomly fails otherwise
fn lessopen_and_lessclose_file_temp ( ) {
// This is mainly to test that $LESSCLOSE gets passed the correct file paths
// In this case, the original file and the temporary file returned by $LESSOPEN
bat ( )
// Need a %s for $LESSOPEN to be valid
. env ( "LESSOPEN" , "echo empty.txt && echo %s >/dev/null" )
. env ( "LESSCLOSE" , "echo lessclose: %s %s" )
. arg ( "--lessopen" )
. arg ( "test.txt" )
. assert ( )
. success ( )
. stdout ( "lessclose: test.txt empty.txt\n" ) ;
}
#[ cfg(unix) ] // Expected output assumed that tests are run on a Unix-like system
#[ cfg(feature = " lessopen " ) ]
#[ test ]
#[ serial ] // Randomly fails otherwise
fn lessopen_and_lessclose_file_piped ( ) {
// This is mainly to test that $LESSCLOSE gets passed the correct file paths
// In these cases, the original file and a dash
bat ( )
// This test will not work properly if $LESSOPEN does not output anything
. env ( "LESSOPEN" , "|cat %s" )
. env ( "LESSCLOSE" , "echo lessclose: %s %s" )
. arg ( "--lessopen" )
. arg ( "test.txt" )
. assert ( )
. success ( )
. stdout ( "hello world\nlessclose: test.txt -\n" ) ;
bat ( )
. env ( "LESSOPEN" , "||cat %s" )
. env ( "LESSCLOSE" , "echo lessclose: %s %s" )
. arg ( "--lessopen" )
. arg ( "empty.txt" )
. assert ( )
. success ( )
. stdout ( "lessclose: empty.txt -\n" ) ;
}
#[ cfg(unix) ] // Expected output assumed that tests are run on a Unix-like system
#[ cfg(feature = " lessopen " ) ]
#[ test ]
#[ serial ] // Randomly fails otherwise
#[ ignore = " randomly failing on some systems " ]
fn lessopen_and_lessclose_stdin_temp ( ) {
// This is mainly to test that $LESSCLOSE gets passed the correct file paths
// In this case, a dash and the temporary file returned by $LESSOPEN
bat ( )
// Need a %s for $LESSOPEN to be valid
. env ( "LESSOPEN" , "-echo empty.txt && echo %s >/dev/null" )
. env ( "LESSCLOSE" , "echo lessclose: %s %s" )
. arg ( "--lessopen" )
. write_stdin ( "test.txt" )
. assert ( )
. success ( )
. stdout ( "lessclose: - empty.txt\n" ) ;
}
#[ cfg(unix) ] // Expected output assumed that tests are run on a Unix-like system
#[ cfg(feature = " lessopen " ) ]
#[ test ]
#[ serial ] // Randomly fails otherwise
fn lessopen_and_lessclose_stdin_piped ( ) {
// This is mainly to test that $LESSCLOSE gets passed the correct file paths
// In these cases, two dashes
bat ( )
// This test will not work properly if $LESSOPEN does not output anything
// Need a %s for $LESSOPEN to be valid
. env ( "LESSOPEN" , "|-cat test.txt && echo %s >/dev/null" )
. env ( "LESSCLOSE" , "echo lessclose: %s %s" )
. arg ( "--lessopen" )
. write_stdin ( "empty.txt" )
. assert ( )
. success ( )
. stdout ( "hello world\nlessclose: - -\n" ) ;
bat ( )
// Need a %s for $LESSOPEN to be valid
. env ( "LESSOPEN" , "||-cat empty.txt && echo %s >/dev/null" )
. env ( "LESSCLOSE" , "echo lessclose: %s %s" )
. arg ( "--lessopen" )
. write_stdin ( "empty.txt" )
. assert ( )
. success ( )
. stdout ( "lessclose: - -\n" ) ;
}
#[ cfg(unix) ] // Expected output assumed that tests are run on a Unix-like system
#[ cfg(feature = " lessopen " ) ]
#[ test ]
fn lessopen_handling_empty_output_file ( ) {
bat ( )
// Need a %s for $LESSOPEN to be valid
. env ( "LESSOPEN" , "|cat empty.txt && echo %s >/dev/null" )
. arg ( "--lessopen" )
. arg ( "test.txt" )
. assert ( )
. success ( )
. stdout ( "hello world\n" ) ;
bat ( )
// Need a %s for $LESSOPEN to be valid
. env ( "LESSOPEN" , "|cat nonexistent.txt && echo %s >/dev/null" )
. arg ( "--lessopen" )
. arg ( "test.txt" )
. assert ( )
. success ( )
. stdout ( "hello world\n" ) ;
bat ( )
// Need a %s for $LESSOPEN to be valid
. env ( "LESSOPEN" , "||cat empty.txt && echo %s >/dev/null" )
. arg ( "--lessopen" )
. arg ( "test.txt" )
. assert ( )
. success ( )
. stdout ( "" ) ;
bat ( )
// Need a %s for $LESSOPEN to be valid
. env ( "LESSOPEN" , "||cat nonexistent.txt && echo %s >/dev/null" )
. arg ( "--lessopen" )
. arg ( "test.txt" )
. assert ( )
. success ( )
. stdout ( "hello world\n" ) ;
}
#[ cfg(unix) ] // Expected output assumed that tests are run on a Unix-like system
#[ cfg(feature = " lessopen " ) ]
#[ test ]
// FIXME
fn lessopen_handling_empty_output_stdin ( ) {
bat ( )
// Need a %s for $LESSOPEN to be valid
. env ( "LESSOPEN" , "|-cat empty.txt && echo %s >/dev/null" )
. arg ( "--lessopen" )
. write_stdin ( "hello world\n" )
. assert ( )
. success ( )
. stdout ( "hello world\n" ) ;
bat ( )
// Need a %s for $LESSOPEN to be valid
. env ( "LESSOPEN" , "|-cat nonexistent.txt && echo %s >/dev/null" )
. arg ( "--lessopen" )
. write_stdin ( "hello world\n" )
. assert ( )
. success ( )
. stdout ( "hello world\n" ) ;
bat ( )
// Need a %s for $LESSOPEN to be valid
. env ( "LESSOPEN" , "||-cat empty.txt && echo %s >/dev/null" )
. arg ( "--lessopen" )
. write_stdin ( "hello world\n" )
. assert ( )
. success ( )
. stdout ( "" ) ;
bat ( )
// Need a %s for $LESSOPEN to be valid
. env ( "LESSOPEN" , "||-cat nonexistent.txt && echo %s >/dev/null" )
. arg ( "--lessopen" )
. write_stdin ( "hello world\n" )
. assert ( )
. success ( )
. stdout ( "hello world\n" ) ;
}
#[ cfg(unix) ] // Expected output assumed that tests are run on a Unix-like system
#[ cfg(feature = " lessopen " ) ]
#[ test ]
fn lessopen_uses_shell ( ) {
bat ( )
. env ( "LESSOPEN" , "|cat < %s" )
. arg ( "--lessopen" )
. arg ( "test.txt" )
. assert ( )
. success ( )
. stdout ( "hello world\n" ) ;
}
#[ cfg(unix) ]
#[ cfg(feature = " lessopen " ) ]
#[ test ]
fn do_not_use_lessopen_by_default ( ) {
bat ( )
. env ( "LESSOPEN" , "|echo File is %s" )
. arg ( "test.txt" )
. assert ( )
. success ( )
. stdout ( "hello world\n" ) ;
}
#[ cfg(unix) ]
#[ cfg(feature = " lessopen " ) ]
#[ test ]
fn do_not_use_lessopen_if_overridden ( ) {
bat ( )
. env ( "LESSOPEN" , "|echo File is %s" )
. arg ( "--lessopen" )
. arg ( "--no-lessopen" )
. arg ( "test.txt" )
. assert ( )
. success ( )
. stdout ( "hello world\n" ) ;
}
#[ cfg(unix) ]
#[ cfg(feature = " lessopen " ) ]
#[ test ]
fn lessopen_validity ( ) {
bat ( )
. env ( "LESSOPEN" , "|echo File is test.txt" )
. arg ( "--lessopen" )
. arg ( "test.txt" )
. assert ( )
. success ( )
. stdout ( "hello world\n" )
. stderr (
"\u{1b}[33m[bat warning]\u{1b}[0m: LESSOPEN ignored: must contain exactly one %s\n" ,
) ;
bat ( )
. env ( "LESSOPEN" , "|echo File is %s" )
. arg ( "--lessopen" )
. arg ( "test.txt" )
. assert ( )
. success ( )
. stdout ( "File is test.txt\n" )
. stderr ( "" ) ;
bat ( )
. env ( "LESSOPEN" , "|echo %s is %s" )
. arg ( "--lessopen" )
. arg ( "test.txt" )
. assert ( )
. success ( )
. stdout ( "hello world\n" )
. stderr (
"\u{1b}[33m[bat warning]\u{1b}[0m: LESSOPEN ignored: must contain exactly one %s\n" ,
) ;
}
// Regression test for issue #2520 and PR #2650
// Syntax highlighting should be the same regardless of
// --map-syntax' case or file extension's case
#[ test ]
fn highlighting_independant_from_map_syntax_case ( ) {
let expected = bat ( )
. arg ( "-f" )
. arg ( "--map-syntax=*.config:JSON" )
. arg ( "map-syntax_case.Config" )
. assert ( )
. get_output ( )
. stdout
. clone ( ) ;
bat ( )
. arg ( "-f" )
. arg ( "--map-syntax=*.Config:JSON" )
. arg ( "map-syntax_case.Config" )
. assert ( )
. success ( )
. stdout ( expected )
. stderr ( "" ) ;
}