mirror of
https://github.com/sharkdp/bat.git
synced 2025-02-03 03:19:20 +01:00
Merge branch 'sharkdp:master' into master
This commit is contained in:
commit
03216c9c18
6
.github/dependabot.yml
vendored
6
.github/dependabot.yml
vendored
@ -16,3 +16,9 @@ updates:
|
|||||||
interval: monthly
|
interval: monthly
|
||||||
time: "04:00"
|
time: "04:00"
|
||||||
timezone: Europe/Berlin
|
timezone: Europe/Berlin
|
||||||
|
- package-ecosystem: "github-actions"
|
||||||
|
directory: "/"
|
||||||
|
schedule:
|
||||||
|
interval: monthly
|
||||||
|
time: "04:00"
|
||||||
|
timezone: Europe/Berlin
|
||||||
|
14
.github/workflows/CICD.yml
vendored
14
.github/workflows/CICD.yml
vendored
@ -24,14 +24,14 @@ jobs:
|
|||||||
default: true
|
default: true
|
||||||
profile: minimal
|
profile: minimal
|
||||||
components: rustfmt
|
components: rustfmt
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v3
|
||||||
- run: cargo fmt -- --check
|
- run: cargo fmt -- --check
|
||||||
|
|
||||||
license_checks:
|
license_checks:
|
||||||
name: License checks
|
name: License checks
|
||||||
runs-on: ubuntu-20.04
|
runs-on: ubuntu-20.04
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v3
|
||||||
with:
|
with:
|
||||||
submodules: true # we especially want to perform license checks on submodules
|
submodules: true # we especially want to perform license checks on submodules
|
||||||
- run: tests/scripts/license-checks.sh
|
- run: tests/scripts/license-checks.sh
|
||||||
@ -43,7 +43,7 @@ jobs:
|
|||||||
MSRV_FEATURES: --no-default-features --features minimal-application,bugreport,build-assets
|
MSRV_FEATURES: --no-default-features --features minimal-application,bugreport,build-assets
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout source code
|
- name: Checkout source code
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
- name: Install rust toolchain (v${{ env.MIN_SUPPORTED_RUST_VERSION }})
|
- name: Install rust toolchain (v${{ env.MIN_SUPPORTED_RUST_VERSION }})
|
||||||
uses: actions-rs/toolchain@v1
|
uses: actions-rs/toolchain@v1
|
||||||
@ -68,7 +68,7 @@ jobs:
|
|||||||
runs-on: ubuntu-20.04
|
runs-on: ubuntu-20.04
|
||||||
steps:
|
steps:
|
||||||
- name: Git checkout
|
- name: Git checkout
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v3
|
||||||
with:
|
with:
|
||||||
submodules: true # we need all syntax and theme submodules
|
submodules: true # we need all syntax and theme submodules
|
||||||
- name: Install Rust toolchain
|
- name: Install Rust toolchain
|
||||||
@ -113,7 +113,7 @@ jobs:
|
|||||||
runs-on: ubuntu-20.04
|
runs-on: ubuntu-20.04
|
||||||
steps:
|
steps:
|
||||||
- name: Git checkout
|
- name: Git checkout
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v3
|
||||||
- name: Prepare environment variables
|
- name: Prepare environment variables
|
||||||
run: |
|
run: |
|
||||||
echo "BAT_SYSTEM_CONFIG_PREFIX=$GITHUB_WORKSPACE/tests/examples/system_config" >> $GITHUB_ENV
|
echo "BAT_SYSTEM_CONFIG_PREFIX=$GITHUB_WORKSPACE/tests/examples/system_config" >> $GITHUB_ENV
|
||||||
@ -139,7 +139,7 @@ jobs:
|
|||||||
runs-on: ubuntu-20.04
|
runs-on: ubuntu-20.04
|
||||||
steps:
|
steps:
|
||||||
- name: Git checkout
|
- name: Git checkout
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v3
|
||||||
- name: Install Rust toolchain
|
- name: Install Rust toolchain
|
||||||
uses: actions-rs/toolchain@v1
|
uses: actions-rs/toolchain@v1
|
||||||
with:
|
with:
|
||||||
@ -186,7 +186,7 @@ jobs:
|
|||||||
- { target: x86_64-unknown-linux-musl , os: ubuntu-20.04, use-cross: true }
|
- { target: x86_64-unknown-linux-musl , os: ubuntu-20.04, use-cross: true }
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout source code
|
- name: Checkout source code
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
- name: Install prerequisites
|
- name: Install prerequisites
|
||||||
shell: bash
|
shell: bash
|
||||||
|
@ -13,6 +13,13 @@
|
|||||||
## `bat` as a library
|
## `bat` as a library
|
||||||
|
|
||||||
|
|
||||||
|
# v0.22.1
|
||||||
|
|
||||||
|
## Bugfixes
|
||||||
|
|
||||||
|
- Bring back pre-processing of ANSI escape characters to so that some common `bat` use cases starts working again. See #2308 (@Enselic)
|
||||||
|
|
||||||
|
|
||||||
# v0.22.0
|
# v0.22.0
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
36
Cargo.lock
generated
36
Cargo.lock
generated
@ -74,7 +74,7 @@ checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bat"
|
name = "bat"
|
||||||
version = "0.22.0"
|
version = "0.22.1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ansi_colours",
|
"ansi_colours",
|
||||||
"ansi_term",
|
"ansi_term",
|
||||||
@ -231,13 +231,13 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "console"
|
name = "console"
|
||||||
version = "0.15.1"
|
version = "0.15.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "89eab4d20ce20cea182308bca13088fecea9c05f6776cf287205d41a0ed3c847"
|
checksum = "c050367d967ced717c04b65d8c619d863ef9292ce0c5760028655a2fb298718c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"encode_unicode",
|
"encode_unicode",
|
||||||
|
"lazy_static",
|
||||||
"libc",
|
"libc",
|
||||||
"once_cell",
|
|
||||||
"terminal_size",
|
"terminal_size",
|
||||||
"unicode-width",
|
"unicode-width",
|
||||||
"winapi",
|
"winapi",
|
||||||
@ -699,9 +699,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "once_cell"
|
name = "once_cell"
|
||||||
version = "1.13.1"
|
version = "1.15.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "074864da206b4973b84eb91683020dbefd6a8c3f0f38e054d93954e891935e4e"
|
checksum = "e82dad04139b71a90c080c8463fe0dc7902db5192d939bd0950f074d014339e1"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "onig"
|
name = "onig"
|
||||||
@ -964,24 +964,24 @@ checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "semver"
|
name = "semver"
|
||||||
version = "1.0.13"
|
version = "1.0.14"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "93f6841e709003d68bb2deee8c343572bf446003ec20a583e76f7b15cebf3711"
|
checksum = "e25dfac463d778e353db5be2449d1cce89bd6fd23c9f1ea21310ce6e5a1b29c4"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde"
|
name = "serde"
|
||||||
version = "1.0.144"
|
version = "1.0.145"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0f747710de3dcd43b88c9168773254e809d8ddbdf9653b84e2554ab219f17860"
|
checksum = "728eb6351430bccb993660dfffc5a72f91ccc1295abaa8ce19b27ebe4f75568b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"serde_derive",
|
"serde_derive",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_derive"
|
name = "serde_derive"
|
||||||
version = "1.0.144"
|
version = "1.0.145"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "94ed3a816fb1d101812f83e789f888322c34e291f894f19590dc310963e87a00"
|
checksum = "81fa1584d3d1bcacd84c277a0dfe21f5b0f6accf4a23d04d4c6d61f1af522b4c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
@ -1160,18 +1160,18 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "thiserror"
|
name = "thiserror"
|
||||||
version = "1.0.33"
|
version = "1.0.37"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3d0a539a918745651435ac7db7a18761589a94cd7e94cd56999f828bf73c8a57"
|
checksum = "10deb33631e3c9018b9baf9dcbbc4f737320d2b576bac10f6aefa048fa407e3e"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"thiserror-impl",
|
"thiserror-impl",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "thiserror-impl"
|
name = "thiserror-impl"
|
||||||
version = "1.0.33"
|
version = "1.0.37"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c251e90f708e16c49a16f4917dc2131e75222b72edfa9cb7f7c58ae56aae0c09"
|
checksum = "982d17546b47146b28f7c22e3d08465f6b8903d0ea13c1660d9d84a6e7adcdbb"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
@ -1226,9 +1226,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unicode-width"
|
name = "unicode-width"
|
||||||
version = "0.1.9"
|
version = "0.1.10"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973"
|
checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "url"
|
name = "url"
|
||||||
|
@ -6,7 +6,7 @@ homepage = "https://github.com/sharkdp/bat"
|
|||||||
license = "MIT/Apache-2.0"
|
license = "MIT/Apache-2.0"
|
||||||
name = "bat"
|
name = "bat"
|
||||||
repository = "https://github.com/sharkdp/bat"
|
repository = "https://github.com/sharkdp/bat"
|
||||||
version = "0.22.0"
|
version = "0.22.1"
|
||||||
exclude = ["assets/syntaxes/*", "assets/themes/*"]
|
exclude = ["assets/syntaxes/*", "assets/themes/*"]
|
||||||
build = "build.rs"
|
build = "build.rs"
|
||||||
edition = '2018'
|
edition = '2018'
|
||||||
@ -44,15 +44,15 @@ atty = { version = "0.2.14", optional = true }
|
|||||||
ansi_term = "^0.12.1"
|
ansi_term = "^0.12.1"
|
||||||
ansi_colours = "^1.1"
|
ansi_colours = "^1.1"
|
||||||
bincode = "1.0"
|
bincode = "1.0"
|
||||||
console = "0.15.1"
|
console = "0.15.2"
|
||||||
flate2 = "1.0"
|
flate2 = "1.0"
|
||||||
once_cell = "1.13"
|
once_cell = "1.15"
|
||||||
thiserror = "1.0"
|
thiserror = "1.0"
|
||||||
wild = { version = "2.1", optional = true }
|
wild = { version = "2.1", optional = true }
|
||||||
content_inspector = "0.2.4"
|
content_inspector = "0.2.4"
|
||||||
encoding = "0.2"
|
encoding = "0.2"
|
||||||
shell-words = { version = "1.1.0", optional = true }
|
shell-words = { version = "1.1.0", optional = true }
|
||||||
unicode-width = "0.1.9"
|
unicode-width = "0.1.10"
|
||||||
globset = "0.4"
|
globset = "0.4"
|
||||||
serde = { version = "1.0", features = ["derive"] }
|
serde = { version = "1.0", features = ["derive"] }
|
||||||
serde_yaml = "0.8"
|
serde_yaml = "0.8"
|
||||||
|
116
assets/completions/bat.bash.in
vendored
116
assets/completions/bat.bash.in
vendored
@ -10,6 +10,27 @@ __bat_init_completion()
|
|||||||
_get_comp_words_by_ref "$@" cur prev words cword
|
_get_comp_words_by_ref "$@" cur prev words cword
|
||||||
}
|
}
|
||||||
|
|
||||||
|
__bat_escape_completions()
|
||||||
|
{
|
||||||
|
# Do not escape if completing a quoted value.
|
||||||
|
[[ $cur == [\"\']* ]] && return 0
|
||||||
|
# printf -v to an array index is available in bash >= 4.1.
|
||||||
|
# Use it if available, as -o filenames is semantically incorrect if
|
||||||
|
# we are not actually completing filenames, and it has side effects
|
||||||
|
# (e.g. adds trailing slash to candidates matching present dirs).
|
||||||
|
if ((
|
||||||
|
BASH_VERSINFO[0] > 4 || \
|
||||||
|
BASH_VERSINFO[0] == 4 && BASH_VERSINFO[1] > 0
|
||||||
|
)); then
|
||||||
|
local i
|
||||||
|
for i in ${!COMPREPLY[*]}; do
|
||||||
|
printf -v "COMPREPLY[i]" %q "${COMPREPLY[i]}"
|
||||||
|
done
|
||||||
|
else
|
||||||
|
compopt -o filenames
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
_bat() {
|
_bat() {
|
||||||
local cur prev words cword split=false
|
local cur prev words cword split=false
|
||||||
if declare -F _init_completion >/dev/null 2>&1; then
|
if declare -F _init_completion >/dev/null 2>&1; then
|
||||||
@ -27,7 +48,12 @@ _bat() {
|
|||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
COMPREPLY=($(compgen -W "
|
COMPREPLY=($(compgen -W "
|
||||||
--build --clear --source --target --blank --help
|
--build
|
||||||
|
--clear
|
||||||
|
--source
|
||||||
|
--target
|
||||||
|
--blank
|
||||||
|
--help
|
||||||
" -- "$cur"))
|
" -- "$cur"))
|
||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
@ -40,13 +66,26 @@ _bat() {
|
|||||||
printf "%s\n" "$lang"
|
printf "%s\n" "$lang"
|
||||||
done
|
done
|
||||||
)" -- "$cur"))
|
)" -- "$cur"))
|
||||||
compopt -o filenames # for escaping
|
__bat_escape_completions
|
||||||
return 0
|
return 0
|
||||||
;;
|
;;
|
||||||
-H | --highlight-line | --diff-context | --tabs | --terminal-width | \
|
-H | --highlight-line | \
|
||||||
-m | --map-syntax | --style | --line-range | -h | --help | -V | \
|
--diff-context | \
|
||||||
--version | --diagnostic | --config-file | --config-dir | \
|
--tabs | \
|
||||||
--cache-dir | --generate-config-file)
|
--terminal-width | \
|
||||||
|
-m | --map-syntax | \
|
||||||
|
--ignored-suffix | \
|
||||||
|
--list-themes | \
|
||||||
|
--line-range | \
|
||||||
|
-L | --list-languages | \
|
||||||
|
--diagnostic | \
|
||||||
|
--acknowledgements | \
|
||||||
|
-h | --help | \
|
||||||
|
-V | --version | \
|
||||||
|
--cache-dir | \
|
||||||
|
--config-dir | \
|
||||||
|
--config-file | \
|
||||||
|
--generate-config-file)
|
||||||
# argument required but no completion available, or option
|
# argument required but no completion available, or option
|
||||||
# causes an exit
|
# causes an exit
|
||||||
return 0
|
return 0
|
||||||
@ -74,22 +113,71 @@ _bat() {
|
|||||||
--theme)
|
--theme)
|
||||||
local IFS=$'\n'
|
local IFS=$'\n'
|
||||||
COMPREPLY=($(compgen -W "$("$1" --list-themes)" -- "$cur"))
|
COMPREPLY=($(compgen -W "$("$1" --list-themes)" -- "$cur"))
|
||||||
compopt -o filenames # for escaping
|
__bat_escape_completions
|
||||||
return 0
|
return 0
|
||||||
;;
|
;;
|
||||||
|
--style)
|
||||||
|
# shellcheck disable=SC2034
|
||||||
|
local -a styles=(
|
||||||
|
default
|
||||||
|
full
|
||||||
|
auto
|
||||||
|
plain
|
||||||
|
changes
|
||||||
|
header
|
||||||
|
header-filename
|
||||||
|
header-filesize
|
||||||
|
grid
|
||||||
|
rule
|
||||||
|
numbers
|
||||||
|
snip
|
||||||
|
)
|
||||||
|
# shellcheck disable=SC2016
|
||||||
|
if declare -F _comp_delimited >/dev/null 2>&1; then
|
||||||
|
# bash-completion > 2.11
|
||||||
|
_comp_delimited , -W '"${styles[@]}"'
|
||||||
|
else
|
||||||
|
COMPREPLY=($(compgen -W '${styles[@]}' -- "$cur"))
|
||||||
|
fi
|
||||||
|
return 0
|
||||||
esac
|
esac
|
||||||
|
|
||||||
$split && return 0
|
$split && return 0
|
||||||
|
|
||||||
if [[ $cur == -* ]]; then
|
if [[ $cur == -* ]]; then
|
||||||
|
# --unbuffered excluded intentionally (no-op)
|
||||||
COMPREPLY=($(compgen -W "
|
COMPREPLY=($(compgen -W "
|
||||||
--show-all --plain --language --highlight-line
|
--show-all
|
||||||
--file-name --diff --diff-context --tabs --wrap
|
--plain
|
||||||
--terminal-width --number --color --italic-text
|
--language
|
||||||
--decorations --paging --pager --map-syntax --theme
|
--highlight-line
|
||||||
--list-themes --style --line-range --list-languages
|
--file-name
|
||||||
--help --version --force-colorization --unbuffered
|
--diff
|
||||||
--diagnostic --config-file --config-dir --cache-dir
|
--diff-context
|
||||||
|
--tabs
|
||||||
|
--wrap
|
||||||
|
--terminal-width
|
||||||
|
--number
|
||||||
|
--color
|
||||||
|
--italic-text
|
||||||
|
--decorations
|
||||||
|
--force-colorization
|
||||||
|
--paging
|
||||||
|
--pager
|
||||||
|
--map-syntax
|
||||||
|
--ignored-suffix
|
||||||
|
--theme
|
||||||
|
--list-themes
|
||||||
|
--style
|
||||||
|
--line-range
|
||||||
|
--list-languages
|
||||||
|
--diagnostic
|
||||||
|
--acknowledgements
|
||||||
|
--help
|
||||||
|
--version
|
||||||
|
--cache-dir
|
||||||
|
--config-dir
|
||||||
|
--config-file
|
||||||
--generate-config-file
|
--generate-config-file
|
||||||
" -- "$cur"))
|
" -- "$cur"))
|
||||||
return 0
|
return 0
|
||||||
|
@ -186,7 +186,7 @@ man 2 select
|
|||||||
### On Ubuntu (`apt` を使用)
|
### On Ubuntu (`apt` を使用)
|
||||||
*... や他のDebianベースのLinuxディストリビューション*
|
*... や他のDebianベースのLinuxディストリビューション*
|
||||||
|
|
||||||
Ubuntu Eoan 19.10 または Debian 不安定版 sid 以降の [the Ubuntu `bat` package](https://packages.ubuntu.com/eoan/bat) または [the Debian `bat` package](https://packages.debian.org/sid/bat) からインストールできます:
|
[20.04 ("Focal") 以降の Ubuntu](https://packages.ubuntu.com/search?keywords=bat&exact=1) または [2021 年 8 月以降の Debian (Debian 11 - "Bullseye")](https://packages.debian.org/bullseye/bat) では `bat` パッケージが利用できます。
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
apt install bat
|
apt install bat
|
||||||
|
@ -46,6 +46,7 @@ pub(crate) mod printer;
|
|||||||
pub mod style;
|
pub mod style;
|
||||||
pub(crate) mod syntax_mapping;
|
pub(crate) mod syntax_mapping;
|
||||||
mod terminal;
|
mod terminal;
|
||||||
|
mod vscreen;
|
||||||
pub(crate) mod wrapping;
|
pub(crate) mod wrapping;
|
||||||
|
|
||||||
pub use pretty_printer::{Input, PrettyPrinter, Syntax};
|
pub use pretty_printer::{Input, PrettyPrinter, Syntax};
|
||||||
|
@ -1,28 +1,37 @@
|
|||||||
use std::fmt::Write;
|
use std::fmt::Write;
|
||||||
|
|
||||||
|
use console::AnsiCodeIterator;
|
||||||
|
|
||||||
/// Expand tabs like an ANSI-enabled expand(1).
|
/// Expand tabs like an ANSI-enabled expand(1).
|
||||||
pub fn expand_tabs(mut text: &str, width: usize, cursor: &mut usize) -> String {
|
pub fn expand_tabs(line: &str, width: usize, cursor: &mut usize) -> String {
|
||||||
let mut buffer = String::with_capacity(text.len() * 2);
|
let mut buffer = String::with_capacity(line.len() * 2);
|
||||||
|
|
||||||
while let Some(index) = text.find('\t') {
|
for chunk in AnsiCodeIterator::new(line) {
|
||||||
// Add previous text.
|
match chunk {
|
||||||
if index > 0 {
|
(text, true) => buffer.push_str(text),
|
||||||
*cursor += index;
|
(mut text, false) => {
|
||||||
buffer.push_str(&text[0..index]);
|
while let Some(index) = text.find('\t') {
|
||||||
|
// Add previous text.
|
||||||
|
if index > 0 {
|
||||||
|
*cursor += index;
|
||||||
|
buffer.push_str(&text[0..index]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add tab.
|
||||||
|
let spaces = width - (*cursor % width);
|
||||||
|
*cursor += spaces;
|
||||||
|
buffer.push_str(&*" ".repeat(spaces));
|
||||||
|
|
||||||
|
// Next.
|
||||||
|
text = &text[index + 1..text.len()];
|
||||||
|
}
|
||||||
|
|
||||||
|
*cursor += text.len();
|
||||||
|
buffer.push_str(text);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add tab.
|
|
||||||
let spaces = width - (*cursor % width);
|
|
||||||
*cursor += spaces;
|
|
||||||
buffer.push_str(&*" ".repeat(spaces));
|
|
||||||
|
|
||||||
// Next.
|
|
||||||
text = &text[index + 1..text.len()];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
*cursor += text.len();
|
|
||||||
buffer.push_str(text);
|
|
||||||
|
|
||||||
buffer
|
buffer
|
||||||
}
|
}
|
||||||
|
|
||||||
|
232
src/printer.rs
232
src/printer.rs
@ -6,6 +6,8 @@ use ansi_term::Style;
|
|||||||
|
|
||||||
use bytesize::ByteSize;
|
use bytesize::ByteSize;
|
||||||
|
|
||||||
|
use console::AnsiCodeIterator;
|
||||||
|
|
||||||
use syntect::easy::HighlightLines;
|
use syntect::easy::HighlightLines;
|
||||||
use syntect::highlighting::Color;
|
use syntect::highlighting::Color;
|
||||||
use syntect::highlighting::Theme;
|
use syntect::highlighting::Theme;
|
||||||
@ -31,6 +33,7 @@ use crate::line_range::RangeCheckResult;
|
|||||||
use crate::preprocessor::{expand_tabs, replace_nonprintable};
|
use crate::preprocessor::{expand_tabs, replace_nonprintable};
|
||||||
use crate::style::StyleComponent;
|
use crate::style::StyleComponent;
|
||||||
use crate::terminal::{as_terminal_escaped, to_ansi_color};
|
use crate::terminal::{as_terminal_escaped, to_ansi_color};
|
||||||
|
use crate::vscreen::AnsiStyle;
|
||||||
use crate::wrapping::WrappingMode;
|
use crate::wrapping::WrappingMode;
|
||||||
|
|
||||||
pub(crate) trait Printer {
|
pub(crate) trait Printer {
|
||||||
@ -119,6 +122,7 @@ pub(crate) struct InteractivePrinter<'a> {
|
|||||||
config: &'a Config<'a>,
|
config: &'a Config<'a>,
|
||||||
decorations: Vec<Box<dyn Decoration>>,
|
decorations: Vec<Box<dyn Decoration>>,
|
||||||
panel_width: usize,
|
panel_width: usize,
|
||||||
|
ansi_style: AnsiStyle,
|
||||||
content_type: Option<ContentType>,
|
content_type: Option<ContentType>,
|
||||||
#[cfg(feature = "git")]
|
#[cfg(feature = "git")]
|
||||||
pub line_changes: &'a Option<LineChanges>,
|
pub line_changes: &'a Option<LineChanges>,
|
||||||
@ -202,6 +206,7 @@ impl<'a> InteractivePrinter<'a> {
|
|||||||
config,
|
config,
|
||||||
decorations,
|
decorations,
|
||||||
content_type: input.reader.content_type,
|
content_type: input.reader.content_type,
|
||||||
|
ansi_style: AnsiStyle::new(),
|
||||||
#[cfg(feature = "git")]
|
#[cfg(feature = "git")]
|
||||||
line_changes,
|
line_changes,
|
||||||
highlighter_from_set,
|
highlighter_from_set,
|
||||||
@ -480,7 +485,7 @@ impl<'a> Printer for InteractivePrinter<'a> {
|
|||||||
self.config.highlighted_lines.0.check(line_number) == RangeCheckResult::InRange;
|
self.config.highlighted_lines.0.check(line_number) == RangeCheckResult::InRange;
|
||||||
|
|
||||||
if highlight_this_line && self.config.theme == "ansi" {
|
if highlight_this_line && self.config.theme == "ansi" {
|
||||||
write!(handle, "\x1B[4m")?;
|
self.ansi_style.update("^[4m");
|
||||||
}
|
}
|
||||||
|
|
||||||
let background_color = self
|
let background_color = self
|
||||||
@ -507,37 +512,51 @@ impl<'a> Printer for InteractivePrinter<'a> {
|
|||||||
let italics = self.config.use_italic_text;
|
let italics = self.config.use_italic_text;
|
||||||
|
|
||||||
for &(style, region) in ®ions {
|
for &(style, region) in ®ions {
|
||||||
let text = &*self.preprocess(region, &mut cursor_total);
|
let ansi_iterator = AnsiCodeIterator::new(region);
|
||||||
let text_trimmed = text.trim_end_matches(|c| c == '\r' || c == '\n');
|
for chunk in ansi_iterator {
|
||||||
|
match chunk {
|
||||||
|
// ANSI escape passthrough.
|
||||||
|
(ansi, true) => {
|
||||||
|
self.ansi_style.update(ansi);
|
||||||
|
write!(handle, "{}", ansi)?;
|
||||||
|
}
|
||||||
|
|
||||||
write!(
|
// Regular text.
|
||||||
handle,
|
(text, false) => {
|
||||||
"{}",
|
let text = &*self.preprocess(text, &mut cursor_total);
|
||||||
as_terminal_escaped(
|
let text_trimmed = text.trim_end_matches(|c| c == '\r' || c == '\n');
|
||||||
style,
|
|
||||||
text_trimmed,
|
|
||||||
true_color,
|
|
||||||
colored_output,
|
|
||||||
italics,
|
|
||||||
background_color
|
|
||||||
)
|
|
||||||
)?;
|
|
||||||
|
|
||||||
if text.len() != text_trimmed.len() {
|
write!(
|
||||||
if let Some(background_color) = background_color {
|
handle,
|
||||||
let ansi_style = Style {
|
"{}",
|
||||||
background: to_ansi_color(background_color, true_color),
|
as_terminal_escaped(
|
||||||
..Default::default()
|
style,
|
||||||
};
|
&format!("{}{}", self.ansi_style, text_trimmed),
|
||||||
|
true_color,
|
||||||
|
colored_output,
|
||||||
|
italics,
|
||||||
|
background_color
|
||||||
|
)
|
||||||
|
)?;
|
||||||
|
|
||||||
let width = if cursor_total <= cursor_max {
|
if text.len() != text_trimmed.len() {
|
||||||
cursor_max - cursor_total + 1
|
if let Some(background_color) = background_color {
|
||||||
} else {
|
let ansi_style = Style {
|
||||||
0
|
background: to_ansi_color(background_color, true_color),
|
||||||
};
|
..Default::default()
|
||||||
write!(handle, "{}", ansi_style.paint(" ".repeat(width)))?;
|
};
|
||||||
|
|
||||||
|
let width = if cursor_total <= cursor_max {
|
||||||
|
cursor_max - cursor_total + 1
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
};
|
||||||
|
write!(handle, "{}", ansi_style.paint(" ".repeat(width)))?;
|
||||||
|
}
|
||||||
|
write!(handle, "{}", &text[text_trimmed.len()..])?;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
write!(handle, "{}", &text[text_trimmed.len()..])?;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -546,82 +565,98 @@ impl<'a> Printer for InteractivePrinter<'a> {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for &(style, region) in ®ions {
|
for &(style, region) in ®ions {
|
||||||
let text = self.preprocess(
|
let ansi_iterator = AnsiCodeIterator::new(region);
|
||||||
region.trim_end_matches(|c| c == '\r' || c == '\n'),
|
for chunk in ansi_iterator {
|
||||||
&mut cursor_total,
|
match chunk {
|
||||||
);
|
// ANSI escape passthrough.
|
||||||
|
(ansi, true) => {
|
||||||
let mut max_width = cursor_max - cursor;
|
self.ansi_style.update(ansi);
|
||||||
|
write!(handle, "{}", ansi)?;
|
||||||
// line buffer (avoid calling write! for every character)
|
|
||||||
let mut line_buf = String::with_capacity(max_width * 4);
|
|
||||||
|
|
||||||
// Displayed width of line_buf
|
|
||||||
let mut current_width = 0;
|
|
||||||
|
|
||||||
for c in text.chars() {
|
|
||||||
// calculate the displayed width for next character
|
|
||||||
let cw = c.width().unwrap_or(0);
|
|
||||||
current_width += cw;
|
|
||||||
|
|
||||||
// if next character cannot be printed on this line,
|
|
||||||
// flush the buffer.
|
|
||||||
if current_width > max_width {
|
|
||||||
// Generate wrap padding if not already generated.
|
|
||||||
if panel_wrap.is_none() {
|
|
||||||
panel_wrap = if self.panel_width > 0 {
|
|
||||||
Some(format!(
|
|
||||||
"{} ",
|
|
||||||
self.decorations
|
|
||||||
.iter()
|
|
||||||
.map(|d| d.generate(line_number, true, self).text)
|
|
||||||
.collect::<Vec<String>>()
|
|
||||||
.join(" ")
|
|
||||||
))
|
|
||||||
} else {
|
|
||||||
Some("".to_string())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// It wraps.
|
// Regular text.
|
||||||
write!(
|
(text, false) => {
|
||||||
handle,
|
let text = self.preprocess(
|
||||||
"{}\n{}",
|
text.trim_end_matches(|c| c == '\r' || c == '\n'),
|
||||||
as_terminal_escaped(
|
&mut cursor_total,
|
||||||
style,
|
);
|
||||||
&line_buf,
|
|
||||||
self.config.true_color,
|
|
||||||
self.config.colored_output,
|
|
||||||
self.config.use_italic_text,
|
|
||||||
background_color
|
|
||||||
),
|
|
||||||
panel_wrap.clone().unwrap()
|
|
||||||
)?;
|
|
||||||
|
|
||||||
cursor = 0;
|
let mut max_width = cursor_max - cursor;
|
||||||
max_width = cursor_max;
|
|
||||||
|
|
||||||
line_buf.clear();
|
// line buffer (avoid calling write! for every character)
|
||||||
current_width = cw;
|
let mut line_buf = String::with_capacity(max_width * 4);
|
||||||
|
|
||||||
|
// Displayed width of line_buf
|
||||||
|
let mut current_width = 0;
|
||||||
|
|
||||||
|
for c in text.chars() {
|
||||||
|
// calculate the displayed width for next character
|
||||||
|
let cw = c.width().unwrap_or(0);
|
||||||
|
current_width += cw;
|
||||||
|
|
||||||
|
// if next character cannot be printed on this line,
|
||||||
|
// flush the buffer.
|
||||||
|
if current_width > max_width {
|
||||||
|
// Generate wrap padding if not already generated.
|
||||||
|
if panel_wrap.is_none() {
|
||||||
|
panel_wrap = if self.panel_width > 0 {
|
||||||
|
Some(format!(
|
||||||
|
"{} ",
|
||||||
|
self.decorations
|
||||||
|
.iter()
|
||||||
|
.map(|d| d
|
||||||
|
.generate(line_number, true, self)
|
||||||
|
.text)
|
||||||
|
.collect::<Vec<String>>()
|
||||||
|
.join(" ")
|
||||||
|
))
|
||||||
|
} else {
|
||||||
|
Some("".to_string())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// It wraps.
|
||||||
|
write!(
|
||||||
|
handle,
|
||||||
|
"{}\n{}",
|
||||||
|
as_terminal_escaped(
|
||||||
|
style,
|
||||||
|
&*format!("{}{}", self.ansi_style, line_buf),
|
||||||
|
self.config.true_color,
|
||||||
|
self.config.colored_output,
|
||||||
|
self.config.use_italic_text,
|
||||||
|
background_color
|
||||||
|
),
|
||||||
|
panel_wrap.clone().unwrap()
|
||||||
|
)?;
|
||||||
|
|
||||||
|
cursor = 0;
|
||||||
|
max_width = cursor_max;
|
||||||
|
|
||||||
|
line_buf.clear();
|
||||||
|
current_width = cw;
|
||||||
|
}
|
||||||
|
|
||||||
|
line_buf.push(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
// flush the buffer
|
||||||
|
cursor += current_width;
|
||||||
|
write!(
|
||||||
|
handle,
|
||||||
|
"{}",
|
||||||
|
as_terminal_escaped(
|
||||||
|
style,
|
||||||
|
&*format!("{}{}", self.ansi_style, line_buf),
|
||||||
|
self.config.true_color,
|
||||||
|
self.config.colored_output,
|
||||||
|
self.config.use_italic_text,
|
||||||
|
background_color
|
||||||
|
)
|
||||||
|
)?;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
line_buf.push(c);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// flush the buffer
|
|
||||||
cursor += current_width;
|
|
||||||
write!(
|
|
||||||
handle,
|
|
||||||
"{}",
|
|
||||||
as_terminal_escaped(
|
|
||||||
style,
|
|
||||||
&line_buf,
|
|
||||||
self.config.true_color,
|
|
||||||
self.config.colored_output,
|
|
||||||
self.config.use_italic_text,
|
|
||||||
background_color
|
|
||||||
)
|
|
||||||
)?;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(background_color) = background_color {
|
if let Some(background_color) = background_color {
|
||||||
@ -640,6 +675,7 @@ impl<'a> Printer for InteractivePrinter<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if highlight_this_line && self.config.theme == "ansi" {
|
if highlight_this_line && self.config.theme == "ansi" {
|
||||||
|
self.ansi_style.update("^[24m");
|
||||||
write!(handle, "\x1B[24m")?;
|
write!(handle, "\x1B[24m")?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
212
src/vscreen.rs
Normal file
212
src/vscreen.rs
Normal file
@ -0,0 +1,212 @@
|
|||||||
|
use std::fmt::{Display, Formatter};
|
||||||
|
|
||||||
|
// Wrapper to avoid unnecessary branching when input doesn't have ANSI escape sequences.
|
||||||
|
pub struct AnsiStyle {
|
||||||
|
attributes: Option<Attributes>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AnsiStyle {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
AnsiStyle { attributes: None }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn update(&mut self, sequence: &str) -> bool {
|
||||||
|
match &mut self.attributes {
|
||||||
|
Some(a) => a.update(sequence),
|
||||||
|
None => {
|
||||||
|
self.attributes = Some(Attributes::new());
|
||||||
|
self.attributes.as_mut().unwrap().update(sequence)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for AnsiStyle {
|
||||||
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||||
|
match self.attributes {
|
||||||
|
Some(ref a) => a.fmt(f),
|
||||||
|
None => Ok(()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Attributes {
|
||||||
|
foreground: String,
|
||||||
|
background: String,
|
||||||
|
underlined: String,
|
||||||
|
|
||||||
|
/// The character set to use.
|
||||||
|
/// REGEX: `\^[()][AB0-3]`
|
||||||
|
charset: String,
|
||||||
|
|
||||||
|
/// A buffer for unknown sequences.
|
||||||
|
unknown_buffer: String,
|
||||||
|
|
||||||
|
/// ON: ^[1m
|
||||||
|
/// OFF: ^[22m
|
||||||
|
bold: String,
|
||||||
|
|
||||||
|
/// ON: ^[2m
|
||||||
|
/// OFF: ^[22m
|
||||||
|
dim: String,
|
||||||
|
|
||||||
|
/// ON: ^[4m
|
||||||
|
/// OFF: ^[24m
|
||||||
|
underline: String,
|
||||||
|
|
||||||
|
/// ON: ^[3m
|
||||||
|
/// OFF: ^[23m
|
||||||
|
italic: String,
|
||||||
|
|
||||||
|
/// ON: ^[9m
|
||||||
|
/// OFF: ^[29m
|
||||||
|
strike: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Attributes {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Attributes {
|
||||||
|
foreground: "".to_owned(),
|
||||||
|
background: "".to_owned(),
|
||||||
|
underlined: "".to_owned(),
|
||||||
|
charset: "".to_owned(),
|
||||||
|
unknown_buffer: "".to_owned(),
|
||||||
|
bold: "".to_owned(),
|
||||||
|
dim: "".to_owned(),
|
||||||
|
underline: "".to_owned(),
|
||||||
|
italic: "".to_owned(),
|
||||||
|
strike: "".to_owned(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Update the attributes with an escape sequence.
|
||||||
|
/// Returns `false` if the sequence is unsupported.
|
||||||
|
pub fn update(&mut self, sequence: &str) -> bool {
|
||||||
|
let mut chars = sequence.char_indices().skip(1);
|
||||||
|
|
||||||
|
if let Some((_, t)) = chars.next() {
|
||||||
|
match t {
|
||||||
|
'(' => self.update_with_charset('(', chars.map(|(_, c)| c)),
|
||||||
|
')' => self.update_with_charset(')', chars.map(|(_, c)| c)),
|
||||||
|
'[' => {
|
||||||
|
if let Some((i, last)) = chars.last() {
|
||||||
|
// SAFETY: Always starts with ^[ and ends with m.
|
||||||
|
self.update_with_csi(last, &sequence[2..i])
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => self.update_with_unsupported(sequence),
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn sgr_reset(&mut self) {
|
||||||
|
self.foreground.clear();
|
||||||
|
self.background.clear();
|
||||||
|
self.underlined.clear();
|
||||||
|
self.bold.clear();
|
||||||
|
self.dim.clear();
|
||||||
|
self.underline.clear();
|
||||||
|
self.italic.clear();
|
||||||
|
self.strike.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update_with_sgr(&mut self, parameters: &str) -> bool {
|
||||||
|
let mut iter = parameters
|
||||||
|
.split(';')
|
||||||
|
.map(|p| if p.is_empty() { "0" } else { p })
|
||||||
|
.map(|p| p.parse::<u16>())
|
||||||
|
.map(|p| p.unwrap_or(0)); // Treat errors as 0.
|
||||||
|
|
||||||
|
while let Some(p) = iter.next() {
|
||||||
|
match p {
|
||||||
|
0 => self.sgr_reset(),
|
||||||
|
1 => self.bold = format!("\x1B[{}m", parameters),
|
||||||
|
2 => self.dim = format!("\x1B[{}m", parameters),
|
||||||
|
3 => self.italic = format!("\x1B[{}m", parameters),
|
||||||
|
4 => self.underline = format!("\x1B[{}m", parameters),
|
||||||
|
23 => self.italic.clear(),
|
||||||
|
24 => self.underline.clear(),
|
||||||
|
22 => {
|
||||||
|
self.bold.clear();
|
||||||
|
self.dim.clear();
|
||||||
|
}
|
||||||
|
30..=39 => self.foreground = Self::parse_color(p, &mut iter),
|
||||||
|
40..=49 => self.background = Self::parse_color(p, &mut iter),
|
||||||
|
58..=59 => self.underlined = Self::parse_color(p, &mut iter),
|
||||||
|
90..=97 => self.foreground = Self::parse_color(p, &mut iter),
|
||||||
|
100..=107 => self.foreground = Self::parse_color(p, &mut iter),
|
||||||
|
_ => {
|
||||||
|
// Unsupported SGR sequence.
|
||||||
|
// Be compatible and pretend one just wasn't was provided.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update_with_csi(&mut self, finalizer: char, sequence: &str) -> bool {
|
||||||
|
if finalizer == 'm' {
|
||||||
|
self.update_with_sgr(sequence)
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update_with_unsupported(&mut self, sequence: &str) -> bool {
|
||||||
|
self.unknown_buffer.push_str(sequence);
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update_with_charset(&mut self, kind: char, set: impl Iterator<Item = char>) -> bool {
|
||||||
|
self.charset = format!("\x1B{}{}", kind, set.take(1).collect::<String>());
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_color(color: u16, parameters: &mut dyn Iterator<Item = u16>) -> String {
|
||||||
|
match color % 10 {
|
||||||
|
8 => match parameters.next() {
|
||||||
|
Some(5) /* 256-color */ => format!("\x1B[{};5;{}m", color, join(";", 1, parameters)),
|
||||||
|
Some(2) /* 24-bit color */ => format!("\x1B[{};2;{}m", color, join(";", 3, parameters)),
|
||||||
|
Some(c) => format!("\x1B[{};{}m", color, c),
|
||||||
|
_ => "".to_owned(),
|
||||||
|
},
|
||||||
|
9 => "".to_owned(),
|
||||||
|
_ => format!("\x1B[{}m", color),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for Attributes {
|
||||||
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||||
|
write!(
|
||||||
|
f,
|
||||||
|
"{}{}{}{}{}{}{}{}{}",
|
||||||
|
self.foreground,
|
||||||
|
self.background,
|
||||||
|
self.underlined,
|
||||||
|
self.charset,
|
||||||
|
self.bold,
|
||||||
|
self.dim,
|
||||||
|
self.underline,
|
||||||
|
self.italic,
|
||||||
|
self.strike,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn join(
|
||||||
|
delimiter: &str,
|
||||||
|
limit: usize,
|
||||||
|
iterator: &mut dyn Iterator<Item = impl ToString>,
|
||||||
|
) -> String {
|
||||||
|
iterator
|
||||||
|
.take(limit)
|
||||||
|
.map(|i| i.to_string())
|
||||||
|
.collect::<Vec<String>>()
|
||||||
|
.join(delimiter)
|
||||||
|
}
|
@ -1442,6 +1442,26 @@ fn ansi_highlight_underline() {
|
|||||||
.stderr("");
|
.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("");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn ignored_suffix_arg() {
|
fn ignored_suffix_arg() {
|
||||||
bat()
|
bat()
|
||||||
|
Loading…
Reference in New Issue
Block a user