1use assert_cmd::Command;
2use predicates::{prelude::predicate, str::PredicateStrExt};
4use std::str::from_utf8;
6const EXAMPLES_DIR: &str = "tests/examples";
8fn bat_with_config() -> Command {
9 let mut cmd = Command::cargo_bin("bat").unwrap();
10 cmd.current_dir("tests/examples");
11 cmd.env_remove("PAGER");
12 cmd.env_remove("BAT_PAGER");
13 cmd.env_remove("BAT_CONFIG_PATH");
14 cmd.env_remove("BAT_STYLE");
15 cmd.env_remove("BAT_THEME");
16 cmd.env_remove("BAT_TABS");
21 let mut cmd = bat_with_config();
22 cmd.arg("--no-config");
32 .stdout("hello world\n")
39 .write_stdin("foo\nbar\n")
42 .stdout("foo\nbar\n");
52 .stdout("hello world\nhello world\n");
56fn concatenate_stdin() {
61 .write_stdin("stdin\n")
64 .stdout("hello world\nstdin\nhello world\n");
68fn concatenate_empty_first() {
74 .stdout("hello world\n");
78fn concatenate_empty_last() {
84 .stdout("hello world\n");
88fn concatenate_empty_both() {
98fn concatenate_empty_between() {
105 .stdout("hello world\nhello world\n");
109fn concatenate_empty_first_and_last() {
116 .stdout("hello world\n");
120fn concatenate_single_line() {
122 .arg("single-line.txt")
123 .arg("single-line.txt")
126 .stdout("Single LineSingle Line");
130fn concatenate_single_line_empty() {
132 .arg("single-line.txt")
134 .arg("single-line.txt")
137 .stdout("Single LineSingle Line");
143 .arg("multiline.txt")
144 .arg("--style=numbers")
145 .arg("--decorations=always")
148 .stdout(" 1 line 1\n 2 line 2\n 3 line 3\n 4 line 4\n");
154 .arg("multiline.txt")
155 .arg("--line-range=2:3")
158 .stdout("line 2\nline 3\n");
162fn line_range_first_two() {
164 .arg("multiline.txt")
165 .arg("--line-range=:2")
168 .stdout("line 1\nline 2\n");
172fn line_range_last_3() {
174 .arg("multiline.txt")
175 .arg("--line-range=2:")
178 .stdout("line 2\nline 3\nline 4\n");
182fn line_range_multiple() {
184 .arg("multiline.txt")
185 .arg("--line-range=1:2")
186 .arg("--line-range=4:4")
189 .stdout("line 1\nline 2\nline 4\n");
197 .arg("--style=numbers")
198 .arg("--decorations=always")
216fn tabs_passthrough_wrapped() {
220 .arg("--style=plain")
221 .arg("--decorations=always")
243 .arg("--style=plain")
244 .arg("--decorations=always")
266 .arg("--style=plain")
267 .arg("--decorations=always")
285fn tabs_passthrough() {
289 .arg("--style=plain")
290 .arg("--decorations=always")
312 .arg("--style=plain")
313 .arg("--decorations=always")
335 .arg("--style=plain")
336 .arg("--decorations=always")
354fn fail_non_existing() {
355 bat().arg("non-existing-file").assert().failure();
360 bat().arg("sub_directory").assert().failure();
364fn do_not_exit_directory() {
366 .arg("sub_directory")
369 .stdout("hello world\n")
376 .env("PAGER", "echo pager-output")
377 .arg("--paging=always")
381 .stdout(predicate::eq("pager-output\n").normalize());
385fn pager_overwrite() {
387 .env("PAGER", "echo other-pager")
388 .env("BAT_PAGER", "echo pager-output")
389 .arg("--paging=always")
393 .stdout(predicate::eq("pager-output\n").normalize());
399 .env("PAGER", "echo other-pager")
400 .env("BAT_PAGER", "")
401 .arg("--paging=always")
405 .stdout(predicate::eq("hello world\n").normalize());
409fn pager_value_bat() {
412 .arg("--paging=always")
419fn alias_pager_disable() {
421 .env("PAGER", "echo other-pager")
426 .stdout(predicate::eq("hello world\n").normalize());
430fn alias_pager_disable_long_overrides_short() {
432 .env("PAGER", "echo pager-output")
434 .arg("--paging=always")
438 .stdout(predicate::eq("pager-output\n").normalize());
442fn config_location_test() {
444 .env("BAT_CONFIG_PATH", "bat.conf")
445 .arg("--config-file")
448 .stdout("bat.conf\n");
452fn config_read_arguments_from_file() {
454 .env("BAT_CONFIG_PATH", "bat.conf")
458 .stdout(predicate::eq("dummy-pager-from-config\n").normalize());
463 // The output will be converted to UTF-8 with a leading UTF-8 BOM
466 .arg("--decorations=always")
467 .arg("test_UTF-16LE.txt")
470 .stdout(std::str::from_utf8(b"\xEF\xBB\xBFhello world\n").unwrap());
474fn can_print_file_named_cache() {
484fn can_print_file_named_cache_with_additional_argument() {
490 .stdout("test\nhello world\n")
495fn can_print_file_starting_with_cache() {
505fn does_not_print_unwanted_file_named_cache() {
506 bat_with_config().arg("cach").assert().failure();
512 .arg("unicode-wrap.txt")
513 .arg("--style=numbers,snip")
514 .arg("--decorations=always")
515 .arg("--terminal-width=40")
519 " 1 ビタミンA ビタミンD ビタミンE ビ
525 3 고양이 고양이 고양이 고양이 고양이
535 5 1 บวก 2 บวก 3 บวก 4 บวก 5 บวก 6 บวก
536 7 บวก 8 บวก 9 บวก 10 บวก 11 บวก 12
537 บวก 13 บวก 14 บวก 15 บวก 16 บวก 17
540 7 Бельгия Болгария Чехия Дания Герман
541 ия Эстония Ирландия Греция Испания
542 Франция Хорватия Италия Кипр Латвия
543 Литва Люксембург Венгрия Мальта Ни
544 дерланды Австрия Польша Португалия
545 Румыния Словения Словакия Финляндия
546 Швеция Великобритания
554 .arg("multiline.txt")
555 .arg("--style=numbers,snip")
556 .arg("--decorations=always")
557 .arg("--line-range=1:2")
558 .arg("--line-range=4:")
559 .arg("--terminal-width=80")
565 ...─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ 8< ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─
572fn empty_file_leads_to_empty_output_with_grid_enabled() {
576 .arg("--decorations=always")
577 .arg("--terminal-width=80")
584fn empty_file_leads_to_empty_output_with_rule_enabled() {
588 .arg("--decorations=always")
589 .arg("--terminal-width=80")
599 .arg("--decorations=always")
600 .arg("--style=header")
602 .arg("--file-name=foo")
605 .stdout("File: foo\n")
610fn filename_binary() {
613 .arg("--decorations=always")
614 .arg("--style=header")
616 .arg("--file-name=foo")
619 .stdout("File: foo <BINARY>\n")
626 .arg("--decorations=always")
627 .arg("--style=header")
630 .write_stdin("stdin\n")
631 .arg("--file-name=foo")
634 .stdout("File: foo\n")
639fn filename_stdin_binary() {
640 let vec = vec![0; 1];
642 .arg("--decorations=always")
643 .arg("--style=header")
645 .arg("--file-name=foo")
648 .stdout("File: foo <BINARY>\n")
653fn filename_multiple_ok() {
655 .arg("--decorations=always")
656 .arg("--style=header")
659 .arg("--file-name=foo")
660 .arg("single-line.txt")
661 .arg("--file-name=bar")
664 .stdout("File: foo\n\nFile: bar\n")
669fn filename_multiple_err() {
671 .arg("--decorations=always")
672 .arg("--style=header")
675 .arg("--file-name=foo")
676 .arg("single-line.txt")
684 .arg("--decorations=always")
685 .arg("--style=header")
687 .arg("single-line.txt")
689 .stdout("File: test.txt\nhello world\n\nFile: single-line.txt\nSingle Line\n")
694fn header_padding_rule() {
696 .arg("--decorations=always")
697 .arg("--style=header,rule")
698 .arg("--terminal-width=80")
700 .arg("single-line.txt")
705────────────────────────────────────────────────────────────────────────────────
714fn grid_overrides_rule() {
716 .arg("--decorations=always")
717 .arg("--style=grid,rule")
718 .arg("--terminal-width=80")
720 .arg("single-line.txt")
724────────────────────────────────────────────────────────────────────────────────
726────────────────────────────────────────────────────────────────────────────────
727────────────────────────────────────────────────────────────────────────────────
729────────────────────────────────────────────────────────────────────────────────
732 .stderr("\x1b[33m[bat warning]\x1b[0m: Style 'rule' is a subset of style 'grid', 'rule' will not be visible.\n");
735#[cfg(target_os = "linux")]
737fn file_with_invalid_utf8_filename() {
741 use std::os::unix::ffi::OsStrExt;
743 use tempdir::TempDir;
745 let tmp_dir = TempDir::new("bat_test").expect("can create temporary directory");
746 let file_path = tmp_dir
748 .join(OsStr::from_bytes(b"test-invalid-utf8-\xC3(.rs"));
750 let mut file = File::create(&file_path).expect("can create temporary file");
751 writeln!(file, "dummy content").expect("can write to file");
755 .arg(file_path.as_os_str())
758 .stdout("dummy content\n");
762fn do_not_panic_regression_tests() {
771 .arg("--color=always")
772 .arg(&format!("regression_tests/{}", filename))
779fn do_not_detect_different_syntax_for_stdin_and_files() {
780 let file = "regression_tests/issue_985.js";
782 let cmd_for_file = bat()
783 .arg("--color=always")
784 .arg("--map-syntax=*.js:Markdown")
785 .arg(&format!("--file-name={}", file))
786 .arg("--style=plain")
791 let cmd_for_stdin = bat()
792 .arg("--color=always")
793 .arg("--map-syntax=*.js:Markdown")
794 .arg("--style=plain")
795 .arg(&format!("--file-name={}", file))
796 .pipe_stdin(Path::new(EXAMPLES_DIR).join(file))
802 from_utf8(&cmd_for_file.get_output().stdout).expect("output is valid utf-8"),
803 from_utf8(&cmd_for_stdin.get_output().stdout).expect("output is valid utf-8")
811 .arg("nonprintable.txt")
813 .stdout("hello·world␊\n├──┤␍␀␇␈␛")
818fn plain_mode_does_not_add_nonexisting_newline() {
820 .arg("--paging=never")
821 .arg("--color=never")
822 .arg("--decorations=always")
823 .arg("--style=plain")
824 .arg("single-line.txt")
827 .stdout("Single Line");
830// Regression test for https://github.com/sharkdp/bat/issues/299
832fn grid_for_file_without_newline() {
834 .arg("--paging=never")
835 .arg("--color=never")
836 .arg("--terminal-width=80")
838 .arg("--decorations=always")
840 .arg("single-line.txt")
845───────┬────────────────────────────────────────────────────────────────────────
846 │ File: single-line.txt
847───────┼────────────────────────────────────────────────────────────────────────
849───────┴────────────────────────────────────────────────────────────────────────
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list