mirror of
https://github.com/sharkdp/bat.git
synced 2025-09-01 10:52:24 +01:00
Compare commits
6 Commits
v0.24.0
...
bat-plugin
Author | SHA1 | Date | |
---|---|---|---|
|
aa35cb52c4 | ||
|
446b9181e6 | ||
|
040242c9be | ||
|
dbf78d280a | ||
|
bc91af3ee5 | ||
|
3811615606 |
6
.github/dependabot.yml
vendored
6
.github/dependabot.yml
vendored
@@ -16,9 +16,3 @@ updates:
|
||||
interval: monthly
|
||||
time: "04:00"
|
||||
timezone: Europe/Berlin
|
||||
- package-ecosystem: "github-actions"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: monthly
|
||||
time: "04:00"
|
||||
timezone: Europe/Berlin
|
||||
|
385
.github/workflows/CICD.yml
vendored
385
.github/workflows/CICD.yml
vendored
@@ -1,8 +1,8 @@
|
||||
name: CICD
|
||||
|
||||
env:
|
||||
MIN_SUPPORTED_RUST_VERSION: "1.51.0"
|
||||
CICD_INTERMEDIATES_DIR: "_cicd-intermediates"
|
||||
MSRV_FEATURES: --no-default-features --features minimal-application,bugreport,build-assets
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
@@ -14,100 +14,89 @@ on:
|
||||
- '*'
|
||||
|
||||
jobs:
|
||||
all-jobs:
|
||||
if: always() # Otherwise this job is skipped if the matrix job fails
|
||||
name: all-jobs
|
||||
runs-on: ubuntu-latest
|
||||
needs:
|
||||
- crate_metadata
|
||||
- ensure_cargo_fmt
|
||||
- min_version
|
||||
- license_checks
|
||||
- test_with_new_syntaxes_and_themes
|
||||
- test_with_system_config
|
||||
- documentation
|
||||
- cargo-audit
|
||||
- build
|
||||
steps:
|
||||
- run: jq --exit-status 'all(.result == "success")' <<< '${{ toJson(needs) }}'
|
||||
|
||||
crate_metadata:
|
||||
name: Extract crate metadata
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Extract crate information
|
||||
id: crate_metadata
|
||||
run: |
|
||||
cargo metadata --no-deps --format-version 1 | jq -r '"name=" + .packages[0].name' | tee -a $GITHUB_OUTPUT
|
||||
cargo metadata --no-deps --format-version 1 | jq -r '"version=" + .packages[0].version' | tee -a $GITHUB_OUTPUT
|
||||
cargo metadata --no-deps --format-version 1 | jq -r '"maintainer=" + .packages[0].authors[0]' | tee -a $GITHUB_OUTPUT
|
||||
cargo metadata --no-deps --format-version 1 | jq -r '"homepage=" + .packages[0].homepage' | tee -a $GITHUB_OUTPUT
|
||||
cargo metadata --no-deps --format-version 1 | jq -r '"msrv=" + .packages[0].rust_version' | tee -a $GITHUB_OUTPUT
|
||||
outputs:
|
||||
name: ${{ steps.crate_metadata.outputs.name }}
|
||||
version: ${{ steps.crate_metadata.outputs.version }}
|
||||
maintainer: ${{ steps.crate_metadata.outputs.maintainer }}
|
||||
homepage: ${{ steps.crate_metadata.outputs.homepage }}
|
||||
msrv: ${{ steps.crate_metadata.outputs.msrv }}
|
||||
|
||||
ensure_cargo_fmt:
|
||||
name: Ensure 'cargo fmt' has been run
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- uses: dtolnay/rust-toolchain@stable
|
||||
- uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: stable
|
||||
default: true
|
||||
profile: minimal
|
||||
components: rustfmt
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v2
|
||||
- run: cargo fmt -- --check
|
||||
|
||||
min_version:
|
||||
name: Minimum supported rust version
|
||||
runs-on: ubuntu-20.04
|
||||
needs: crate_metadata
|
||||
steps:
|
||||
- name: Checkout source code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Install rust toolchain (v${{ needs.crate_metadata.outputs.msrv }})
|
||||
uses: dtolnay/rust-toolchain@master
|
||||
with:
|
||||
toolchain: ${{ needs.crate_metadata.outputs.msrv }}
|
||||
components: clippy
|
||||
- name: Run clippy (on minimum supported rust version to prevent warnings we can't fix)
|
||||
run: cargo clippy --locked --all-targets ${{ env.MSRV_FEATURES }}
|
||||
- name: Run tests
|
||||
run: cargo test --locked ${{ env.MSRV_FEATURES }}
|
||||
|
||||
license_checks:
|
||||
name: License checks
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
submodules: true # we especially want to perform license checks on submodules
|
||||
- run: tests/scripts/license-checks.sh
|
||||
|
||||
min_version:
|
||||
name: Minimum supported rust version
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- name: Checkout source code
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Install rust toolchain (v${{ env.MIN_SUPPORTED_RUST_VERSION }})
|
||||
uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: ${{ env.MIN_SUPPORTED_RUST_VERSION }}
|
||||
default: true
|
||||
profile: minimal # minimal component installation (ie, no documentation)
|
||||
components: clippy
|
||||
- name: Run clippy (on minimum supported rust version to prevent warnings we can't fix)
|
||||
uses: actions-rs/cargo@v1
|
||||
with:
|
||||
command: clippy
|
||||
args: --locked --all-targets --all-features
|
||||
- name: Run tests
|
||||
uses: actions-rs/cargo@v1
|
||||
with:
|
||||
command: test
|
||||
args: --locked
|
||||
|
||||
test_with_new_syntaxes_and_themes:
|
||||
name: Run tests with updated syntaxes and themes
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- name: Git checkout
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
submodules: true # we need all syntax and theme submodules
|
||||
- name: Install Rust toolchain
|
||||
uses: dtolnay/rust-toolchain@stable
|
||||
uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: stable
|
||||
default: true
|
||||
profile: minimal
|
||||
- name: Build and install bat
|
||||
run: cargo install --locked --path .
|
||||
uses: actions-rs/cargo@v1
|
||||
with:
|
||||
command: install
|
||||
args: --locked --path .
|
||||
- name: Rebuild binary assets (syntaxes and themes)
|
||||
run: bash assets/create.sh
|
||||
- name: Build and install bat with updated assets
|
||||
run: cargo install --locked --path .
|
||||
uses: actions-rs/cargo@v1
|
||||
with:
|
||||
command: install
|
||||
args: --locked --path .
|
||||
- name: Run unit tests with new syntaxes and themes
|
||||
run: cargo test --locked --release
|
||||
uses: actions-rs/cargo@v1
|
||||
with:
|
||||
command: test
|
||||
args: --locked --release
|
||||
- name: Run ignored-by-default unit tests with new syntaxes and themes
|
||||
run: cargo test --locked --release --test assets -- --ignored
|
||||
uses: actions-rs/cargo@v1
|
||||
with:
|
||||
command: test
|
||||
args: --locked --release -- --ignored
|
||||
- name: Syntax highlighting regression test
|
||||
run: tests/syntax-tests/regression_test.sh
|
||||
- name: List of languages
|
||||
@@ -117,48 +106,41 @@ jobs:
|
||||
- name: Test custom assets
|
||||
run: tests/syntax-tests/test_custom_assets.sh
|
||||
|
||||
test_with_system_config:
|
||||
name: Run tests with system wide configuration
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- name: Git checkout
|
||||
uses: actions/checkout@v4
|
||||
- name: Prepare environment variables
|
||||
run: |
|
||||
echo "BAT_SYSTEM_CONFIG_PREFIX=$GITHUB_WORKSPACE/tests/examples/system_config" >> $GITHUB_ENV
|
||||
- name: Install Rust toolchain
|
||||
uses: dtolnay/rust-toolchain@stable
|
||||
- name: Build and install bat
|
||||
run: cargo install --locked --path .
|
||||
- name: Run unit tests
|
||||
run: cargo test --locked --test system_wide_config -- --ignored
|
||||
|
||||
documentation:
|
||||
name: Documentation
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- name: Git checkout
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v2
|
||||
- name: Install Rust toolchain
|
||||
uses: dtolnay/rust-toolchain@stable
|
||||
uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: stable
|
||||
default: true
|
||||
profile: minimal
|
||||
- name: Print -h
|
||||
uses: actions-rs/cargo@v1
|
||||
with:
|
||||
command: run
|
||||
args: --locked -- -h
|
||||
- name: Print --help
|
||||
uses: actions-rs/cargo@v1
|
||||
with:
|
||||
command: run
|
||||
args: --locked -- --help
|
||||
- name: Show man page
|
||||
run: man $(find . -name bat.1)
|
||||
- name: Check documentation
|
||||
env:
|
||||
RUSTDOCFLAGS: -D warnings
|
||||
run: cargo doc --locked --no-deps --document-private-items --all-features
|
||||
- name: Show man page
|
||||
run: man $(find . -name bat.1)
|
||||
|
||||
cargo-audit:
|
||||
name: cargo audit
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- run: cargo audit
|
||||
uses: actions-rs/cargo@v1
|
||||
with:
|
||||
command: doc
|
||||
args: --locked --no-deps --document-private-items --all-features
|
||||
|
||||
build:
|
||||
name: ${{ matrix.job.target }} (${{ matrix.job.os }})
|
||||
runs-on: ${{ matrix.job.os }}
|
||||
needs: crate_metadata
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
@@ -169,16 +151,14 @@ jobs:
|
||||
- { target: i686-pc-windows-msvc , os: windows-2019 }
|
||||
- { target: i686-unknown-linux-gnu , os: ubuntu-20.04, use-cross: true }
|
||||
- { target: i686-unknown-linux-musl , os: ubuntu-20.04, use-cross: true }
|
||||
- { target: x86_64-apple-darwin , os: macos-12 }
|
||||
- { target: x86_64-apple-darwin , os: macos-10.15 }
|
||||
- { target: x86_64-pc-windows-gnu , os: windows-2019 }
|
||||
- { target: x86_64-pc-windows-msvc , os: windows-2019 }
|
||||
- { target: x86_64-unknown-linux-gnu , os: ubuntu-20.04, use-cross: true }
|
||||
- { target: x86_64-unknown-linux-musl , os: ubuntu-20.04, use-cross: true }
|
||||
env:
|
||||
BUILD_CMD: cargo
|
||||
steps:
|
||||
- name: Checkout source code
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Install prerequisites
|
||||
shell: bash
|
||||
@@ -188,21 +168,21 @@ jobs:
|
||||
aarch64-unknown-linux-gnu) sudo apt-get -y update ; sudo apt-get -y install gcc-aarch64-linux-gnu ;;
|
||||
esac
|
||||
|
||||
- name: Install Rust toolchain
|
||||
uses: dtolnay/rust-toolchain@stable
|
||||
with:
|
||||
targets: ${{ matrix.job.target }}
|
||||
|
||||
- name: Install cross
|
||||
if: matrix.job.use-cross
|
||||
uses: taiki-e/install-action@v2
|
||||
with:
|
||||
tool: cross
|
||||
|
||||
- name: Overwrite build command env variable
|
||||
if: matrix.job.use-cross
|
||||
- name: Extract crate information
|
||||
shell: bash
|
||||
run: echo "BUILD_CMD=cross" >> $GITHUB_ENV
|
||||
run: |
|
||||
echo "PROJECT_NAME=$(sed -n 's/^name = "\(.*\)"/\1/p' Cargo.toml | head -n1)" >> $GITHUB_ENV
|
||||
echo "PROJECT_VERSION=$(sed -n 's/^version = "\(.*\)"/\1/p' Cargo.toml | head -n1)" >> $GITHUB_ENV
|
||||
echo "PROJECT_MAINTAINER=$(sed -n 's/^authors = \["\(.*\)"\]/\1/p' Cargo.toml)" >> $GITHUB_ENV
|
||||
echo "PROJECT_HOMEPAGE=$(sed -n 's/^homepage = "\(.*\)"/\1/p' Cargo.toml)" >> $GITHUB_ENV
|
||||
|
||||
- name: Install Rust toolchain
|
||||
uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: stable
|
||||
target: ${{ matrix.job.target }}
|
||||
override: true
|
||||
profile: minimal # minimal component installation (ie, no documentation)
|
||||
|
||||
- name: Show version information (Rust, cargo, GCC)
|
||||
shell: bash
|
||||
@@ -215,11 +195,14 @@ jobs:
|
||||
rustc -V
|
||||
|
||||
- name: Build
|
||||
shell: bash
|
||||
run: $BUILD_CMD build --locked --release --target=${{ matrix.job.target }}
|
||||
uses: actions-rs/cargo@v1
|
||||
with:
|
||||
use-cross: ${{ matrix.job.use-cross }}
|
||||
command: build
|
||||
args: --locked --release --target=${{ matrix.job.target }}
|
||||
|
||||
- name: Set binary name & path
|
||||
id: bin
|
||||
- name: Strip debug information from executable
|
||||
id: strip
|
||||
shell: bash
|
||||
run: |
|
||||
# Figure out suffix of binary
|
||||
@@ -228,13 +211,31 @@ jobs:
|
||||
*-pc-windows-*) EXE_suffix=".exe" ;;
|
||||
esac;
|
||||
|
||||
# Setup paths
|
||||
BIN_NAME="${{ needs.crate_metadata.outputs.name }}${EXE_suffix}"
|
||||
BIN_PATH="target/${{ matrix.job.target }}/release/${BIN_NAME}"
|
||||
# Figure out what strip tool to use if any
|
||||
STRIP="strip"
|
||||
case ${{ matrix.job.target }} in
|
||||
arm-unknown-linux-*) STRIP="arm-linux-gnueabihf-strip" ;;
|
||||
aarch64-unknown-linux-gnu) STRIP="aarch64-linux-gnu-strip" ;;
|
||||
*-pc-windows-msvc) STRIP="" ;;
|
||||
esac;
|
||||
|
||||
# Let subsequent steps know where to find the binary
|
||||
echo "BIN_PATH=${BIN_PATH}" >> $GITHUB_OUTPUT
|
||||
echo "BIN_NAME=${BIN_NAME}" >> $GITHUB_OUTPUT
|
||||
# Setup paths
|
||||
BIN_DIR="${{ env.CICD_INTERMEDIATES_DIR }}/stripped-release-bin/"
|
||||
mkdir -p "${BIN_DIR}"
|
||||
BIN_NAME="${{ env.PROJECT_NAME }}${EXE_suffix}"
|
||||
BIN_PATH="${BIN_DIR}/${BIN_NAME}"
|
||||
|
||||
# Copy the release build binary to the result location
|
||||
cp "target/${{ matrix.job.target }}/release/${BIN_NAME}" "${BIN_DIR}"
|
||||
|
||||
# Also strip if possible
|
||||
if [ -n "${STRIP}" ]; then
|
||||
"${STRIP}" "${BIN_PATH}"
|
||||
fi
|
||||
|
||||
# Let subsequent steps know where to find the (stripped) bin
|
||||
echo ::set-output name=BIN_PATH::${BIN_PATH}
|
||||
echo ::set-output name=BIN_NAME::${BIN_NAME}
|
||||
|
||||
- name: Set testing options
|
||||
id: test-options
|
||||
@@ -242,55 +243,73 @@ jobs:
|
||||
run: |
|
||||
# test only library unit tests and binary for arm-type targets
|
||||
unset CARGO_TEST_OPTIONS
|
||||
unset CARGO_TEST_OPTIONS ; case ${{ matrix.job.target }} in arm-* | aarch64-*) CARGO_TEST_OPTIONS="--lib --bin ${{ needs.crate_metadata.outputs.name }}" ;; esac;
|
||||
echo "CARGO_TEST_OPTIONS=${CARGO_TEST_OPTIONS}" >> $GITHUB_OUTPUT
|
||||
unset CARGO_TEST_OPTIONS ; case ${{ matrix.job.target }} in arm-* | aarch64-*) CARGO_TEST_OPTIONS="--lib --bin ${PROJECT_NAME}" ;; esac;
|
||||
echo ::set-output name=CARGO_TEST_OPTIONS::${CARGO_TEST_OPTIONS}
|
||||
|
||||
- name: Run tests
|
||||
shell: bash
|
||||
run: |
|
||||
if [[ ${{ matrix.job.os }} = windows-* ]]
|
||||
then
|
||||
powershell.exe -command "$BUILD_CMD test --locked --target=${{ matrix.job.target }} ${{ steps.test-options.outputs.CARGO_TEST_OPTIONS}}"
|
||||
else
|
||||
$BUILD_CMD test --locked --target=${{ matrix.job.target }} ${{ steps.test-options.outputs.CARGO_TEST_OPTIONS}}
|
||||
fi
|
||||
uses: actions-rs/cargo@v1
|
||||
with:
|
||||
use-cross: ${{ matrix.job.use-cross }}
|
||||
command: test
|
||||
args: --locked --target=${{ matrix.job.target }} ${{ steps.test-options.outputs.CARGO_TEST_OPTIONS}}
|
||||
|
||||
- name: Run bat
|
||||
shell: bash
|
||||
run: $BUILD_CMD run --locked --target=${{ matrix.job.target }} -- --paging=never --color=always --theme=ansi Cargo.toml src/config.rs
|
||||
uses: actions-rs/cargo@v1
|
||||
with:
|
||||
use-cross: ${{ matrix.job.use-cross }}
|
||||
command: run
|
||||
args: --locked --target=${{ matrix.job.target }} -- --paging=never --color=always --theme=ansi Cargo.toml src/config.rs
|
||||
|
||||
- name: Show diagnostics (bat --diagnostic)
|
||||
shell: bash
|
||||
run: $BUILD_CMD run --locked --target=${{ matrix.job.target }} -- --paging=never --color=always --theme=ansi Cargo.toml src/config.rs --diagnostic
|
||||
uses: actions-rs/cargo@v1
|
||||
with:
|
||||
use-cross: ${{ matrix.job.use-cross }}
|
||||
command: run
|
||||
args: --locked --target=${{ matrix.job.target }} -- --paging=never --color=always --theme=ansi Cargo.toml src/config.rs --diagnostic
|
||||
|
||||
- name: "Feature check: regex-onig"
|
||||
shell: bash
|
||||
run: $BUILD_CMD check --locked --target=${{ matrix.job.target }} --verbose --lib --no-default-features --features regex-onig
|
||||
uses: actions-rs/cargo@v1
|
||||
with:
|
||||
use-cross: ${{ matrix.job.use-cross }}
|
||||
command: check
|
||||
args: --locked --target=${{ matrix.job.target }} --verbose --lib --no-default-features --features regex-onig
|
||||
|
||||
- name: "Feature check: regex-onig,git"
|
||||
shell: bash
|
||||
run: $BUILD_CMD check --locked --target=${{ matrix.job.target }} --verbose --lib --no-default-features --features regex-onig,git
|
||||
uses: actions-rs/cargo@v1
|
||||
with:
|
||||
use-cross: ${{ matrix.job.use-cross }}
|
||||
command: check
|
||||
args: --locked --target=${{ matrix.job.target }} --verbose --lib --no-default-features --features regex-onig,git
|
||||
|
||||
- name: "Feature check: regex-onig,paging"
|
||||
shell: bash
|
||||
run: $BUILD_CMD check --locked --target=${{ matrix.job.target }} --verbose --lib --no-default-features --features regex-onig,paging
|
||||
uses: actions-rs/cargo@v1
|
||||
with:
|
||||
use-cross: ${{ matrix.job.use-cross }}
|
||||
command: check
|
||||
args: --locked --target=${{ matrix.job.target }} --verbose --lib --no-default-features --features regex-onig,paging
|
||||
|
||||
- name: "Feature check: regex-onig,git,paging"
|
||||
shell: bash
|
||||
run: $BUILD_CMD check --locked --target=${{ matrix.job.target }} --verbose --lib --no-default-features --features regex-onig,git,paging
|
||||
uses: actions-rs/cargo@v1
|
||||
with:
|
||||
use-cross: ${{ matrix.job.use-cross }}
|
||||
command: check
|
||||
args: --locked --target=${{ matrix.job.target }} --verbose --lib --no-default-features --features regex-onig,git,paging
|
||||
|
||||
- name: "Feature check: minimal-application"
|
||||
shell: bash
|
||||
run: $BUILD_CMD check --locked --target=${{ matrix.job.target }} --verbose --no-default-features --features minimal-application
|
||||
uses: actions-rs/cargo@v1
|
||||
with:
|
||||
use-cross: ${{ matrix.job.use-cross }}
|
||||
command: check
|
||||
args: --locked --target=${{ matrix.job.target }} --verbose --no-default-features --features minimal-application
|
||||
|
||||
- name: Create tarball
|
||||
id: package
|
||||
shell: bash
|
||||
run: |
|
||||
PKG_suffix=".tar.gz" ; case ${{ matrix.job.target }} in *-pc-windows-*) PKG_suffix=".zip" ;; esac;
|
||||
PKG_BASENAME=${{ needs.crate_metadata.outputs.name }}-v${{ needs.crate_metadata.outputs.version }}-${{ matrix.job.target }}
|
||||
PKG_BASENAME=${PROJECT_NAME}-v${PROJECT_VERSION}-${{ matrix.job.target }}
|
||||
PKG_NAME=${PKG_BASENAME}${PKG_suffix}
|
||||
echo "PKG_NAME=${PKG_NAME}" >> $GITHUB_OUTPUT
|
||||
echo ::set-output name=PKG_NAME::${PKG_NAME}
|
||||
|
||||
PKG_STAGING="${{ env.CICD_INTERMEDIATES_DIR }}/package"
|
||||
ARCHIVE_DIR="${PKG_STAGING}/${PKG_BASENAME}/"
|
||||
@@ -298,19 +317,19 @@ jobs:
|
||||
mkdir -p "${ARCHIVE_DIR}/autocomplete"
|
||||
|
||||
# Binary
|
||||
cp "${{ steps.bin.outputs.BIN_PATH }}" "$ARCHIVE_DIR"
|
||||
cp "${{ steps.strip.outputs.BIN_PATH }}" "$ARCHIVE_DIR"
|
||||
|
||||
# Man page
|
||||
cp 'target/${{ matrix.job.target }}/release/build/${{ env.PROJECT_NAME }}'-*/out/assets/manual/bat.1 "$ARCHIVE_DIR"
|
||||
|
||||
# README, LICENSE and CHANGELOG files
|
||||
cp "README.md" "LICENSE-MIT" "LICENSE-APACHE" "CHANGELOG.md" "$ARCHIVE_DIR"
|
||||
|
||||
# Man page
|
||||
cp 'target/${{ matrix.job.target }}/release/build/${{ needs.crate_metadata.outputs.name }}'-*/out/assets/manual/bat.1 "$ARCHIVE_DIR"
|
||||
|
||||
# Autocompletion files
|
||||
cp 'target/${{ matrix.job.target }}/release/build/${{ needs.crate_metadata.outputs.name }}'-*/out/assets/completions/bat.bash "$ARCHIVE_DIR/autocomplete/${{ needs.crate_metadata.outputs.name }}.bash"
|
||||
cp 'target/${{ matrix.job.target }}/release/build/${{ needs.crate_metadata.outputs.name }}'-*/out/assets/completions/bat.fish "$ARCHIVE_DIR/autocomplete/${{ needs.crate_metadata.outputs.name }}.fish"
|
||||
cp 'target/${{ matrix.job.target }}/release/build/${{ needs.crate_metadata.outputs.name }}'-*/out/assets/completions/_bat.ps1 "$ARCHIVE_DIR/autocomplete/_${{ needs.crate_metadata.outputs.name }}.ps1"
|
||||
cp 'target/${{ matrix.job.target }}/release/build/${{ needs.crate_metadata.outputs.name }}'-*/out/assets/completions/bat.zsh "$ARCHIVE_DIR/autocomplete/${{ needs.crate_metadata.outputs.name }}.zsh"
|
||||
cp 'target/${{ matrix.job.target }}/release/build/${{ env.PROJECT_NAME }}'-*/out/assets/completions/bat.bash "$ARCHIVE_DIR/autocomplete/${{ env.PROJECT_NAME }}.bash"
|
||||
cp 'target/${{ matrix.job.target }}/release/build/${{ env.PROJECT_NAME }}'-*/out/assets/completions/bat.fish "$ARCHIVE_DIR/autocomplete/${{ env.PROJECT_NAME }}.fish"
|
||||
cp 'target/${{ matrix.job.target }}/release/build/${{ env.PROJECT_NAME }}'-*/out/assets/completions/_bat.ps1 "$ARCHIVE_DIR/autocomplete/_${{ env.PROJECT_NAME }}.ps1"
|
||||
cp 'target/${{ matrix.job.target }}/release/build/${{ env.PROJECT_NAME }}'-*/out/assets/completions/bat.zsh "$ARCHIVE_DIR/autocomplete/${{ env.PROJECT_NAME }}.zsh"
|
||||
|
||||
# base compressed package
|
||||
pushd "${PKG_STAGING}/" >/dev/null
|
||||
@@ -321,7 +340,7 @@ jobs:
|
||||
popd >/dev/null
|
||||
|
||||
# Let subsequent steps know where to find the compressed package
|
||||
echo "PKG_PATH=${PKG_STAGING}/${PKG_NAME}" >> $GITHUB_OUTPUT
|
||||
echo ::set-output name=PKG_PATH::"${PKG_STAGING}/${PKG_NAME}"
|
||||
|
||||
- name: Create Debian package
|
||||
id: debian-package
|
||||
@@ -333,10 +352,10 @@ jobs:
|
||||
DPKG_DIR="${DPKG_STAGING}/dpkg"
|
||||
mkdir -p "${DPKG_DIR}"
|
||||
|
||||
DPKG_BASENAME=${{ needs.crate_metadata.outputs.name }}
|
||||
DPKG_CONFLICTS=${{ needs.crate_metadata.outputs.name }}-musl
|
||||
case ${{ matrix.job.target }} in *-musl) DPKG_BASENAME=${{ needs.crate_metadata.outputs.name }}-musl ; DPKG_CONFLICTS=${{ needs.crate_metadata.outputs.name }} ;; esac;
|
||||
DPKG_VERSION=${{ needs.crate_metadata.outputs.version }}
|
||||
DPKG_BASENAME=${PROJECT_NAME}
|
||||
DPKG_CONFLICTS=${PROJECT_NAME}-musl
|
||||
case ${{ matrix.job.target }} in *-musl) DPKG_BASENAME=${PROJECT_NAME}-musl ; DPKG_CONFLICTS=${PROJECT_NAME} ;; esac;
|
||||
DPKG_VERSION=${PROJECT_VERSION}
|
||||
|
||||
unset DPKG_ARCH
|
||||
case ${{ matrix.job.target }} in
|
||||
@@ -348,19 +367,19 @@ jobs:
|
||||
esac;
|
||||
|
||||
DPKG_NAME="${DPKG_BASENAME}_${DPKG_VERSION}_${DPKG_ARCH}.deb"
|
||||
echo "DPKG_NAME=${DPKG_NAME}" >> $GITHUB_OUTPUT
|
||||
echo ::set-output name=DPKG_NAME::${DPKG_NAME}
|
||||
|
||||
# Binary
|
||||
install -Dm755 "${{ steps.bin.outputs.BIN_PATH }}" "${DPKG_DIR}/usr/bin/${{ steps.bin.outputs.BIN_NAME }}"
|
||||
install -Dm755 "${{ steps.strip.outputs.BIN_PATH }}" "${DPKG_DIR}/usr/bin/${{ steps.strip.outputs.BIN_NAME }}"
|
||||
|
||||
# Man page
|
||||
install -Dm644 'target/${{ matrix.job.target }}/release/build/${{ needs.crate_metadata.outputs.name }}'-*/out/assets/manual/bat.1 "${DPKG_DIR}/usr/share/man/man1/${{ needs.crate_metadata.outputs.name }}.1"
|
||||
gzip -n --best "${DPKG_DIR}/usr/share/man/man1/${{ needs.crate_metadata.outputs.name }}.1"
|
||||
install -Dm644 'target/${{ matrix.job.target }}/release/build/${{ env.PROJECT_NAME }}'-*/out/assets/manual/bat.1 "${DPKG_DIR}/usr/share/man/man1/${{ env.PROJECT_NAME }}.1"
|
||||
gzip -n --best "${DPKG_DIR}/usr/share/man/man1/${{ env.PROJECT_NAME }}.1"
|
||||
|
||||
# Autocompletion files
|
||||
install -Dm644 'target/${{ matrix.job.target }}/release/build/${{ needs.crate_metadata.outputs.name }}'-*/out/assets/completions/bat.bash "${DPKG_DIR}/usr/share/bash-completion/completions/${{ needs.crate_metadata.outputs.name }}"
|
||||
install -Dm644 'target/${{ matrix.job.target }}/release/build/${{ needs.crate_metadata.outputs.name }}'-*/out/assets/completions/bat.fish "${DPKG_DIR}/usr/share/fish/vendor_completions.d/${{ needs.crate_metadata.outputs.name }}.fish"
|
||||
install -Dm644 'target/${{ matrix.job.target }}/release/build/${{ needs.crate_metadata.outputs.name }}'-*/out/assets/completions/bat.zsh "${DPKG_DIR}/usr/share/zsh/vendor-completions/_${{ needs.crate_metadata.outputs.name }}"
|
||||
install -Dm644 'target/${{ matrix.job.target }}/release/build/${{ env.PROJECT_NAME }}'-*/out/assets/completions/bat.bash "${DPKG_DIR}/usr/share/bash-completion/completions/${{ env.PROJECT_NAME }}"
|
||||
install -Dm644 'target/${{ matrix.job.target }}/release/build/${{ env.PROJECT_NAME }}'-*/out/assets/completions/bat.fish "${DPKG_DIR}/usr/share/fish/vendor_completions.d/${{ env.PROJECT_NAME }}.fish"
|
||||
install -Dm644 'target/${{ matrix.job.target }}/release/build/${{ env.PROJECT_NAME }}'-*/out/assets/completions/bat.zsh "${DPKG_DIR}/usr/share/zsh/vendor-completions/_${{ env.PROJECT_NAME }}"
|
||||
|
||||
# README and LICENSE
|
||||
install -Dm644 "README.md" "${DPKG_DIR}/usr/share/doc/${DPKG_BASENAME}/README.md"
|
||||
@@ -371,12 +390,12 @@ jobs:
|
||||
|
||||
cat > "${DPKG_DIR}/usr/share/doc/${DPKG_BASENAME}/copyright" <<EOF
|
||||
Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
|
||||
Upstream-Name: ${{ needs.crate_metadata.outputs.name }}
|
||||
Source: ${{ needs.crate_metadata.outputs.homepage }}
|
||||
Upstream-Name: ${{ env.PROJECT_NAME }}
|
||||
Source: ${{ env.PROJECT_HOMEPAGE }}
|
||||
|
||||
Files: *
|
||||
Copyright: ${{ needs.crate_metadata.outputs.maintainer }}
|
||||
Copyright: $COPYRIGHT_YEARS ${{ needs.crate_metadata.outputs.maintainer }}
|
||||
Copyright: ${{ env.PROJECT_MAINTAINER }}
|
||||
Copyright: $COPYRIGHT_YEARS ${{ env.PROJECT_MAINTAINER }}
|
||||
License: Apache-2.0 or MIT
|
||||
|
||||
License: Apache-2.0
|
||||
@@ -417,17 +436,17 @@ jobs:
|
||||
Version: ${DPKG_VERSION}
|
||||
Section: utils
|
||||
Priority: optional
|
||||
Maintainer: ${{ needs.crate_metadata.outputs.maintainer }}
|
||||
Homepage: ${{ needs.crate_metadata.outputs.homepage }}
|
||||
Maintainer: ${{ env.PROJECT_MAINTAINER }}
|
||||
Homepage: ${{ env.PROJECT_HOMEPAGE }}
|
||||
Architecture: ${DPKG_ARCH}
|
||||
Provides: ${{ needs.crate_metadata.outputs.name }}
|
||||
Provides: ${{ env.PROJECT_NAME }}
|
||||
Conflicts: ${DPKG_CONFLICTS}
|
||||
Description: cat(1) clone with wings.
|
||||
A cat(1) clone with syntax highlighting and Git integration.
|
||||
EOF
|
||||
|
||||
DPKG_PATH="${DPKG_STAGING}/${DPKG_NAME}"
|
||||
echo "DPKG_PATH=${DPKG_PATH}" >> $GITHUB_OUTPUT
|
||||
echo ::set-output name=DPKG_PATH::${DPKG_PATH}
|
||||
|
||||
# build dpkg
|
||||
fakeroot dpkg-deb --build "${DPKG_DIR}" "${DPKG_PATH}"
|
||||
@@ -450,7 +469,7 @@ jobs:
|
||||
shell: bash
|
||||
run: |
|
||||
unset IS_RELEASE ; if [[ $GITHUB_REF =~ ^refs/tags/v[0-9].* ]]; then IS_RELEASE='true' ; fi
|
||||
echo "IS_RELEASE=${IS_RELEASE}" >> $GITHUB_OUTPUT
|
||||
echo ::set-output name=IS_RELEASE::${IS_RELEASE}
|
||||
|
||||
- name: Publish archives and packages
|
||||
uses: softprops/action-gh-release@v1
|
||||
@@ -461,15 +480,3 @@ jobs:
|
||||
${{ steps.debian-package.outputs.DPKG_PATH }}
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
winget:
|
||||
name: Publish to Winget
|
||||
runs-on: ubuntu-latest
|
||||
needs: build
|
||||
if: startsWith(github.ref, 'refs/tags/v')
|
||||
steps:
|
||||
- uses: vedantmgoyal2009/winget-releaser@v2
|
||||
with:
|
||||
identifier: sharkdp.bat
|
||||
installers-regex: '-pc-windows-msvc\.zip$'
|
||||
token: ${{ secrets.WINGET_TOKEN }}
|
||||
|
16
.gitmodules
vendored
16
.gitmodules
vendored
@@ -244,19 +244,3 @@
|
||||
url = https://github.com/victor-gp/cmd-help-sublime-syntax.git
|
||||
branch = main
|
||||
shallow = true
|
||||
[submodule "assets/syntaxes/02_Extra/TodoTxt"]
|
||||
path = assets/syntaxes/02_Extra/TodoTxt
|
||||
url = https://github.com/dertuxmalwieder/SublimeTodoTxt
|
||||
[submodule "assets/syntaxes/02_Extra/Ada"]
|
||||
path = assets/syntaxes/02_Extra/Ada
|
||||
url = https://github.com/wiremoons/ada-sublime-syntax
|
||||
|
||||
[submodule "assets/syntaxes/02_Extra/Crontab"]
|
||||
path = assets/syntaxes/02_Extra/Crontab
|
||||
url = https://github.com/michaelblyons/SublimeSyntax-Crontab
|
||||
[submodule "assets/syntaxes/02_Extra/NSIS"]
|
||||
path = assets/syntaxes/02_Extra/NSIS
|
||||
url = https://github.com/SublimeText/NSIS
|
||||
[submodule "assets/syntaxes/02_Extra/vscode-wgsl"]
|
||||
path = assets/syntaxes/02_Extra/vscode-wgsl
|
||||
url = https://github.com/PolyMeilex/vscode-wgsl.git
|
||||
|
108
CHANGELOG.md
108
CHANGELOG.md
@@ -1,125 +1,21 @@
|
||||
# v0.24.0
|
||||
|
||||
## Features
|
||||
|
||||
- Add environment variable `BAT_PAGING`, see #2629 (@einfachIrgendwer0815)
|
||||
- Add opt-in (`--features lessopen`) support for `LESSOPEN` and `LESSCLOSE`. See #1597, #1739, #2444, #2602, and #2662 (@Anomalocaridid)
|
||||
|
||||
## Bugfixes
|
||||
|
||||
- Fix `more` not being found on Windows when provided via `BAT_PAGER`, see #2570, #2580, and #2651 (@mataha)
|
||||
- Switched default behavior of `--map-syntax` to be case insensitive #2520
|
||||
- Updated version of `serde_yaml` to `0.9`. See #2627 (@Raghav-Bell)
|
||||
- Fix arithmetic overflow in `LineRange::from` and `LineRange::parse_range`, see #2674, #2698 (@skoriop)
|
||||
- Fix paging not happening when stdout is interactive but stdin is not, see #2574 (@Nigecat)
|
||||
- Make `-pp` override `--paging` and vice versa when passed as a later argument, see #2660 (@J-Kappes)
|
||||
|
||||
## Other
|
||||
|
||||
- Output directory for generated assets (completion, manual) can be customized, see #2515 (@tranzystorek-io)
|
||||
- Use the `is-terminal` crate instead of `atty`, see #2530 (@nickelc)
|
||||
- Add Winget Releaser workflow, see #2519 (@sitiom)
|
||||
- Bump MSRV to 1.70, see #2651 (@mataha)
|
||||
|
||||
## Syntaxes
|
||||
|
||||
- Associate `os-release` with `bash` syntax, see #2587 (@cyqsimon)
|
||||
- Associate `Containerfile` with `Dockerfile` syntax, see #2606 (@einfachIrgendwer0815)
|
||||
- Replaced quotes with double quotes so fzf integration example script works on windows and linux. see #2095 (@johnmatthiggins)
|
||||
- Associate `ksh` files with `bash` syntax, see #2633 (@johnmatthiggins)
|
||||
- Associate `sarif` files with `JSON` syntax, see #2695 (@rhysd)
|
||||
- Associate `ron` files with `rust` syntax, see #2427 (@YeungOnion)
|
||||
- Add support for [WebGPU Shader Language](https://www.w3.org/TR/WGSL/), see #2692 (@rhysd)
|
||||
- Add `.dpkg-new` and `.dpkg-tmp` to ignored suffixe, see #2595 (@scop)
|
||||
- fix: Add syntax mapping `*.jsonl` => `json`, see #2539 (@WinterCore)
|
||||
- Update `Julia` syntax, see #2553 (@dependabot)
|
||||
- add `NSIS` support, see #2577 (@idleberg)
|
||||
- Update `ssh-config`, see #2697 (@mrmeszaros)
|
||||
|
||||
## `bat` as a library
|
||||
|
||||
- Add optional output_buffer arg to `Controller::run()` and `Controller::run_with_error_handler()`, see #2618 (@Piturnah)
|
||||
|
||||
|
||||
# v0.23.0
|
||||
|
||||
## Features
|
||||
|
||||
- Implemented `-S` and `--chop-long-lines` flags as aliases for `--wrap=never`. See #2309 (@johnmatthiggins)
|
||||
- Breaking change: Environment variables can now override config file settings (but command-line arguments still have the highest precedence), see #1152, #1281, and #2381 (@aaronkollasch)
|
||||
- Implemented `--nonprintable-notation=caret` to support showing non-printable characters using caret notation. See #2429 (@einfachIrgendwer0815)
|
||||
|
||||
## Bugfixes
|
||||
|
||||
- Fix `bat cache --clear` not clearing the `--target` dir if specified. See #2393 (@miles170)
|
||||
|
||||
## Other
|
||||
|
||||
- Various bash completion improvements, see #2310 (@scop)
|
||||
- Disable completion of `cache` subcommand, see #2399 (@cyqsimon)
|
||||
- Signifigantly improve startup performance on macOS, see #2442 (@BlackHoleFox)
|
||||
- Bump MSRV to 1.62, see #2496 (@Enselic)
|
||||
|
||||
## Syntaxes
|
||||
|
||||
- Added support for Ada, see #1300 and #2316 (@dkm)
|
||||
- Added `todo.txt` syntax, see #2375 (@BANOnotIT)
|
||||
- Improve Manpage.sublime-syntax. See #2364 (@Freed-Wu) and #2461 (@keith-hall)
|
||||
- Added a new `requirements.txt` syntax, see #2361 (@Freed-Wu)
|
||||
- Added a new VimHelp syntax, see #2366 (@Freed-Wu)
|
||||
- Associate `pdm.lock` with `TOML` syntax, see #2410
|
||||
- `Todo.txt`: Fix highlighting of contexts and projects at beginning of done.txt, see #2411
|
||||
- `cmd-help`: overhaul scope names (colors) to improve theme support; misc syntax improvements. See #2419 (@victor-gp)
|
||||
- Added support for Crontab, see #2509 (@keith-hall)
|
||||
|
||||
## Themes
|
||||
|
||||
## `bat` as a library
|
||||
|
||||
- `PrettyPrinter::header` correctly displays a header with the filename, see #2378 and #2406 (@cstyles)
|
||||
|
||||
|
||||
# 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
|
||||
# unreleased
|
||||
|
||||
## Features
|
||||
|
||||
- Make the default macOS theme depend on Dark Mode. See #2197, #1746 (@Enselic)
|
||||
- Support for separate system and user config files. See #668 (@patrickpichler)
|
||||
|
||||
## Bugfixes
|
||||
|
||||
- Prevent fork nightmare with `PAGER=batcat`. See #2235 (@johnmatthiggins)
|
||||
- Make `--no-paging`/`-P` override `--paging=...` if passed as a later arg, see #2201 (@themkat)
|
||||
- `--map-syntax` and `--ignored-suffix` now works together, see #2093 (@czzrr)
|
||||
- Strips byte order mark from output when in non-loop-through mode. See #1922 (@dag-h)
|
||||
|
||||
## Other
|
||||
|
||||
- Relaxed glibc requirements on amd64, see #2106 and #2194 (@sharkdp)
|
||||
- Improved fish completions. See #2275 (@zgracem)
|
||||
- Stop pre-processing ANSI escape characters. Syntax highlighting on ANSI escaped input is not supported. See #2185 and #2189 (@Enselic)
|
||||
|
||||
## Syntaxes
|
||||
|
||||
- NSE (Nmap Scripting Engine) is mapped to Lua, see #2151 (@Cre3per)
|
||||
- Correctly color `fstab` dump and pass fields, see #2246 (@yuvalmo)
|
||||
- Update `Command Help` syntax, see #2255
|
||||
- `Julia`: Fix syntax highlighting for function name starting with `struct`, see #2230
|
||||
- Minor update to `LiveScript`, see #2291
|
||||
- Associate `.mts` and `.cts` files with the `TypeScript` syntax. See #2236 (@kidonng)
|
||||
- Fish history is mapped to YAML. See #2237 (@kidonng)
|
||||
## Themes
|
||||
|
||||
## `bat` as a library
|
||||
|
||||
- Make `bat::PrettyPrinter::syntaxes()` iterate over new `bat::Syntax` struct instead of `&syntect::parsing::SyntaxReference`. See #2222 (@Enselic)
|
||||
- Clear highlights after printing, see #1919 and #1920 (@rhysd)
|
||||
|
||||
|
||||
# v0.21.0
|
||||
|
||||
|
@@ -33,7 +33,7 @@ section in the README.
|
||||
|
||||
Please consider opening a
|
||||
[feature request ticket](https://github.com/sharkdp/bat/issues/new?assignees=&labels=feature-request&template=feature_request.md)
|
||||
first in order to give us a chance to discuss the details and specifics of the potential new feature before you go and build it.
|
||||
first in order to give us a chance to discuss the feature first.
|
||||
|
||||
|
||||
## Adding new syntaxes/languages or themes
|
||||
@@ -50,12 +50,12 @@ first.
|
||||
|
||||
## Regression tests
|
||||
|
||||
You are **strongly encouraged** to add regression tests. Regression tests are great,
|
||||
You are strongly encouraged to add regression tests. Regression tests are great,
|
||||
not least because they:
|
||||
|
||||
* ensure that your contribution will never completely stop working.
|
||||
* ensure that your contribution will never completely stop working,
|
||||
|
||||
* makes code reviews easier, because it becomes very clear what the code is
|
||||
* makes code review easier, because it becomes very clear what the code is
|
||||
supposed to do.
|
||||
|
||||
For functional changes, you most likely want to add a test to
|
||||
|
1068
Cargo.lock
generated
1068
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
71
Cargo.toml
71
Cargo.toml
@@ -3,14 +3,13 @@ authors = ["David Peter <mail@david-peter.de>"]
|
||||
categories = ["command-line-utilities"]
|
||||
description = "A cat(1) clone with wings."
|
||||
homepage = "https://github.com/sharkdp/bat"
|
||||
license = "MIT OR Apache-2.0"
|
||||
license = "MIT/Apache-2.0"
|
||||
name = "bat"
|
||||
repository = "https://github.com/sharkdp/bat"
|
||||
version = "0.24.0"
|
||||
version = "0.21.0"
|
||||
exclude = ["assets/syntaxes/*", "assets/themes/*"]
|
||||
build = "build.rs"
|
||||
edition = '2018'
|
||||
rust-version = "1.70"
|
||||
|
||||
[features]
|
||||
default = ["application"]
|
||||
@@ -25,15 +24,16 @@ application = [
|
||||
# Mainly for developers that want to iterate quickly
|
||||
# Be aware that the included features might change in the future
|
||||
minimal-application = [
|
||||
"atty",
|
||||
"clap",
|
||||
"etcetera",
|
||||
"dirs-next",
|
||||
"paging",
|
||||
"regex-onig",
|
||||
"wild",
|
||||
"rlua"
|
||||
]
|
||||
git = ["git2"] # Support indicating git modifications
|
||||
paging = ["shell-words", "grep-cli"] # Support applying a pager on the output
|
||||
lessopen = ["run_script", "os_str_bytes"] # Support $LESSOPEN preprocessor
|
||||
build-assets = ["syntect/yaml-load", "syntect/plist-load", "regex", "walkdir"]
|
||||
|
||||
# You need to use one of these if you depend on bat as a library:
|
||||
@@ -41,35 +41,35 @@ regex-onig = ["syntect/regex-onig"] # Use the "oniguruma" regex engine
|
||||
regex-fancy = ["syntect/regex-fancy"] # Use the rust-only "fancy-regex" engine
|
||||
|
||||
[dependencies]
|
||||
nu-ansi-term = "0.49.0"
|
||||
ansi_colours = "^1.2"
|
||||
atty = { version = "0.2.14", optional = true }
|
||||
ansi_term = "^0.12.1"
|
||||
ansi_colours = "^1.1"
|
||||
bincode = "1.0"
|
||||
console = "0.15.5"
|
||||
console = "0.15.0"
|
||||
flate2 = "1.0"
|
||||
once_cell = "1.18"
|
||||
once_cell = "1.10"
|
||||
thiserror = "1.0"
|
||||
wild = { version = "2.1", optional = true }
|
||||
wild = { version = "2.0", optional = true }
|
||||
content_inspector = "0.2.4"
|
||||
encoding = "0.2"
|
||||
shell-words = { version = "1.1.0", optional = true }
|
||||
unicode-width = "0.1.10"
|
||||
unicode-width = "0.1.9"
|
||||
globset = "0.4"
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
serde_yaml = "0.9"
|
||||
serde_yaml = "0.8"
|
||||
semver = "1.0"
|
||||
path_abs = { version = "0.5", default-features = false }
|
||||
clircle = "0.4"
|
||||
clircle = "0.3"
|
||||
bugreport = { version = "0.5.0", optional = true }
|
||||
etcetera = { version = "0.8.0", optional = true }
|
||||
grep-cli = { version = "0.1.9", optional = true }
|
||||
regex = { version = "1.8.3", optional = true }
|
||||
walkdir = { version = "2.3", optional = true }
|
||||
bytesize = { version = "1.3.0" }
|
||||
encoding_rs = "0.8.33"
|
||||
os_str_bytes = { version = "~6.4", optional = true }
|
||||
run_script = { version = "^0.10.0", optional = true}
|
||||
dirs-next = { version = "2.0.0", optional = true }
|
||||
grep-cli = { version = "0.1.6", optional = true }
|
||||
regex = { version = "1.5.5", optional = true }
|
||||
walkdir = { version = "2.0", optional = true }
|
||||
bytesize = { version = "1.1.0" }
|
||||
rlua = { version = "0.19", optional = true }
|
||||
|
||||
[dependencies.git2]
|
||||
version = "0.18"
|
||||
version = "0.14"
|
||||
optional = true
|
||||
default-features = false
|
||||
|
||||
@@ -79,31 +79,24 @@ default-features = false
|
||||
features = ["parsing"]
|
||||
|
||||
[dependencies.clap]
|
||||
version = "4.4.6"
|
||||
version = "2.34"
|
||||
optional = true
|
||||
features = ["wrap_help", "cargo"]
|
||||
|
||||
[target.'cfg(target_os = "macos")'.dependencies]
|
||||
home = "0.5.4"
|
||||
plist = "1.4.3"
|
||||
default-features = false
|
||||
features = ["suggestions", "color", "wrap_help"]
|
||||
|
||||
[dev-dependencies]
|
||||
assert_cmd = "2.0.10"
|
||||
expect-test = "1.4.1"
|
||||
serial_test = { version = "2.0.0", default-features = false }
|
||||
predicates = "3.0.3"
|
||||
assert_cmd = "2.0.4"
|
||||
serial_test = "0.6.0"
|
||||
predicates = "2.1.1"
|
||||
wait-timeout = "0.2.0"
|
||||
tempfile = "3.8.0"
|
||||
tempfile = "3.3.0"
|
||||
|
||||
[target.'cfg(unix)'.dev-dependencies]
|
||||
nix = { version = "0.26.2", default-features = false, features = ["term"] }
|
||||
nix = { version = "0.24.1", default-features = false, features = ["term"] }
|
||||
|
||||
[build-dependencies.clap]
|
||||
version = "4.4.6"
|
||||
optional = true
|
||||
features = ["wrap_help", "cargo"]
|
||||
[build-dependencies]
|
||||
clap = { version = "2.34", optional = true }
|
||||
|
||||
[profile.release]
|
||||
lto = true
|
||||
strip = true
|
||||
codegen-units = 1
|
||||
|
@@ -1,4 +1,4 @@
|
||||
Copyright (c) 2018-2023 bat-developers (https://github.com/sharkdp/bat).
|
||||
Copyright (c) 2018-2021 bat-developers (https://github.com/sharkdp/bat).
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
45
README.md
45
README.md
@@ -32,16 +32,6 @@ A special *thank you* goes to our biggest <a href="doc/sponsors.md">sponsors</a>
|
||||
<sup>Add Single Sign-On (and more) in minutes instead of months.</sup>
|
||||
</a>
|
||||
|
||||
<a href="https://www.warp.dev/?utm_source=github&utm_medium=referral&utm_campaign=bat_20231001">
|
||||
<img src="doc/sponsors/warp-logo.png" width="200" alt="Warp">
|
||||
<br>
|
||||
<strong>Warp is a modern, Rust-based terminal with AI built in<br>so you and your team can build great software, faster.</strong>
|
||||
<br>
|
||||
<sub>Feel more productive on the command line with parameterized commands,</sub>
|
||||
<br>
|
||||
<sup>autosuggestions, and an IDE-like text editor.</sup>
|
||||
</a>
|
||||
|
||||
### Syntax highlighting
|
||||
|
||||
`bat` supports syntax highlighting for a large number of programming and markup
|
||||
@@ -128,7 +118,7 @@ use `bat`s `--color=always` option to force colorized output. You can also use `
|
||||
option to restrict the load times for long files:
|
||||
|
||||
```bash
|
||||
fzf --preview "bat --color=always --style=numbers --line-range=:500 {}"
|
||||
fzf --preview 'bat --color=always --style=numbers --line-range=:500 {}'
|
||||
```
|
||||
|
||||
For more information, see [`fzf`'s `README`](https://github.com/junegunn/fzf#preview-window).
|
||||
@@ -238,17 +228,6 @@ help() {
|
||||
|
||||
Then you can do `$ help cp` or `$ help git commit`.
|
||||
|
||||
When you are using `zsh`, you can also use global aliases to override `-h` and `--help` entirely:
|
||||
|
||||
```bash
|
||||
alias -g -- -h='-h 2>&1 | bat --language=help --style=plain'
|
||||
alias -g -- --help='--help 2>&1 | bat --language=help --style=plain'
|
||||
```
|
||||
|
||||
This way, you can keep on using `cp --help`, but get colorized help pages.
|
||||
|
||||
Be aware that in some cases, `-h` may not be a shorthand of `--help` (for example with `ls`).
|
||||
|
||||
Please report any issues with the help syntax in [this repository](https://github.com/victor-gp/cmd-help-sublime-syntax).
|
||||
|
||||
|
||||
@@ -388,7 +367,7 @@ Existing packages may be available, but are not officially supported and may con
|
||||
|
||||
### On macOS (or Linux) via Homebrew
|
||||
|
||||
You can install `bat` with [Homebrew](https://formulae.brew.sh/formula/bat):
|
||||
You can install `bat` with [Homebrew on MacOS](https://formulae.brew.sh/formula/bat) or [Homebrew on Linux](https://formulae.brew.sh/formula-linux/bat):
|
||||
|
||||
```bash
|
||||
brew install bat
|
||||
@@ -411,14 +390,6 @@ take a look at the ["Using `bat` on Windows"](#using-bat-on-windows) section.
|
||||
|
||||
You will need to install the [Visual C++ Redistributable](https://support.microsoft.com/en-us/help/2977003/the-latest-supported-visual-c-downloads) package.
|
||||
|
||||
#### With WinGet
|
||||
|
||||
You can install `bat` via [WinGet](https://learn.microsoft.com/en-us/windows/package-manager/winget):
|
||||
|
||||
```bash
|
||||
winget install sharkdp.bat
|
||||
```
|
||||
|
||||
#### With Chocolatey
|
||||
|
||||
You can install `bat` via [Chocolatey](https://chocolatey.org/packages/Bat):
|
||||
@@ -447,7 +418,7 @@ binaries are also available: look for archives with `musl` in the file name.
|
||||
|
||||
### From source
|
||||
|
||||
If you want to build `bat` from source, you need Rust 1.70.0 or
|
||||
If you want to build `bat` from source, you need Rust 1.51 or
|
||||
higher. You can then use `cargo` to build everything:
|
||||
|
||||
```bash
|
||||
@@ -668,10 +639,6 @@ A default configuration file can be created with the `--generate-config-file` op
|
||||
bat --generate-config-file
|
||||
```
|
||||
|
||||
There is also now a systemwide configuration file, which is located under `/etc/bat/config` on
|
||||
Linux and Mac OS and `C:\ProgramData\bat\config` on windows. If the system wide configuration
|
||||
file is present, the content of the user configuration will simply be appended to it.
|
||||
|
||||
### Format
|
||||
|
||||
The configuration file is a simple list of command line arguments. Use `bat --help` to see a full list of possible options and values. In addition, you can add comments by prepending a line with the `#` character.
|
||||
@@ -713,7 +680,9 @@ Windows 10 natively supports colors in both `conhost.exe` (Command Prompt) and P
|
||||
well as in newer versions of bash. On earlier versions of Windows, you can use
|
||||
[Cmder](http://cmder.net/), which includes [ConEmu](https://conemu.github.io/).
|
||||
|
||||
**Note:** Old versions of `less` do not correctly interpret colors on Windows. To fix this, you can add the optional Unix tools to your PATH when installing Git. If you don’t have any other pagers installed, you can disable paging entirely by passing `--paging=never` or by setting `BAT_PAGER` to an empty string.
|
||||
**Note:** The Git and MSYS versions of `less` do not correctly interpret colors on Windows. If you
|
||||
don’t have any other pagers installed, you can disable paging entirely by passing `--paging=never`
|
||||
or by setting `BAT_PAGER` to an empty string.
|
||||
|
||||
### Cygwin
|
||||
|
||||
@@ -828,7 +797,7 @@ There are a lot of alternatives, if you are looking for similar programs. See
|
||||
[this document](doc/alternatives.md) for a comparison.
|
||||
|
||||
## License
|
||||
Copyright (c) 2018-2023 [bat-developers](https://github.com/sharkdp/bat).
|
||||
Copyright (c) 2018-2021 [bat-developers](https://github.com/sharkdp/bat).
|
||||
|
||||
`bat` is made available under the terms of either the MIT License or the Apache License 2.0, at your option.
|
||||
|
||||
|
BIN
assets/acknowledgements.bin
vendored
BIN
assets/acknowledgements.bin
vendored
Binary file not shown.
5
assets/completions/_bat.ps1.in
vendored
5
assets/completions/_bat.ps1.in
vendored
@@ -59,8 +59,6 @@ Register-ArgumentCompleter -Native -CommandName '{{PROJECT_EXECUTABLE}}' -Script
|
||||
[CompletionResult]::new('--unbuffered', 'unbuffered', [CompletionResultType]::ParameterName, 'unbuffered')
|
||||
[CompletionResult]::new('--no-config', 'no-config', [CompletionResultType]::ParameterName, 'Do not use the configuration file')
|
||||
[CompletionResult]::new('--no-custom-assets', 'no-custom-assets', [CompletionResultType]::ParameterName, 'Do not load custom assets')
|
||||
[CompletionResult]::new('--lessopen', 'lessopen', [CompletionResultType]::ParameterName, 'Enable the $LESSOPEN preprocessor')
|
||||
[CompletionResult]::new('--no-lessopen', 'no-lessopen', [CompletionResultType]::ParameterName, 'Disable the $LESSOPEN preprocessor if enabled (overrides --lessopen)')
|
||||
[CompletionResult]::new('--config-file', 'config-file', [CompletionResultType]::ParameterName, 'Show path to the configuration file.')
|
||||
[CompletionResult]::new('--generate-config-file', 'generate-config-file', [CompletionResultType]::ParameterName, 'Generates a default configuration file.')
|
||||
[CompletionResult]::new('--config-dir', 'config-dir', [CompletionResultType]::ParameterName, 'Show bat''s configuration directory.')
|
||||
@@ -70,8 +68,7 @@ Register-ArgumentCompleter -Native -CommandName '{{PROJECT_EXECUTABLE}}' -Script
|
||||
[CompletionResult]::new('--help', 'help', [CompletionResultType]::ParameterName, 'Print this help message.')
|
||||
[CompletionResult]::new('-V', 'V', [CompletionResultType]::ParameterName, 'Show version information.')
|
||||
[CompletionResult]::new('--version', 'version', [CompletionResultType]::ParameterName, 'Show version information.')
|
||||
## Completion of the 'cache' command itself is removed for better UX
|
||||
## See https://github.com/sharkdp/bat/issues/2085#issuecomment-1271646802
|
||||
[CompletionResult]::new('cache', 'cache', [CompletionResultType]::ParameterValue, 'Modify the syntax-definition and theme cache')
|
||||
break
|
||||
}
|
||||
'{{PROJECT_EXECUTABLE}};cache' {
|
||||
|
123
assets/completions/bat.bash.in
vendored
123
assets/completions/bat.bash.in
vendored
@@ -10,29 +10,8 @@ __bat_init_completion()
|
||||
_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() {
|
||||
local cur prev words split=false
|
||||
local cur prev words cword split=false
|
||||
if declare -F _init_completion >/dev/null 2>&1; then
|
||||
_init_completion -s || return 0
|
||||
else
|
||||
@@ -48,12 +27,7 @@ _bat() {
|
||||
;;
|
||||
esac
|
||||
COMPREPLY=($(compgen -W "
|
||||
--build
|
||||
--clear
|
||||
--source
|
||||
--target
|
||||
--blank
|
||||
--help
|
||||
--build --clear --source --target --blank --help
|
||||
" -- "$cur"))
|
||||
return 0
|
||||
fi
|
||||
@@ -66,27 +40,13 @@ _bat() {
|
||||
printf "%s\n" "$lang"
|
||||
done
|
||||
)" -- "$cur"))
|
||||
__bat_escape_completions
|
||||
compopt -o filenames # for escaping
|
||||
return 0
|
||||
;;
|
||||
-H | --highlight-line | \
|
||||
--diff-context | \
|
||||
--tabs | \
|
||||
--terminal-width | \
|
||||
-m | --map-syntax | \
|
||||
--ignored-suffix | \
|
||||
--list-themes | \
|
||||
--line-range | \
|
||||
-L | --list-languages | \
|
||||
--lessopen | \
|
||||
--diagnostic | \
|
||||
--acknowledgements | \
|
||||
-h | --help | \
|
||||
-V | --version | \
|
||||
--cache-dir | \
|
||||
--config-dir | \
|
||||
--config-file | \
|
||||
--generate-config-file)
|
||||
-H | --highlight-line | --diff-context | --tabs | --terminal-width | \
|
||||
-m | --map-syntax | --style | --line-range | -h | --help | -V | \
|
||||
--version | --diagnostic | --config-file | --config-dir | \
|
||||
--cache-dir | --generate-config-file)
|
||||
# argument required but no completion available, or option
|
||||
# causes an exit
|
||||
return 0
|
||||
@@ -114,79 +74,28 @@ _bat() {
|
||||
--theme)
|
||||
local IFS=$'\n'
|
||||
COMPREPLY=($(compgen -W "$("$1" --list-themes)" -- "$cur"))
|
||||
__bat_escape_completions
|
||||
compopt -o filenames # for escaping
|
||||
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
|
||||
|
||||
$split && return 0
|
||||
|
||||
if [[ $cur == -* ]]; then
|
||||
# --unbuffered excluded intentionally (no-op)
|
||||
COMPREPLY=($(compgen -W "
|
||||
--show-all
|
||||
--plain
|
||||
--language
|
||||
--highlight-line
|
||||
--file-name
|
||||
--diff
|
||||
--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
|
||||
--lessopen
|
||||
--diagnostic
|
||||
--acknowledgements
|
||||
--help
|
||||
--version
|
||||
--cache-dir
|
||||
--config-dir
|
||||
--config-file
|
||||
--show-all --plain --language --highlight-line
|
||||
--file-name --diff --diff-context --tabs --wrap
|
||||
--terminal-width --number --color --italic-text
|
||||
--decorations --paging --pager --map-syntax --theme
|
||||
--list-themes --style --line-range --list-languages
|
||||
--help --version --force-colorization --unbuffered
|
||||
--diagnostic --config-file --config-dir --cache-dir
|
||||
--generate-config-file
|
||||
" -- "$cur"))
|
||||
return 0
|
||||
fi
|
||||
|
||||
_filedir
|
||||
((cword == 1)) && COMPREPLY+=($(compgen -W cache -- "$cur"))
|
||||
|
||||
## Completion of the 'cache' command itself is removed for better UX
|
||||
## See https://github.com/sharkdp/bat/issues/2085#issuecomment-1271646802
|
||||
} && complete -F _bat {{PROJECT_EXECUTABLE}}
|
||||
|
230
assets/completions/bat.fish.in
vendored
230
assets/completions/bat.fish.in
vendored
@@ -1,222 +1,78 @@
|
||||
# Fish Shell Completions
|
||||
# Copy or symlink to $XDG_CONFIG_HOME/fish/completions/{{PROJECT_EXECUTABLE}}.fish
|
||||
# ($XDG_CONFIG_HOME is usually set to ~/.config)
|
||||
# Place or symlink to $XDG_CONFIG_HOME/fish/completions/{{PROJECT_EXECUTABLE}}.fish ($XDG_CONFIG_HOME is usually set to ~/.config)
|
||||
|
||||
# `bat` is `batcat` on Debian and Ubuntu
|
||||
set bat {{PROJECT_EXECUTABLE}}
|
||||
# Helper function:
|
||||
function __{{PROJECT_EXECUTABLE}}_autocomplete_languages --description "A helper function used by "(status filename)
|
||||
{{PROJECT_EXECUTABLE}} --list-languages | awk -F':' '
|
||||
{
|
||||
lang=$1
|
||||
split($2, exts, ",")
|
||||
|
||||
# Helper functions:
|
||||
|
||||
function __bat_complete_files -a token
|
||||
# Cheat to complete files by calling `complete -C` on a fake command name,
|
||||
# like `__fish_complete_directories` does.
|
||||
set -l fake_command aaabccccdeeeeefffffffffgghhhhhhiiiii
|
||||
complete -C"$fake_command $token"
|
||||
for (i in exts) {
|
||||
ext=exts[i]
|
||||
if (ext !~ /[A-Z].*/ && ext !~ /^\..*rc$/) {
|
||||
print ext"\t"lang
|
||||
}
|
||||
}
|
||||
}
|
||||
' | sort
|
||||
end
|
||||
|
||||
function __bat_complete_one_language -a comp
|
||||
command $bat --list-languages | string split -f1 : | string match -e "$comp"
|
||||
end
|
||||
|
||||
function __bat_complete_list_languages
|
||||
for spec in (command $bat --list-languages)
|
||||
set -l name (string split -f1 : $spec)
|
||||
for ext in (string split -f2 : $spec | string split ,)
|
||||
test -n "$ext"; or continue
|
||||
string match -rq '[/*]' $ext; and continue
|
||||
printf "%s\t%s\n" $ext $name
|
||||
end
|
||||
printf "%s\t\n" $name
|
||||
end
|
||||
end
|
||||
|
||||
function __bat_complete_map_syntax
|
||||
set -l token (commandline -ct)
|
||||
|
||||
if string match -qr '(?<glob>.+):(?<syntax>.*)' -- $token
|
||||
# If token ends with a colon, complete with the list of language names.
|
||||
set -f comps $glob:(__bat_complete_one_language $syntax)
|
||||
else if string match -qr '\*' -- $token
|
||||
# If token contains a globbing character (`*`), complete only possible
|
||||
# globs in the current directory
|
||||
set -f comps (__bat_complete_files $token | string match -er '[*]'):
|
||||
else
|
||||
# Complete files (and globs).
|
||||
set -f comps (__bat_complete_files $token | string match -erv '/$'):
|
||||
end
|
||||
|
||||
if set -q comps[1]
|
||||
printf "%s\t\n" $comps
|
||||
end
|
||||
end
|
||||
|
||||
function __bat_cache_subcommand
|
||||
__fish_seen_subcommand_from cache
|
||||
end
|
||||
|
||||
# Returns true if no exclusive arguments seen.
|
||||
function __bat_no_excl_args
|
||||
not __bat_cache_subcommand; and not __fish_seen_argument \
|
||||
-s h -l help \
|
||||
-s V -l version \
|
||||
-l acknowledgements \
|
||||
-l config-dir -l config-file \
|
||||
-l diagnostic \
|
||||
-l list-languages -l list-themes
|
||||
end
|
||||
|
||||
# Returns true if the 'cache' subcommand is seen without any exclusive arguments.
|
||||
function __bat_cache_no_excl
|
||||
__bat_cache_subcommand; and not __fish_seen_argument \
|
||||
-s h -l help \
|
||||
-l acknowledgements -l build -l clear
|
||||
end
|
||||
|
||||
function __bat_style_opts
|
||||
set -l style_opts \
|
||||
"default,recommended components" \
|
||||
"auto,same as 'default' unless piped" \
|
||||
"full,all components" \
|
||||
"plain,no components" \
|
||||
"changes,Git change markers" \
|
||||
"header,alias for header-filename" \
|
||||
"header-filename,filename above content" \
|
||||
"header-filesize,filesize above content" \
|
||||
"grid,lines b/w sidebar/header/content" \
|
||||
"numbers,line numbers in sidebar" \
|
||||
"rule,separate files" \
|
||||
"snip,separate ranges"
|
||||
|
||||
string replace , \t $style_opts
|
||||
end
|
||||
|
||||
# Use option argument descriptions to indicate which is the default, saving
|
||||
# horizontal space and making sure the option description isn't truncated.
|
||||
set -l color_opts '
|
||||
auto\tdefault
|
||||
never\t
|
||||
always\t
|
||||
'
|
||||
set -l decorations_opts $color_opts
|
||||
set -l paging_opts $color_opts
|
||||
|
||||
# Include some examples so we can indicate the default.
|
||||
set -l pager_opts '
|
||||
less\tdefault
|
||||
less\ -FR\t
|
||||
more\t
|
||||
vimpager\t
|
||||
'
|
||||
|
||||
set -l italic_text_opts '
|
||||
always\t
|
||||
never\tdefault
|
||||
'
|
||||
|
||||
set -l wrap_opts '
|
||||
auto\tdefault
|
||||
never\t
|
||||
character\t
|
||||
'
|
||||
|
||||
# While --tabs theoretically takes any number, most people should be OK with these.
|
||||
# Specifying a list lets us explain what 0 does.
|
||||
set -l tabs_opts '
|
||||
0\tpass\ tabs\ through\ directly
|
||||
1\t
|
||||
2\t
|
||||
4\t
|
||||
8\t
|
||||
'
|
||||
|
||||
# Completions:
|
||||
|
||||
complete -c $bat -l acknowledgements -d "Print acknowledgements" -n __fish_is_first_arg
|
||||
complete -c {{PROJECT_EXECUTABLE}} -l color -xka "auto never always" -d "Specify when to use colored output (default: auto)" -n "not __fish_seen_subcommand_from cache"
|
||||
|
||||
complete -c $bat -l color -x -a "$color_opts" -d "When to use colored output" -n __bat_no_excl_args
|
||||
complete -c {{PROJECT_EXECUTABLE}} -l config-dir -d "Display location of '{{PROJECT_EXECUTABLE}}' configuration directory" -n "not __fish_seen_subcommand_from cache"
|
||||
|
||||
complete -c $bat -l config-dir -f -d "Display location of configuration directory" -n __fish_is_first_arg
|
||||
complete -c {{PROJECT_EXECUTABLE}} -l config-file -d "Display location of '{{PROJECT_EXECUTABLE}}' configuration file" -n "not __fish_seen_subcommand_from cache"
|
||||
|
||||
complete -c $bat -l config-file -f -d "Display location of configuration file" -n __fish_is_first_arg
|
||||
complete -c {{PROJECT_EXECUTABLE}} -l decorations -xka "auto never always" -d "Specify when to use the decorations specified with '--style' (default: auto)" -n "not __fish_seen_subcommand_from cache"
|
||||
|
||||
complete -c $bat -l decorations -x -a "$decorations_opts" -d "When to use --style decorations" -n __bat_no_excl_args
|
||||
complete -c {{PROJECT_EXECUTABLE}} -s h -l help -d "Print help message" -n "not __fish_seen_subcommand_from cache"
|
||||
|
||||
complete -c $bat -l diagnostic -d "Print diagnostic info for bug reports" -n __fish_is_first_arg
|
||||
complete -c {{PROJECT_EXECUTABLE}} -s H -l highlight-line -x -d "<N> Highlight the N-th line with a different background color" -n "not __fish_seen_subcommand_from cache"
|
||||
|
||||
complete -c $bat -s d -l diff -d "Only show lines with Git changes" -n __bat_no_excl_args
|
||||
complete -c {{PROJECT_EXECUTABLE}} -l italic-text -xka "always never" -d "Specify when to use ANSI sequences for italic text (default: never)" -n "not __fish_seen_subcommand_from cache"
|
||||
|
||||
complete -c $bat -l diff-context -x -d "Show N context lines around Git changes" -n "__fish_seen_argument -s d -l diff"
|
||||
complete -c {{PROJECT_EXECUTABLE}} -s l -l language -d "Set the language for syntax highlighting" -n "not __fish_seen_subcommand_from cache" -xa "(__{{PROJECT_EXECUTABLE}}_autocomplete_languages)"
|
||||
|
||||
complete -c $bat -l file-name -x -d "Specify the display name" -n __bat_no_excl_args
|
||||
complete -c {{PROJECT_EXECUTABLE}} -s r -l line-range -x -d "<N:M> Only print the specified range of lines for each file" -n "not __fish_seen_subcommand_from cache"
|
||||
|
||||
complete -c $bat -s f -l force-colorization -d "Force color and decorations" -n __bat_no_excl_args
|
||||
complete -c {{PROJECT_EXECUTABLE}} -l list-languages -d "Display list of supported languages for syntax highlighting" -n "not __fish_seen_subcommand_from cache"
|
||||
|
||||
complete -c $bat -s h -d "Print a concise overview" -n __fish_is_first_arg
|
||||
complete -c {{PROJECT_EXECUTABLE}} -l list-themes -d "Display a list of supported themes for syntax highlighting" -n "not __fish_seen_subcommand_from cache"
|
||||
|
||||
complete -c $bat -l help -f -d "Print all help information" -n __fish_is_first_arg
|
||||
complete -c {{PROJECT_EXECUTABLE}} -s m -l map-syntax -x -d "<from:to> Map a file extension or file name to an existing syntax" -n "not __fish_seen_subcommand_from cache"
|
||||
|
||||
complete -c $bat -s H -l highlight-line -x -d "Highlight line(s) N[:M]" -n __bat_no_excl_args
|
||||
complete -c {{PROJECT_EXECUTABLE}} -s n -l number -d "Only show line numbers, no other decorations. Alias for '--style=numbers'" -n "not __fish_seen_subcommand_from cache"
|
||||
|
||||
complete -c $bat -l ignored-suffix -x -d "Ignore extension" -n __bat_no_excl_args
|
||||
complete -c {{PROJECT_EXECUTABLE}} -l pager -x -d "<command> Specify which pager program to use (default: less)" -n "not __fish_seen_subcommand_from cache"
|
||||
|
||||
complete -c $bat -l italic-text -x -a "$italic_text_opts" -d "When to use italic text in the output" -n __bat_no_excl_args
|
||||
complete -c {{PROJECT_EXECUTABLE}} -l paging -xka "auto never always" -d "Specify when to use the pager (default: auto)" -n "not __fish_seen_subcommand_from cache"
|
||||
|
||||
complete -c $bat -s l -l language -x -k -a "(__bat_complete_list_languages)" -d "Set the syntax highlighting language" -n __bat_no_excl_args
|
||||
complete -c {{PROJECT_EXECUTABLE}} -s p -l plain -d "Only show plain style, no decorations. Alias for '--style=plain'" -n "not __fish_seen_subcommand_from cache"
|
||||
|
||||
complete -c $bat -l lessopen -d "Enable the $LESSOPEN preprocessor" -n __fish_is_first_arg
|
||||
complete -c {{PROJECT_EXECUTABLE}} -s P -d "Disable paging. Alias for '--paging=never'" -n "not __fish_seen_subcommand_from cache"
|
||||
|
||||
complete -c $bat -s r -l line-range -x -d "Only print lines [M]:[N] (either optional)" -n __bat_no_excl_args
|
||||
complete -c {{PROJECT_EXECUTABLE}} -s A -l show-all -d "Show non-printable characters like space/tab/newline" -n "not __fish_seen_subcommand_from cache"
|
||||
|
||||
complete -c $bat -l list-languages -f -d "List syntax highlighting languages" -n __fish_is_first_arg
|
||||
complete -c {{PROJECT_EXECUTABLE}} -l style -xka "default auto full plain changes header header-filename header-filesize grid rule numbers snip" -d "Comma-separated list of style elements or presets to display with file contents" -n "not __fish_seen_subcommand_from cache"
|
||||
|
||||
complete -c $bat -l list-themes -f -d "List syntax highlighting themes" -n __fish_is_first_arg
|
||||
complete -c {{PROJECT_EXECUTABLE}} -l tabs -x -d "<T> Set the tab width to T spaces (width of 0 passes tabs through directly)" -n "not __fish_seen_subcommand_from cache"
|
||||
|
||||
complete -c $bat -s m -l map-syntax -x -a "(__bat_complete_map_syntax)" -d "Map <glob pattern>:<language syntax>" -n __bat_no_excl_args
|
||||
complete -c {{PROJECT_EXECUTABLE}} -l terminal-width -x -d "<width> Explicitly set terminal width; Prefix with '+' or '-' to offset (default width is auto determined)" -n "not __fish_seen_subcommand_from cache"
|
||||
|
||||
complete -c $bat -s n -l number -d "Only show line numbers, no other decorations" -n __bat_no_excl_args
|
||||
complete -c {{PROJECT_EXECUTABLE}} -l theme -xka "({{PROJECT_EXECUTABLE}} --list-themes | cat)" -d "Set the theme for syntax highlighting" -n "not __fish_seen_subcommand_from cache"
|
||||
|
||||
complete -c $bat -l pager -x -a "$pager_opts" -d "Which pager to use" -n __bat_no_excl_args
|
||||
complete -c {{PROJECT_EXECUTABLE}} -s u -l unbuffered -d "POSIX-compliant unbuffered output. Option is ignored" -n "not __fish_seen_subcommand_from cache"
|
||||
|
||||
complete -c $bat -l paging -x -a "$paging_opts" -d "When to use the pager" -n __bat_no_excl_args
|
||||
complete -c {{PROJECT_EXECUTABLE}} -s V -l version -d "Show version information" -n "not __fish_seen_subcommand_from cache"
|
||||
|
||||
complete -c $bat -s p -l plain -d "Disable decorations" -n __bat_no_excl_args
|
||||
|
||||
complete -c $bat -o pp -d "Disable decorations and paging" -n __bat_no_excl_args
|
||||
|
||||
complete -c $bat -s P -d "Disable paging" -n __bat_no_excl_args
|
||||
|
||||
complete -c $bat -s A -l show-all -d "Show non-printable characters" -n __bat_no_excl_args
|
||||
|
||||
complete -c $bat -l style -x -k -a "(__fish_complete_list , __bat_style_opts)" -d "Specify which non-content elements to display" -n __bat_no_excl_args
|
||||
|
||||
complete -c $bat -l tabs -x -a "$tabs_opts" -d "Set tab width" -n __bat_no_excl_args
|
||||
|
||||
complete -c $bat -l terminal-width -x -d "Set terminal <width>, +<offset>, or -<offset>" -n __bat_no_excl_args
|
||||
|
||||
complete -c $bat -l theme -x -a "(command $bat --list-themes | command cat)" -d "Set the syntax highlighting theme" -n __bat_no_excl_args
|
||||
|
||||
complete -c $bat -s V -l version -f -d "Show version information" -n __fish_is_first_arg
|
||||
|
||||
complete -c $bat -l wrap -x -a "$wrap_opts" -d "Text-wrapping mode" -n __bat_no_excl_args
|
||||
complete -c {{PROJECT_EXECUTABLE}} -l wrap -xka "auto never character" -d "<mode> Specify the text-wrapping mode (default: auto)" -n "not __fish_seen_subcommand_from cache"
|
||||
|
||||
# Sub-command 'cache' completions
|
||||
## Completion of the 'cache' command itself is removed for better UX
|
||||
## See https://github.com/sharkdp/bat/issues/2085#issuecomment-1271646802
|
||||
complete -c {{PROJECT_EXECUTABLE}} -a "cache" -d "Modify the syntax/language definition cache" -n "not __fish_seen_subcommand_from cache"
|
||||
|
||||
complete -c $bat -l build -f -d "Parse new definitions into cache" -n __bat_cache_no_excl
|
||||
complete -c {{PROJECT_EXECUTABLE}} -l build -f -d "Parse syntaxes/language definitions into cache" -n "__fish_seen_subcommand_from cache"
|
||||
|
||||
complete -c $bat -l clear -f -d "Reset definitions to defaults" -n __bat_cache_no_excl
|
||||
|
||||
complete -c $bat -l blank -f -d "Create new data instead of appending" -n "__bat_cache_subcommand; and not __fish_seen_argument -l clear"
|
||||
|
||||
complete -c $bat -l source -x -a "(__fish_complete_directories)" -d "Load syntaxes and themes from DIR" -n "__bat_cache_subcommand; and not __fish_seen_argument -l clear"
|
||||
|
||||
complete -c $bat -l target -x -a "(__fish_complete_directories)" -d "Store cache in DIR" -n __bat_cache_subcommand
|
||||
|
||||
complete -c $bat -l acknowledgements -d "Build acknowledgements.bin" -n __bat_cache_no_excl
|
||||
|
||||
complete -c $bat -s h -d "Print a concise overview of $bat-cache help" -n __bat_cache_no_excl
|
||||
|
||||
complete -c $bat -l help -f -d "Print all $bat-cache help" -n __bat_cache_no_excl
|
||||
|
||||
# vim:ft=fish
|
||||
complete -c {{PROJECT_EXECUTABLE}} -l clear -f -d "Reset syntaxes/language definitions to default settings" -n "__fish_seen_subcommand_from cache"
|
||||
|
12
assets/completions/bat.zsh.in
vendored
12
assets/completions/bat.zsh.in
vendored
@@ -46,8 +46,6 @@ _{{PROJECT_EXECUTABLE}}_main() {
|
||||
'(: --list-themes --list-languages -L)'{-L,--list-languages}'[Display all supported languages]'
|
||||
'(: --no-config)'--no-config'[Do not use the configuration file]'
|
||||
'(: --no-custom-assets)'--no-custom-assets'[Do not load custom assets]'
|
||||
'(: --lessopen)'--lessopen'[Enable the $LESSOPEN preprocessor]'
|
||||
'(: --no-lessopen)'--no-lessopen'[Disable the $LESSOPEN preprocessor if enabled (overrides --lessopen)]'
|
||||
'(: --config-dir)'--config-dir'[Show bat'"'"'s configuration directory]'
|
||||
'(: --config-file)'--config-file'[Show path to the configuration file]'
|
||||
'(: --generate-config-file)'--generate-config-file'[Generates a default configuration file]'
|
||||
@@ -82,10 +80,15 @@ _{{PROJECT_EXECUTABLE}}_main() {
|
||||
esac
|
||||
}
|
||||
|
||||
# first positional argument
|
||||
if (( ${#words} == 2 )); then
|
||||
local -a subcommands
|
||||
subcommands=('cache:Modify the syntax-definition and theme cache')
|
||||
_describe subcommand subcommands
|
||||
_{{PROJECT_EXECUTABLE}}_main
|
||||
else
|
||||
case $words[2] in
|
||||
cache)
|
||||
## Completion of the 'cache' command itself is removed for better UX
|
||||
## See https://github.com/sharkdp/bat/issues/2085#issuecomment-1271646802
|
||||
_{{PROJECT_EXECUTABLE}}_cache_subcommand
|
||||
;;
|
||||
|
||||
@@ -93,3 +96,4 @@ case $words[2] in
|
||||
_{{PROJECT_EXECUTABLE}}_main
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
|
31
assets/manual/bat.1.in
vendored
31
assets/manual/bat.1.in
vendored
@@ -25,23 +25,11 @@ either '--language value', '--language=value', '-l value' or '-lvalue'.
|
||||
Show non\-printable characters like space, tab or newline. Use '\-\-tabs' to
|
||||
control the width of the tab\-placeholders.
|
||||
.HP
|
||||
\fB\-\-nonprintable\-notation\fR <notation>
|
||||
.IP
|
||||
Specify how to display non-printable characters when using \-\-show\-all.
|
||||
|
||||
Possible values:
|
||||
.RS
|
||||
.IP "caret"
|
||||
Use character sequences like ^G, ^J, ^@, .. to identify non-printable characters
|
||||
.IP "unicode"
|
||||
Use special Unicode code points to identify non-printable characters
|
||||
.RE
|
||||
.HP
|
||||
\fB\-p\fR, \fB\-\-plain\fR
|
||||
.IP
|
||||
Only show plain style, no decorations. This is an alias for
|
||||
\&'\-\-style=plain'. When '\-p' is used twice ('\-pp'), it also disables
|
||||
automatic paging (alias for '\-\-style=plain \fB\-\-paging\fR=\fI\,never\/\fR').
|
||||
automatic paging (alias for '\-\-style=plain \fB\-\-pager\fR=\fI\,never\/\fR').
|
||||
.HP
|
||||
\fB\-l\fR, \fB\-\-language\fR <language>
|
||||
.IP
|
||||
@@ -243,23 +231,6 @@ If you ever want to remove the custom languages, you can clear the cache with `\
|
||||
Similarly to custom languages, {{PROJECT_EXECUTABLE}} supports Sublime Text \fB.tmTheme\fR themes.
|
||||
These can be installed to `\fB$({{PROJECT_EXECUTABLE}} --config-dir)/themes\fR`, and are added to the cache with
|
||||
`\fB{{PROJECT_EXECUTABLE}} cache --build`.
|
||||
|
||||
.SH "INPUT PREPROCESSOR"
|
||||
Much like less(1) does, {{PROJECT_EXECUTABLE}} supports input preprocessors via the LESSOPEN and LESSCLOSE environment variables.
|
||||
In addition, {{PROJECT_EXECUTABLE}} attempts to be as compatible with less's preprocessor implementation as possible.
|
||||
|
||||
To use the preprocessor, call:
|
||||
|
||||
\fB{{PROJECT_EXECUTABLE}} --lessopen\fR
|
||||
|
||||
Alternatively, the preprocessor may be enabled by default by adding the '\-\-lessopen' option to the configuration file.
|
||||
|
||||
To temporarily disable the preprocessor if it is enabled by default, call:
|
||||
|
||||
\fB{{PROJECT_EXECUTABLE}} --no-lessopen\fR
|
||||
|
||||
For more information, see the "INPUT PREPROCESSOR" section of less(1).
|
||||
|
||||
.SH "MORE INFORMATION"
|
||||
|
||||
For more information and up-to-date documentation, visit the {{PROJECT_EXECUTABLE}} repo:
|
||||
|
13
assets/patches/TodoTxt.sublime-syntax.patch
vendored
13
assets/patches/TodoTxt.sublime-syntax.patch
vendored
@@ -1,13 +0,0 @@
|
||||
diff --git syntaxes/02_Extra/TodoTxt/TodoTxt.sublime-syntax syntaxes/02_Extra/TodoTxt/TodoTxt.sublime-syntax
|
||||
index 6c75dbb..0115978 100644
|
||||
--- syntaxes/02_Extra/TodoTxt/TodoTxt.sublime-syntax
|
||||
+++ syntaxes/02_Extra/TodoTxt/TodoTxt.sublime-syntax
|
||||
@@ -68,7 +68,7 @@ contexts:
|
||||
|
||||
- match: (\s+[^\s:]+:[^\s:]+)+\s*$
|
||||
comment: Custom attributes
|
||||
- scope: variable.annotation.todotxt.attribute
|
||||
+ scope: variable.other.todotxt.attribute
|
||||
|
||||
comments:
|
||||
# Comments begin with a '//' and finish at the end of the line.
|
20
assets/patches/TwoDark.tmTheme.patch
vendored
20
assets/patches/TwoDark.tmTheme.patch
vendored
@@ -1,20 +0,0 @@
|
||||
diff --git themes/TwoDark/TwoDark.tmTheme themes/TwoDark/TwoDark.tmTheme
|
||||
index 87fd358..56376d3 100644
|
||||
--- themes/TwoDark/TwoDark.tmTheme
|
||||
+++ themes/TwoDark/TwoDark.tmTheme
|
||||
@@ -533,7 +533,7 @@
|
||||
<key>name</key>
|
||||
<string>Json key</string>
|
||||
<key>scope</key>
|
||||
- <string>source.json meta.structure.dictionary.json string.quoted.double.json</string>
|
||||
+ <string>source.json meta.mapping.key.json string.quoted.double.json</string>
|
||||
<key>settings</key>
|
||||
<dict>
|
||||
<key>foreground</key>
|
||||
@@ -875,4 +875,4 @@
|
||||
<key>comment</key>
|
||||
<string>Work in progress</string>
|
||||
</dict>
|
||||
-</plist>
|
||||
\ No newline at end of file
|
||||
+</plist>
|
BIN
assets/syntaxes.bin
vendored
BIN
assets/syntaxes.bin
vendored
Binary file not shown.
1
assets/syntaxes/02_Extra/Ada
vendored
1
assets/syntaxes/02_Extra/Ada
vendored
Submodule assets/syntaxes/02_Extra/Ada deleted from e2b8fd5175
2
assets/syntaxes/02_Extra/CMake
vendored
2
assets/syntaxes/02_Extra/CMake
vendored
Submodule assets/syntaxes/02_Extra/CMake updated: eb40ede56c...ab6ef4ef9f
1
assets/syntaxes/02_Extra/Crontab
vendored
1
assets/syntaxes/02_Extra/Crontab
vendored
Submodule assets/syntaxes/02_Extra/Crontab deleted from 54f1fa7ff0
2
assets/syntaxes/02_Extra/Docker
vendored
2
assets/syntaxes/02_Extra/Docker
vendored
Submodule assets/syntaxes/02_Extra/Docker updated: 0f6b7bc87a...9e9a518aed
@@ -8,7 +8,6 @@ file_extensions:
|
||||
- .env.local
|
||||
- .env.sample
|
||||
- .env.example
|
||||
- .env.template
|
||||
- .env.test
|
||||
- .env.test.local
|
||||
- .env.testing
|
||||
@@ -24,10 +23,6 @@ file_extensions:
|
||||
- .env.defaults
|
||||
- .envrc
|
||||
- .flaskenv
|
||||
- env
|
||||
- env.example
|
||||
- env.sample
|
||||
- env.template
|
||||
scope: source.env
|
||||
contexts:
|
||||
main:
|
||||
|
@@ -95,7 +95,7 @@ contexts:
|
||||
|
||||
fstab_dump:
|
||||
- include: comment
|
||||
- match: '\s*[012]\s*'
|
||||
- match: '\s*[01]\s*'
|
||||
comment: dump field
|
||||
scope: constant.numeric
|
||||
set: fstab_pass
|
||||
@@ -107,7 +107,7 @@ contexts:
|
||||
|
||||
fstab_pass:
|
||||
- include: comment
|
||||
- match: '\s*[012]\s*'
|
||||
- match: '\s*[01]\s*'
|
||||
comment: pass field
|
||||
scope: constant.numeric
|
||||
set: expected_eol
|
||||
|
2
assets/syntaxes/02_Extra/HTML (Twig)
vendored
2
assets/syntaxes/02_Extra/HTML (Twig)
vendored
Submodule assets/syntaxes/02_Extra/HTML (Twig) updated: aedf955eba...77def406d7
3
assets/syntaxes/02_Extra/INI.sublime-syntax
vendored
3
assets/syntaxes/02_Extra/INI.sublime-syntax
vendored
@@ -16,9 +16,6 @@ file_extensions:
|
||||
- url
|
||||
- URL
|
||||
- .editorconfig
|
||||
- .coveragerc
|
||||
- .pylintrc
|
||||
- .gitlint
|
||||
- .hgrc
|
||||
- hgrc
|
||||
scope: source.ini
|
||||
|
2
assets/syntaxes/02_Extra/Julia
vendored
2
assets/syntaxes/02_Extra/Julia
vendored
Submodule assets/syntaxes/02_Extra/Julia updated: 98233f96d4...1e55f3211b
2
assets/syntaxes/02_Extra/LiveScript
vendored
2
assets/syntaxes/02_Extra/LiveScript
vendored
Submodule assets/syntaxes/02_Extra/LiveScript updated: d82aeb737d...2575013851
37
assets/syntaxes/02_Extra/Manpage.sublime-syntax
vendored
37
assets/syntaxes/02_Extra/Manpage.sublime-syntax
vendored
@@ -53,16 +53,6 @@ contexts:
|
||||
embed: synopsis
|
||||
escape: '(?={{section_heading}})'
|
||||
|
||||
- match: '^(?:COMMANDS)\b'
|
||||
scope: markup.heading.commands.man
|
||||
embed: commands-start
|
||||
escape: '(?={{section_heading}})'
|
||||
|
||||
- match: '^(?:ENVIRONMENT\s+VARIABLES)'
|
||||
scope: markup.heading.env.man
|
||||
embed: environment-variables
|
||||
escape: '(?={{section_heading}})'
|
||||
|
||||
- match: '{{section_heading}}'
|
||||
scope: markup.heading.other.man
|
||||
embed: options # some man pages put command line options under the description heading
|
||||
@@ -85,7 +75,7 @@ contexts:
|
||||
|
||||
options:
|
||||
# command-line options like --option=value, --some-flag, or -x
|
||||
- match: '^[ ]{7}(?=-|\+)'
|
||||
- match: '^[ ]{7}(?=-)'
|
||||
push: expect-command-line-option
|
||||
- match: '(?:[^a-zA-Z0-9_-]|^|\s){{command_line_option}}'
|
||||
captures:
|
||||
@@ -106,7 +96,7 @@ contexts:
|
||||
- include: env-var
|
||||
|
||||
expect-command-line-option:
|
||||
- match: '[A-Za-z0-9-\.\?:#\$\+]+'
|
||||
- match: '[A-Za-z0-9-]+'
|
||||
scope: entity.name.command-line-option.man
|
||||
- match: '(\[)(=)'
|
||||
captures:
|
||||
@@ -132,7 +122,7 @@ contexts:
|
||||
pop: true
|
||||
|
||||
expect-parameter:
|
||||
- match: '[A-Za-z0-9-_]+'
|
||||
- match: '[A-Za-z0-9-]+'
|
||||
scope: variable.parameter.man
|
||||
- match: (?=\s+\|)
|
||||
pop: true
|
||||
@@ -145,10 +135,6 @@ contexts:
|
||||
scope: punctuation.section.brackets.end.man
|
||||
pop: true
|
||||
- include: expect-parameter
|
||||
- match: '<'
|
||||
scope: punctuation.definition.generic.begin.man
|
||||
- match: '>'
|
||||
scope: punctuation.definition.generic.end.man
|
||||
- match: '$|(?=[],]|{{command_line_option}})'
|
||||
pop: true
|
||||
|
||||
@@ -183,20 +169,3 @@ contexts:
|
||||
- match: \[
|
||||
scope: punctuation.section.brackets.begin.man
|
||||
push: command-line-option-or-pipe
|
||||
|
||||
commands-start:
|
||||
- match: (?=^[ ]{7}.*(?:[ ]<|[|]))
|
||||
push: commands
|
||||
|
||||
commands:
|
||||
- match: '^[ ]{7}([a-z_\-]+)(?=[ ]|$)'
|
||||
captures:
|
||||
1: entity.name.command.man
|
||||
push: expect-parameter
|
||||
- match: '^[ ]{7}(?=[\[<]|\w+[|\]])'
|
||||
push: expect-parameter
|
||||
|
||||
environment-variables:
|
||||
- match: '^[ ]{7}([A-Z_]+)\b'
|
||||
captures:
|
||||
1: support.constant.environment-variable.man
|
||||
|
2
assets/syntaxes/02_Extra/MediaWiki
vendored
2
assets/syntaxes/02_Extra/MediaWiki
vendored
Submodule assets/syntaxes/02_Extra/MediaWiki updated: 5dceaa9dd9...81bf97cace
1
assets/syntaxes/02_Extra/NSIS
vendored
1
assets/syntaxes/02_Extra/NSIS
vendored
Submodule assets/syntaxes/02_Extra/NSIS deleted from 619a65a04e
2
assets/syntaxes/02_Extra/PowerShell
vendored
2
assets/syntaxes/02_Extra/PowerShell
vendored
Submodule assets/syntaxes/02_Extra/PowerShell updated: c0372a1d2d...742f0b5d4b
@@ -1,120 +0,0 @@
|
||||
%YAML 1.2
|
||||
---
|
||||
# http://www.sublimetext.com/docs/syntax.html
|
||||
name: Requirements.txt
|
||||
scope: source.requirements-txt
|
||||
# https://pip.pypa.io/en/stable/reference/requirements-file-format/
|
||||
# https://github.com/raimon49/requirements.txt.vim/blob/f246bd10155fbc3b1a9e2fff6c95b21521b09116/ftdetect/requirements.vim
|
||||
file_extensions:
|
||||
- requirements.txt
|
||||
- requirements.in
|
||||
- pip
|
||||
# https://github.com/sublimehq/Packages/pull/2760/files
|
||||
first_line_match: |-
|
||||
(?xi:
|
||||
^ \#! .* \bpip # shebang
|
||||
| ^ \s* \# .*? -\*- .*? \bpip-requirements\b .*? -\*- # editorconfig
|
||||
| ^ \s* \# (vim?|ex): .*? \brequirements\b # modeline
|
||||
)
|
||||
# pip install -r
|
||||
# pip-compile
|
||||
|
||||
variables:
|
||||
operator: '===?|<=?|>=?|~=|!='
|
||||
|
||||
contexts:
|
||||
main:
|
||||
- match: '(?i)\d+[\da-z\-_\.\*]*'
|
||||
scope: constant.other.version-control.requirements-txt
|
||||
- match: '(?i)^\[?--?[\da-z\-]*\]?'
|
||||
scope: entity.name.function.option.requirements-txt
|
||||
- match: '{{operator}}'
|
||||
scope: keyword.operator.logical.requirements-txt
|
||||
- match: '(\[)'
|
||||
captures:
|
||||
1: punctuation.section.braces.begin.requirements-txt
|
||||
push:
|
||||
- meta_scope: variable.function.extra.requirements-txt
|
||||
- match: ','
|
||||
scope: punctuation.separator.requirements-txt
|
||||
- match: '(\])'
|
||||
captures:
|
||||
1: punctuation.section.braces.end.requirements-txt
|
||||
pop: true
|
||||
- match: '(git\+?|hg\+|svn\+|bzr\+).*://.\S+'
|
||||
scope: markup.underline.link.versioncontrols.requirements-txt
|
||||
- match: '(@\s)?(https?|ftp|gopher)://?[^\s/$.?#].\S*'
|
||||
scope: markup.underline.link.url.requirements-txt
|
||||
captures:
|
||||
1: punctuation.definition.keyword.requirements-txt
|
||||
- match: '(?i)^[a-z\d_\-\.]*[a-z\d]'
|
||||
scope: variable.parameter.package-name.requirements-txt
|
||||
- match: '(;)'
|
||||
captures:
|
||||
1: punctuation.definition.annotation.requirements-txt
|
||||
push:
|
||||
- meta_scope: meta.annotation.requirements-txt
|
||||
# https://pip.pypa.io/en/stable/reference/inspect-report/#example
|
||||
- match: |-
|
||||
(?x:
|
||||
implementation_name
|
||||
| implementation_version
|
||||
| os_name
|
||||
| platform_machine
|
||||
| platform_release
|
||||
| platform_system
|
||||
| platform_version
|
||||
| python_full_version
|
||||
| platform_python_implementation
|
||||
| python_version
|
||||
| sys_platform
|
||||
)
|
||||
scope: variable.language.requirements-txt
|
||||
- match: '{{operator}}'
|
||||
scope: keyword.operator.logical.requirements-txt
|
||||
# https://pip.pypa.io/en/stable/reference/requirement-specifiers/#examples
|
||||
- match: '(")'
|
||||
captures:
|
||||
1: punctuation.definition.string.begin.double.requirements-txt
|
||||
push:
|
||||
- meta_scope: string.quoted.double.requirements-txt
|
||||
- match: '\\"'
|
||||
scope: constant.character.escape.double.requirements-txt
|
||||
- match: '(")'
|
||||
captures:
|
||||
1: punctuation.definition.string.end.double.requirements-txt
|
||||
pop: true
|
||||
- match: "(')"
|
||||
captures:
|
||||
1: punctuation.definition.string.begin.single.requirements-txt
|
||||
push:
|
||||
- meta_scope: string.quoted.single.requirements-txt
|
||||
- match: '\\'''
|
||||
scope: constant.character.escape.single.requirements-txt
|
||||
- match: "(')"
|
||||
captures:
|
||||
1: punctuation.definition.string.end.single.requirements-txt
|
||||
pop: true
|
||||
- match: '(.(?=#)|$)'
|
||||
pop: true
|
||||
- match: '(\$)(\{)'
|
||||
captures:
|
||||
1: punctuation.definition.keyword.requirements-txt
|
||||
2: punctuation.definition.begin.parameter.requirements-txt
|
||||
push:
|
||||
- meta_scope: variable.parameter.requirements-txt
|
||||
- match: '(\})'
|
||||
captures:
|
||||
1: punctuation.definition.end.parameter.requirements-txt
|
||||
pop: true
|
||||
- match: '(#)'
|
||||
captures:
|
||||
1: punctuation.definition.comment.requirements-txt
|
||||
push:
|
||||
- meta_scope: comment.line.requirements-txt
|
||||
- match: '(-*-) coding: .* (-*-)'
|
||||
captures:
|
||||
1: punctuation.definition.begin.pep263.requirements-txt
|
||||
2: punctuation.definition.end.pep263.requirements-txt
|
||||
- match: '$'
|
||||
pop: true
|
2
assets/syntaxes/02_Extra/TOML
vendored
2
assets/syntaxes/02_Extra/TOML
vendored
Submodule assets/syntaxes/02_Extra/TOML updated: fd0bf3e5d6...ed38438900
1
assets/syntaxes/02_Extra/TodoTxt
vendored
1
assets/syntaxes/02_Extra/TodoTxt
vendored
Submodule assets/syntaxes/02_Extra/TodoTxt deleted from 071a004217
@@ -4,8 +4,6 @@
|
||||
name: TypeScript
|
||||
file_extensions:
|
||||
- ts
|
||||
- mts
|
||||
- cts
|
||||
scope: source.ts
|
||||
contexts:
|
||||
main:
|
||||
|
104
assets/syntaxes/02_Extra/VimHelp.sublime-syntax
vendored
104
assets/syntaxes/02_Extra/VimHelp.sublime-syntax
vendored
@@ -1,104 +0,0 @@
|
||||
%YAML 1.2
|
||||
---
|
||||
# http://www.sublimetext.com/docs/syntax.html
|
||||
scope: source.vimhelp
|
||||
file_extensions:
|
||||
# shortname
|
||||
- vimhelp
|
||||
|
||||
# $VIMRUNTIME/syntax/help.vim
|
||||
contexts:
|
||||
main:
|
||||
- match: '(?<=^\s*)(vim?|ex):\s*([a-z]+(=[^\s:]+)?(\s+|:))+'
|
||||
scope: comment.line.modeline.vimhelp
|
||||
- match: '^[-A-Z .][-A-Z0-9 .()_]*(?=\s+\*|$)'
|
||||
scope: markup.heading.headline.vimhelp
|
||||
- match: '^(===.*===)$'
|
||||
captures:
|
||||
1: punctuation.definition.heading.1.setext.vimhelp
|
||||
push:
|
||||
- meta_scope: markup.heading.1.setext.vimhelp
|
||||
- match: '\t| '
|
||||
pop: true
|
||||
- match: '^(---.*---)$'
|
||||
captures:
|
||||
1: punctuation.definition.heading.2.setext.vimhelp
|
||||
push:
|
||||
- meta_scope: markup.heading.2.setext.vimhelp
|
||||
- match: '\t| '
|
||||
pop: true
|
||||
- match: '(?:^| )(>)$'
|
||||
captures:
|
||||
1: punctuation.definition.blockquote.begin.vimhelp
|
||||
push:
|
||||
- meta_scope: markup.quote.vimhelp
|
||||
- match: '^(<)'
|
||||
captures:
|
||||
1: punctuation.definition.blockquote.end.vimhelp
|
||||
pop: true
|
||||
- match: '^(?=\S)'
|
||||
pop: true
|
||||
- match: '(?<!\\)(\|)([#-)!+-~]+)(\|)'
|
||||
captures:
|
||||
1: punctuation.definition.link.begin.vimhelp
|
||||
2: markup.underline.link.vimhelp
|
||||
3: punctuation.definition.link.end.vimhelp
|
||||
- match: '(\*)([#-)!+-~]+)(\*)(?:\s|$)'
|
||||
captures:
|
||||
1: punctuation.definition.constant.begin.vimhelp
|
||||
2: entity.name.reference.link.vimhelp
|
||||
3: punctuation.definition.constant.end.vimhelp
|
||||
- match: '\bVim version [0-9][0-9.a-z]*'
|
||||
scope: variable.language.vimhelp
|
||||
- match: 'N?VIM REFERENCE.*'
|
||||
scope: variable.language.vimhelp
|
||||
- match: '('')([a-z]{2,}|t_..)('')'
|
||||
captures:
|
||||
1: punctuation.definition.link.option.begin.vimhelp
|
||||
2: markup.underline.link.option.vimhelp
|
||||
3: punctuation.definition.link.option.end.vimhelp
|
||||
- match: '(`)([^` \t]+)(`)'
|
||||
captures:
|
||||
1: punctuation.definition.link.command.begin.vimhelp
|
||||
2: markup.underline.link.command.vimhelp
|
||||
3: punctuation.definition.link.command.end.vimhelp
|
||||
- match: '(?<=^|[^a-z"\[])(`)([^`]+)(`)(?=[^a-z\t."'']|$)'
|
||||
captures:
|
||||
1: punctuation.definition.link.command.begin.vimhelp
|
||||
2: markup.underline.link.command.vimhelp
|
||||
3: punctuation.definition.link.command.end.vimhelp
|
||||
- match: '(?<=\s*)(.*?)(?=\s?)(~)$'
|
||||
captures:
|
||||
1: markup.heading.header.vimhelp
|
||||
2: punctuation.definition.keyword.vimhelp
|
||||
- match: '(.*) (?=`$)'
|
||||
captures:
|
||||
1: variable.other.graphic.vimhelp
|
||||
2: punctuation.definition.keyword.vimhelp
|
||||
- match: '\b(note:?|Note:?|NOTE:?|Notes:?)\b'
|
||||
scope: constant.other.note.vimhelp
|
||||
- match: '\b(WARNING:?|Warning:)\b'
|
||||
scope: constant.other.warning.vimhelp
|
||||
- match: '\b(DEPRECATED:?|Deprecated:)\b'
|
||||
scope: constant.other.deprecated.vimhelp
|
||||
- match: '(\{)([-_a-zA-Z0-9''"*+/:%#=\[\]<>.,]+)(\})'
|
||||
captures:
|
||||
1: punctuation.definition.constant.begin.vimhelp
|
||||
2: constant.numeric.vimhelp
|
||||
3: punctuation.definition.constant.end.vimhelp
|
||||
- match: '\[(range|line|count|offset|\+?cmd|(\+|-|)num|\+\+opt)\]'
|
||||
scope: constant.numeric.vimhelp
|
||||
- match: '\[(arg(uments)?|ident|addr|group)\]'
|
||||
scope: constant.numeric.vimhelp
|
||||
- match: '\[(readonly|fifo|socket|converted|crypted)\]'
|
||||
scope: constant.numeric.vimhelp
|
||||
- match: '<[-a-zA-Z0-9_]+>'
|
||||
scope: markup.underline.link.key.vimhelp
|
||||
- match: '<[SCM]-.>'
|
||||
scope: markup.underline.link.key.vimhelp
|
||||
- match: 'CTRL-((SHIFT-)?.|Break|PageUp|PageDown|Insert|Del|\{char\})'
|
||||
scope: markup.underline.link.key.vimhelp
|
||||
- match: '(META|ALT)-.'
|
||||
scope: markup.underline.link.key.vimhelp
|
||||
- match: '\b(((https?|ftp|gopher)://|(mailto|file|news):)[^'' <>"]+|(www|web|w3)[a-z0-9_-]*\.[a-z0-9._-]+\.[^'' <>"]+)[a-zA-Z0-9/]'
|
||||
scope: markup.underline.link.url.vimhelp
|
2
assets/syntaxes/02_Extra/cmd-help
vendored
2
assets/syntaxes/02_Extra/cmd-help
vendored
Submodule assets/syntaxes/02_Extra/cmd-help updated: f41e5fc838...1e513f5f19
76
assets/syntaxes/02_Extra/log.sublime-syntax
vendored
76
assets/syntaxes/02_Extra/log.sublime-syntax
vendored
@@ -7,15 +7,8 @@ scope: text.log
|
||||
variables:
|
||||
ipv4_part: (?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)
|
||||
hours_minutes_seconds: (?:[01]\d|2[0-3]):(?:[0-5]\d):(?:[0-5]\d)
|
||||
error: \b(?i:fail(?:ure|ed)?|error|exception|fatal|critical)\b
|
||||
warning: \b(?i:warn(?:ing)?)\b
|
||||
info: \b(?i:info)\b
|
||||
debug: \b(?i:debug)\b
|
||||
contexts:
|
||||
main:
|
||||
- include: log_level_lines
|
||||
- include: main_without_log_level_line
|
||||
main_without_log_level_line:
|
||||
- match: (\w+)(=)
|
||||
captures:
|
||||
1: variable.parameter.log
|
||||
@@ -32,58 +25,16 @@ contexts:
|
||||
- include: dates
|
||||
- include: ip_addresses
|
||||
- include: numbers
|
||||
- include: log_levels
|
||||
- match: \b(?i:fail(?:ure|ed)?|error|exception)\b
|
||||
scope: markup.error.log
|
||||
- match: \b(?i:warn(?:ing)?)\b
|
||||
scope: markup.warning.log
|
||||
- match: \b(?i:debug)\b
|
||||
scope: markup.info.log
|
||||
#- include: scope:text.html.markdown#autolink-inet
|
||||
- match: \b\w+:/{2,3}
|
||||
scope: markup.underline.link.scheme.log
|
||||
push: url-host
|
||||
log_level_lines:
|
||||
- match: ^(?=.*{{error}})
|
||||
push:
|
||||
- error_line
|
||||
- main_pop_at_eol
|
||||
- match: ^(?=.*{{warning}})
|
||||
push:
|
||||
- warning_line
|
||||
- main_pop_at_eol
|
||||
- match: ^(?=.*{{info}})
|
||||
push:
|
||||
- info_line
|
||||
- main_pop_at_eol
|
||||
- match: ^(?=.*{{debug}})
|
||||
push:
|
||||
- debug_line
|
||||
- main_pop_at_eol
|
||||
log_levels:
|
||||
- match: '{{error}}'
|
||||
scope: markup.error.log
|
||||
- match: '{{warning}}'
|
||||
scope: markup.warning.log
|
||||
- match: '{{info}}'
|
||||
scope: markup.info.log
|
||||
- match: '{{debug}}'
|
||||
scope: markup.info.log
|
||||
error_line:
|
||||
- meta_scope: meta.annotation.error-line.log
|
||||
- include: immediately_pop
|
||||
warning_line:
|
||||
- meta_scope: meta.annotation.warning-line.log
|
||||
- include: immediately_pop
|
||||
info_line:
|
||||
- meta_scope: meta.annotation.info-line.log
|
||||
- include: immediately_pop
|
||||
debug_line:
|
||||
- meta_scope: meta.annotation.debug-line.log
|
||||
- include: immediately_pop
|
||||
immediately_pop:
|
||||
- match: ''
|
||||
pop: true
|
||||
pop_at_eol:
|
||||
- match: $
|
||||
pop: true
|
||||
main_pop_at_eol:
|
||||
- include: main_without_log_level_line
|
||||
- include: pop_at_eol
|
||||
dates:
|
||||
- match: \b\d{4}-\d{2}-\d{2}(?=\b|T)
|
||||
scope: meta.date.log meta.number.integer.decimal.log constant.numeric.value.log
|
||||
@@ -98,12 +49,14 @@ contexts:
|
||||
scope: meta.time.log meta.number.integer.decimal.log constant.numeric.value.log
|
||||
captures:
|
||||
1: punctuation.separator.decimal.log
|
||||
- include: immediately_pop
|
||||
- match: ''
|
||||
pop: true
|
||||
maybe_date_time_separator:
|
||||
- match: T(?={{hours_minutes_seconds}})
|
||||
scope: meta.date.log meta.time.log keyword.other.log
|
||||
set: time
|
||||
- include: immediately_pop
|
||||
- match: ''
|
||||
pop: true
|
||||
ip_addresses:
|
||||
- match: \b(?=(?:{{ipv4_part}}\.){3}{{ipv4_part}}\b)
|
||||
push:
|
||||
@@ -112,7 +65,8 @@ contexts:
|
||||
scope: constant.numeric.value.log
|
||||
- match: \.
|
||||
scope: punctuation.separator.sequence.log
|
||||
- include: immediately_pop
|
||||
- match: ''
|
||||
pop: true
|
||||
- match: (?=(?:\h{0,4}:){2,6}\h{1,4}\b)
|
||||
push:
|
||||
- meta_scope: meta.ipaddress.v6.log meta.number.integer.hexadecimal.log
|
||||
@@ -120,7 +74,8 @@ contexts:
|
||||
scope: constant.numeric.value.log
|
||||
- match: ':'
|
||||
scope: punctuation.separator.sequence.log
|
||||
- include: immediately_pop
|
||||
- match: ''
|
||||
pop: true
|
||||
numbers:
|
||||
- match: \b(0x)(\h+)(?:(\.)(\h+))?\b
|
||||
scope: meta.number.float.hexadecimal.log
|
||||
@@ -172,7 +127,8 @@ contexts:
|
||||
pop: true
|
||||
- match: '[^?!.,:*_~\s<&()%]+|\S'
|
||||
scope: markup.underline.link.path.log
|
||||
- include: immediately_pop
|
||||
- match: ''
|
||||
pop: true
|
||||
double_quoted_string:
|
||||
- meta_scope: string.quoted.double.log
|
||||
- match: \\"
|
||||
|
2
assets/syntaxes/02_Extra/ssh-config
vendored
2
assets/syntaxes/02_Extra/ssh-config
vendored
Submodule assets/syntaxes/02_Extra/ssh-config updated: bf49e9181c...e1012e9f13
419
assets/syntaxes/02_Extra/syntax_test_helphelp.txt
vendored
419
assets/syntaxes/02_Extra/syntax_test_helphelp.txt
vendored
@@ -1,419 +0,0 @@
|
||||
# SYNTAX TEST "VimHelp.sublime-syntax"
|
||||
*helphelp.txt* Nvim
|
||||
# <- punctuation.definition.constant.begin
|
||||
#^^^^^^^^^^^^ entity.name.reference.link
|
||||
# ^ punctuation.definition.constant.end
|
||||
|
||||
|
||||
VIM REFERENCE MANUAL by Bram Moolenaar
|
||||
# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ variable.language
|
||||
|
||||
|
||||
Help on help files *helphelp*
|
||||
|
||||
Type |gO| to see the table of contents.
|
||||
# ^ punctuation.definition.link.begin
|
||||
# ^^ markup.underline.link
|
||||
# ^ punctuation.definition.link.end
|
||||
|
||||
==============================================================================
|
||||
#^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ punctuation.definition.heading.1.setext
|
||||
1. Help commands *online-help*
|
||||
#^^^^^^^^^^^^^^^ markup.heading.1.setext
|
||||
|
||||
*help* *<Help>* *:h* *:help* *<F1>* *i_<F1>* *i_<Help>*
|
||||
<Help> or
|
||||
#^^^^^ markup.underline.link.key
|
||||
:h[elp] Open a window and display the help file in read-only
|
||||
mode. If there is a help window open already, use
|
||||
that one. Otherwise, if the current window uses the
|
||||
full width of the screen or is at least 80 characters
|
||||
wide, the help window will appear just above the
|
||||
current window. Otherwise the new window is put at
|
||||
the very top.
|
||||
The 'helplang' option is used to select a language, if
|
||||
# ^ punctuation.definition.link.option.begin
|
||||
# ^^^^^^^^ markup.underline.link.option
|
||||
# ^ punctuation.definition.link.option.end
|
||||
the main help file is available in several languages.
|
||||
|
||||
Type |gO| to see the table of contents.
|
||||
|
||||
*{subject}* *E149* *E661*
|
||||
:h[elp] {subject} Like ":help", additionally jump to the tag {subject}.
|
||||
For example: >
|
||||
:help options
|
||||
|
||||
< {subject} can include wildcards such as "*", "?" and
|
||||
# ^ punctuation.definition.constant.begin
|
||||
# ^^^^^^^ constant.numeric
|
||||
# ^ punctuation.definition.constant.end
|
||||
"[a-z]":
|
||||
:help z? jump to help for any "z" command
|
||||
:help z. jump to the help for "z."
|
||||
But when a tag exists it is taken literally:
|
||||
:help :? jump to help for ":?"
|
||||
|
||||
If there is no full match for the pattern, or there
|
||||
are several matches, the "best" match will be used.
|
||||
A sophisticated algorithm is used to decide which
|
||||
match is better than another one. These items are
|
||||
considered in the computation:
|
||||
- A match with same case is much better than a match
|
||||
with different case.
|
||||
- A match that starts after a non-alphanumeric
|
||||
character is better than a match in the middle of a
|
||||
word.
|
||||
- A match at or near the beginning of the tag is
|
||||
better than a match further on.
|
||||
- The more alphanumeric characters match, the better.
|
||||
- The shorter the length of the match, the better.
|
||||
|
||||
The 'helplang' option is used to select a language, if
|
||||
the {subject} is available in several languages.
|
||||
To find a tag in a specific language, append "@ab",
|
||||
where "ab" is the two-letter language code. See
|
||||
|help-translated|.
|
||||
|
||||
Note that the longer the {subject} you give, the less
|
||||
matches will be found. You can get an idea how this
|
||||
all works by using commandline completion (type CTRL-D
|
||||
# ^^^^^^ markup.underline.link.key
|
||||
after ":help subject" |c_CTRL-D|).
|
||||
If there are several matches, you can have them listed
|
||||
by hitting CTRL-D. Example: >
|
||||
:help cont<Ctrl-D>
|
||||
|
||||
< Instead of typing ":help CTRL-V" to search for help
|
||||
for CTRL-V you can type: >
|
||||
:help ^V
|
||||
< This also works together with other characters, for
|
||||
example to find help for CTRL-V in Insert mode: >
|
||||
:help i^V
|
||||
<
|
||||
It is also possible to first do ":help" and then
|
||||
use ":tag {pattern}" in the help window. The
|
||||
":tnext" command can then be used to jump to other
|
||||
matches, "tselect" to list matches and choose one. >
|
||||
:help index
|
||||
:tselect /.*mode
|
||||
|
||||
< When there is no argument you will see matches for
|
||||
"help", to avoid listing all possible matches (that
|
||||
would be very slow).
|
||||
The number of matches displayed is limited to 300.
|
||||
|
||||
The `:help` command can be followed by '|' and another
|
||||
command, but you don't need to escape the '|' inside a
|
||||
help command. So these both work: >
|
||||
:help |
|
||||
:help k| only
|
||||
< Note that a space before the '|' is seen as part of
|
||||
# ^^^^ constant.other.note
|
||||
the ":help" argument.
|
||||
You can also use <NL> or <CR> to separate the help
|
||||
command from a following command. You need to type
|
||||
CTRL-V first to insert the <NL> or <CR>. Example: >
|
||||
:help so<C-V><CR>only
|
||||
<
|
||||
|
||||
:h[elp]! [subject] Like ":help", but in non-English help files prefer to
|
||||
find a tag in a file with the same language as the
|
||||
current file. See |help-translated|.
|
||||
|
||||
*:helpc* *:helpclose*
|
||||
:helpc[lose] Close one help window, if there is one.
|
||||
Vim will try to restore the window layout (including
|
||||
cursor position) to the same layout it was before
|
||||
opening the help window initially. This might cause
|
||||
triggering several autocommands.
|
||||
|
||||
*:helpg* *:helpgrep*
|
||||
:helpg[rep] {pattern}[@xx]
|
||||
Search all help text files and make a list of lines
|
||||
in which {pattern} matches. Jumps to the first match.
|
||||
The optional [@xx] specifies that only matches in the
|
||||
"xx" language are to be found.
|
||||
You can navigate through the matches with the
|
||||
|quickfix| commands, e.g., |:cnext| to jump to the
|
||||
next one. Or use |:cwindow| to get the list of
|
||||
matches in the quickfix window.
|
||||
{pattern} is used as a Vim regexp |pattern|.
|
||||
'ignorecase' is not used, add "\c" to ignore case.
|
||||
Example for case sensitive search: >
|
||||
:helpgrep Uganda
|
||||
< Example for case ignoring search: >
|
||||
:helpgrep uganda\c
|
||||
< Example for searching in French help: >
|
||||
:helpgrep backspace@fr
|
||||
< The pattern does not support line breaks, it must
|
||||
match within one line. You can use |:grep| instead,
|
||||
but then you need to get the list of help files in a
|
||||
complicated way.
|
||||
Cannot be followed by another command, everything is
|
||||
used as part of the pattern. But you can use
|
||||
|:execute| when needed.
|
||||
Compressed help files will not be searched (Fedora
|
||||
compresses the help files).
|
||||
|
||||
*:lh* *:lhelpgrep*
|
||||
:lh[elpgrep] {pattern}[@xx]
|
||||
Same as ":helpgrep", except the location list is used
|
||||
instead of the quickfix list. If the help window is
|
||||
already opened, then the location list for that window
|
||||
is used. Otherwise, a new help window is opened and
|
||||
the location list for that window is set. The
|
||||
location list for the current window is not changed
|
||||
then.
|
||||
|
||||
*:exu* *:exusage*
|
||||
:exu[sage] Show help on Ex commands. Added to simulate the Nvi
|
||||
command.
|
||||
|
||||
*:viu* *:viusage*
|
||||
:viu[sage] Show help on Normal mode commands. Added to simulate
|
||||
the Nvi command.
|
||||
|
||||
When no argument is given to |:help| the file given with the 'helpfile' option
|
||||
will be opened. Otherwise the specified tag is searched for in all "doc/tags"
|
||||
files in the directories specified in the 'runtimepath' option.
|
||||
|
||||
If you would like to open the help in the current window, see this tip:
|
||||
|help-curwin|.
|
||||
|
||||
The initial height of the help window can be set with the 'helpheight' option
|
||||
(default 20).
|
||||
*help-buffer-options*
|
||||
When the help buffer is created, several local options are set to make sure
|
||||
the help text is displayed as it was intended:
|
||||
'iskeyword' nearly all ASCII chars except ' ', '*', '"' and '|'
|
||||
'foldmethod' "manual"
|
||||
'tabstop' 8
|
||||
'arabic' off
|
||||
'binary' off
|
||||
'buflisted' off
|
||||
'cursorbind' off
|
||||
'diff' off
|
||||
'foldenable' off
|
||||
'list' off
|
||||
'modifiable' off
|
||||
'number' off
|
||||
'relativenumber' off
|
||||
'rightleft' off
|
||||
'scrollbind' off
|
||||
'spell' off
|
||||
|
||||
Jump to specific subjects by using tags. This can be done in two ways:
|
||||
- Use the "CTRL-]" command while standing on the name of a command or option.
|
||||
This only works when the tag is a keyword. "<C-Leftmouse>" and
|
||||
"g<LeftMouse>" work just like "CTRL-]".
|
||||
- use the ":ta {subject}" command. This also works with non-keyword
|
||||
characters.
|
||||
|
||||
Use CTRL-T or CTRL-O to jump back.
|
||||
Use ":q" to close the help window.
|
||||
|
||||
If there are several matches for an item you are looking for, this is how you
|
||||
can jump to each one of them:
|
||||
1. Open a help window
|
||||
2. Use the ":tag" command with a slash prepended to the tag. E.g.: >
|
||||
:tag /min
|
||||
3. Use ":tnext" to jump to the next matching tag.
|
||||
|
||||
It is possible to add help files for plugins and other items. You don't need
|
||||
to change the distributed help files for that. See |add-local-help|.
|
||||
|
||||
To write a local help file, see |write-local-help|.
|
||||
|
||||
Note that the title lines from the local help files are automagically added to
|
||||
the "LOCAL ADDITIONS" section in the "help.txt" help file |local-additions|.
|
||||
This is done when viewing the file in Vim, the file itself is not changed. It
|
||||
is done by going through all help files and obtaining the first line of each
|
||||
file. The files in $VIMRUNTIME/doc are skipped.
|
||||
|
||||
*help-xterm-window*
|
||||
If you want to have the help in another xterm window, you could use this
|
||||
command: >
|
||||
:!xterm -e vim +help &
|
||||
<
|
||||
|
||||
*:helpt* *:helptags*
|
||||
*E150* *E151* *E152* *E153* *E154* *E670* *E856*
|
||||
:helpt[ags] [++t] {dir}
|
||||
Generate the help tags file(s) for directory {dir}.
|
||||
When {dir} is ALL then all "doc" directories in
|
||||
'runtimepath' will be used.
|
||||
|
||||
All "*.txt" and "*.??x" files in the directory and
|
||||
sub-directories are scanned for a help tag definition
|
||||
in between stars. The "*.??x" files are for
|
||||
translated docs, they generate the "tags-??" file, see
|
||||
|help-translated|. The generated tags files are
|
||||
sorted.
|
||||
When there are duplicates an error message is given.
|
||||
An existing tags file is silently overwritten.
|
||||
|
||||
The optional "++t" argument forces adding the
|
||||
"help-tags" tag. This is also done when the {dir} is
|
||||
equal to $VIMRUNTIME/doc.
|
||||
|
||||
To rebuild the help tags in the runtime directory
|
||||
(requires write permission there): >
|
||||
:helptags $VIMRUNTIME/doc
|
||||
<
|
||||
|
||||
|
||||
==============================================================================
|
||||
2. Translated help files *help-translated*
|
||||
|
||||
It is possible to add translated help files, next to the original English help
|
||||
files. Vim will search for all help in "doc" directories in 'runtimepath'.
|
||||
|
||||
At this moment translations are available for:
|
||||
Chinese - multiple authors
|
||||
French - translated by David Blanchet
|
||||
Italian - translated by Antonio Colombo
|
||||
Japanese - multiple authors
|
||||
Polish - translated by Mikolaj Machowski
|
||||
Russian - translated by Vassily Ragosin
|
||||
See the Vim website to find them: http://www.vim.org/translations.php
|
||||
|
||||
A set of translated help files consists of these files:
|
||||
|
||||
help.abx
|
||||
howto.abx
|
||||
...
|
||||
tags-ab
|
||||
|
||||
"ab" is the two-letter language code. Thus for Italian the names are:
|
||||
|
||||
help.itx
|
||||
howto.itx
|
||||
...
|
||||
tags-it
|
||||
|
||||
The 'helplang' option can be set to the preferred language(s). The default is
|
||||
set according to the environment. Vim will first try to find a matching tag
|
||||
in the preferred language(s). English is used when it cannot be found.
|
||||
|
||||
To find a tag in a specific language, append "@ab" to a tag, where "ab" is the
|
||||
two-letter language code. Example: >
|
||||
:he user-manual@it
|
||||
:he user-manual@en
|
||||
The first one finds the Italian user manual, even when 'helplang' is empty.
|
||||
The second one finds the English user manual, even when 'helplang' is set to
|
||||
"it".
|
||||
|
||||
When using command-line completion for the ":help" command, the "@en"
|
||||
extension is only shown when a tag exists for multiple languages. When the
|
||||
tag only exists for English "@en" is omitted. When the first candidate has an
|
||||
"@ab" extension and it matches the first language in 'helplang' "@ab" is also
|
||||
omitted.
|
||||
|
||||
When using |CTRL-]| or ":help!" in a non-English help file Vim will try to
|
||||
find the tag in the same language. If not found then 'helplang' will be used
|
||||
to select a language.
|
||||
|
||||
Help files must use latin1 or utf-8 encoding. Vim assumes the encoding is
|
||||
utf-8 when finding non-ASCII characters in the first line. Thus you must
|
||||
translate the header with "For Vim version".
|
||||
|
||||
The same encoding must be used for the help files of one language in one
|
||||
directory. You can use a different encoding for different languages and use
|
||||
a different encoding for help files of the same language but in a different
|
||||
directory.
|
||||
|
||||
Hints for translators:
|
||||
- Do not translate the tags. This makes it possible to use 'helplang' to
|
||||
specify the preferred language. You may add new tags in your language.
|
||||
- When you do not translate a part of a file, add tags to the English version,
|
||||
using the "tag@en" notation.
|
||||
- Make a package with all the files and the tags file available for download.
|
||||
Users can drop it in one of the "doc" directories and start use it.
|
||||
Report this to Bram, so that he can add a link on www.vim.org.
|
||||
- Use the |:helptags| command to generate the tags files. It will find all
|
||||
languages in the specified directory.
|
||||
|
||||
==============================================================================
|
||||
3. Writing help files *help-writing*
|
||||
|
||||
For ease of use, a Vim help file for a plugin should follow the format of the
|
||||
standard Vim help files, except for the first line. If you are writing a new
|
||||
help file it's best to copy one of the existing files and use it as a
|
||||
template.
|
||||
|
||||
The first line in a help file should have the following format:
|
||||
|
||||
*plugin_name.txt* {short description of the plugin}
|
||||
|
||||
The first field is a help tag where ":help plugin_name" will jump to. The
|
||||
remainder of the line, after a Tab, describes the plugin purpose in a short
|
||||
way. This will show up in the "LOCAL ADDITIONS" section of the main help
|
||||
file. Check there that it shows up properly: |local-additions|.
|
||||
|
||||
If you want to add a version number or last modification date, put it in the
|
||||
second line, right aligned.
|
||||
|
||||
At the bottom of the help file, place a Vim modeline to set the 'textwidth'
|
||||
and 'tabstop' options and the 'filetype' to "help". Never set a global option
|
||||
in such a modeline, that can have undesired consequences.
|
||||
|
||||
|
||||
TAGS
|
||||
|
||||
To define a help tag, place the name between asterisks (*tag-name*). The
|
||||
tag-name should be different from all the Vim help tag names and ideally
|
||||
should begin with the name of the Vim plugin. The tag name is usually right
|
||||
aligned on a line.
|
||||
|
||||
When referring to an existing help tag and to create a hot-link, place the
|
||||
name between two bars (|) eg. |help-writing|.
|
||||
|
||||
When referring to a Vim command and to create a hot-link, place the
|
||||
name between two backticks, eg. inside `:filetype`. You will see this is
|
||||
highlighted as a command, like a code block (see below).
|
||||
|
||||
When referring to a Vim option in the help file, place the option name between
|
||||
two single quotes, eg. 'statusline'
|
||||
|
||||
When referring to any other technical term, such as a filename or function
|
||||
parameter, surround it in backticks, eg. `~/.path/to/init.vim`.
|
||||
|
||||
|
||||
HIGHLIGHTING
|
||||
|
||||
To define a column heading, use a tilde character at the end of the line.
|
||||
This will highlight the column heading in a different color. E.g.
|
||||
|
||||
Column heading~
|
||||
#^^^^^^^^^^^^^ markup.heading.header
|
||||
# ^ punctuation.definition.keyword
|
||||
|
||||
To separate sections in a help file, place a series of '=' characters in a
|
||||
line starting from the first column. The section separator line is highlighted
|
||||
differently.
|
||||
|
||||
To quote a block of ex-commands verbatim, place a greater than (>) character
|
||||
at the end of the line before the block and a less than (<) character as the
|
||||
first non-blank on a line following the block. Any line starting in column 1
|
||||
also implicitly stops the block of ex-commands before it. E.g. >
|
||||
function Example_Func()
|
||||
echo "Example"
|
||||
endfunction
|
||||
<
|
||||
|
||||
The following are highlighted differently in a Vim help file:
|
||||
- a special key name expressed either in <> notation as in <PageDown>, or
|
||||
as a Ctrl character as in CTRL-X
|
||||
- anything between {braces}, e.g. {lhs} and {rhs}
|
||||
|
||||
The word "Note", "Notes" and similar automagically receive distinctive
|
||||
highlighting. So do these:
|
||||
*Todo something to do
|
||||
*Error something wrong
|
||||
|
||||
You can find the details in $VIMRUNTIME/syntax/help.vim
|
||||
|
||||
|
||||
vim:tw=78:ts=8:noet:ft=help:norl:
|
||||
#^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ comment.line.modeline
|
102
assets/syntaxes/02_Extra/syntax_test_man.man
vendored
102
assets/syntaxes/02_Extra/syntax_test_man.man
vendored
@@ -157,108 +157,6 @@ ENVIRONMENT
|
||||
systemd reads the log level from this environment variable. This
|
||||
can be overridden with --log-level=.
|
||||
|
||||
ENVIRONMENT VARIABLES
|
||||
Various Git commands use the following environment variables:
|
||||
|
||||
The Git Repository
|
||||
These environment variables apply to all core Git commands. Nb: it is
|
||||
worth noting that they may be used/overridden by SCMS sitting above Git
|
||||
so take care if using a foreign front-end.
|
||||
|
||||
GIT_INDEX_FILE
|
||||
# ^^^^^^^^^^^^^^ support.constant.environment-variable
|
||||
This environment allows the specification of an alternate index
|
||||
file. If not specified, the default of $GIT_DIR/index is used.
|
||||
|
||||
GIT_INDEX_VERSION
|
||||
# ^^^^^^^^^^^^^^^^^ support.constant.environment-variable
|
||||
This environment variable allows the specification of an index
|
||||
version for new repositories. It won’t affect existing index files.
|
||||
By default index file version 2 or 3 is used. See git-update-
|
||||
index(1) for more information.
|
||||
|
||||
COMMANDS
|
||||
This section only lists general commands. For input and output com‐
|
||||
mands, refer to sway-input(5) and sway-output(5).
|
||||
|
||||
The following commands may only be used in the configuration file.
|
||||
|
||||
bar [<bar-id>] <bar-subcommands...>
|
||||
# ^^^ entity.name.command
|
||||
# ^ punctuation.section.brackets.begin
|
||||
# ^ punctuation.definition.generic.begin
|
||||
# ^^^^^^ variable.parameter
|
||||
# ^ punctuation.definition.generic.end
|
||||
# ^ punctuation.section.brackets.end
|
||||
# ^ punctuation.definition.generic.begin
|
||||
# ^^^^^^^^^^^^^^^ variable.parameter
|
||||
# ^ punctuation.definition.generic.end
|
||||
For details on bar subcommands, see sway-bar(5).
|
||||
|
||||
default_orientation horizontal|vertical|auto
|
||||
# ^^^^^^^^^^^^^^^^^^^ entity.name.command
|
||||
# ^^^^^^^^^^ variable.parameter
|
||||
# ^ keyword.operator.logical
|
||||
# ^^^^^^^^ variable.parameter
|
||||
# ^ keyword.operator.logical
|
||||
# ^^^^ variable.parameter
|
||||
Sets the default container layout for tiled containers.
|
||||
|
||||
include <path>
|
||||
Includes another file from path. path can be either a full path or
|
||||
a path relative to the parent config, and expands shell syntax (see
|
||||
wordexp(3) for details). The same include file can only be included
|
||||
once; subsequent attempts will be ignored.
|
||||
|
||||
The following commands cannot be used directly in the configuration
|
||||
# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - variable - entity
|
||||
file. They are expected to be used with bindsym or at runtime through
|
||||
# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - variable - entity
|
||||
swaymsg(1).
|
||||
|
||||
border none|normal|csd|pixel [<n>]
|
||||
Set border style for focused window. normal includes a border of
|
||||
thickness n and a title bar. pixel is a border without title bar n
|
||||
pixels thick. Default is normal with border thickness 2. csd is
|
||||
short for client-side-decorations, which allows the client to draw
|
||||
its own decorations.
|
||||
|
||||
border toggle
|
||||
# ^^^^^^ entity.name.command
|
||||
Cycles through the available border styles.
|
||||
|
||||
exit
|
||||
# ^^^^ entity.name.command
|
||||
Exit sway and end your Wayland session.
|
||||
|
||||
floating enable|disable|toggle
|
||||
Make focused view floating, non-floating, or the opposite of what
|
||||
it is now.
|
||||
|
||||
<criteria> focus
|
||||
# ^ punctuation.definition.generic.begin
|
||||
# ^^^^^^^^ variable.parameter
|
||||
# ^ punctuation.definition.generic.end
|
||||
# ^^^^^ variable.parameter
|
||||
Moves focus to the container that matches the specified criteria.
|
||||
|
||||
gaps inner|outer|horizontal|vertical|top|right|bottom|left all|current
|
||||
set|plus|minus|toggle <amount>
|
||||
# ^^^ variable.parameter
|
||||
# ^ keyword.operator.logical
|
||||
Changes the inner or outer gaps for either all workspaces or the
|
||||
current workspace. outer gaps can be altered per side with top,
|
||||
right, bottom, and left or per direction with horizontal and verti‐
|
||||
cal.
|
||||
|
||||
layout toggle [split|tabbed|stacking|splitv|splith]
|
||||
[split|tabbed|stacking|splitv|splith]...
|
||||
# ^ punctuation.section.brackets.begin
|
||||
# ^^^^^ variable.parameter
|
||||
# ^ keyword.operator.logical
|
||||
Cycles the layout mode of the focused container through a list of
|
||||
layouts.
|
||||
|
||||
SEE ALSO
|
||||
The systemd Homepage[11], systemd-system.conf(5), locale.conf(5)
|
||||
# ^^^^^^^^^^^^^^^^^^^ entity.name.function
|
||||
|
@@ -1,82 +0,0 @@
|
||||
# SYNTAX TEST "Requirementstxt.sublime-syntax"
|
||||
# Options
|
||||
# <- punctuation.definition.comment
|
||||
# ^^^^^^^ comment.line
|
||||
--allow-external
|
||||
#^^^^^^^^^^^^^^^ entity.name.function.option
|
||||
--allow-unverified
|
||||
|
||||
# Freeze packages
|
||||
alabaster==0.7.6
|
||||
Babel>=2.9.1
|
||||
docutils==0.12
|
||||
gevent_subprocess==0.1.2
|
||||
gitpython==3.0.7
|
||||
hg-diff==1.2.4
|
||||
#^^^^^^ variable.parameter.package-name
|
||||
# ^^ keyword.operator.logical
|
||||
# ^^^^^ constant.other
|
||||
Jinja2>=2.8.1
|
||||
MarkupSafe==0.23
|
||||
Pygments==2.7.4
|
||||
pytz==2015.7
|
||||
six==1.10.0
|
||||
snowballstemmer==1.2.0
|
||||
Sphinx==1.3.3
|
||||
sphinx-rtd-theme==0.1.9
|
||||
svn==1.0.1
|
||||
zope.interface==4.2.0
|
||||
|
||||
# Examples from PEP508
|
||||
# c.f. https://www.python.org/dev/peps/pep-0508/
|
||||
requests [security,tests] >= 2.8.1, == 2.8.* ; python_version < "2.7" # Comment
|
||||
#^^^^^^^ variable.parameter.package-name
|
||||
# ^^^^^^^^^^^^^^^^ variable.function.extra
|
||||
# ^ punctuation.section.braces.begin
|
||||
# ^ punctuation.separator
|
||||
# ^ punctuation.section.braces.end
|
||||
# ^^ keyword.operator.logical
|
||||
# ^^^^^ constant.other
|
||||
# ^^ keyword.operator.logical
|
||||
# ^^^^^ constant.other
|
||||
# ^ punctuation.definition.annotation
|
||||
# ^^^^^^^^^^^^^^^^^^^^^^^^ meta.annotation
|
||||
# ^^^^^^^^^^^^^^ variable.language
|
||||
# ^ keyword.operator.logical
|
||||
# ^ punctuation.definition.string.begin.double
|
||||
# ^^^^^ string.quoted.double.requirements-txt
|
||||
# ^ punctuation.definition.string.end.double
|
||||
# ^^^^^^^^^ comment.line
|
||||
pip @ https://github.com/pypa/pip/archive/1.3.1.zip#sha1=da9234ee9982d4bbb3c72346a6de940a148ea686
|
||||
# ^ punctuation.definition.keyword
|
||||
# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ markup.underline.link.url
|
||||
name @ gopher:/foo/com"
|
||||
foobar[quux]<2,>=3; os_name=='a'
|
||||
|
||||
# VCS repositories
|
||||
-e git+git://git.myproject.org/MyProject#egg=MyProject # Git
|
||||
# <- entity.name.function.option
|
||||
#^ entity.name.function.option
|
||||
# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ markup.underline.link.versioncontrols
|
||||
# ^^^^^^^^^^^^^^^ - comment.line
|
||||
# ^^^^^ comment.line
|
||||
-e git://git.myproject.org/MyProject.git@v1.0#egg=MyProject
|
||||
# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ markup.underline.link.versioncontrols
|
||||
-e hg+https://hg.myproject.org/MyProject#egg=MyProject # Mercurial
|
||||
# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ markup.underline.link.versioncontrols
|
||||
# ^^^^^^^^^^^ comment.line
|
||||
-e hg+http://hg.myproject.org/MyProject@da39a3ee5e6b#egg=MyProject
|
||||
# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ markup.underline.link.versioncontrols
|
||||
-e svn+http://svn.myproject.org/svn/MyProject/trunk@2019#egg=MyProject # Subversion
|
||||
# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ markup.underline.link.versioncontrols
|
||||
# ^^^^^^^^^^^^ comment.line
|
||||
-e bzr+ssh://user@myproject.org/MyProject/trunk#egg=MyProject # Bazaar
|
||||
# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ markup.underline.link.versioncontrols
|
||||
# ^^^^^^^^ comment.line
|
||||
-e bzr+https://bzr.myproject.org/MyProject/trunk@2019#egg=MyProject
|
||||
# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ markup.underline.link.versioncontrols
|
||||
|
||||
# Project or archive URL
|
||||
https://github.com/pallets/click/archive/7.0.zip#egg=click
|
||||
#^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ markup.underline.link.url
|
||||
# ^^^^^^^^^^ - comment.line
|
1
assets/syntaxes/02_Extra/vscode-wgsl
vendored
1
assets/syntaxes/02_Extra/vscode-wgsl
vendored
Submodule assets/syntaxes/02_Extra/vscode-wgsl deleted from acf26718d7
198
assets/syntaxes/02_Extra/wgsl.sublime-syntax
vendored
198
assets/syntaxes/02_Extra/wgsl.sublime-syntax
vendored
@@ -1,198 +0,0 @@
|
||||
%YAML 1.2
|
||||
---
|
||||
# http://www.sublimetext.com/docs/syntax.html
|
||||
name: WGSL
|
||||
file_extensions:
|
||||
- wgsl
|
||||
scope: source.wgsl
|
||||
contexts:
|
||||
main:
|
||||
- include: line_comments
|
||||
- include: block_comments
|
||||
- include: keywords
|
||||
- include: attributes
|
||||
- include: functions
|
||||
- include: function_calls
|
||||
- include: constants
|
||||
- include: types
|
||||
- include: variables
|
||||
- include: punctuation
|
||||
attributes:
|
||||
- match: '(@)([A-Za-z_]+)'
|
||||
comment: attribute declaration
|
||||
scope: meta.attribute.wgsl
|
||||
captures:
|
||||
1: keyword.operator.attribute.at
|
||||
2: entity.name.attribute.wgsl
|
||||
block_comments:
|
||||
- match: /\*\*/
|
||||
comment: empty block comments
|
||||
scope: comment.block.wgsl
|
||||
- match: /\*\*
|
||||
comment: block documentation comments
|
||||
push:
|
||||
- meta_scope: comment.block.documentation.wgsl
|
||||
- match: \*/
|
||||
pop: true
|
||||
- include: block_comments
|
||||
- match: /\*(?!\*)
|
||||
comment: block comments
|
||||
push:
|
||||
- meta_scope: comment.block.wgsl
|
||||
- match: \*/
|
||||
pop: true
|
||||
- include: block_comments
|
||||
constants:
|
||||
- match: '(-?\b[0-9][0-9]*\.[0-9][0-9]*)([eE][+-]?[0-9]+)?\b'
|
||||
comment: decimal float literal
|
||||
scope: constant.numeric.float.wgsl
|
||||
- match: '-?\b0x[0-9a-fA-F]+\b|\b0\b|-?\b[1-9][0-9]*\b'
|
||||
comment: int literal
|
||||
scope: constant.numeric.decimal.wgsl
|
||||
- match: '\b0x[0-9a-fA-F]+u\b|\b0u\b|\b[1-9][0-9]*u\b'
|
||||
comment: uint literal
|
||||
scope: constant.numeric.decimal.wgsl
|
||||
- match: \b(true|false)\b
|
||||
comment: boolean constant
|
||||
scope: constant.language.boolean.wgsl
|
||||
function_calls:
|
||||
- match: '([A-Za-z0-9_]+)(\()'
|
||||
comment: function/method calls
|
||||
captures:
|
||||
1: entity.name.function.wgsl
|
||||
2: punctuation.brackets.round.wgsl
|
||||
push:
|
||||
- meta_scope: meta.function.call.wgsl
|
||||
- match: \)
|
||||
captures:
|
||||
0: punctuation.brackets.round.wgsl
|
||||
pop: true
|
||||
- include: line_comments
|
||||
- include: block_comments
|
||||
- include: keywords
|
||||
- include: attributes
|
||||
- include: function_calls
|
||||
- include: constants
|
||||
- include: types
|
||||
- include: variables
|
||||
- include: punctuation
|
||||
functions:
|
||||
- match: '\b(fn)\s+([A-Za-z0-9_]+)((\()|(<))'
|
||||
comment: function definition
|
||||
captures:
|
||||
1: keyword.other.fn.wgsl
|
||||
2: entity.name.function.wgsl
|
||||
4: punctuation.brackets.round.wgsl
|
||||
push:
|
||||
- meta_scope: meta.function.definition.wgsl
|
||||
- match: '\{'
|
||||
captures:
|
||||
0: punctuation.brackets.curly.wgsl
|
||||
pop: true
|
||||
- include: line_comments
|
||||
- include: block_comments
|
||||
- include: keywords
|
||||
- include: attributes
|
||||
- include: function_calls
|
||||
- include: constants
|
||||
- include: types
|
||||
- include: variables
|
||||
- include: punctuation
|
||||
keywords:
|
||||
- match: \b(bitcast|block|break|case|continue|continuing|default|discard|else|elseif|enable|fallthrough|for|function|if|loop|private|read|read_write|return|storage|switch|uniform|while|workgroup|write)\b
|
||||
comment: other keywords
|
||||
scope: keyword.control.wgsl
|
||||
- match: \b(asm|const|do|enum|handle|mat|premerge|regardless|typedef|unless|using|vec|void)\b
|
||||
comment: reserved keywords
|
||||
scope: keyword.control.wgsl
|
||||
- match: \b(let|var)\b
|
||||
comment: storage keywords
|
||||
scope: keyword.other.wgsl storage.type.wgsl
|
||||
- match: \b(type)\b
|
||||
comment: type keyword
|
||||
scope: keyword.declaration.type.wgsl storage.type.wgsl
|
||||
- match: \b(enum)\b
|
||||
comment: enum keyword
|
||||
scope: keyword.declaration.enum.wgsl storage.type.wgsl
|
||||
- match: \b(struct)\b
|
||||
comment: struct keyword
|
||||
scope: keyword.declaration.struct.wgsl storage.type.wgsl
|
||||
- match: \bfn\b
|
||||
comment: fn
|
||||
scope: keyword.other.fn.wgsl
|
||||
- match: (\^|\||\|\||&&|<<|>>|!)(?!=)
|
||||
comment: logical operators
|
||||
scope: keyword.operator.logical.wgsl
|
||||
- match: '&(?![&=])'
|
||||
comment: logical AND, borrow references
|
||||
scope: keyword.operator.borrow.and.wgsl
|
||||
- match: (\+=|-=|\*=|/=|%=|\^=|&=|\|=|<<=|>>=)
|
||||
comment: assignment operators
|
||||
scope: keyword.operator.assignment.wgsl
|
||||
- match: '(?<![<>])=(?!=|>)'
|
||||
comment: single equal
|
||||
scope: keyword.operator.assignment.equal.wgsl
|
||||
- match: (=(=)?(?!>)|!=|<=|(?<!=)>=)
|
||||
comment: comparison operators
|
||||
scope: keyword.operator.comparison.wgsl
|
||||
- match: '(([+%]|(\*(?!\w)))(?!=))|(-(?!>))|(/(?!/))'
|
||||
comment: math operators
|
||||
scope: keyword.operator.math.wgsl
|
||||
- match: \.(?!\.)
|
||||
comment: dot access
|
||||
scope: keyword.operator.access.dot.wgsl
|
||||
- match: '->'
|
||||
comment: dashrocket, skinny arrow
|
||||
scope: keyword.operator.arrow.skinny.wgsl
|
||||
line_comments:
|
||||
- match: \s*//.*
|
||||
comment: single line comment
|
||||
scope: comment.line.double-slash.wgsl
|
||||
punctuation:
|
||||
- match: ','
|
||||
comment: comma
|
||||
scope: punctuation.comma.wgsl
|
||||
- match: '[{}]'
|
||||
comment: curly braces
|
||||
scope: punctuation.brackets.curly.wgsl
|
||||
- match: '[()]'
|
||||
comment: parentheses, round brackets
|
||||
scope: punctuation.brackets.round.wgsl
|
||||
- match: ;
|
||||
comment: semicolon
|
||||
scope: punctuation.semi.wgsl
|
||||
- match: '[\[\]]'
|
||||
comment: square brackets
|
||||
scope: punctuation.brackets.square.wgsl
|
||||
- match: '(?<![=-])[<>]'
|
||||
comment: angle brackets
|
||||
scope: punctuation.brackets.angle.wgsl
|
||||
types:
|
||||
- match: \b(bool|i32|u32|f32)\b
|
||||
comment: scalar Types
|
||||
scope: storage.type.wgsl
|
||||
- match: \b(i64|u64|f64)\b
|
||||
comment: reserved scalar Types
|
||||
scope: storage.type.wgsl
|
||||
- match: \b(vec2i|vec3i|vec4i|vec2u|vec3u|vec4u|vec2f|vec3f|vec4f|vec2h|vec3h|vec4h)\b
|
||||
comment: vector type aliasses
|
||||
scope: storage.type.wgsl
|
||||
- match: \b(mat2x2f|mat2x3f|mat2x4f|mat3x2f|mat3x3f|mat3x4f|mat4x2f|mat4x3f|mat4x4f|mat2x2h|mat2x3h|mat2x4h|mat3x2h|mat3x3h|mat3x4h|mat4x2h|mat4x3h|mat4x4h)\b
|
||||
comment: matrix type aliasses
|
||||
scope: storage.type.wgsl
|
||||
- match: '\b(vec[2-4]|mat[2-4]x[2-4])\b'
|
||||
comment: vector/matrix types
|
||||
scope: storage.type.wgsl
|
||||
- match: \b(atomic)\b
|
||||
comment: atomic types
|
||||
scope: storage.type.wgsl
|
||||
- match: \b(array)\b
|
||||
comment: array types
|
||||
scope: storage.type.wgsl
|
||||
- match: '\b([A-Z][A-Za-z0-9]*)\b'
|
||||
comment: Custom type
|
||||
scope: entity.name.type.wgsl
|
||||
variables:
|
||||
- match: '\b(?<!(?<!\.)\.)(?:r#(?!(crate|[Ss]elf|super)))?[a-z0-9_]+\b'
|
||||
comment: variables
|
||||
scope: variable.other.wgsl
|
BIN
assets/themes.bin
vendored
BIN
assets/themes.bin
vendored
Binary file not shown.
2
assets/themes/zenburn
vendored
2
assets/themes/zenburn
vendored
Submodule assets/themes/zenburn updated: 43dc527731...702023d80d
4
build.rs
4
build.rs
@@ -43,9 +43,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
variables.insert("PROJECT_EXECUTABLE_UPPERCASE", &executable_name_uppercase);
|
||||
variables.insert("PROJECT_VERSION", PROJECT_VERSION);
|
||||
|
||||
let out_dir_env = std::env::var_os("BAT_ASSETS_GEN_DIR")
|
||||
.or_else(|| std::env::var_os("OUT_DIR"))
|
||||
.expect("BAT_ASSETS_GEN_DIR or OUT_DIR to be set in build.rs");
|
||||
let out_dir_env = std::env::var_os("OUT_DIR").expect("OUT_DIR to be set in build.rs");
|
||||
let out_dir = Path::new(&out_dir_env);
|
||||
|
||||
fs::create_dir_all(out_dir.join("assets/manual")).unwrap();
|
||||
|
@@ -186,7 +186,7 @@ man 2 select
|
||||
### On Ubuntu (`apt` を使用)
|
||||
*... や他のDebianベースのLinuxディストリビューション*
|
||||
|
||||
[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` パッケージが利用できます。
|
||||
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) からインストールできます:
|
||||
|
||||
```bash
|
||||
apt install bat
|
||||
@@ -366,7 +366,7 @@ ansible-galaxy install aeimer.install_bat
|
||||
### From source
|
||||
|
||||
|
||||
`bat` をソースからビルドしたいならば、Rust 1.70.0 以上の環境が必要です。
|
||||
`bat` をソースからビルドしたいならば、Rust 1.51 以上の環境が必要です。
|
||||
`cargo` を使用してビルドすることができます:
|
||||
|
||||
```bash
|
||||
|
@@ -416,7 +416,7 @@ scoop install bat
|
||||
|
||||
### 소스에서
|
||||
|
||||
`bat`의 소스를 빌드하기 위해서는, Rust 1.70.0 이상이 필요합니다.
|
||||
`bat`의 소스를 빌드하기 위해서는, Rust 1.51 이상이 필요합니다.
|
||||
`cargo`를 이용해 전부 빌드할 수 있습니다:
|
||||
|
||||
```bash
|
||||
|
@@ -130,8 +130,8 @@ git show v0.6.0:src/main.rs | bat -l rs
|
||||
|
||||
#### `xclip`
|
||||
|
||||
Нумерация строк и отображение изменений затрудняет копирование содержимого файлов в буфер обмена.
|
||||
Чтобы справиться с этим, используйте флаг `-p`/`--plain` или просто перенаправьте стандартный вывод в `xclip`:
|
||||
Нумерация стро и отображение изменений затрудняет копирование содержимого файлов в буфер обмена.
|
||||
Чтобы спроваиться с этим, используйте флаг `-p`/`--plain` или просто перенаправьте стандартный вывод в `xclip`:
|
||||
```bash
|
||||
bat main.cpp | xclip
|
||||
```
|
||||
@@ -344,7 +344,7 @@ ansible-galaxy install aeimer.install_bat
|
||||
|
||||
### Из исходников
|
||||
|
||||
Если вы желаете установить `bat` из исходников, вам понадобится Rust 1.70.0 или выше. После этого используйте `cargo`, чтобы все скомпилировать:
|
||||
Если вы желаете установить `bat` из исходников, вам понадобится Rust 1.51 или выше. После этого используйте `cargo`, чтобы все скомпилировать:
|
||||
|
||||
```bash
|
||||
cargo install --locked bat
|
||||
@@ -487,7 +487,7 @@ bat --generate-config-file
|
||||
# Использовать синтаксис C++ для всех Arduino .ino файлов
|
||||
--map-syntax "*.ino:C++"
|
||||
|
||||
# Использовать синтаксис Git Ignore для всех файлов .ignore
|
||||
# Использовать синтаксик Git Ignore для всех файлов .ignore
|
||||
--map-syntax ".ignore:Git Ignore"
|
||||
```
|
||||
|
||||
@@ -535,7 +535,7 @@ bat() {
|
||||
`bat` поддерживает терминалы *с* и *без* поддержки truecolor. Однако подсветка синтаксиса не оптимизирована для терминалов с 8-битными цветами, и рекомендуется использовать терминалы с поддержкой 24-битных цветов (`terminator`, `konsole`, `iTerm2`, ...).
|
||||
Смотрите [эту статью](https://gist.github.com/XVilka/8346728) для полного списка терминалов.
|
||||
|
||||
Удостоверьтесь, что переменная `COLORTERM` равна `truecolor` или
|
||||
Удостовертесь, что переменная `COLORTERM` равна `truecolor` или
|
||||
`24bit`. Иначе `bat` не сможет определить поддержку 24-битных цветов (и будет использовать 8-битные).
|
||||
|
||||
### Текст и номера строк плохо видны
|
||||
@@ -550,7 +550,7 @@ bat() {
|
||||
``` bash
|
||||
iconv -f ISO-8859-1 -t UTF-8 my-file.php | bat
|
||||
```
|
||||
Внимание: вам может понадобиться флаг `-l`/`--language`, если `bat` не сможет автоматически определить синтаксис.
|
||||
Внимание: вам может понадобится флаг `-l`/`--language`, если `bat` не сможет автоматически определить синтаксис.
|
||||
|
||||
## Разработка
|
||||
|
||||
@@ -568,7 +568,7 @@ cargo test
|
||||
# Установка (релизная версия)
|
||||
cargo install --locked
|
||||
|
||||
# Компилирование исполняемого файла bat с другим синтаксисом и темами
|
||||
# Компилирование исполняего файла bat с другим синтаксисом и темами
|
||||
bash assets/create.sh
|
||||
cargo install --locked --force
|
||||
```
|
||||
@@ -592,6 +592,6 @@ cargo install --locked --force
|
||||
## Лицензия
|
||||
Copyright (c) 2018-2021 [Разработчики bat](https://github.com/sharkdp/bat).
|
||||
|
||||
`bat` распространяется под лицензиями MIT License и Apache License 2.0 (на выбор пользователя).
|
||||
`bat` распостраняется под лицензями MIT License и Apache License 2.0 (на выбор пользователя).
|
||||
|
||||
Смотрите [LICENSE-APACHE](LICENSE-APACHE) и [LICENSE-MIT](LICENSE-MIT) для более подробного ознакомления.
|
||||
|
@@ -372,7 +372,7 @@ scoop install bat
|
||||
|
||||
### 从源码编译
|
||||
|
||||
如果你想要自己构建`bat`,那么你需要安装有高于1.70.0版本的 Rust。
|
||||
如果你想要自己构建`bat`,那么你需要安装有高于1.51版本的 Rust。
|
||||
|
||||
使用以下命令编译。
|
||||
|
||||
@@ -550,7 +550,7 @@ bat --generate-config-file
|
||||
# 在终端中以斜体输出文本(不是所有终端都支持)
|
||||
--italic-text=always
|
||||
|
||||
# 使用 C++ 语法来给 Arduino 的 .ino 文件提供高亮
|
||||
# 使用 C++ 语法来给 Ardiuno 的 .ino 文件提供高亮
|
||||
--map-syntax "*.ino:C++"
|
||||
```
|
||||
|
||||
|
@@ -4,17 +4,17 @@ The following table tries to give an overview *from `bat`s perspective*, i.e. we
|
||||
categories which are relevant for `bat`. Some of these projects have completely different goals and
|
||||
if you are not looking for a program like `bat`, this comparison might not be for you.
|
||||
|
||||
| | bat | [pygments](http://pygments.org/) | [highlight](http://www.andre-simon.de/doku/highlight/highlight.php) | [ccat](https://github.com/jingweno/ccat) | [source-highlight](https://www.gnu.org/software/src-highlite/) | [hicat](https://github.com/rstacruz/hicat) | [coderay](https://github.com/rubychan/coderay) | [rouge](https://github.com/jneen/rouge) | [clp](https://github.com/jpe90/clp) |
|
||||
|----------------------------------------------|---------------------------------------------------------------------|----------------------------------|---------------------------------------------------------------------|------------------------------------------|----------------------------------------------------------------|-----------------------------------------------------|-----------------------------------------------------|-----------------------------------------------------|-----------------------------------------------------|
|
||||
| Drop-in `cat` replacement | :heavy_check_mark: [*](https://github.com/sharkdp/bat/issues/134) | :x: | :x: | (:heavy_check_mark:) | :x: | :x: [*](https://github.com/rstacruz/hicat/issues/6) | :x: | :x: | :x: |
|
||||
| Git integration | :heavy_check_mark: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: |
|
||||
| Automatic paging | :heavy_check_mark: | :x: | :x: | :x: | :x: | :heavy_check_mark: | :x: | :x: | :x: |
|
||||
| Languages (circa) | 150 | 300 | 200 | 7 | 80 | 130 | 30 | 130 | 150 |
|
||||
| Extensible (languages, themes) | :heavy_check_mark: | (:heavy_check_mark:) | (:heavy_check_mark:) | :x: | (:heavy_check_mark:) | :x: | :x: | :x: | :heavy_check_mark: |
|
||||
| Advanced highlighting (e.g. nested syntaxes) | :heavy_check_mark: | :heavy_check_mark: | (:heavy_check_mark:) ? | :x: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
|
||||
| Execution time [ms] (`jquery-3.3.1.js`) | 422 | 455 | 299 | 39 | 208 | 287 | 128 | 740 | 22 |
|
||||
| Execution time [ms] (`miniz.c`) | 27 | 169 | 19 | 4 | 36 | 131 | 58 | 231 | 4 |
|
||||
| Execution time [ms] (957 kB XML file) | 215 | 296 | 236 | 165 | 83 | 412 | 135 | 386 | 127 |
|
||||
| | bat | [pygments](http://pygments.org/) | [highlight](http://www.andre-simon.de/doku/highlight/highlight.php) | [ccat](https://github.com/jingweno/ccat) | [source-highlight](https://www.gnu.org/software/src-highlite/) | [hicat](https://github.com/rstacruz/hicat) | [coderay](https://github.com/rubychan/coderay) | [rouge](https://github.com/jneen/rouge) |
|
||||
|----------------------------------------------|---------------------------------------------------------------------|----------------------------------|---------------------------------------------------------------------|------------------------------------------|----------------------------------------------------------------|-----------------------------------------------------|-----------------------------------------------------|-----------------------------------------------------|
|
||||
| Drop-in `cat` replacement | :heavy_check_mark: [*](https://github.com/sharkdp/bat/issues/134) | :x: | :x: | (:heavy_check_mark:) | :x: | :x: [*](https://github.com/rstacruz/hicat/issues/6) | :x: | :x: |
|
||||
| Git integration | :heavy_check_mark: | :x: | :x: | :x: | :x: | :x: | :x: | :x: |
|
||||
| Automatic paging | :heavy_check_mark: | :x: | :x: | :x: | :x: | :heavy_check_mark: | :x: | :x: |
|
||||
| Languages (circa) | 150 | 300 | 200 | 7 | 80 | 130 | 30 | 130 |
|
||||
| Extensible (languages, themes) | :heavy_check_mark: | (:heavy_check_mark:) | (:heavy_check_mark:) | :x: | (:heavy_check_mark:) | :x: | :x: | :x: |
|
||||
| Advanced highlighting (e.g. nested syntaxes) | :heavy_check_mark: | :heavy_check_mark: | (:heavy_check_mark:) ? | :x: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
|
||||
| Execution time [ms] (`jquery-3.3.1.js`) | 624 | 789 | 400 | 80 | 300 | 316 | 157 | 695 |
|
||||
| Execution time [ms] (`miniz.c`) | 66 | 656 | 26 | 8 | 53 | 141 | 75 | 254 |
|
||||
| Execution time [ms] (370 kB XML file) | 238 | 487 | 129 | 111 | 110 | 339 | 147 | 359 |
|
||||
|
||||
If you think that some entries in this table are outdated or wrong, please open a ticket or pull
|
||||
request.
|
||||
@@ -49,7 +49,6 @@ cmd_source_highlight="source-highlight --failsafe --infer-lang -f esc -i '$SRC'"
|
||||
cmd_hicat="hicat '$SRC'"
|
||||
cmd_coderay="coderay '$SRC'"
|
||||
cmd_rouge="rougify '$SRC'"
|
||||
cmd_clp="clp '$SRC'"
|
||||
|
||||
hyperfine --warmup 3 \
|
||||
"$cmd_bat" \
|
||||
@@ -61,5 +60,4 @@ hyperfine --warmup 3 \
|
||||
"$cmd_hicat" \
|
||||
"$cmd_coderay" \
|
||||
"$cmd_rouge" \
|
||||
"$cmd_clp" \
|
||||
```
|
||||
|
@@ -16,9 +16,6 @@ in the `.sublime-syntax` format.
|
||||
2. If the Sublime Text syntax is only available as a `.tmLanguage` file, open the file in
|
||||
Sublime Text and convert it to a `.sublime-syntax` file via *Tools* -> *Developer* ->
|
||||
*New Syntax from XXX.tmLanguage...*. Save the new file in the `assets/syntaxes` folder.
|
||||
If only `.tmLanguage.json` or `.tmLanguage.yml` file is available, use
|
||||
[PackageDev](https://packagecontrol.io/packages/PackageDev) to convert it to `.tmLanguage.plist`
|
||||
format and then rename the converted file to `.tmLanguage` file.
|
||||
|
||||
3. Run the `assets/create.sh` script. It calls `bat cache --build` to parse all available
|
||||
`.sublime-syntax` files and serialize them to a `syntaxes.bin` file.
|
||||
@@ -80,14 +77,12 @@ themes (`bat cache --clear`).
|
||||
|
||||
The following files have been manually modified after converting from a `.tmLanguage` file:
|
||||
|
||||
* `Apache.sublime_syntax`=> removed `conf` and `CONF` file types.
|
||||
* `Apache.sublime_syntax`=> removed `.conf` and `.CONF` file types.
|
||||
* `Dart.sublime-syntax` => removed `#regex.dart` include.
|
||||
* `DotENV.sublime-syntax` => added `.env.template`, `env` and `env.*` file types ([upstream PR](https://github.com/zaynali53/DotENV/pull/17)).
|
||||
* `INI.sublime-syntax` => added `.coveragerc`, `.pylintrc`, `.gitlint`, `.hgrc`, `hgrc`, and `desktop` file types and support for comments after section headers.
|
||||
* `INI.sublime-syntax` => added `.hgrc`, `hgrc`, and `desktop` file types and support for comments after section headers
|
||||
* `Org mode.sublime-syntax` => removed `task` file type.
|
||||
* `Robot.sublime_syntax` => changed name to "Robot Framework", added `.resource` extension.
|
||||
* `SML.sublime_syntax` => removed `ml` file type.
|
||||
* `wgsl.sublime-syntax` => added `wgsl` file extension.
|
||||
* `Robot.sublime_syntax` => changed name to "Robot Framework", added `.resource` extension
|
||||
|
||||
### Non-submodule additions
|
||||
|
||||
|
@@ -1,167 +0,0 @@
|
||||
A cat(1) clone with syntax highlighting and Git integration.
|
||||
|
||||
Usage: bat [OPTIONS] [FILE]...
|
||||
bat <COMMAND>
|
||||
|
||||
Arguments:
|
||||
[FILE]...
|
||||
File(s) to print / concatenate. Use a dash ('-') or no argument at all to read from
|
||||
standard input.
|
||||
|
||||
Options:
|
||||
-A, --show-all
|
||||
Show non-printable characters like space, tab or newline. This option can also be used to
|
||||
print binary files. Use '--tabs' to control the width of the tab-placeholders.
|
||||
|
||||
--nonprintable-notation <notation>
|
||||
Set notation for non-printable characters.
|
||||
|
||||
Possible values:
|
||||
* unicode (␇, ␊, ␀, ..)
|
||||
* caret (^G, ^J, ^@, ..)
|
||||
|
||||
-p, --plain...
|
||||
Only show plain style, no decorations. This is an alias for '--style=plain'. When '-p' is
|
||||
used twice ('-pp'), it also disables automatic paging (alias for '--style=plain
|
||||
--paging=never').
|
||||
|
||||
-l, --language <language>
|
||||
Explicitly set the language for syntax highlighting. The language can be specified as a
|
||||
name (like 'C++' or 'LaTeX') or possible file extension (like 'cpp', 'hpp' or 'md'). Use
|
||||
'--list-languages' to show all supported language names and file extensions.
|
||||
|
||||
-H, --highlight-line <N:M>
|
||||
Highlight the specified line ranges with a different background color For example:
|
||||
'--highlight-line 40' highlights line 40
|
||||
'--highlight-line 30:40' highlights lines 30 to 40
|
||||
'--highlight-line :40' highlights lines 1 to 40
|
||||
'--highlight-line 40:' highlights lines 40 to the end of the file
|
||||
'--highlight-line 30:+10' highlights lines 30 to 40
|
||||
|
||||
--file-name <name>
|
||||
Specify the name to display for a file. Useful when piping data to bat from STDIN when bat
|
||||
does not otherwise know the filename. Note that the provided file name is also used for
|
||||
syntax detection.
|
||||
|
||||
-d, --diff
|
||||
Only show lines that have been added/removed/modified with respect to the Git index. Use
|
||||
--diff-context=N to control how much context you want to see.
|
||||
|
||||
--diff-context <N>
|
||||
Include N lines of context around added/removed/modified lines when using '--diff'.
|
||||
|
||||
--tabs <T>
|
||||
Set the tab width to T spaces. Use a width of 0 to pass tabs through directly
|
||||
|
||||
--wrap <mode>
|
||||
Specify the text-wrapping mode (*auto*, never, character). The '--terminal-width' option
|
||||
can be used in addition to control the output width.
|
||||
|
||||
-S, --chop-long-lines
|
||||
Truncate all lines longer than screen width. Alias for '--wrap=never'.
|
||||
|
||||
--terminal-width <width>
|
||||
Explicitly set the width of the terminal instead of determining it automatically. If
|
||||
prefixed with '+' or '-', the value will be treated as an offset to the actual terminal
|
||||
width. See also: '--wrap'.
|
||||
|
||||
-n, --number
|
||||
Only show line numbers, no other decorations. This is an alias for '--style=numbers'
|
||||
|
||||
--color <when>
|
||||
Specify when to use colored output. The automatic mode only enables colors if an
|
||||
interactive terminal is detected - colors are automatically disabled if the output goes to
|
||||
a pipe.
|
||||
Possible values: *auto*, never, always.
|
||||
|
||||
--italic-text <when>
|
||||
Specify when to use ANSI sequences for italic text in the output. Possible values: always,
|
||||
*never*.
|
||||
|
||||
--decorations <when>
|
||||
Specify when to use the decorations that have been specified via '--style'. The automatic
|
||||
mode only enables decorations if an interactive terminal is detected. Possible values:
|
||||
*auto*, never, always.
|
||||
|
||||
-f, --force-colorization
|
||||
Alias for '--decorations=always --color=always'. This is useful if the output of bat is
|
||||
piped to another program, but you want to keep the colorization/decorations.
|
||||
|
||||
--paging <when>
|
||||
Specify when to use the pager. To disable the pager, use --paging=never' or its
|
||||
alias,'-P'. To disable the pager permanently, set BAT_PAGING to 'never'. To control which
|
||||
pager is used, see the '--pager' option. Possible values: *auto*, never, always.
|
||||
|
||||
--pager <command>
|
||||
Determine which pager is used. This option will override the PAGER and BAT_PAGER
|
||||
environment variables. The default pager is 'less'. To control when the pager is used, see
|
||||
the '--paging' option. Example: '--pager "less -RF"'.
|
||||
|
||||
-m, --map-syntax <glob:syntax>
|
||||
Map a glob pattern to an existing syntax name. The glob pattern is matched on the full
|
||||
path and the filename. For example, to highlight *.build files with the Python syntax, use
|
||||
-m '*.build:Python'. To highlight files named '.myignore' with the Git Ignore syntax, use
|
||||
-m '.myignore:Git Ignore'. Note that the right-hand side is the *name* of the syntax, not
|
||||
a file extension.
|
||||
|
||||
--ignored-suffix <ignored-suffix>
|
||||
Ignore extension. For example:
|
||||
'bat --ignored-suffix ".dev" my_file.json.dev' will use JSON syntax, and ignore '.dev'
|
||||
|
||||
--theme <theme>
|
||||
Set the theme for syntax highlighting. Use '--list-themes' to see all available themes. To
|
||||
set a default theme, add the '--theme="..."' option to the configuration file or export
|
||||
the BAT_THEME environment variable (e.g.: export BAT_THEME="...").
|
||||
|
||||
--list-themes
|
||||
Display a list of supported themes for syntax highlighting.
|
||||
|
||||
--style <components>
|
||||
Configure which elements (line numbers, file headers, grid borders, Git modifications, ..)
|
||||
to display in addition to the file contents. The argument is a comma-separated list of
|
||||
components to display (e.g. 'numbers,changes,grid') or a pre-defined style ('full'). To
|
||||
set a default style, add the '--style=".."' option to the configuration file or export the
|
||||
BAT_STYLE environment variable (e.g.: export BAT_STYLE="..").
|
||||
|
||||
Possible values:
|
||||
|
||||
* default: enables recommended style components (default).
|
||||
* full: enables all available components.
|
||||
* auto: same as 'default', unless the output is piped.
|
||||
* plain: disables all available components.
|
||||
* changes: show Git modification markers.
|
||||
* header: alias for 'header-filename'.
|
||||
* header-filename: show filenames before the content.
|
||||
* header-filesize: show file sizes before the content.
|
||||
* grid: vertical/horizontal lines to separate side bar
|
||||
and the header from the content.
|
||||
* rule: horizontal lines to delimit files.
|
||||
* numbers: show line numbers in the side bar.
|
||||
* snip: draw separation lines between distinct line ranges.
|
||||
|
||||
-r, --line-range <N:M>
|
||||
Only print the specified range of lines for each file. For example:
|
||||
'--line-range 30:40' prints lines 30 to 40
|
||||
'--line-range :40' prints lines 1 to 40
|
||||
'--line-range 40:' prints lines 40 to the end of the file
|
||||
'--line-range 40' only prints line 40
|
||||
'--line-range 30:+10' prints lines 30 to 40
|
||||
|
||||
-L, --list-languages
|
||||
Display a list of supported languages for syntax highlighting.
|
||||
|
||||
-u, --unbuffered
|
||||
This option exists for POSIX-compliance reasons ('u' is for 'unbuffered'). The output is
|
||||
always unbuffered - this option is simply ignored.
|
||||
|
||||
--diagnostic
|
||||
Show diagnostic information for bug reports.
|
||||
|
||||
--acknowledgements
|
||||
Show acknowledgements.
|
||||
|
||||
-h, --help
|
||||
Print help (see a summary with '-h')
|
||||
|
||||
-V, --version
|
||||
Print version
|
@@ -5,7 +5,7 @@
|
||||
- [ ] Update version in `Cargo.toml`. Run `cargo build` to update `Cargo.lock`.
|
||||
Make sure to `git add` the `Cargo.lock` changes as well.
|
||||
- [ ] Find the current min. supported Rust version by running
|
||||
`cargo metadata --no-deps --format-version 1 | jq -r '.packages[0].rust_version'`.
|
||||
`grep '^\s*MIN_SUPPORTED_RUST_VERSION' .github/workflows/CICD.yml`.
|
||||
- [ ] Update the version and the min. supported Rust version in `README.md` and
|
||||
`doc/README-*.md`. Check with
|
||||
`git grep -i -e 'rust.*1\.' -e '1\..*rust' | grep README | grep -v tests/`.
|
||||
@@ -20,7 +20,7 @@
|
||||
|
||||
## Documentation
|
||||
|
||||
- [ ] Review [`-h`](./short-help.txt), [`--help`](./long-help.txt), and the `man` page. The `man` page is shown in
|
||||
- [ ] Review `-h`, `--help`, and the `man` page. All of these are shown in
|
||||
the output of the CI job called *Documentation*, so look there.
|
||||
The CI workflow corresponding to the tip of the master branch is a good place to look.
|
||||
|
||||
|
@@ -1,56 +0,0 @@
|
||||
A cat(1) clone with wings.
|
||||
|
||||
Usage: bat [OPTIONS] [FILE]...
|
||||
bat <COMMAND>
|
||||
|
||||
Arguments:
|
||||
[FILE]... File(s) to print / concatenate. Use '-' for standard input.
|
||||
|
||||
Options:
|
||||
-A, --show-all
|
||||
Show non-printable characters (space, tab, newline, ..).
|
||||
--nonprintable-notation <notation>
|
||||
Set notation for non-printable characters.
|
||||
-p, --plain...
|
||||
Show plain style (alias for '--style=plain').
|
||||
-l, --language <language>
|
||||
Set the language for syntax highlighting.
|
||||
-H, --highlight-line <N:M>
|
||||
Highlight lines N through M.
|
||||
--file-name <name>
|
||||
Specify the name to display for a file.
|
||||
-d, --diff
|
||||
Only show lines that have been added/removed/modified.
|
||||
--tabs <T>
|
||||
Set the tab width to T spaces.
|
||||
--wrap <mode>
|
||||
Specify the text-wrapping mode (*auto*, never, character).
|
||||
-S, --chop-long-lines
|
||||
Truncate all lines longer than screen width. Alias for '--wrap=never'.
|
||||
-n, --number
|
||||
Show line numbers (alias for '--style=numbers').
|
||||
--color <when>
|
||||
When to use colors (*auto*, never, always).
|
||||
--italic-text <when>
|
||||
Use italics in output (always, *never*)
|
||||
--decorations <when>
|
||||
When to show the decorations (*auto*, never, always).
|
||||
--paging <when>
|
||||
Specify when to use the pager, or use `-P` to disable (*auto*, never, always).
|
||||
-m, --map-syntax <glob:syntax>
|
||||
Use the specified syntax for files matching the glob pattern ('*.cpp:C++').
|
||||
--theme <theme>
|
||||
Set the color theme for syntax highlighting.
|
||||
--list-themes
|
||||
Display all supported highlighting themes.
|
||||
--style <components>
|
||||
Comma-separated list of style elements to display (*default*, auto, full, plain, changes,
|
||||
header, header-filename, header-filesize, grid, rule, numbers, snip).
|
||||
-r, --line-range <N:M>
|
||||
Only print the lines from N to M.
|
||||
-L, --list-languages
|
||||
Display all supported languages.
|
||||
-h, --help
|
||||
Print help (see more with '--help')
|
||||
-V, --version
|
||||
Print version
|
Binary file not shown.
Before Width: | Height: | Size: 817 KiB |
@@ -1,17 +0,0 @@
|
||||
use bat::{assets::HighlightingAssets, config::Config, controller::Controller, Input};
|
||||
|
||||
fn main() {
|
||||
let mut buffer = String::new();
|
||||
let config = Config {
|
||||
colored_output: true,
|
||||
..Default::default()
|
||||
};
|
||||
let assets = HighlightingAssets::from_binary();
|
||||
let controller = Controller::new(&config, &assets);
|
||||
let input = Input::from_file(file!());
|
||||
controller
|
||||
.run(vec![input.into()], Some(&mut buffer))
|
||||
.unwrap();
|
||||
|
||||
println!("{buffer}");
|
||||
}
|
@@ -1,4 +1,4 @@
|
||||
/// A simple program that lists all supported syntaxes and themes.
|
||||
/// A simple program that prints its own source code using the bat library
|
||||
use bat::PrettyPrinter;
|
||||
|
||||
fn main() {
|
||||
|
@@ -23,8 +23,7 @@ fn main() {
|
||||
}],
|
||||
};
|
||||
|
||||
let mut bytes = Vec::with_capacity(128);
|
||||
serde_yaml::to_writer(&mut bytes, &person).unwrap();
|
||||
let bytes = serde_yaml::to_vec(&person).unwrap();
|
||||
PrettyPrinter::new()
|
||||
.language("yaml")
|
||||
.line_numbers(true)
|
||||
|
21
plugins/curl.lua
Normal file
21
plugins/curl.lua
Normal file
@@ -0,0 +1,21 @@
|
||||
function tempdir()
|
||||
local stream = assert(io.popen('mktemp --directory'))
|
||||
local output = stream:read('*all')
|
||||
stream:close()
|
||||
return string.gsub(output, "\n", "")
|
||||
end
|
||||
|
||||
function preprocess(path_or_url)
|
||||
filename_from_url = string.match(path_or_url, '^https?://.*/(.*)$')
|
||||
if filename_from_url then
|
||||
local temp_directory = tempdir()
|
||||
local new_path = temp_directory .. "/" .. filename_from_url
|
||||
|
||||
-- TODO: how to prevent shell injection bugs?
|
||||
os.execute("curl --silent '" .. path_or_url .. "' --output '" .. new_path .. "'")
|
||||
|
||||
return new_path
|
||||
else
|
||||
return path_or_url
|
||||
end
|
||||
end
|
17
plugins/directories.lua
Normal file
17
plugins/directories.lua
Normal file
@@ -0,0 +1,17 @@
|
||||
-- https://stackoverflow.com/a/3254007/704831
|
||||
function is_dir(path)
|
||||
local f = io.open(path, "r")
|
||||
local ok, err, code = f:read(1)
|
||||
f:close()
|
||||
return code == 21
|
||||
end
|
||||
|
||||
function preprocess(path)
|
||||
if is_dir(path) then
|
||||
tmpfile = os.tmpname()
|
||||
os.execute("ls -alh --color=always '" .. path .. "' > '" .. tmpfile .. "'")
|
||||
return tmpfile
|
||||
else
|
||||
return path
|
||||
end
|
||||
end
|
21
plugins/hexyl.lua
Normal file
21
plugins/hexyl.lua
Normal file
@@ -0,0 +1,21 @@
|
||||
-- Note: this plugin depends on the existence of 'inspect' [1] and 'hexyl' [2]
|
||||
--
|
||||
-- [1] https://github.com/sharkdp/content_inspector
|
||||
-- [2] https://github.com/sharkdp/hexyl
|
||||
|
||||
function is_binary(path)
|
||||
local stream = assert(io.popen("inspect '" .. path .. "'"))
|
||||
local output = stream:read('*all')
|
||||
stream:close()
|
||||
return string.find(output, ": binary\n")
|
||||
end
|
||||
|
||||
function preprocess(path)
|
||||
if is_binary(path) then
|
||||
tmpfile = os.tmpname()
|
||||
os.execute("hexyl --length 1024 --no-position --border=none --no-squeezing '" .. path .. "' > '" .. tmpfile .. "'")
|
||||
return tmpfile
|
||||
else
|
||||
return path
|
||||
end
|
||||
end
|
21
plugins/uncompress.lua
Normal file
21
plugins/uncompress.lua
Normal file
@@ -0,0 +1,21 @@
|
||||
function tempdir()
|
||||
local stream = assert(io.popen('mktemp --directory'))
|
||||
local output = stream:read('*all')
|
||||
stream:close()
|
||||
return string.gsub(output, "\n", "")
|
||||
end
|
||||
|
||||
function preprocess(path)
|
||||
prefix = string.match(path, '^(.*)%.gz$')
|
||||
if prefix then
|
||||
local temp_directory = tempdir()
|
||||
local new_path = temp_directory .. "/" .. prefix
|
||||
|
||||
-- TODO: how to prevent shell injection bugs?
|
||||
os.execute("gunzip < '" .. path .. "' > '" .. new_path .. "'")
|
||||
|
||||
return new_path
|
||||
else
|
||||
return path
|
||||
end
|
||||
end
|
@@ -84,7 +84,7 @@ impl HighlightingAssets {
|
||||
/// platform, the default theme depends on
|
||||
/// ```bash
|
||||
/// defaults read -globalDomain AppleInterfaceStyle
|
||||
/// ```
|
||||
/// ````
|
||||
/// To avoid the overhead of the check on macOS, simply specify a theme
|
||||
/// explicitly via `--theme`, `BAT_THEME`, or `~/.config/bat`.
|
||||
///
|
||||
@@ -401,21 +401,11 @@ fn asset_from_cache<T: serde::de::DeserializeOwned>(
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
fn macos_dark_mode_active() -> bool {
|
||||
const PREFERENCES_FILE: &str = "Library/Preferences/.GlobalPreferences.plist";
|
||||
const STYLE_KEY: &str = "AppleInterfaceStyle";
|
||||
|
||||
let preferences_file = home::home_dir()
|
||||
.map(|home| home.join(PREFERENCES_FILE))
|
||||
.expect("Could not get home directory");
|
||||
|
||||
match plist::Value::from_file(preferences_file).map(|file| file.into_dictionary()) {
|
||||
Ok(Some(preferences)) => match preferences.get(STYLE_KEY).and_then(|val| val.as_string()) {
|
||||
Some(value) => value == "Dark",
|
||||
// If the key does not exist, then light theme is currently in use.
|
||||
None => false,
|
||||
},
|
||||
// Unreachable, in theory. All macOS users have a home directory and preferences file setup.
|
||||
Ok(None) | Err(_) => true,
|
||||
let mut defaults_cmd = std::process::Command::new("defaults");
|
||||
defaults_cmd.args(&["read", "-globalDomain", "AppleInterfaceStyle"]);
|
||||
match defaults_cmd.output() {
|
||||
Ok(output) => output.stdout == b"Dark\n",
|
||||
Err(_) => true,
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -7,7 +7,7 @@ use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::error::*;
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Default, Serialize, Deserialize)]
|
||||
#[derive(Debug, PartialEq, Default, Serialize, Deserialize)]
|
||||
pub struct AssetsMetadata {
|
||||
bat_version: Option<String>,
|
||||
creation_time: Option<SystemTime>,
|
||||
|
@@ -1,4 +1,3 @@
|
||||
use std::fmt::Write;
|
||||
use std::fs::read_to_string;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
@@ -125,7 +124,7 @@ fn append_to_acknowledgements(
|
||||
relative_path: &str,
|
||||
license_text: &str,
|
||||
) {
|
||||
write!(acknowledgements, "## {}\n\n{}", relative_path, license_text).ok();
|
||||
acknowledgements.push_str(&format!("## {}\n\n{}", relative_path, license_text));
|
||||
|
||||
// Make sure the last char is a newline to not mess up formatting later
|
||||
if acknowledgements
|
||||
|
@@ -1,11 +1,13 @@
|
||||
use std::collections::HashSet;
|
||||
use std::env;
|
||||
use std::io::IsTerminal;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::path::Path;
|
||||
use std::str::FromStr;
|
||||
|
||||
use atty::{self, Stream};
|
||||
|
||||
use crate::{
|
||||
clap_app,
|
||||
config::{get_args_from_config_file, get_args_from_env_opts_var, get_args_from_env_vars},
|
||||
config::{get_args_from_config_file, get_args_from_env_var},
|
||||
};
|
||||
use clap::ArgMatches;
|
||||
|
||||
@@ -20,7 +22,7 @@ use bat::{
|
||||
input::Input,
|
||||
line_range::{HighlightedLineRanges, LineRange, LineRanges},
|
||||
style::{StyleComponent, StyleComponents},
|
||||
MappingTarget, NonprintableNotation, PagingMode, SyntaxMapping, WrappingMode,
|
||||
MappingTarget, PagingMode, SyntaxMapping, WrappingMode,
|
||||
};
|
||||
|
||||
fn is_truecolor_terminal() -> bool {
|
||||
@@ -30,16 +32,16 @@ fn is_truecolor_terminal() -> bool {
|
||||
}
|
||||
|
||||
pub struct App {
|
||||
pub matches: ArgMatches,
|
||||
pub matches: ArgMatches<'static>,
|
||||
interactive_output: bool,
|
||||
}
|
||||
|
||||
impl App {
|
||||
pub fn new() -> Result<Self> {
|
||||
#[cfg(windows)]
|
||||
let _ = nu_ansi_term::enable_ansi_support();
|
||||
let _ = ansi_term::enable_ansi_support();
|
||||
|
||||
let interactive_output = std::io::stdout().is_terminal();
|
||||
let interactive_output = atty::is(Stream::Stdout);
|
||||
|
||||
Ok(App {
|
||||
matches: Self::matches(interactive_output)?,
|
||||
@@ -47,35 +49,21 @@ impl App {
|
||||
})
|
||||
}
|
||||
|
||||
fn matches(interactive_output: bool) -> Result<ArgMatches> {
|
||||
let args = if wild::args_os().nth(1) == Some("cache".into()) {
|
||||
// Skip the config file and env vars
|
||||
|
||||
wild::args_os().collect::<Vec<_>>()
|
||||
} else if wild::args_os().any(|arg| arg == "--no-config") {
|
||||
fn matches(interactive_output: bool) -> Result<ArgMatches<'static>> {
|
||||
let args = if wild::args_os().nth(1) == Some("cache".into())
|
||||
|| wild::args_os().any(|arg| arg == "--no-config")
|
||||
{
|
||||
// Skip the arguments in bats config file
|
||||
|
||||
let mut cli_args = wild::args_os();
|
||||
let mut args = get_args_from_env_vars();
|
||||
|
||||
// Put the zero-th CLI argument (program name) first
|
||||
args.insert(0, cli_args.next().unwrap());
|
||||
|
||||
// .. and the rest at the end
|
||||
cli_args.for_each(|a| args.push(a));
|
||||
|
||||
args
|
||||
wild::args_os().collect::<Vec<_>>()
|
||||
} else {
|
||||
let mut cli_args = wild::args_os();
|
||||
|
||||
// Read arguments from bats config file
|
||||
let mut args = get_args_from_env_opts_var()
|
||||
let mut args = get_args_from_env_var()
|
||||
.unwrap_or_else(get_args_from_config_file)
|
||||
.map_err(|_| "Could not parse configuration file")?;
|
||||
|
||||
// Selected env vars supersede config vars
|
||||
args.extend(get_args_from_env_vars());
|
||||
|
||||
// Put the zero-th CLI argument (program name) first
|
||||
args.insert(0, cli_args.next().unwrap());
|
||||
|
||||
@@ -91,19 +79,19 @@ impl App {
|
||||
pub fn config(&self, inputs: &[Input]) -> Result<Config> {
|
||||
let style_components = self.style_components()?;
|
||||
|
||||
let paging_mode = match self.matches.get_one::<String>("paging").map(|s| s.as_str()) {
|
||||
let paging_mode = match self.matches.value_of("paging") {
|
||||
Some("always") => PagingMode::Always,
|
||||
Some("never") => PagingMode::Never,
|
||||
Some("auto") | None => {
|
||||
// If we have -pp as an option when in auto mode, the pager should be disabled.
|
||||
let extra_plain = self.matches.get_count("plain") > 1;
|
||||
if extra_plain || self.matches.get_flag("no-paging") {
|
||||
let extra_plain = self.matches.occurrences_of("plain") > 1;
|
||||
if extra_plain || self.matches.is_present("no-paging") {
|
||||
PagingMode::Never
|
||||
} else if inputs.iter().any(Input::is_stdin) {
|
||||
// If we are reading from stdin, only enable paging if we write to an
|
||||
// interactive terminal and if we do not *read* from an interactive
|
||||
// terminal.
|
||||
if self.interactive_output && !std::io::stdin().is_terminal() {
|
||||
if self.interactive_output && !atty::is(Stream::Stdin) {
|
||||
PagingMode::QuitIfOneScreen
|
||||
} else {
|
||||
PagingMode::Never
|
||||
@@ -119,13 +107,13 @@ impl App {
|
||||
|
||||
let mut syntax_mapping = SyntaxMapping::builtin();
|
||||
|
||||
if let Some(values) = self.matches.get_many::<String>("ignored-suffix") {
|
||||
if let Some(values) = self.matches.values_of("ignored-suffix") {
|
||||
for suffix in values {
|
||||
syntax_mapping.insert_ignored_suffix(suffix);
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(values) = self.matches.get_many::<String>("map-syntax") {
|
||||
if let Some(values) = self.matches.values_of("map-syntax") {
|
||||
for from_to in values {
|
||||
let parts: Vec<_> = from_to.split(':').collect();
|
||||
|
||||
@@ -137,10 +125,7 @@ impl App {
|
||||
}
|
||||
}
|
||||
|
||||
let maybe_term_width = self
|
||||
.matches
|
||||
.get_one::<String>("terminal-width")
|
||||
.and_then(|w| {
|
||||
let maybe_term_width = self.matches.value_of("terminal-width").and_then(|w| {
|
||||
if w.starts_with('+') || w.starts_with('-') {
|
||||
// Treat argument as a delta to the current terminal width
|
||||
w.parse().ok().map(|delta: i16| {
|
||||
@@ -160,30 +145,16 @@ impl App {
|
||||
|
||||
Ok(Config {
|
||||
true_color: is_truecolor_terminal(),
|
||||
language: self
|
||||
.matches
|
||||
.get_one::<String>("language")
|
||||
.map(|s| s.as_str())
|
||||
.or_else(|| {
|
||||
if self.matches.get_flag("show-all") {
|
||||
language: self.matches.value_of("language").or_else(|| {
|
||||
if self.matches.is_present("show-all") {
|
||||
Some("show-nonprintable")
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}),
|
||||
show_nonprintable: self.matches.get_flag("show-all"),
|
||||
nonprintable_notation: match self
|
||||
.matches
|
||||
.get_one::<String>("nonprintable-notation")
|
||||
.map(|s| s.as_str())
|
||||
{
|
||||
Some("unicode") => NonprintableNotation::Unicode,
|
||||
Some("caret") => NonprintableNotation::Caret,
|
||||
_ => unreachable!("other values for --nonprintable-notation are not allowed"),
|
||||
},
|
||||
show_nonprintable: self.matches.is_present("show-all"),
|
||||
wrapping_mode: if self.interactive_output || maybe_term_width.is_some() {
|
||||
if !self.matches.get_flag("chop-long-lines") {
|
||||
match self.matches.get_one::<String>("wrap").map(|s| s.as_str()) {
|
||||
match self.matches.value_of("wrap") {
|
||||
Some("character") => WrappingMode::Character,
|
||||
Some("never") => WrappingMode::NoWrapping(true),
|
||||
Some("auto") | None => {
|
||||
@@ -195,16 +166,13 @@ impl App {
|
||||
}
|
||||
_ => unreachable!("other values for --wrap are not allowed"),
|
||||
}
|
||||
} else {
|
||||
WrappingMode::NoWrapping(true)
|
||||
}
|
||||
} else {
|
||||
// We don't have the tty width when piping to another program.
|
||||
// There's no point in wrapping when this is the case.
|
||||
WrappingMode::NoWrapping(false)
|
||||
},
|
||||
colored_output: self.matches.get_flag("force-colorization")
|
||||
|| match self.matches.get_one::<String>("color").map(|s| s.as_str()) {
|
||||
colored_output: self.matches.is_present("force-colorization")
|
||||
|| match self.matches.value_of("color") {
|
||||
Some("always") => true,
|
||||
Some("never") => false,
|
||||
Some("auto") => env::var_os("NO_COLOR").is_none() && self.interactive_output,
|
||||
@@ -213,17 +181,14 @@ impl App {
|
||||
paging_mode,
|
||||
term_width: maybe_term_width.unwrap_or(Term::stdout().size().1 as usize),
|
||||
loop_through: !(self.interactive_output
|
||||
|| self.matches.get_one::<String>("color").map(|s| s.as_str()) == Some("always")
|
||||
|| self
|
||||
.matches
|
||||
.get_one::<String>("decorations")
|
||||
.map(|s| s.as_str())
|
||||
== Some("always")
|
||||
|| self.matches.get_flag("force-colorization")),
|
||||
|| self.matches.value_of("color") == Some("always")
|
||||
|| self.matches.value_of("decorations") == Some("always")
|
||||
|| self.matches.is_present("force-colorization")),
|
||||
tab_width: self
|
||||
.matches
|
||||
.get_one::<String>("tabs")
|
||||
.value_of("tabs")
|
||||
.map(String::from)
|
||||
.or_else(|| env::var("BAT_TABS").ok())
|
||||
.and_then(|t| t.parse().ok())
|
||||
.unwrap_or(
|
||||
if style_components.plain() && paging_mode == PagingMode::Never {
|
||||
@@ -234,8 +199,9 @@ impl App {
|
||||
),
|
||||
theme: self
|
||||
.matches
|
||||
.get_one::<String>("theme")
|
||||
.value_of("theme")
|
||||
.map(String::from)
|
||||
.or_else(|| env::var("BAT_THEME").ok())
|
||||
.map(|s| {
|
||||
if s == "default" {
|
||||
String::from(HighlightingAssets::default_theme())
|
||||
@@ -244,21 +210,19 @@ impl App {
|
||||
}
|
||||
})
|
||||
.unwrap_or_else(|| String::from(HighlightingAssets::default_theme())),
|
||||
visible_lines: match self.matches.try_contains_id("diff").unwrap_or_default()
|
||||
&& self.matches.get_flag("diff")
|
||||
{
|
||||
visible_lines: match self.matches.is_present("diff") {
|
||||
#[cfg(feature = "git")]
|
||||
true => VisibleLines::DiffContext(
|
||||
self.matches
|
||||
.get_one::<String>("diff-context")
|
||||
.value_of("diff-context")
|
||||
.and_then(|t| t.parse().ok())
|
||||
.unwrap_or(2),
|
||||
),
|
||||
|
||||
_ => VisibleLines::Ranges(
|
||||
self.matches
|
||||
.get_many::<String>("line-range")
|
||||
.map(|vs| vs.map(|s| LineRange::from(s.as_str())).collect())
|
||||
.values_of("line-range")
|
||||
.map(|vs| vs.map(LineRange::from).collect())
|
||||
.transpose()?
|
||||
.map(LineRanges::from)
|
||||
.unwrap_or_default(),
|
||||
@@ -266,49 +230,50 @@ impl App {
|
||||
},
|
||||
style_components,
|
||||
syntax_mapping,
|
||||
pager: self.matches.get_one::<String>("pager").map(|s| s.as_str()),
|
||||
use_italic_text: self
|
||||
.matches
|
||||
.get_one::<String>("italic-text")
|
||||
.map(|s| s.as_str())
|
||||
== Some("always"),
|
||||
pager: self.matches.value_of("pager"),
|
||||
use_italic_text: self.matches.value_of("italic-text") == Some("always"),
|
||||
highlighted_lines: self
|
||||
.matches
|
||||
.get_many::<String>("highlight-line")
|
||||
.map(|ws| ws.map(|s| LineRange::from(s.as_str())).collect())
|
||||
.values_of("highlight-line")
|
||||
.map(|ws| ws.map(LineRange::from).collect())
|
||||
.transpose()?
|
||||
.map(LineRanges::from)
|
||||
.map(HighlightedLineRanges)
|
||||
.unwrap_or_default(),
|
||||
use_custom_assets: !self.matches.get_flag("no-custom-assets"),
|
||||
#[cfg(feature = "lessopen")]
|
||||
use_lessopen: self.matches.get_flag("lessopen"),
|
||||
use_custom_assets: !self.matches.is_present("no-custom-assets"),
|
||||
plugins: self
|
||||
.matches
|
||||
.values_of_os("load-plugin")
|
||||
.unwrap_or_default()
|
||||
.collect(),
|
||||
})
|
||||
}
|
||||
|
||||
pub fn inputs(&self) -> Result<Vec<Input>> {
|
||||
let filenames: Option<Vec<&Path>> = self
|
||||
.matches
|
||||
.get_many::<PathBuf>("file-name")
|
||||
.map(|vs| vs.map(|p| p.as_path()).collect::<Vec<_>>());
|
||||
|
||||
let files: Option<Vec<&Path>> = self
|
||||
.matches
|
||||
.get_many::<PathBuf>("FILE")
|
||||
.map(|vs| vs.map(|p| p.as_path()).collect::<Vec<_>>());
|
||||
|
||||
// verify equal length of file-names and input FILEs
|
||||
if filenames.is_some()
|
||||
&& files.is_some()
|
||||
&& filenames.as_ref().map(|v| v.len()) != files.as_ref().map(|v| v.len())
|
||||
match self.matches.values_of("file-name") {
|
||||
Some(ref filenames)
|
||||
if self.matches.values_of_os("FILE").is_some()
|
||||
&& filenames.len() != self.matches.values_of_os("FILE").unwrap().len() =>
|
||||
{
|
||||
return Err("Must be one file name per input type.".into());
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
let filenames: Option<Vec<&Path>> = self
|
||||
.matches
|
||||
.values_of_os("file-name")
|
||||
.map(|values| values.map(Path::new).collect());
|
||||
|
||||
let mut filenames_or_none: Box<dyn Iterator<Item = Option<&Path>>> = match filenames {
|
||||
Some(filenames) => Box::new(filenames.into_iter().map(Some)),
|
||||
None => Box::new(std::iter::repeat(None)),
|
||||
};
|
||||
let files: Option<Vec<&Path>> = self
|
||||
.matches
|
||||
.values_of_os("FILE")
|
||||
.map(|vs| vs.map(Path::new).collect());
|
||||
|
||||
if files.is_none() {
|
||||
return Ok(vec![new_stdin_input(
|
||||
filenames_or_none.next().unwrap_or(None),
|
||||
@@ -334,16 +299,26 @@ impl App {
|
||||
|
||||
fn style_components(&self) -> Result<StyleComponents> {
|
||||
let matches = &self.matches;
|
||||
let mut styled_components = StyleComponents(
|
||||
if matches.get_one::<String>("decorations").map(|s| s.as_str()) == Some("never") {
|
||||
let mut styled_components =
|
||||
StyleComponents(if matches.value_of("decorations") == Some("never") {
|
||||
HashSet::new()
|
||||
} else if matches.get_flag("number") {
|
||||
} else if matches.is_present("number") {
|
||||
[StyleComponent::LineNumbers].iter().cloned().collect()
|
||||
} else if 0 < matches.get_count("plain") {
|
||||
} else if matches.is_present("plain") {
|
||||
[StyleComponent::Plain].iter().cloned().collect()
|
||||
} else {
|
||||
let env_style_components: Option<Vec<StyleComponent>> = env::var("BAT_STYLE")
|
||||
.ok()
|
||||
.map(|style_str| {
|
||||
style_str
|
||||
.split(',')
|
||||
.map(StyleComponent::from_str)
|
||||
.collect::<Result<Vec<StyleComponent>>>()
|
||||
})
|
||||
.transpose()?;
|
||||
|
||||
matches
|
||||
.get_one::<String>("style")
|
||||
.value_of("style")
|
||||
.map(|styles| {
|
||||
styles
|
||||
.split(',')
|
||||
@@ -351,6 +326,7 @@ impl App {
|
||||
.filter_map(|style| style.ok())
|
||||
.collect::<Vec<_>>()
|
||||
})
|
||||
.or(env_style_components)
|
||||
.unwrap_or_else(|| vec![StyleComponent::Default])
|
||||
.into_iter()
|
||||
.map(|style| style.components(self.interactive_output))
|
||||
@@ -358,8 +334,7 @@ impl App {
|
||||
acc.extend(components.iter().cloned());
|
||||
acc
|
||||
})
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
// If `grid` is set, remove `rule` as it is a subset of `grid`, and print a warning.
|
||||
if styled_components.grid() && styled_components.0.remove(&StyleComponent::Rule) {
|
||||
|
@@ -1,24 +1,31 @@
|
||||
use std::borrow::Cow;
|
||||
use std::fs;
|
||||
use std::io;
|
||||
use std::path::Path;
|
||||
use std::path::PathBuf;
|
||||
|
||||
use clap::crate_version;
|
||||
|
||||
use crate::directories::PROJECT_DIRS;
|
||||
|
||||
use bat::assets::HighlightingAssets;
|
||||
use bat::assets_metadata::AssetsMetadata;
|
||||
use bat::error::*;
|
||||
|
||||
pub fn clear_assets(cache_dir: &Path) {
|
||||
clear_asset(cache_dir.join("themes.bin"), "theme set cache");
|
||||
clear_asset(cache_dir.join("syntaxes.bin"), "syntax set cache");
|
||||
clear_asset(cache_dir.join("metadata.yaml"), "metadata file");
|
||||
pub fn config_dir() -> Cow<'static, str> {
|
||||
PROJECT_DIRS.config_dir().to_string_lossy()
|
||||
}
|
||||
|
||||
pub fn assets_from_cache_or_binary(
|
||||
use_custom_assets: bool,
|
||||
cache_dir: &Path,
|
||||
) -> Result<HighlightingAssets> {
|
||||
pub fn cache_dir() -> Cow<'static, str> {
|
||||
PROJECT_DIRS.cache_dir().to_string_lossy()
|
||||
}
|
||||
|
||||
pub fn clear_assets() {
|
||||
clear_asset("themes.bin", "theme set cache");
|
||||
clear_asset("syntaxes.bin", "syntax set cache");
|
||||
clear_asset("metadata.yaml", "metadata file");
|
||||
}
|
||||
|
||||
pub fn assets_from_cache_or_binary(use_custom_assets: bool) -> Result<HighlightingAssets> {
|
||||
let cache_dir = PROJECT_DIRS.cache_dir();
|
||||
if let Some(metadata) = AssetsMetadata::load_from_folder(cache_dir)? {
|
||||
if !metadata.is_compatible_with(crate_version!()) {
|
||||
return Err(format!(
|
||||
@@ -43,8 +50,9 @@ pub fn assets_from_cache_or_binary(
|
||||
Ok(custom_assets.unwrap_or_else(HighlightingAssets::from_binary))
|
||||
}
|
||||
|
||||
fn clear_asset(path: PathBuf, description: &str) {
|
||||
fn clear_asset(filename: &str, description: &str) {
|
||||
print!("Clearing {} ... ", description);
|
||||
let path = PROJECT_DIRS.cache_dir().join(filename);
|
||||
match fs::remove_file(&path) {
|
||||
Err(err) if err.kind() == io::ErrorKind::NotFound => {
|
||||
println!("skipped (not present)");
|
||||
|
@@ -1,9 +1,7 @@
|
||||
use clap::{
|
||||
crate_name, crate_version, value_parser, Arg, ArgAction, ArgGroup, ColorChoice, Command,
|
||||
};
|
||||
use clap::{crate_name, crate_version, App as ClapApp, AppSettings, Arg, ArgGroup, SubCommand};
|
||||
use once_cell::sync::Lazy;
|
||||
use std::env;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::path::Path;
|
||||
|
||||
static VERSION: Lazy<String> = Lazy::new(|| {
|
||||
#[cfg(feature = "bugreport")]
|
||||
@@ -18,39 +16,48 @@ static VERSION: Lazy<String> = Lazy::new(|| {
|
||||
}
|
||||
});
|
||||
|
||||
pub fn build_app(interactive_output: bool) -> Command {
|
||||
let color_when = if interactive_output && env::var_os("NO_COLOR").is_none() {
|
||||
ColorChoice::Auto
|
||||
pub fn build_app(interactive_output: bool) -> ClapApp<'static, 'static> {
|
||||
let clap_color_setting = if interactive_output && env::var_os("NO_COLOR").is_none() {
|
||||
AppSettings::ColoredHelp
|
||||
} else {
|
||||
ColorChoice::Never
|
||||
AppSettings::ColorNever
|
||||
};
|
||||
|
||||
let mut app = Command::new(crate_name!())
|
||||
let mut app = ClapApp::new(crate_name!())
|
||||
.version(VERSION.as_str())
|
||||
.color(color_when)
|
||||
.hide_possible_values(true)
|
||||
.args_conflicts_with_subcommands(true)
|
||||
.allow_external_subcommands(true)
|
||||
.disable_help_subcommand(true)
|
||||
.global_setting(clap_color_setting)
|
||||
.global_setting(AppSettings::DeriveDisplayOrder)
|
||||
.global_setting(AppSettings::UnifiedHelpMessage)
|
||||
.global_setting(AppSettings::HidePossibleValuesInHelp)
|
||||
.setting(AppSettings::ArgsNegateSubcommands)
|
||||
.setting(AppSettings::AllowExternalSubcommands)
|
||||
.setting(AppSettings::DisableHelpSubcommand)
|
||||
.setting(AppSettings::VersionlessSubcommands)
|
||||
.max_term_width(100)
|
||||
.about("A cat(1) clone with wings.")
|
||||
.about(
|
||||
"A cat(1) clone with wings.\n\n\
|
||||
Use '--help' instead of '-h' to see a more detailed version of the help text.",
|
||||
)
|
||||
.after_help(
|
||||
"Note: `bat -h` prints a short and concise overview while `bat --help` gives all \
|
||||
details.",
|
||||
)
|
||||
.long_about("A cat(1) clone with syntax highlighting and Git integration.")
|
||||
.arg(
|
||||
Arg::new("FILE")
|
||||
Arg::with_name("FILE")
|
||||
.help("File(s) to print / concatenate. Use '-' for standard input.")
|
||||
.long_help(
|
||||
"File(s) to print / concatenate. Use a dash ('-') or no argument at all \
|
||||
to read from standard input.",
|
||||
)
|
||||
.num_args(1..)
|
||||
.value_parser(value_parser!(PathBuf)),
|
||||
.multiple(true)
|
||||
.empty_values(false),
|
||||
)
|
||||
.arg(
|
||||
Arg::new("show-all")
|
||||
Arg::with_name("show-all")
|
||||
.long("show-all")
|
||||
.alias("show-nonprintable")
|
||||
.short('A')
|
||||
.action(ArgAction::SetTrue)
|
||||
.short("A")
|
||||
.conflicts_with("language")
|
||||
.help("Show non-printable characters (space, tab, newline, ..).")
|
||||
.long_help(
|
||||
@@ -60,39 +67,22 @@ pub fn build_app(interactive_output: bool) -> Command {
|
||||
),
|
||||
)
|
||||
.arg(
|
||||
Arg::new("nonprintable-notation")
|
||||
.long("nonprintable-notation")
|
||||
.action(ArgAction::Set)
|
||||
.default_value("unicode")
|
||||
.value_parser(["unicode", "caret"])
|
||||
.value_name("notation")
|
||||
.hide_default_value(true)
|
||||
.help("Set notation for non-printable characters.")
|
||||
.long_help(
|
||||
"Set notation for non-printable characters.\n\n\
|
||||
Possible values:\n \
|
||||
* unicode (␇, ␊, ␀, ..)\n \
|
||||
* caret (^G, ^J, ^@, ..)",
|
||||
),
|
||||
)
|
||||
.arg(
|
||||
Arg::new("plain")
|
||||
Arg::with_name("plain")
|
||||
.overrides_with("plain")
|
||||
.overrides_with("number")
|
||||
.overrides_with("paging")
|
||||
.short('p')
|
||||
.short("p")
|
||||
.long("plain")
|
||||
.action(ArgAction::Count)
|
||||
.multiple(true)
|
||||
.help("Show plain style (alias for '--style=plain').")
|
||||
.long_help(
|
||||
"Only show plain style, no decorations. This is an alias for \
|
||||
'--style=plain'. When '-p' is used twice ('-pp'), it also disables \
|
||||
automatic paging (alias for '--style=plain --paging=never').",
|
||||
automatic paging (alias for '--style=plain --pager=never').",
|
||||
),
|
||||
)
|
||||
.arg(
|
||||
Arg::new("language")
|
||||
.short('l')
|
||||
Arg::with_name("language")
|
||||
.short("l")
|
||||
.long("language")
|
||||
.overrides_with("language")
|
||||
.help("Set the language for syntax highlighting.")
|
||||
@@ -101,13 +91,16 @@ pub fn build_app(interactive_output: bool) -> Command {
|
||||
specified as a name (like 'C++' or 'LaTeX') or possible file extension \
|
||||
(like 'cpp', 'hpp' or 'md'). Use '--list-languages' to show all supported \
|
||||
language names and file extensions.",
|
||||
),
|
||||
)
|
||||
.takes_value(true),
|
||||
)
|
||||
.arg(
|
||||
Arg::new("highlight-line")
|
||||
Arg::with_name("highlight-line")
|
||||
.long("highlight-line")
|
||||
.short('H')
|
||||
.action(ArgAction::Append)
|
||||
.short("H")
|
||||
.takes_value(true)
|
||||
.number_of_values(1)
|
||||
.multiple(true)
|
||||
.value_name("N:M")
|
||||
.help("Highlight lines N through M.")
|
||||
.long_help(
|
||||
@@ -121,11 +114,12 @@ pub fn build_app(interactive_output: bool) -> Command {
|
||||
),
|
||||
)
|
||||
.arg(
|
||||
Arg::new("file-name")
|
||||
Arg::with_name("file-name")
|
||||
.long("file-name")
|
||||
.action(ArgAction::Append)
|
||||
.takes_value(true)
|
||||
.number_of_values(1)
|
||||
.multiple(true)
|
||||
.value_name("name")
|
||||
.value_parser(value_parser!(PathBuf))
|
||||
.help("Specify the name to display for a file.")
|
||||
.long_help(
|
||||
"Specify the name to display for a file. Useful when piping \
|
||||
@@ -139,11 +133,9 @@ pub fn build_app(interactive_output: bool) -> Command {
|
||||
{
|
||||
app = app
|
||||
.arg(
|
||||
Arg::new("diff")
|
||||
Arg::with_name("diff")
|
||||
.long("diff")
|
||||
.short('d')
|
||||
.action(ArgAction::SetTrue)
|
||||
.conflicts_with("line-range")
|
||||
.short("d")
|
||||
.help("Only show lines that have been added/removed/modified.")
|
||||
.long_help(
|
||||
"Only show lines that have been added/removed/modified with respect \
|
||||
@@ -151,19 +143,20 @@ pub fn build_app(interactive_output: bool) -> Command {
|
||||
),
|
||||
)
|
||||
.arg(
|
||||
Arg::new("diff-context")
|
||||
Arg::with_name("diff-context")
|
||||
.long("diff-context")
|
||||
.overrides_with("diff-context")
|
||||
.takes_value(true)
|
||||
.value_name("N")
|
||||
.value_parser(
|
||||
|n: &str| {
|
||||
.validator(
|
||||
|n| {
|
||||
n.parse::<usize>()
|
||||
.map_err(|_| "must be a number")
|
||||
.map(|_| n.to_owned()) // Convert to Result<String, &str>
|
||||
.map(|_| ()) // Convert to Result<(), &str>
|
||||
.map_err(|e| e.to_string())
|
||||
}, // Convert to Result<(), String>
|
||||
)
|
||||
.hide_short_help(true)
|
||||
.hidden_short_help(true)
|
||||
.long_help(
|
||||
"Include N lines of context around added/removed/modified lines when using '--diff'.",
|
||||
),
|
||||
@@ -171,15 +164,16 @@ pub fn build_app(interactive_output: bool) -> Command {
|
||||
}
|
||||
|
||||
app = app.arg(
|
||||
Arg::new("tabs")
|
||||
Arg::with_name("tabs")
|
||||
.long("tabs")
|
||||
.overrides_with("tabs")
|
||||
.takes_value(true)
|
||||
.value_name("T")
|
||||
.value_parser(
|
||||
|t: &str| {
|
||||
.validator(
|
||||
|t| {
|
||||
t.parse::<u32>()
|
||||
.map_err(|_t| "must be a number")
|
||||
.map(|_t| t.to_owned()) // Convert to Result<String, &str>
|
||||
.map(|_t| ()) // Convert to Result<(), &str>
|
||||
.map_err(|e| e.to_string())
|
||||
}, // Convert to Result<(), String>
|
||||
)
|
||||
@@ -190,11 +184,12 @@ pub fn build_app(interactive_output: bool) -> Command {
|
||||
),
|
||||
)
|
||||
.arg(
|
||||
Arg::new("wrap")
|
||||
Arg::with_name("wrap")
|
||||
.long("wrap")
|
||||
.overrides_with("wrap")
|
||||
.takes_value(true)
|
||||
.value_name("mode")
|
||||
.value_parser(["auto", "never", "character"])
|
||||
.possible_values(&["auto", "never", "character"])
|
||||
.default_value("auto")
|
||||
.hide_default_value(true)
|
||||
.help("Specify the text-wrapping mode (*auto*, never, character).")
|
||||
@@ -203,27 +198,21 @@ pub fn build_app(interactive_output: bool) -> Command {
|
||||
control the output width."),
|
||||
)
|
||||
.arg(
|
||||
Arg::new("chop-long-lines")
|
||||
.long("chop-long-lines")
|
||||
.short('S')
|
||||
.action(ArgAction::SetTrue)
|
||||
.help("Truncate all lines longer than screen width. Alias for '--wrap=never'."),
|
||||
)
|
||||
.arg(
|
||||
Arg::new("terminal-width")
|
||||
Arg::with_name("terminal-width")
|
||||
.long("terminal-width")
|
||||
.takes_value(true)
|
||||
.value_name("width")
|
||||
.hide_short_help(true)
|
||||
.hidden_short_help(true)
|
||||
.allow_hyphen_values(true)
|
||||
.value_parser(
|
||||
|t: &str| {
|
||||
.validator(
|
||||
|t| {
|
||||
let is_offset = t.starts_with('+') || t.starts_with('-');
|
||||
t.parse::<i32>()
|
||||
.map_err(|_e| "must be an offset or number")
|
||||
.and_then(|v| if v == 0 && !is_offset {
|
||||
Err("terminal width cannot be zero")
|
||||
} else {
|
||||
Ok(t.to_owned())
|
||||
Ok(())
|
||||
})
|
||||
.map_err(|e| e.to_string())
|
||||
})
|
||||
@@ -234,11 +223,10 @@ pub fn build_app(interactive_output: bool) -> Command {
|
||||
),
|
||||
)
|
||||
.arg(
|
||||
Arg::new("number")
|
||||
Arg::with_name("number")
|
||||
.long("number")
|
||||
.overrides_with("number")
|
||||
.short('n')
|
||||
.action(ArgAction::SetTrue)
|
||||
.short("n")
|
||||
.help("Show line numbers (alias for '--style=numbers').")
|
||||
.long_help(
|
||||
"Only show line numbers, no other decorations. This is an alias for \
|
||||
@@ -246,11 +234,12 @@ pub fn build_app(interactive_output: bool) -> Command {
|
||||
),
|
||||
)
|
||||
.arg(
|
||||
Arg::new("color")
|
||||
Arg::with_name("color")
|
||||
.long("color")
|
||||
.overrides_with("color")
|
||||
.takes_value(true)
|
||||
.value_name("when")
|
||||
.value_parser(["auto", "never", "always"])
|
||||
.possible_values(&["auto", "never", "always"])
|
||||
.hide_default_value(true)
|
||||
.default_value("auto")
|
||||
.help("When to use colors (*auto*, never, always).")
|
||||
@@ -262,21 +251,23 @@ pub fn build_app(interactive_output: bool) -> Command {
|
||||
),
|
||||
)
|
||||
.arg(
|
||||
Arg::new("italic-text")
|
||||
Arg::with_name("italic-text")
|
||||
.long("italic-text")
|
||||
.takes_value(true)
|
||||
.value_name("when")
|
||||
.value_parser(["always", "never"])
|
||||
.possible_values(&["always", "never"])
|
||||
.default_value("never")
|
||||
.hide_default_value(true)
|
||||
.help("Use italics in output (always, *never*)")
|
||||
.long_help("Specify when to use ANSI sequences for italic text in the output. Possible values: always, *never*."),
|
||||
)
|
||||
.arg(
|
||||
Arg::new("decorations")
|
||||
Arg::with_name("decorations")
|
||||
.long("decorations")
|
||||
.overrides_with("decorations")
|
||||
.takes_value(true)
|
||||
.value_name("when")
|
||||
.value_parser(["auto", "never", "always"])
|
||||
.possible_values(&["auto", "never", "always"])
|
||||
.default_value("auto")
|
||||
.hide_default_value(true)
|
||||
.help("When to show the decorations (*auto*, never, always).")
|
||||
@@ -287,53 +278,51 @@ pub fn build_app(interactive_output: bool) -> Command {
|
||||
),
|
||||
)
|
||||
.arg(
|
||||
Arg::new("force-colorization")
|
||||
Arg::with_name("force-colorization")
|
||||
.long("force-colorization")
|
||||
.short('f')
|
||||
.action(ArgAction::SetTrue)
|
||||
.short("f")
|
||||
.conflicts_with("color")
|
||||
.conflicts_with("decorations")
|
||||
.overrides_with("force-colorization")
|
||||
.hide_short_help(true)
|
||||
.hidden_short_help(true)
|
||||
.long_help("Alias for '--decorations=always --color=always'. This is useful \
|
||||
if the output of bat is piped to another program, but you want \
|
||||
to keep the colorization/decorations.")
|
||||
)
|
||||
.arg(
|
||||
Arg::new("paging")
|
||||
Arg::with_name("paging")
|
||||
.long("paging")
|
||||
.overrides_with("paging")
|
||||
.overrides_with("no-paging")
|
||||
.overrides_with("plain")
|
||||
.takes_value(true)
|
||||
.value_name("when")
|
||||
.value_parser(["auto", "never", "always"])
|
||||
.possible_values(&["auto", "never", "always"])
|
||||
.default_value("auto")
|
||||
.hide_default_value(true)
|
||||
.help("Specify when to use the pager, or use `-P` to disable (*auto*, never, always).")
|
||||
.long_help(
|
||||
"Specify when to use the pager. To disable the pager, use \
|
||||
--paging=never' or its alias,'-P'. To disable the pager permanently, \
|
||||
set BAT_PAGING to 'never'. To control which pager is used, see the \
|
||||
set BAT_PAGER to an empty string. To control which pager is used, see the \
|
||||
'--pager' option. Possible values: *auto*, never, always."
|
||||
),
|
||||
)
|
||||
.arg(
|
||||
Arg::new("no-paging")
|
||||
.short('P')
|
||||
Arg::with_name("no-paging")
|
||||
.short("P")
|
||||
.long("no-paging")
|
||||
.alias("no-pager")
|
||||
.action(ArgAction::SetTrue)
|
||||
.overrides_with("no-paging")
|
||||
.hide(true)
|
||||
.hide_short_help(true)
|
||||
.hidden(true)
|
||||
.hidden_short_help(true)
|
||||
.help("Alias for '--paging=never'")
|
||||
)
|
||||
.arg(
|
||||
Arg::new("pager")
|
||||
Arg::with_name("pager")
|
||||
.long("pager")
|
||||
.overrides_with("pager")
|
||||
.takes_value(true)
|
||||
.value_name("command")
|
||||
.hide_short_help(true)
|
||||
.hidden_short_help(true)
|
||||
.help("Determine which pager to use.")
|
||||
.long_help(
|
||||
"Determine which pager is used. This option will override the \
|
||||
@@ -343,10 +332,12 @@ pub fn build_app(interactive_output: bool) -> Command {
|
||||
),
|
||||
)
|
||||
.arg(
|
||||
Arg::new("map-syntax")
|
||||
.short('m')
|
||||
Arg::with_name("map-syntax")
|
||||
.short("m")
|
||||
.long("map-syntax")
|
||||
.action(ArgAction::Append)
|
||||
.multiple(true)
|
||||
.takes_value(true)
|
||||
.number_of_values(1)
|
||||
.value_name("glob:syntax")
|
||||
.help("Use the specified syntax for files matching the glob pattern ('*.cpp:C++').")
|
||||
.long_help(
|
||||
@@ -356,21 +347,25 @@ pub fn build_app(interactive_output: bool) -> Command {
|
||||
'.myignore' with the Git Ignore syntax, use -m '.myignore:Git Ignore'. Note \
|
||||
that the right-hand side is the *name* of the syntax, not a file extension.",
|
||||
)
|
||||
.takes_value(true),
|
||||
)
|
||||
.arg(
|
||||
Arg::new("ignored-suffix")
|
||||
.action(ArgAction::Append)
|
||||
Arg::with_name("ignored-suffix")
|
||||
.number_of_values(1)
|
||||
.multiple(true)
|
||||
.takes_value(true)
|
||||
.long("ignored-suffix")
|
||||
.hide_short_help(true)
|
||||
.hidden_short_help(true)
|
||||
.help(
|
||||
"Ignore extension. For example:\n \
|
||||
'bat --ignored-suffix \".dev\" my_file.json.dev' will use JSON syntax, and ignore '.dev'"
|
||||
)
|
||||
)
|
||||
.arg(
|
||||
Arg::new("theme")
|
||||
Arg::with_name("theme")
|
||||
.long("theme")
|
||||
.overrides_with("theme")
|
||||
.takes_value(true)
|
||||
.help("Set the color theme for syntax highlighting.")
|
||||
.long_help(
|
||||
"Set the theme for syntax highlighting. Use '--list-themes' to \
|
||||
@@ -381,21 +376,24 @@ pub fn build_app(interactive_output: bool) -> Command {
|
||||
),
|
||||
)
|
||||
.arg(
|
||||
Arg::new("list-themes")
|
||||
Arg::with_name("list-themes")
|
||||
.long("list-themes")
|
||||
.action(ArgAction::SetTrue)
|
||||
.help("Display all supported highlighting themes.")
|
||||
.long_help("Display a list of supported themes for syntax highlighting."),
|
||||
)
|
||||
.arg(
|
||||
Arg::new("style")
|
||||
Arg::with_name("style")
|
||||
.long("style")
|
||||
.value_name("components")
|
||||
// Need to turn this off for overrides_with to work as we want. See the bottom most
|
||||
// example at https://docs.rs/clap/2.32.0/clap/struct.Arg.html#method.overrides_with
|
||||
.use_delimiter(false)
|
||||
.takes_value(true)
|
||||
.overrides_with("style")
|
||||
.overrides_with("plain")
|
||||
.overrides_with("number")
|
||||
// Cannot use claps built in validation because we have to turn off clap's delimiters
|
||||
.value_parser(|val: &str| {
|
||||
.validator(|val| {
|
||||
let mut invalid_vals = val.split(',').filter(|style| {
|
||||
!&[
|
||||
"auto",
|
||||
@@ -417,7 +415,7 @@ pub fn build_app(interactive_output: bool) -> Command {
|
||||
if let Some(invalid) = invalid_vals.next() {
|
||||
Err(format!("Unknown style, '{}'", invalid))
|
||||
} else {
|
||||
Ok(val.to_owned())
|
||||
Ok(())
|
||||
}
|
||||
})
|
||||
.help(
|
||||
@@ -449,11 +447,14 @@ pub fn build_app(interactive_output: bool) -> Command {
|
||||
),
|
||||
)
|
||||
.arg(
|
||||
Arg::new("line-range")
|
||||
Arg::with_name("line-range")
|
||||
.long("line-range")
|
||||
.short('r')
|
||||
.action(ArgAction::Append)
|
||||
.short("r")
|
||||
.multiple(true)
|
||||
.takes_value(true)
|
||||
.number_of_values(1)
|
||||
.value_name("N:M")
|
||||
.conflicts_with("diff")
|
||||
.help("Only print the lines from N to M.")
|
||||
.long_help(
|
||||
"Only print the specified range of lines for each file. \
|
||||
@@ -466,20 +467,28 @@ pub fn build_app(interactive_output: bool) -> Command {
|
||||
),
|
||||
)
|
||||
.arg(
|
||||
Arg::new("list-languages")
|
||||
Arg::with_name("list-languages")
|
||||
.long("list-languages")
|
||||
.short('L')
|
||||
.action(ArgAction::SetTrue)
|
||||
.short("L")
|
||||
.conflicts_with("list-themes")
|
||||
.help("Display all supported languages.")
|
||||
.long_help("Display a list of supported languages for syntax highlighting."),
|
||||
)
|
||||
.arg(
|
||||
Arg::new("unbuffered")
|
||||
.short('u')
|
||||
Arg::with_name("load-plugin")
|
||||
.long("load-plugin")
|
||||
.multiple(true)
|
||||
.takes_value(true)
|
||||
.number_of_values(1)
|
||||
.value_name("name")
|
||||
.help("Load plugin with specified name.")
|
||||
.hidden_short_help(true)
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("unbuffered")
|
||||
.short("u")
|
||||
.long("unbuffered")
|
||||
.action(ArgAction::SetTrue)
|
||||
.hide_short_help(true)
|
||||
.hidden_short_help(true)
|
||||
.long_help(
|
||||
"This option exists for POSIX-compliance reasons ('u' is for \
|
||||
'unbuffered'). The output is always unbuffered - this option \
|
||||
@@ -487,87 +496,60 @@ pub fn build_app(interactive_output: bool) -> Command {
|
||||
),
|
||||
)
|
||||
.arg(
|
||||
Arg::new("no-config")
|
||||
Arg::with_name("no-config")
|
||||
.long("no-config")
|
||||
.action(ArgAction::SetTrue)
|
||||
.hide(true)
|
||||
.hidden(true)
|
||||
.help("Do not use the configuration file"),
|
||||
)
|
||||
.arg(
|
||||
Arg::new("no-custom-assets")
|
||||
Arg::with_name("no-custom-assets")
|
||||
.long("no-custom-assets")
|
||||
.action(ArgAction::SetTrue)
|
||||
.hide(true)
|
||||
.hidden(true)
|
||||
.help("Do not load custom assets"),
|
||||
);
|
||||
|
||||
#[cfg(feature = "lessopen")]
|
||||
{
|
||||
app = app
|
||||
.arg(
|
||||
Arg::new("lessopen")
|
||||
.long("lessopen")
|
||||
.action(ArgAction::SetTrue)
|
||||
.help("Enable the $LESSOPEN preprocessor"),
|
||||
)
|
||||
.arg(
|
||||
Arg::new("no-lessopen")
|
||||
.long("no-lessopen")
|
||||
.action(ArgAction::SetTrue)
|
||||
.overrides_with("lessopen")
|
||||
.hide(true)
|
||||
.help("Disable the $LESSOPEN preprocessor if enabled (overrides --lessopen)"),
|
||||
)
|
||||
}
|
||||
|
||||
app = app
|
||||
.arg(
|
||||
Arg::new("config-file")
|
||||
Arg::with_name("config-file")
|
||||
.long("config-file")
|
||||
.action(ArgAction::SetTrue)
|
||||
.conflicts_with("list-languages")
|
||||
.conflicts_with("list-themes")
|
||||
.hide(true)
|
||||
.hidden(true)
|
||||
.help("Show path to the configuration file."),
|
||||
)
|
||||
.arg(
|
||||
Arg::new("generate-config-file")
|
||||
Arg::with_name("generate-config-file")
|
||||
.long("generate-config-file")
|
||||
.action(ArgAction::SetTrue)
|
||||
.conflicts_with("list-languages")
|
||||
.conflicts_with("list-themes")
|
||||
.hide(true)
|
||||
.hidden(true)
|
||||
.help("Generates a default configuration file."),
|
||||
)
|
||||
.arg(
|
||||
Arg::new("config-dir")
|
||||
Arg::with_name("config-dir")
|
||||
.long("config-dir")
|
||||
.action(ArgAction::SetTrue)
|
||||
.hide(true)
|
||||
.hidden(true)
|
||||
.help("Show bat's configuration directory."),
|
||||
)
|
||||
.arg(
|
||||
Arg::new("cache-dir")
|
||||
Arg::with_name("cache-dir")
|
||||
.long("cache-dir")
|
||||
.action(ArgAction::SetTrue)
|
||||
.hide(true)
|
||||
.hidden(true)
|
||||
.help("Show bat's cache directory."),
|
||||
)
|
||||
.arg(
|
||||
Arg::new("diagnostic")
|
||||
Arg::with_name("diagnostic")
|
||||
.long("diagnostic")
|
||||
.alias("diagnostics")
|
||||
.action(ArgAction::SetTrue)
|
||||
.hide_short_help(true)
|
||||
.help("Show diagnostic information for bug reports."),
|
||||
.hidden_short_help(true)
|
||||
.help("Show diagnostic information for bug reports.")
|
||||
)
|
||||
.arg(
|
||||
Arg::new("acknowledgements")
|
||||
Arg::with_name("acknowledgements")
|
||||
.long("acknowledgements")
|
||||
.action(ArgAction::SetTrue)
|
||||
.hide_short_help(true)
|
||||
.hidden_short_help(true)
|
||||
.help("Show acknowledgements."),
|
||||
);
|
||||
)
|
||||
.help_message("Print this help message.")
|
||||
.version_message("Show version information.");
|
||||
|
||||
// Check if the current directory contains a file name cache. Otherwise,
|
||||
// enable the 'bat cache' subcommand.
|
||||
@@ -575,14 +557,12 @@ pub fn build_app(interactive_output: bool) -> Command {
|
||||
app
|
||||
} else {
|
||||
app.subcommand(
|
||||
Command::new("cache")
|
||||
.hide(true)
|
||||
SubCommand::with_name("cache")
|
||||
.about("Modify the syntax-definition and theme cache")
|
||||
.arg(
|
||||
Arg::new("build")
|
||||
Arg::with_name("build")
|
||||
.long("build")
|
||||
.short('b')
|
||||
.action(ArgAction::SetTrue)
|
||||
.short("b")
|
||||
.help("Initialize (or update) the syntax/theme cache.")
|
||||
.long_help(
|
||||
"Initialize (or update) the syntax/theme cache by loading from \
|
||||
@@ -590,37 +570,37 @@ pub fn build_app(interactive_output: bool) -> Command {
|
||||
),
|
||||
)
|
||||
.arg(
|
||||
Arg::new("clear")
|
||||
Arg::with_name("clear")
|
||||
.long("clear")
|
||||
.short('c')
|
||||
.action(ArgAction::SetTrue)
|
||||
.short("c")
|
||||
.help("Remove the cached syntax definitions and themes."),
|
||||
)
|
||||
.group(
|
||||
ArgGroup::new("cache-actions")
|
||||
.args(["build", "clear"])
|
||||
ArgGroup::with_name("cache-actions")
|
||||
.args(&["build", "clear"])
|
||||
.required(true),
|
||||
)
|
||||
.arg(
|
||||
Arg::new("source")
|
||||
Arg::with_name("source")
|
||||
.long("source")
|
||||
.requires("build")
|
||||
.takes_value(true)
|
||||
.value_name("dir")
|
||||
.help("Use a different directory to load syntaxes and themes from."),
|
||||
)
|
||||
.arg(
|
||||
Arg::new("target")
|
||||
Arg::with_name("target")
|
||||
.long("target")
|
||||
.requires("build")
|
||||
.takes_value(true)
|
||||
.value_name("dir")
|
||||
.help(
|
||||
"Use a different directory to store the cached syntax and theme set.",
|
||||
),
|
||||
)
|
||||
.arg(
|
||||
Arg::new("blank")
|
||||
Arg::with_name("blank")
|
||||
.long("blank")
|
||||
.action(ArgAction::SetTrue)
|
||||
.requires("build")
|
||||
.help(
|
||||
"Create completely new syntax and theme sets \
|
||||
@@ -628,21 +608,11 @@ pub fn build_app(interactive_output: bool) -> Command {
|
||||
),
|
||||
)
|
||||
.arg(
|
||||
Arg::new("acknowledgements")
|
||||
Arg::with_name("acknowledgements")
|
||||
.long("acknowledgements")
|
||||
.action(ArgAction::SetTrue)
|
||||
.requires("build")
|
||||
.help("Build acknowledgements.bin."),
|
||||
),
|
||||
)
|
||||
.after_long_help(
|
||||
"You can use 'bat cache' to customize syntaxes and themes. \
|
||||
See 'bat cache --help' for more information",
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn verify_app() {
|
||||
build_app(false).debug_assert();
|
||||
}
|
||||
|
@@ -6,22 +6,6 @@ use std::path::PathBuf;
|
||||
|
||||
use crate::directories::PROJECT_DIRS;
|
||||
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
const DEFAULT_SYSTEM_CONFIG_PREFIX: &str = "/etc";
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
const DEFAULT_SYSTEM_CONFIG_PREFIX: &str = "C:\\ProgramData";
|
||||
|
||||
pub fn system_config_file() -> PathBuf {
|
||||
let folder = option_env!("BAT_SYSTEM_CONFIG_PREFIX").unwrap_or(DEFAULT_SYSTEM_CONFIG_PREFIX);
|
||||
let mut path = PathBuf::from(folder);
|
||||
|
||||
path.push("bat");
|
||||
path.push("config");
|
||||
|
||||
path
|
||||
}
|
||||
|
||||
pub fn config_file() -> PathBuf {
|
||||
env::var("BAT_CONFIG_PATH")
|
||||
.ok()
|
||||
@@ -103,21 +87,14 @@ pub fn generate_config_file() -> bat::error::Result<()> {
|
||||
}
|
||||
|
||||
pub fn get_args_from_config_file() -> Result<Vec<OsString>, shell_words::ParseError> {
|
||||
let mut config = String::new();
|
||||
|
||||
if let Ok(c) = fs::read_to_string(system_config_file()) {
|
||||
config.push_str(&c);
|
||||
config.push('\n');
|
||||
Ok(fs::read_to_string(config_file())
|
||||
.ok()
|
||||
.map(|content| get_args_from_str(&content))
|
||||
.transpose()?
|
||||
.unwrap_or_default())
|
||||
}
|
||||
|
||||
if let Ok(c) = fs::read_to_string(config_file()) {
|
||||
config.push_str(&c);
|
||||
}
|
||||
|
||||
get_args_from_str(&config)
|
||||
}
|
||||
|
||||
pub fn get_args_from_env_opts_var() -> Option<Result<Vec<OsString>, shell_words::ParseError>> {
|
||||
pub fn get_args_from_env_var() -> Option<Result<Vec<OsString>, shell_words::ParseError>> {
|
||||
env::var("BAT_OPTS").ok().map(|s| get_args_from_str(&s))
|
||||
}
|
||||
|
||||
@@ -137,21 +114,6 @@ fn get_args_from_str(content: &str) -> Result<Vec<OsString>, shell_words::ParseE
|
||||
.collect())
|
||||
}
|
||||
|
||||
pub fn get_args_from_env_vars() -> Vec<OsString> {
|
||||
[
|
||||
("--tabs", "BAT_TABS"),
|
||||
("--theme", "BAT_THEME"),
|
||||
("--pager", "BAT_PAGER"),
|
||||
("--paging", "BAT_PAGING"),
|
||||
("--style", "BAT_STYLE"),
|
||||
]
|
||||
.iter()
|
||||
.filter_map(|(flag, key)| env::var(key).ok().map(|var| [flag.to_string(), var]))
|
||||
.flatten()
|
||||
.map(|a| a.into())
|
||||
.collect()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn empty() {
|
||||
let args = get_args_from_str("").unwrap();
|
||||
|
@@ -1,11 +1,12 @@
|
||||
use std::env;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
use etcetera::BaseStrategy;
|
||||
use once_cell::sync::Lazy;
|
||||
|
||||
/// Wrapper for 'etcetera' that checks BAT_CACHE_PATH and BAT_CONFIG_DIR and falls back to the
|
||||
/// Windows known folder locations on Windows & the XDG Base Directory Specification everywhere else.
|
||||
/// Wrapper for 'dirs' that treats MacOS more like Linux, by following the XDG specification.
|
||||
/// The `XDG_CACHE_HOME` environment variable is checked first. `BAT_CONFIG_DIR`
|
||||
/// is then checked before the `XDG_CONFIG_HOME` environment variable.
|
||||
/// The fallback directories are `~/.cache/bat` and `~/.config/bat`, respectively.
|
||||
pub struct BatProjectDirs {
|
||||
cache_dir: PathBuf,
|
||||
config_dir: PathBuf,
|
||||
@@ -13,23 +14,24 @@ pub struct BatProjectDirs {
|
||||
|
||||
impl BatProjectDirs {
|
||||
fn new() -> Option<BatProjectDirs> {
|
||||
let basedirs = etcetera::choose_base_strategy().ok()?;
|
||||
let cache_dir = BatProjectDirs::get_cache_dir()?;
|
||||
|
||||
// Checks whether or not `$BAT_CACHE_PATH` exists. If it doesn't, set the cache dir to our
|
||||
// system's default cache home.
|
||||
let cache_dir = if let Some(cache_dir) = env::var_os("BAT_CACHE_PATH").map(PathBuf::from) {
|
||||
cache_dir
|
||||
// Checks whether or not $BAT_CONFIG_DIR exists. If it doesn't, set our config dir
|
||||
// to our system's default configuration home.
|
||||
let config_dir =
|
||||
if let Some(config_dir_op) = env::var_os("BAT_CONFIG_DIR").map(PathBuf::from) {
|
||||
config_dir_op
|
||||
} else {
|
||||
basedirs.cache_dir().join("bat")
|
||||
};
|
||||
#[cfg(target_os = "macos")]
|
||||
let config_dir_op = env::var_os("XDG_CONFIG_HOME")
|
||||
.map(PathBuf::from)
|
||||
.filter(|p| p.is_absolute())
|
||||
.or_else(|| dirs_next::home_dir().map(|d| d.join(".config")));
|
||||
|
||||
// Checks whether or not `$BAT_CONFIG_DIR` exists. If it doesn't, set the config dir to our
|
||||
// system's default configuration home.
|
||||
let config_dir = if let Some(config_dir) = env::var_os("BAT_CONFIG_DIR").map(PathBuf::from)
|
||||
{
|
||||
config_dir
|
||||
} else {
|
||||
basedirs.config_dir().join("bat")
|
||||
#[cfg(not(target_os = "macos"))]
|
||||
let config_dir_op = dirs_next::config_dir();
|
||||
|
||||
config_dir_op.map(|d| d.join("bat"))?
|
||||
};
|
||||
|
||||
Some(BatProjectDirs {
|
||||
@@ -38,6 +40,25 @@ impl BatProjectDirs {
|
||||
})
|
||||
}
|
||||
|
||||
fn get_cache_dir() -> Option<PathBuf> {
|
||||
// on all OS prefer BAT_CACHE_PATH if set
|
||||
let cache_dir_op = env::var_os("BAT_CACHE_PATH").map(PathBuf::from);
|
||||
if cache_dir_op.is_some() {
|
||||
return cache_dir_op;
|
||||
}
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
let cache_dir_op = env::var_os("XDG_CACHE_HOME")
|
||||
.map(PathBuf::from)
|
||||
.filter(|p| p.is_absolute())
|
||||
.or_else(|| dirs_next::home_dir().map(|d| d.join(".cache")));
|
||||
|
||||
#[cfg(not(target_os = "macos"))]
|
||||
let cache_dir_op = dirs_next::cache_dir();
|
||||
|
||||
cache_dir_op.map(|d| d.join("bat"))
|
||||
}
|
||||
|
||||
pub fn cache_dir(&self) -> &Path {
|
||||
&self.cache_dir
|
||||
}
|
||||
|
@@ -8,24 +8,21 @@ mod directories;
|
||||
mod input;
|
||||
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use std::fmt::Write as _;
|
||||
use std::ffi::OsStr;
|
||||
use std::io;
|
||||
use std::io::{BufReader, Write};
|
||||
use std::path::Path;
|
||||
use std::process;
|
||||
|
||||
use nu_ansi_term::Color::Green;
|
||||
use nu_ansi_term::Style;
|
||||
use ansi_term::Colour::Green;
|
||||
use ansi_term::Style;
|
||||
|
||||
use crate::{
|
||||
app::App,
|
||||
config::{config_file, generate_config_file},
|
||||
};
|
||||
|
||||
#[cfg(feature = "bugreport")]
|
||||
use crate::config::system_config_file;
|
||||
|
||||
use assets::{assets_from_cache_or_binary, clear_assets};
|
||||
use assets::{assets_from_cache_or_binary, cache_dir, clear_assets, config_dir};
|
||||
use directories::PROJECT_DIRS;
|
||||
use globset::GlobMatcher;
|
||||
|
||||
@@ -41,38 +38,33 @@ use bat::{
|
||||
const THEME_PREVIEW_DATA: &[u8] = include_bytes!("../../../assets/theme_preview.rs");
|
||||
|
||||
#[cfg(feature = "build-assets")]
|
||||
fn build_assets(matches: &clap::ArgMatches, config_dir: &Path, cache_dir: &Path) -> Result<()> {
|
||||
fn build_assets(matches: &clap::ArgMatches) -> Result<()> {
|
||||
let source_dir = matches
|
||||
.get_one::<String>("source")
|
||||
.value_of("source")
|
||||
.map(Path::new)
|
||||
.unwrap_or_else(|| config_dir);
|
||||
.unwrap_or_else(|| PROJECT_DIRS.config_dir());
|
||||
let target_dir = matches
|
||||
.value_of("target")
|
||||
.map(Path::new)
|
||||
.unwrap_or_else(|| PROJECT_DIRS.cache_dir());
|
||||
|
||||
bat::assets::build(
|
||||
source_dir,
|
||||
!matches.get_flag("blank"),
|
||||
matches.get_flag("acknowledgements"),
|
||||
cache_dir,
|
||||
!matches.is_present("blank"),
|
||||
matches.is_present("acknowledgements"),
|
||||
target_dir,
|
||||
clap::crate_version!(),
|
||||
)
|
||||
}
|
||||
|
||||
fn run_cache_subcommand(
|
||||
matches: &clap::ArgMatches,
|
||||
#[cfg(feature = "build-assets")] config_dir: &Path,
|
||||
default_cache_dir: &Path,
|
||||
) -> Result<()> {
|
||||
let cache_dir = matches
|
||||
.get_one::<String>("target")
|
||||
.map(Path::new)
|
||||
.unwrap_or_else(|| default_cache_dir);
|
||||
|
||||
if matches.get_flag("build") {
|
||||
fn run_cache_subcommand(matches: &clap::ArgMatches) -> Result<()> {
|
||||
if matches.is_present("build") {
|
||||
#[cfg(feature = "build-assets")]
|
||||
build_assets(matches, config_dir, cache_dir)?;
|
||||
build_assets(matches)?;
|
||||
#[cfg(not(feature = "build-assets"))]
|
||||
println!("bat has been built without the 'build-assets' feature. The 'cache --build' option is not available.");
|
||||
} else if matches.get_flag("clear") {
|
||||
clear_assets(cache_dir);
|
||||
} else if matches.is_present("clear") {
|
||||
clear_assets();
|
||||
}
|
||||
|
||||
Ok(())
|
||||
@@ -91,10 +83,10 @@ fn get_syntax_mapping_to_paths<'a>(
|
||||
map
|
||||
}
|
||||
|
||||
pub fn get_languages(config: &Config, cache_dir: &Path) -> Result<String> {
|
||||
pub fn get_languages(config: &Config) -> Result<String> {
|
||||
let mut result: String = String::new();
|
||||
|
||||
let assets = assets_from_cache_or_binary(config.use_custom_assets, cache_dir)?;
|
||||
let assets = assets_from_cache_or_binary(config.use_custom_assets)?;
|
||||
let mut languages = assets
|
||||
.get_syntaxes()?
|
||||
.iter()
|
||||
@@ -134,7 +126,7 @@ pub fn get_languages(config: &Config, cache_dir: &Path) -> Result<String> {
|
||||
|
||||
if config.loop_through {
|
||||
for lang in languages {
|
||||
writeln!(result, "{}:{}", lang.name, lang.file_extensions.join(",")).ok();
|
||||
result += &format!("{}:{}\n", lang.name, lang.file_extensions.join(","));
|
||||
}
|
||||
} else {
|
||||
let longest = languages
|
||||
@@ -155,7 +147,7 @@ pub fn get_languages(config: &Config, cache_dir: &Path) -> Result<String> {
|
||||
};
|
||||
|
||||
for lang in languages {
|
||||
write!(result, "{:width$}{}", lang.name, separator, width = longest).ok();
|
||||
result += &format!("{:width$}{}", lang.name, separator, width = longest);
|
||||
|
||||
// Number of characters on this line so far, wrap before `desired_width`
|
||||
let mut num_chars = 0;
|
||||
@@ -166,11 +158,11 @@ pub fn get_languages(config: &Config, cache_dir: &Path) -> Result<String> {
|
||||
let new_chars = word.len() + comma_separator.len();
|
||||
if num_chars + new_chars >= desired_width {
|
||||
num_chars = 0;
|
||||
write!(result, "\n{:width$}{}", "", separator, width = longest).ok();
|
||||
result += &format!("\n{:width$}{}", "", separator, width = longest);
|
||||
}
|
||||
|
||||
num_chars += new_chars;
|
||||
write!(result, "{}", style.paint(&word[..])).ok();
|
||||
result += &format!("{}", style.paint(&word[..]));
|
||||
if extension.peek().is_some() {
|
||||
result += comma_separator;
|
||||
}
|
||||
@@ -186,8 +178,8 @@ fn theme_preview_file<'a>() -> Input<'a> {
|
||||
Input::from_reader(Box::new(BufReader::new(THEME_PREVIEW_DATA)))
|
||||
}
|
||||
|
||||
pub fn list_themes(cfg: &Config, config_dir: &Path, cache_dir: &Path) -> Result<()> {
|
||||
let assets = assets_from_cache_or_binary(cfg.use_custom_assets, cache_dir)?;
|
||||
pub fn list_themes(cfg: &Config) -> Result<()> {
|
||||
let assets = assets_from_cache_or_binary(cfg.use_custom_assets)?;
|
||||
let mut config = cfg.clone();
|
||||
let mut style = HashSet::new();
|
||||
style.insert(StyleComponent::Plain);
|
||||
@@ -206,7 +198,7 @@ pub fn list_themes(cfg: &Config, config_dir: &Path, cache_dir: &Path) -> Result<
|
||||
)?;
|
||||
config.theme = theme.to_string();
|
||||
Controller::new(&config, &assets)
|
||||
.run(vec![theme_preview_file()], None)
|
||||
.run(vec![theme_preview_file()])
|
||||
.ok();
|
||||
writeln!(stdout)?;
|
||||
}
|
||||
@@ -216,7 +208,7 @@ pub fn list_themes(cfg: &Config, config_dir: &Path, cache_dir: &Path) -> Result<
|
||||
and are added to the cache with `bat cache --build`. \
|
||||
For more information, see:\n\n \
|
||||
https://github.com/sharkdp/bat#adding-new-themes",
|
||||
config_dir.join("themes").to_string_lossy()
|
||||
PROJECT_DIRS.config_dir().join("themes").to_string_lossy()
|
||||
)?;
|
||||
} else {
|
||||
for theme in assets.themes() {
|
||||
@@ -227,21 +219,78 @@ pub fn list_themes(cfg: &Config, config_dir: &Path, cache_dir: &Path) -> Result<
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn run_controller(inputs: Vec<Input>, config: &Config, cache_dir: &Path) -> Result<bool> {
|
||||
let assets = assets_from_cache_or_binary(config.use_custom_assets, cache_dir)?;
|
||||
fn load_and_run_preprocess_plugins(plugins: &[&OsStr], inputs: &mut Vec<Input>) -> Result<()> {
|
||||
use bat::input::InputKind;
|
||||
use rlua::{Function, Lua, Result as LuaResult};
|
||||
use std::fs;
|
||||
use std::path::PathBuf;
|
||||
|
||||
if plugins.is_empty() {
|
||||
// Do not create Lua context if there are no plugins
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let lua = Lua::new();
|
||||
|
||||
for plugin_name in plugins {
|
||||
// TODO: properly load plugins from a central directory + user directories
|
||||
// TODO: how to handle plugin priority?
|
||||
let mut plugin_path = PathBuf::from("plugins");
|
||||
plugin_path.push(plugin_name);
|
||||
|
||||
let plugin_source_code = fs::read_to_string(&plugin_path).map_err(|e| {
|
||||
format!(
|
||||
"Could not load bat plugin '{}': {}",
|
||||
plugin_path.to_string_lossy(),
|
||||
e
|
||||
)
|
||||
})?;
|
||||
|
||||
lua.context::<_, LuaResult<()>>(|lua_ctx| {
|
||||
let globals = lua_ctx.globals();
|
||||
|
||||
lua_ctx.load(&plugin_source_code).exec()?;
|
||||
|
||||
// Plugins are expected to have a 'preprocess' function
|
||||
let preprocess: Function = globals.get("preprocess")?;
|
||||
|
||||
for input in inputs.iter_mut() {
|
||||
if let InputKind::OrdinaryFile(ref mut path) = &mut input.kind {
|
||||
let path_str: String = path.to_string_lossy().into();
|
||||
let new_path = preprocess.call::<_, String>(path_str)?;
|
||||
|
||||
*path = PathBuf::from(new_path);
|
||||
|
||||
// TODO: the following line overwrites actual user provided names. However,
|
||||
// this is necessary to get proper syntax highlighting for the path that
|
||||
// is being provided by the plugin.
|
||||
input.metadata.user_provided_name = Some(path.clone());
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
})
|
||||
.map_err(|e| format!("Error while executing Lua code: {}", e))?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn run_controller(mut inputs: Vec<Input>, config: &Config) -> Result<bool> {
|
||||
load_and_run_preprocess_plugins(&config.plugins, &mut inputs)?;
|
||||
|
||||
let assets = assets_from_cache_or_binary(config.use_custom_assets)?;
|
||||
let controller = Controller::new(config, &assets);
|
||||
controller.run(inputs, None)
|
||||
controller.run(inputs)
|
||||
}
|
||||
|
||||
#[cfg(feature = "bugreport")]
|
||||
fn invoke_bugreport(app: &App, cache_dir: &Path) {
|
||||
fn invoke_bugreport(app: &App) {
|
||||
use bugreport::{bugreport, collector::*, format::Markdown};
|
||||
let pager = bat::config::get_pager_executable(
|
||||
app.matches.get_one::<String>("pager").map(|s| s.as_str()),
|
||||
)
|
||||
let pager = bat::config::get_pager_executable(app.matches.value_of("pager"))
|
||||
.unwrap_or_else(|| "less".to_owned()); // FIXME: Avoid non-canonical path to "less".
|
||||
|
||||
let mut custom_assets_metadata = cache_dir.to_path_buf();
|
||||
let mut custom_assets_metadata = PROJECT_DIRS.cache_dir().to_path_buf();
|
||||
custom_assets_metadata.push("metadata.yaml");
|
||||
|
||||
let mut report = bugreport!()
|
||||
@@ -255,7 +304,6 @@ fn invoke_bugreport(app: &App, cache_dir: &Path) {
|
||||
"LANG",
|
||||
"LC_ALL",
|
||||
"BAT_PAGER",
|
||||
"BAT_PAGING",
|
||||
"BAT_CACHE_PATH",
|
||||
"BAT_CONFIG_PATH",
|
||||
"BAT_OPTS",
|
||||
@@ -268,13 +316,15 @@ fn invoke_bugreport(app: &App, cache_dir: &Path) {
|
||||
"NO_COLOR",
|
||||
"MANPAGER",
|
||||
]))
|
||||
.info(FileContent::new("System Config file", system_config_file()))
|
||||
.info(FileContent::new("Config file", config_file()))
|
||||
.info(FileContent::new(
|
||||
"Custom assets metadata",
|
||||
custom_assets_metadata,
|
||||
))
|
||||
.info(DirectoryEntries::new("Custom assets", cache_dir))
|
||||
.info(DirectoryEntries::new(
|
||||
"Custom assets",
|
||||
PROJECT_DIRS.cache_dir(),
|
||||
))
|
||||
.info(CompileTimeInformation::default());
|
||||
|
||||
#[cfg(feature = "paging")]
|
||||
@@ -293,70 +343,63 @@ fn invoke_bugreport(app: &App, cache_dir: &Path) {
|
||||
/// `Ok(false)` if any intermediate errors occurred (were printed).
|
||||
fn run() -> Result<bool> {
|
||||
let app = App::new()?;
|
||||
let config_dir = PROJECT_DIRS.config_dir();
|
||||
let cache_dir = PROJECT_DIRS.cache_dir();
|
||||
|
||||
if app.matches.get_flag("diagnostic") {
|
||||
if app.matches.is_present("diagnostic") {
|
||||
#[cfg(feature = "bugreport")]
|
||||
invoke_bugreport(&app, cache_dir);
|
||||
invoke_bugreport(&app);
|
||||
#[cfg(not(feature = "bugreport"))]
|
||||
println!("bat has been built without the 'bugreport' feature. The '--diagnostic' option is not available.");
|
||||
return Ok(true);
|
||||
}
|
||||
|
||||
match app.matches.subcommand() {
|
||||
Some(("cache", cache_matches)) => {
|
||||
("cache", Some(cache_matches)) => {
|
||||
// If there is a file named 'cache' in the current working directory,
|
||||
// arguments for subcommand 'cache' are not mandatory.
|
||||
// If there are non-zero arguments, execute the subcommand cache, else, open the file cache.
|
||||
if cache_matches.args_present() {
|
||||
run_cache_subcommand(
|
||||
cache_matches,
|
||||
#[cfg(feature = "build-assets")]
|
||||
config_dir,
|
||||
cache_dir,
|
||||
)?;
|
||||
if !cache_matches.args.is_empty() {
|
||||
run_cache_subcommand(cache_matches)?;
|
||||
Ok(true)
|
||||
} else {
|
||||
let inputs = vec![Input::ordinary_file("cache")];
|
||||
let config = app.config(&inputs)?;
|
||||
|
||||
run_controller(inputs, &config, cache_dir)
|
||||
run_controller(inputs, &config)
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
let inputs = app.inputs()?;
|
||||
let config = app.config(&inputs)?;
|
||||
|
||||
if app.matches.get_flag("list-languages") {
|
||||
let languages: String = get_languages(&config, cache_dir)?;
|
||||
if app.matches.is_present("list-languages") {
|
||||
let languages: String = get_languages(&config)?;
|
||||
let inputs: Vec<Input> = vec![Input::from_reader(Box::new(languages.as_bytes()))];
|
||||
let plain_config = Config {
|
||||
style_components: StyleComponents::new(StyleComponent::Plain.components(false)),
|
||||
paging_mode: PagingMode::QuitIfOneScreen,
|
||||
..Default::default()
|
||||
};
|
||||
run_controller(inputs, &plain_config, cache_dir)
|
||||
} else if app.matches.get_flag("list-themes") {
|
||||
list_themes(&config, config_dir, cache_dir)?;
|
||||
run_controller(inputs, &plain_config)
|
||||
} else if app.matches.is_present("list-themes") {
|
||||
list_themes(&config)?;
|
||||
Ok(true)
|
||||
} else if app.matches.get_flag("config-file") {
|
||||
} else if app.matches.is_present("config-file") {
|
||||
println!("{}", config_file().to_string_lossy());
|
||||
Ok(true)
|
||||
} else if app.matches.get_flag("generate-config-file") {
|
||||
} else if app.matches.is_present("generate-config-file") {
|
||||
generate_config_file()?;
|
||||
Ok(true)
|
||||
} else if app.matches.get_flag("config-dir") {
|
||||
writeln!(io::stdout(), "{}", config_dir.to_string_lossy())?;
|
||||
} else if app.matches.is_present("config-dir") {
|
||||
writeln!(io::stdout(), "{}", config_dir())?;
|
||||
Ok(true)
|
||||
} else if app.matches.get_flag("cache-dir") {
|
||||
writeln!(io::stdout(), "{}", cache_dir.to_string_lossy())?;
|
||||
} else if app.matches.is_present("cache-dir") {
|
||||
writeln!(io::stdout(), "{}", cache_dir())?;
|
||||
Ok(true)
|
||||
} else if app.matches.get_flag("acknowledgements") {
|
||||
} else if app.matches.is_present("acknowledgements") {
|
||||
writeln!(io::stdout(), "{}", bat::assets::get_acknowledgements())?;
|
||||
Ok(true)
|
||||
} else {
|
||||
run_controller(inputs, &config, cache_dir)
|
||||
run_controller(inputs, &config)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,11 +1,12 @@
|
||||
use crate::line_range::{HighlightedLineRanges, LineRanges};
|
||||
use crate::nonprintable_notation::NonprintableNotation;
|
||||
#[cfg(feature = "paging")]
|
||||
use crate::paging::PagingMode;
|
||||
use crate::style::StyleComponents;
|
||||
use crate::syntax_mapping::SyntaxMapping;
|
||||
use crate::wrapping::WrappingMode;
|
||||
|
||||
use std::ffi::OsStr;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum VisibleLines {
|
||||
/// Show all lines which are included in the line ranges
|
||||
@@ -40,9 +41,6 @@ pub struct Config<'a> {
|
||||
/// Whether or not to show/replace non-printable characters like space, tab and newline.
|
||||
pub show_nonprintable: bool,
|
||||
|
||||
/// The configured notation for non-printable characters
|
||||
pub nonprintable_notation: NonprintableNotation,
|
||||
|
||||
/// The character width of the terminal
|
||||
pub term_width: usize,
|
||||
|
||||
@@ -91,9 +89,8 @@ pub struct Config<'a> {
|
||||
/// cached assets) are not available, assets from the binary will be used instead.
|
||||
pub use_custom_assets: bool,
|
||||
|
||||
// Whether or not to use $LESSOPEN if set
|
||||
#[cfg(feature = "lessopen")]
|
||||
pub use_lessopen: bool,
|
||||
/// List of bat plugins to be loaded
|
||||
pub plugins: Vec<&'a OsStr>,
|
||||
}
|
||||
|
||||
#[cfg(all(feature = "minimal-application", feature = "paging"))]
|
||||
|
@@ -6,47 +6,33 @@ use crate::config::{Config, VisibleLines};
|
||||
use crate::diff::{get_git_diff, LineChanges};
|
||||
use crate::error::*;
|
||||
use crate::input::{Input, InputReader, OpenedInput};
|
||||
#[cfg(feature = "lessopen")]
|
||||
use crate::lessopen::LessOpenPreprocessor;
|
||||
#[cfg(feature = "git")]
|
||||
use crate::line_range::LineRange;
|
||||
use crate::line_range::{LineRanges, RangeCheckResult};
|
||||
use crate::output::OutputType;
|
||||
#[cfg(feature = "paging")]
|
||||
use crate::paging::PagingMode;
|
||||
use crate::printer::{InteractivePrinter, OutputHandle, Printer, SimplePrinter};
|
||||
use crate::printer::{InteractivePrinter, Printer, SimplePrinter};
|
||||
|
||||
use clircle::{Clircle, Identifier};
|
||||
|
||||
pub struct Controller<'a> {
|
||||
config: &'a Config<'a>,
|
||||
assets: &'a HighlightingAssets,
|
||||
#[cfg(feature = "lessopen")]
|
||||
preprocessor: Option<LessOpenPreprocessor>,
|
||||
}
|
||||
|
||||
impl<'b> Controller<'b> {
|
||||
pub fn new<'a>(config: &'a Config, assets: &'a HighlightingAssets) -> Controller<'a> {
|
||||
Controller {
|
||||
config,
|
||||
assets,
|
||||
#[cfg(feature = "lessopen")]
|
||||
preprocessor: LessOpenPreprocessor::new().ok(),
|
||||
}
|
||||
Controller { config, assets }
|
||||
}
|
||||
|
||||
pub fn run(
|
||||
&self,
|
||||
inputs: Vec<Input>,
|
||||
output_buffer: Option<&mut dyn std::fmt::Write>,
|
||||
) -> Result<bool> {
|
||||
self.run_with_error_handler(inputs, output_buffer, default_error_handler)
|
||||
pub fn run(&self, inputs: Vec<Input>) -> Result<bool> {
|
||||
self.run_with_error_handler(inputs, default_error_handler)
|
||||
}
|
||||
|
||||
pub fn run_with_error_handler(
|
||||
&self,
|
||||
inputs: Vec<Input>,
|
||||
output_buffer: Option<&mut dyn std::fmt::Write>,
|
||||
handle_error: impl Fn(&Error, &mut dyn Write),
|
||||
) -> Result<bool> {
|
||||
let mut output_type;
|
||||
@@ -88,10 +74,7 @@ impl<'b> Controller<'b> {
|
||||
clircle::Identifier::stdout()
|
||||
};
|
||||
|
||||
let mut writer = match output_buffer {
|
||||
Some(buf) => OutputHandle::FmtWrite(buf),
|
||||
None => OutputHandle::IoWrite(output_type.handle()?),
|
||||
};
|
||||
let writer = output_type.handle()?;
|
||||
let mut no_errors: bool = true;
|
||||
let stderr = io::stderr();
|
||||
|
||||
@@ -99,24 +82,17 @@ impl<'b> Controller<'b> {
|
||||
let identifier = stdout_identifier.as_ref();
|
||||
let is_first = index == 0;
|
||||
let result = if input.is_stdin() {
|
||||
self.print_input(input, &mut writer, io::stdin().lock(), identifier, is_first)
|
||||
self.print_input(input, writer, io::stdin().lock(), identifier, is_first)
|
||||
} else {
|
||||
// Use dummy stdin since stdin is actually not used (#1902)
|
||||
self.print_input(input, &mut writer, io::empty(), identifier, is_first)
|
||||
self.print_input(input, writer, io::empty(), identifier, is_first)
|
||||
};
|
||||
if let Err(error) = result {
|
||||
match writer {
|
||||
// It doesn't make much sense to send errors straight to stderr if the user
|
||||
// provided their own buffer, so we just return it.
|
||||
OutputHandle::FmtWrite(_) => return Err(error),
|
||||
OutputHandle::IoWrite(ref mut writer) => {
|
||||
if attached_to_pager {
|
||||
handle_error(&error, writer);
|
||||
} else {
|
||||
handle_error(&error, &mut stderr.lock());
|
||||
}
|
||||
}
|
||||
}
|
||||
no_errors = false;
|
||||
}
|
||||
}
|
||||
@@ -127,23 +103,12 @@ impl<'b> Controller<'b> {
|
||||
fn print_input<R: BufRead>(
|
||||
&self,
|
||||
input: Input,
|
||||
writer: &mut OutputHandle,
|
||||
writer: &mut dyn Write,
|
||||
stdin: R,
|
||||
stdout_identifier: Option<&Identifier>,
|
||||
is_first: bool,
|
||||
) -> Result<()> {
|
||||
let mut opened_input = {
|
||||
#[cfg(feature = "lessopen")]
|
||||
match self.preprocessor {
|
||||
Some(ref preprocessor) if self.config.use_lessopen => {
|
||||
preprocessor.open(input, stdin, stdout_identifier)?
|
||||
}
|
||||
_ => input.open(stdin, stdout_identifier)?,
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "lessopen"))]
|
||||
input.open(stdin, stdout_identifier)?
|
||||
};
|
||||
let mut opened_input = input.open(stdin, stdout_identifier)?;
|
||||
#[cfg(feature = "git")]
|
||||
let line_changes = if self.config.visible_lines.diff_mode()
|
||||
|| (!self.config.loop_through && self.config.style_components.changes())
|
||||
@@ -199,7 +164,7 @@ impl<'b> Controller<'b> {
|
||||
fn print_file(
|
||||
&self,
|
||||
printer: &mut dyn Printer,
|
||||
writer: &mut OutputHandle,
|
||||
writer: &mut dyn Write,
|
||||
input: &mut OpenedInput,
|
||||
add_header_padding: bool,
|
||||
#[cfg(feature = "git")] line_changes: &Option<LineChanges>,
|
||||
@@ -237,7 +202,7 @@ impl<'b> Controller<'b> {
|
||||
fn print_file_ranges(
|
||||
&self,
|
||||
printer: &mut dyn Printer,
|
||||
writer: &mut OutputHandle,
|
||||
writer: &mut dyn Write,
|
||||
reader: &mut InputReader,
|
||||
line_ranges: &LineRanges,
|
||||
) -> Result<()> {
|
||||
|
@@ -1,7 +1,7 @@
|
||||
#[cfg(feature = "git")]
|
||||
use crate::diff::LineChange;
|
||||
use crate::printer::{Colors, InteractivePrinter};
|
||||
use nu_ansi_term::Style;
|
||||
use ansi_term::Style;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub(crate) struct DecorationText {
|
||||
|
@@ -17,11 +17,11 @@ pub enum LineChange {
|
||||
pub type LineChanges = HashMap<u32, LineChange>;
|
||||
|
||||
pub fn get_git_diff(filename: &Path) -> Option<LineChanges> {
|
||||
let repo = Repository::discover(filename).ok()?;
|
||||
let repo = Repository::discover(&filename).ok()?;
|
||||
|
||||
let repo_path_absolute = fs::canonicalize(repo.workdir()?).ok()?;
|
||||
|
||||
let filepath_absolute = fs::canonicalize(filename).ok()?;
|
||||
let filepath_absolute = fs::canonicalize(&filename).ok()?;
|
||||
let filepath_relative_to_repo = filepath_absolute.strip_prefix(&repo_path_absolute).ok()?;
|
||||
|
||||
let mut diff_options = DiffOptions::new();
|
||||
|
10
src/error.rs
10
src/error.rs
@@ -7,8 +7,6 @@ pub enum Error {
|
||||
#[error(transparent)]
|
||||
Io(#[from] ::std::io::Error),
|
||||
#[error(transparent)]
|
||||
Fmt(#[from] ::std::fmt::Error),
|
||||
#[error(transparent)]
|
||||
SyntectError(#[from] ::syntect::Error),
|
||||
#[error(transparent)]
|
||||
SyntectLoadingError(#[from] ::syntect::LoadingError),
|
||||
@@ -28,12 +26,6 @@ pub enum Error {
|
||||
InvalidPagerValueBat,
|
||||
#[error("{0}")]
|
||||
Msg(String),
|
||||
#[cfg(feature = "lessopen")]
|
||||
#[error(transparent)]
|
||||
VarError(#[from] ::std::env::VarError),
|
||||
#[cfg(feature = "lessopen")]
|
||||
#[error(transparent)]
|
||||
CommandParseError(#[from] ::shell_words::ParseError),
|
||||
}
|
||||
|
||||
impl From<&'static str> for Error {
|
||||
@@ -51,7 +43,7 @@ impl From<String> for Error {
|
||||
pub type Result<T> = std::result::Result<T, Error>;
|
||||
|
||||
pub fn default_error_handler(error: &Error, output: &mut dyn Write) {
|
||||
use nu_ansi_term::Color::Red;
|
||||
use ansi_term::Colour::Red;
|
||||
|
||||
match error {
|
||||
Error::Io(ref io_error) if io_error.kind() == ::std::io::ErrorKind::BrokenPipe => {
|
||||
|
14
src/input.rs
14
src/input.rs
@@ -69,7 +69,8 @@ impl InputDescription {
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) enum InputKind<'a> {
|
||||
pub enum InputKind<'a> {
|
||||
// TODO
|
||||
OrdinaryFile(PathBuf),
|
||||
StdIn,
|
||||
CustomReader(Box<dyn Read + 'a>),
|
||||
@@ -86,14 +87,15 @@ impl<'a> InputKind<'a> {
|
||||
}
|
||||
|
||||
#[derive(Clone, Default)]
|
||||
pub(crate) struct InputMetadata {
|
||||
pub(crate) user_provided_name: Option<PathBuf>,
|
||||
pub struct InputMetadata {
|
||||
// TODO
|
||||
pub user_provided_name: Option<PathBuf>,
|
||||
pub(crate) size: Option<u64>,
|
||||
}
|
||||
|
||||
pub struct Input<'a> {
|
||||
pub(crate) kind: InputKind<'a>,
|
||||
pub(crate) metadata: InputMetadata,
|
||||
pub kind: InputKind<'a>, // TODO
|
||||
pub metadata: InputMetadata, // TODO
|
||||
pub(crate) description: InputDescription,
|
||||
}
|
||||
|
||||
@@ -256,7 +258,7 @@ pub(crate) struct InputReader<'a> {
|
||||
}
|
||||
|
||||
impl<'a> InputReader<'a> {
|
||||
pub(crate) fn new<R: BufRead + 'a>(mut reader: R) -> InputReader<'a> {
|
||||
fn new<R: BufRead + 'a>(mut reader: R) -> InputReader<'a> {
|
||||
let mut first_line = vec![];
|
||||
reader.read_until(b'\n', &mut first_line).ok();
|
||||
|
||||
|
@@ -3,7 +3,7 @@
|
||||
use std::ffi::OsStr;
|
||||
use std::process::Command;
|
||||
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub enum LessVersion {
|
||||
Less(usize),
|
||||
BusyBox,
|
||||
|
401
src/lessopen.rs
401
src/lessopen.rs
@@ -1,401 +0,0 @@
|
||||
#![cfg(feature = "lessopen")]
|
||||
|
||||
use std::convert::TryFrom;
|
||||
use std::env;
|
||||
use std::fs::File;
|
||||
use std::io::{BufRead, BufReader, Cursor, Read, Write};
|
||||
use std::path::PathBuf;
|
||||
use std::str;
|
||||
|
||||
use clircle::{Clircle, Identifier};
|
||||
use os_str_bytes::RawOsString;
|
||||
use run_script::{IoOptions, ScriptOptions};
|
||||
|
||||
use crate::error::Result;
|
||||
use crate::{
|
||||
bat_warning,
|
||||
input::{Input, InputKind, InputReader, OpenedInput, OpenedInputKind},
|
||||
};
|
||||
|
||||
/// Preprocess files and/or stdin using $LESSOPEN and $LESSCLOSE
|
||||
pub(crate) struct LessOpenPreprocessor {
|
||||
lessopen: String,
|
||||
lessclose: Option<String>,
|
||||
command_options: ScriptOptions,
|
||||
kind: LessOpenKind,
|
||||
/// Whether or not data piped via stdin is to be preprocessed
|
||||
preprocess_stdin: bool,
|
||||
}
|
||||
|
||||
enum LessOpenKind {
|
||||
Piped,
|
||||
PipedIgnoreExitCode,
|
||||
TempFile,
|
||||
}
|
||||
|
||||
impl LessOpenPreprocessor {
|
||||
/// Create a new instance of LessOpenPreprocessor
|
||||
/// Will return Ok if and only if $LESSOPEN is set and contains exactly one %s
|
||||
pub(crate) fn new() -> Result<LessOpenPreprocessor> {
|
||||
let lessopen = env::var("LESSOPEN")?;
|
||||
|
||||
// Ignore $LESSOPEN if it does not contains exactly one %s
|
||||
// Note that $LESSCLOSE has no such requirement
|
||||
if lessopen.match_indices("%s").count() != 1 {
|
||||
let error_msg = "LESSOPEN ignored: must contain exactly one %s";
|
||||
bat_warning!("{}", error_msg);
|
||||
return Err(error_msg.into());
|
||||
}
|
||||
|
||||
// "||" means pipe directly to bat without making a temporary file
|
||||
// Also, if preprocessor output is empty and exit code is zero, use the empty output
|
||||
// Otherwise, if output is empty and exit code is nonzero, use original file contents
|
||||
let (kind, lessopen) = if lessopen.starts_with("||") {
|
||||
(LessOpenKind::Piped, lessopen.chars().skip(2).collect())
|
||||
// "|" means pipe, but ignore exit code, always using preprocessor output
|
||||
} else if lessopen.starts_with('|') {
|
||||
(
|
||||
LessOpenKind::PipedIgnoreExitCode,
|
||||
lessopen.chars().skip(1).collect(),
|
||||
)
|
||||
// If neither appear, write output to a temporary file and read from that
|
||||
} else {
|
||||
(LessOpenKind::TempFile, lessopen)
|
||||
};
|
||||
|
||||
// "-" means that stdin is preprocessed along with files and may appear alongside "|" and "||"
|
||||
let (stdin, lessopen) = if lessopen.starts_with('-') {
|
||||
(true, lessopen.chars().skip(1).collect())
|
||||
} else {
|
||||
(false, lessopen)
|
||||
};
|
||||
|
||||
let mut command_options = ScriptOptions::new();
|
||||
command_options.runner = env::var("SHELL").ok();
|
||||
command_options.input_redirection = IoOptions::Pipe;
|
||||
|
||||
Ok(Self {
|
||||
lessopen: lessopen.replacen("%s", "$1", 1),
|
||||
lessclose: env::var("LESSCLOSE")
|
||||
.ok()
|
||||
.map(|str| str.replacen("%s", "$1", 1).replacen("%s", "$2", 1)),
|
||||
command_options,
|
||||
kind,
|
||||
preprocess_stdin: stdin,
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) fn open<'a, R: BufRead + 'a>(
|
||||
&self,
|
||||
input: Input<'a>,
|
||||
mut stdin: R,
|
||||
stdout_identifier: Option<&Identifier>,
|
||||
) -> Result<OpenedInput<'a>> {
|
||||
let (lessopen_stdout, path_str, kind) = match input.kind {
|
||||
InputKind::OrdinaryFile(ref path) => {
|
||||
let path_str = match path.to_str() {
|
||||
Some(str) => str,
|
||||
None => return input.open(stdin, stdout_identifier),
|
||||
};
|
||||
|
||||
let (exit_code, lessopen_stdout, _) = match run_script::run(
|
||||
&self.lessopen,
|
||||
&vec![path_str.to_string()],
|
||||
&self.command_options,
|
||||
) {
|
||||
Ok(output) => output,
|
||||
Err(_) => return input.open(stdin, stdout_identifier),
|
||||
};
|
||||
|
||||
if self.fall_back_to_original_file(&lessopen_stdout, exit_code) {
|
||||
return input.open(stdin, stdout_identifier);
|
||||
}
|
||||
|
||||
(
|
||||
RawOsString::from_string(lessopen_stdout),
|
||||
path_str.to_string(),
|
||||
OpenedInputKind::OrdinaryFile(path.to_path_buf()),
|
||||
)
|
||||
}
|
||||
InputKind::StdIn => {
|
||||
if self.preprocess_stdin {
|
||||
if let Some(stdout) = stdout_identifier {
|
||||
let input_identifier = Identifier::try_from(clircle::Stdio::Stdin)
|
||||
.map_err(|e| format!("Stdin: Error identifying file: {}", e))?;
|
||||
if stdout.surely_conflicts_with(&input_identifier) {
|
||||
return Err("IO circle detected. The input from stdin is also an output. Aborting to avoid infinite loop.".into());
|
||||
}
|
||||
}
|
||||
|
||||
// stdin isn't Clone, so copy it to a cloneable buffer
|
||||
let mut stdin_buffer = Vec::new();
|
||||
stdin.read_to_end(&mut stdin_buffer).unwrap();
|
||||
|
||||
let mut lessopen_handle = match run_script::spawn(
|
||||
&self.lessopen,
|
||||
&vec!["-".to_string()],
|
||||
&self.command_options,
|
||||
) {
|
||||
Ok(handle) => handle,
|
||||
Err(_) => {
|
||||
return input.open(stdin, stdout_identifier);
|
||||
}
|
||||
};
|
||||
|
||||
if lessopen_handle
|
||||
.stdin
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.write_all(&stdin_buffer.clone())
|
||||
.is_err()
|
||||
{
|
||||
return input.open(stdin, stdout_identifier);
|
||||
}
|
||||
|
||||
let lessopen_output = match lessopen_handle.wait_with_output() {
|
||||
Ok(output) => output,
|
||||
Err(_) => {
|
||||
return input.open(Cursor::new(stdin_buffer), stdout_identifier);
|
||||
}
|
||||
};
|
||||
|
||||
if lessopen_output.stdout.is_empty()
|
||||
&& (!lessopen_output.status.success()
|
||||
|| matches!(self.kind, LessOpenKind::PipedIgnoreExitCode))
|
||||
{
|
||||
return input.open(Cursor::new(stdin_buffer), stdout_identifier);
|
||||
}
|
||||
|
||||
(
|
||||
RawOsString::assert_from_raw_vec(lessopen_output.stdout),
|
||||
"-".to_string(),
|
||||
OpenedInputKind::StdIn,
|
||||
)
|
||||
} else {
|
||||
return input.open(stdin, stdout_identifier);
|
||||
}
|
||||
}
|
||||
InputKind::CustomReader(_) => {
|
||||
return input.open(stdin, stdout_identifier);
|
||||
}
|
||||
};
|
||||
|
||||
Ok(OpenedInput {
|
||||
kind,
|
||||
reader: InputReader::new(BufReader::new(
|
||||
if matches!(self.kind, LessOpenKind::TempFile) {
|
||||
// Remove newline at end of temporary file path returned by $LESSOPEN
|
||||
let stdout = match lessopen_stdout.strip_suffix("\n") {
|
||||
Some(stripped) => stripped.to_owned(),
|
||||
None => lessopen_stdout,
|
||||
};
|
||||
|
||||
let stdout = stdout.into_os_string();
|
||||
|
||||
let file = match File::open(PathBuf::from(&stdout)) {
|
||||
Ok(file) => file,
|
||||
Err(_) => {
|
||||
return input.open(stdin, stdout_identifier);
|
||||
}
|
||||
};
|
||||
|
||||
Preprocessed {
|
||||
kind: PreprocessedKind::TempFile(file),
|
||||
lessclose: self.lessclose.clone(),
|
||||
command_args: vec![path_str, stdout.to_str().unwrap().to_string()],
|
||||
command_options: self.command_options.clone(),
|
||||
}
|
||||
} else {
|
||||
Preprocessed {
|
||||
kind: PreprocessedKind::Piped(Cursor::new(lessopen_stdout.into_raw_vec())),
|
||||
lessclose: self.lessclose.clone(),
|
||||
command_args: vec![path_str, "-".to_string()],
|
||||
command_options: self.command_options.clone(),
|
||||
}
|
||||
},
|
||||
)),
|
||||
metadata: input.metadata,
|
||||
description: input.description,
|
||||
})
|
||||
}
|
||||
|
||||
fn fall_back_to_original_file(&self, lessopen_output: &str, exit_code: i32) -> bool {
|
||||
lessopen_output.is_empty()
|
||||
&& (exit_code != 0 || matches!(self.kind, LessOpenKind::PipedIgnoreExitCode))
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
/// For testing purposes only
|
||||
/// Create an instance of LessOpenPreprocessor with specified valued for $LESSOPEN and $LESSCLOSE
|
||||
fn mock_new(lessopen: Option<&str>, lessclose: Option<&str>) -> Result<LessOpenPreprocessor> {
|
||||
if let Some(command) = lessopen {
|
||||
env::set_var("LESSOPEN", command)
|
||||
} else {
|
||||
env::remove_var("LESSOPEN")
|
||||
}
|
||||
|
||||
if let Some(command) = lessclose {
|
||||
env::set_var("LESSCLOSE", command)
|
||||
} else {
|
||||
env::remove_var("LESSCLOSE")
|
||||
}
|
||||
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
enum PreprocessedKind {
|
||||
Piped(Cursor<Vec<u8>>),
|
||||
TempFile(File),
|
||||
}
|
||||
|
||||
impl Read for PreprocessedKind {
|
||||
fn read(&mut self, buf: &mut [u8]) -> std::result::Result<usize, std::io::Error> {
|
||||
match self {
|
||||
PreprocessedKind::Piped(data) => data.read(buf),
|
||||
PreprocessedKind::TempFile(data) => data.read(buf),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Preprocessed {
|
||||
kind: PreprocessedKind,
|
||||
lessclose: Option<String>,
|
||||
command_args: Vec<String>,
|
||||
command_options: ScriptOptions,
|
||||
}
|
||||
|
||||
impl Read for Preprocessed {
|
||||
fn read(&mut self, buf: &mut [u8]) -> std::result::Result<usize, std::io::Error> {
|
||||
self.kind.read(buf)
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for Preprocessed {
|
||||
fn drop(&mut self) {
|
||||
if let Some(ref command) = self.lessclose {
|
||||
self.command_options.output_redirection = IoOptions::Inherit;
|
||||
|
||||
run_script::run(command, &self.command_args, &self.command_options)
|
||||
.expect("failed to run $LESSCLOSE to clean up file");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
// All tests here are serial because they all involve reading and writing environment variables
|
||||
// Running them in parallel causes these tests and some others to randomly fail
|
||||
use serial_test::serial;
|
||||
|
||||
use super::*;
|
||||
|
||||
/// Reset environment variables after each test as a precaution
|
||||
fn reset_env_vars() {
|
||||
env::remove_var("LESSOPEN");
|
||||
env::remove_var("LESSCLOSE");
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[serial]
|
||||
fn test_just_lessopen() -> Result<()> {
|
||||
let preprocessor = LessOpenPreprocessor::mock_new(Some("|batpipe %s"), None)?;
|
||||
|
||||
assert_eq!(preprocessor.lessopen, "batpipe $1");
|
||||
assert!(preprocessor.lessclose.is_none());
|
||||
|
||||
reset_env_vars();
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[serial]
|
||||
fn test_just_lessclose() -> Result<()> {
|
||||
let preprocessor = LessOpenPreprocessor::mock_new(None, Some("lessclose.sh %s %s"));
|
||||
|
||||
assert!(preprocessor.is_err());
|
||||
|
||||
reset_env_vars();
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[serial]
|
||||
fn test_both_lessopen_and_lessclose() -> Result<()> {
|
||||
let preprocessor =
|
||||
LessOpenPreprocessor::mock_new(Some("lessopen.sh %s"), Some("lessclose.sh %s %s"))?;
|
||||
|
||||
assert_eq!(preprocessor.lessopen, "lessopen.sh $1");
|
||||
assert_eq!(preprocessor.lessclose.unwrap(), "lessclose.sh $1 $2");
|
||||
|
||||
reset_env_vars();
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[serial]
|
||||
fn test_lessopen_prefixes() -> Result<()> {
|
||||
let preprocessor = LessOpenPreprocessor::mock_new(Some("batpipe %s"), None)?;
|
||||
|
||||
assert_eq!(preprocessor.lessopen, "batpipe $1");
|
||||
assert!(matches!(preprocessor.kind, LessOpenKind::TempFile));
|
||||
assert!(!preprocessor.preprocess_stdin);
|
||||
|
||||
let preprocessor = LessOpenPreprocessor::mock_new(Some("|batpipe %s"), None)?;
|
||||
|
||||
assert_eq!(preprocessor.lessopen, "batpipe $1");
|
||||
assert!(matches!(
|
||||
preprocessor.kind,
|
||||
LessOpenKind::PipedIgnoreExitCode
|
||||
));
|
||||
assert!(!preprocessor.preprocess_stdin);
|
||||
|
||||
let preprocessor = LessOpenPreprocessor::mock_new(Some("||batpipe %s"), None)?;
|
||||
|
||||
assert_eq!(preprocessor.lessopen, "batpipe $1");
|
||||
assert!(matches!(preprocessor.kind, LessOpenKind::Piped));
|
||||
assert!(!preprocessor.preprocess_stdin);
|
||||
|
||||
let preprocessor = LessOpenPreprocessor::mock_new(Some("-batpipe %s"), None)?;
|
||||
|
||||
assert_eq!(preprocessor.lessopen, "batpipe $1");
|
||||
assert!(matches!(preprocessor.kind, LessOpenKind::TempFile));
|
||||
assert!(preprocessor.preprocess_stdin);
|
||||
|
||||
let preprocessor = LessOpenPreprocessor::mock_new(Some("|-batpipe %s"), None)?;
|
||||
|
||||
assert_eq!(preprocessor.lessopen, "batpipe $1");
|
||||
assert!(matches!(
|
||||
preprocessor.kind,
|
||||
LessOpenKind::PipedIgnoreExitCode
|
||||
));
|
||||
assert!(preprocessor.preprocess_stdin);
|
||||
|
||||
let preprocessor = LessOpenPreprocessor::mock_new(Some("||-batpipe %s"), None)?;
|
||||
|
||||
assert_eq!(preprocessor.lessopen, "batpipe $1");
|
||||
assert!(matches!(preprocessor.kind, LessOpenKind::Piped));
|
||||
assert!(preprocessor.preprocess_stdin);
|
||||
|
||||
reset_env_vars();
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[serial]
|
||||
fn replace_part_of_argument() -> Result<()> {
|
||||
let preprocessor =
|
||||
LessOpenPreprocessor::mock_new(Some("|echo File:%s"), Some("echo File:%s Temp:%s"))?;
|
||||
|
||||
assert_eq!(preprocessor.lessopen, "echo File:$1");
|
||||
assert_eq!(preprocessor.lessclose.unwrap(), "echo File:$1 Temp:$2");
|
||||
|
||||
reset_env_vars();
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
@@ -34,10 +34,7 @@ mod diff;
|
||||
pub mod error;
|
||||
pub mod input;
|
||||
mod less;
|
||||
#[cfg(feature = "lessopen")]
|
||||
mod lessopen;
|
||||
pub mod line_range;
|
||||
pub(crate) mod nonprintable_notation;
|
||||
mod output;
|
||||
#[cfg(feature = "paging")]
|
||||
mod pager;
|
||||
@@ -52,8 +49,7 @@ mod terminal;
|
||||
mod vscreen;
|
||||
pub(crate) mod wrapping;
|
||||
|
||||
pub use nonprintable_notation::NonprintableNotation;
|
||||
pub use pretty_printer::{Input, PrettyPrinter, Syntax};
|
||||
pub use pretty_printer::{Input, PrettyPrinter};
|
||||
pub use syntax_mapping::{MappingTarget, SyntaxMapping};
|
||||
pub use wrapping::WrappingMode;
|
||||
|
||||
|
@@ -53,7 +53,7 @@ impl LineRange {
|
||||
let more_lines = &line_numbers[1][1..]
|
||||
.parse()
|
||||
.map_err(|_| "Invalid character after +")?;
|
||||
new_range.lower.saturating_add(*more_lines)
|
||||
new_range.lower + more_lines
|
||||
} else if first_byte == Some(b'-') {
|
||||
// this will prevent values like "-+5" even though "+5" is valid integer
|
||||
if line_numbers[1][1..].bytes().next() == Some(b'+') {
|
||||
@@ -128,13 +128,6 @@ fn test_parse_plus() {
|
||||
assert_eq!(50, range.upper);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_plus_overflow() {
|
||||
let range = LineRange::from(&format!("{}:+1", usize::MAX)).expect("Shouldn't fail on test!");
|
||||
assert_eq!(usize::MAX, range.lower);
|
||||
assert_eq!(usize::MAX, range.upper);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_plus_fail() {
|
||||
let range = LineRange::from("40:+z");
|
||||
@@ -175,7 +168,7 @@ fn test_parse_minus_fail() {
|
||||
assert!(range.is_err());
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||
#[derive(Copy, Clone, Debug, PartialEq)]
|
||||
pub enum RangeCheckResult {
|
||||
// Within one of the given ranges
|
||||
InRange,
|
||||
|
@@ -1,7 +1,7 @@
|
||||
#[macro_export]
|
||||
macro_rules! bat_warning {
|
||||
($($arg:tt)*) => ({
|
||||
use nu_ansi_term::Color::Yellow;
|
||||
use ansi_term::Colour::Yellow;
|
||||
eprintln!("{}: {}", Yellow.paint("[bat warning]"), format!($($arg)*));
|
||||
})
|
||||
}
|
||||
|
@@ -1,12 +0,0 @@
|
||||
/// How to print non-printable characters with
|
||||
/// [crate::config::Config::show_nonprintable]
|
||||
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
|
||||
#[non_exhaustive]
|
||||
pub enum NonprintableNotation {
|
||||
/// Use caret notation (^G, ^J, ^@, ..)
|
||||
Caret,
|
||||
|
||||
/// Use unicode notation (␇, ␊, ␀, ..)
|
||||
#[default]
|
||||
Unicode,
|
||||
}
|
@@ -114,10 +114,6 @@ impl OutputType {
|
||||
p.args(args);
|
||||
}
|
||||
p.env("LESSCHARSET", "UTF-8");
|
||||
|
||||
#[cfg(feature = "lessopen")]
|
||||
// Ensures that 'less' does not preprocess input again if '$LESSOPEN' is set.
|
||||
p.arg("--no-lessopen");
|
||||
} else {
|
||||
p.args(args);
|
||||
};
|
||||
|
20
src/pager.rs
20
src/pager.rs
@@ -40,23 +40,15 @@ impl PagerKind {
|
||||
fn from_bin(bin: &str) -> PagerKind {
|
||||
use std::path::Path;
|
||||
|
||||
// Set to `less` by default on most Linux distros.
|
||||
let pager_bin = Path::new(bin).file_stem();
|
||||
|
||||
// The name of the current running binary. Normally `bat` but sometimes
|
||||
// `batcat` for compatibility reasons.
|
||||
let current_bin = env::args_os().next();
|
||||
|
||||
// Check if the current running binary is set to be our pager.
|
||||
let is_current_bin_pager = current_bin
|
||||
.map(|s| Path::new(&s).file_stem() == pager_bin)
|
||||
.unwrap_or(false);
|
||||
|
||||
match pager_bin.map(|s| s.to_string_lossy()).as_deref() {
|
||||
match Path::new(bin)
|
||||
.file_stem()
|
||||
.map(|s| s.to_string_lossy())
|
||||
.as_deref()
|
||||
{
|
||||
Some("bat") => PagerKind::Bat,
|
||||
Some("less") => PagerKind::Less,
|
||||
Some("more") => PagerKind::More,
|
||||
Some("most") => PagerKind::Most,
|
||||
_ if is_current_bin_pager => PagerKind::Bat,
|
||||
_ => PagerKind::Unknown,
|
||||
}
|
||||
}
|
||||
|
@@ -1,7 +1,12 @@
|
||||
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
|
||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||
pub enum PagingMode {
|
||||
Always,
|
||||
QuitIfOneScreen,
|
||||
#[default]
|
||||
Never,
|
||||
}
|
||||
|
||||
impl Default for PagingMode {
|
||||
fn default() -> Self {
|
||||
PagingMode::Never
|
||||
}
|
||||
}
|
||||
|
@@ -1,9 +1,5 @@
|
||||
use std::fmt::Write;
|
||||
|
||||
use console::AnsiCodeIterator;
|
||||
|
||||
use crate::nonprintable_notation::NonprintableNotation;
|
||||
|
||||
/// Expand tabs like an ANSI-enabled expand(1).
|
||||
pub fn expand_tabs(line: &str, width: usize, cursor: &mut usize) -> String {
|
||||
let mut buffer = String::with_capacity(line.len() * 2);
|
||||
@@ -22,7 +18,7 @@ pub fn expand_tabs(line: &str, width: usize, cursor: &mut usize) -> String {
|
||||
// Add tab.
|
||||
let spaces = width - (*cursor % width);
|
||||
*cursor += spaces;
|
||||
buffer.push_str(&" ".repeat(spaces));
|
||||
buffer.push_str(&*" ".repeat(spaces));
|
||||
|
||||
// Next.
|
||||
text = &text[index + 1..text.len()];
|
||||
@@ -51,11 +47,7 @@ fn try_parse_utf8_char(input: &[u8]) -> Option<(char, usize)> {
|
||||
decoded.map(|(seq, n)| (seq.chars().next().unwrap(), n))
|
||||
}
|
||||
|
||||
pub fn replace_nonprintable(
|
||||
input: &[u8],
|
||||
tab_width: usize,
|
||||
nonprintable_notation: NonprintableNotation,
|
||||
) -> String {
|
||||
pub fn replace_nonprintable(input: &[u8], tab_width: usize) -> String {
|
||||
let mut output = String::new();
|
||||
|
||||
let tab_width = if tab_width == 0 { 4 } else { tab_width };
|
||||
@@ -85,37 +77,19 @@ pub fn replace_nonprintable(
|
||||
}
|
||||
// line feed
|
||||
'\x0A' => {
|
||||
output.push_str(match nonprintable_notation {
|
||||
NonprintableNotation::Caret => "^J\x0A",
|
||||
NonprintableNotation::Unicode => "␊\x0A",
|
||||
});
|
||||
output.push_str("␊\x0A");
|
||||
line_idx = 0;
|
||||
}
|
||||
// carriage return
|
||||
'\x0D' => output.push_str(match nonprintable_notation {
|
||||
NonprintableNotation::Caret => "^M",
|
||||
NonprintableNotation::Unicode => "␍",
|
||||
}),
|
||||
'\x0D' => output.push('␍'),
|
||||
// null
|
||||
'\x00' => output.push_str(match nonprintable_notation {
|
||||
NonprintableNotation::Caret => "^@",
|
||||
NonprintableNotation::Unicode => "␀",
|
||||
}),
|
||||
'\x00' => output.push('␀'),
|
||||
// bell
|
||||
'\x07' => output.push_str(match nonprintable_notation {
|
||||
NonprintableNotation::Caret => "^G",
|
||||
NonprintableNotation::Unicode => "␇",
|
||||
}),
|
||||
'\x07' => output.push('␇'),
|
||||
// backspace
|
||||
'\x08' => output.push_str(match nonprintable_notation {
|
||||
NonprintableNotation::Caret => "^H",
|
||||
NonprintableNotation::Unicode => "␈",
|
||||
}),
|
||||
'\x08' => output.push('␈'),
|
||||
// escape
|
||||
'\x1B' => output.push_str(match nonprintable_notation {
|
||||
NonprintableNotation::Caret => "^[",
|
||||
NonprintableNotation::Unicode => "␛",
|
||||
}),
|
||||
'\x1B' => output.push('␛'),
|
||||
// printable ASCII
|
||||
c if c.is_ascii_alphanumeric()
|
||||
|| c.is_ascii_punctuation()
|
||||
@@ -127,7 +101,7 @@ pub fn replace_nonprintable(
|
||||
c => output.push_str(&c.escape_unicode().collect::<String>()),
|
||||
}
|
||||
} else {
|
||||
write!(output, "\\x{:02X}", input[idx]).ok();
|
||||
output.push_str(&format!("\\x{:02X}", input[idx]));
|
||||
idx += 1;
|
||||
}
|
||||
}
|
||||
|
@@ -2,6 +2,7 @@ use std::io::Read;
|
||||
use std::path::Path;
|
||||
|
||||
use console::Term;
|
||||
use syntect::parsing::SyntaxReference;
|
||||
|
||||
use crate::{
|
||||
assets::HighlightingAssets,
|
||||
@@ -10,7 +11,7 @@ use crate::{
|
||||
error::Result,
|
||||
input,
|
||||
line_range::{HighlightedLineRanges, LineRange, LineRanges},
|
||||
style::StyleComponent,
|
||||
style::{StyleComponent, StyleComponents},
|
||||
SyntaxMapping, WrappingMode,
|
||||
};
|
||||
|
||||
@@ -19,8 +20,7 @@ use crate::paging::PagingMode;
|
||||
|
||||
#[derive(Default)]
|
||||
struct ActiveStyleComponents {
|
||||
header_filename: bool,
|
||||
#[cfg(feature = "git")]
|
||||
header: bool,
|
||||
vcs_modification_markers: bool,
|
||||
grid: bool,
|
||||
rule: bool,
|
||||
@@ -28,12 +28,6 @@ struct ActiveStyleComponents {
|
||||
snip: bool,
|
||||
}
|
||||
|
||||
#[non_exhaustive]
|
||||
pub struct Syntax {
|
||||
pub name: String,
|
||||
pub file_extensions: Vec<String>,
|
||||
}
|
||||
|
||||
pub struct PrettyPrinter<'a> {
|
||||
inputs: Vec<Input<'a>>,
|
||||
config: Config<'a>,
|
||||
@@ -140,7 +134,7 @@ impl<'a> PrettyPrinter<'a> {
|
||||
|
||||
/// Whether to show a header with the file name
|
||||
pub fn header(&mut self, yes: bool) -> &mut Self {
|
||||
self.active_style_components.header_filename = yes;
|
||||
self.active_style_components.header = yes;
|
||||
self
|
||||
}
|
||||
|
||||
@@ -246,61 +240,51 @@ impl<'a> PrettyPrinter<'a> {
|
||||
self.assets.themes()
|
||||
}
|
||||
|
||||
pub fn syntaxes(&self) -> impl Iterator<Item = Syntax> + '_ {
|
||||
pub fn syntaxes(&self) -> impl Iterator<Item = &SyntaxReference> {
|
||||
// We always use assets from the binary, which are guaranteed to always
|
||||
// be valid, so get_syntaxes() can never fail here
|
||||
self.assets
|
||||
.get_syntaxes()
|
||||
.unwrap()
|
||||
.iter()
|
||||
.filter(|s| !s.hidden)
|
||||
.map(|s| Syntax {
|
||||
name: s.name.clone(),
|
||||
file_extensions: s.file_extensions.clone(),
|
||||
})
|
||||
self.assets.get_syntaxes().unwrap().iter()
|
||||
}
|
||||
|
||||
/// Pretty-print all specified inputs. This method will "use" all stored inputs.
|
||||
/// If you want to call 'print' multiple times, you have to call the appropriate
|
||||
/// input_* methods again.
|
||||
pub fn print(&mut self) -> Result<bool> {
|
||||
let highlight_lines = std::mem::take(&mut self.highlighted_lines);
|
||||
self.config.highlighted_lines = HighlightedLineRanges(LineRanges::from(highlight_lines));
|
||||
self.config.highlighted_lines =
|
||||
HighlightedLineRanges(LineRanges::from(self.highlighted_lines.clone()));
|
||||
self.config.term_width = self
|
||||
.term_width
|
||||
.unwrap_or_else(|| Term::stdout().size().1 as usize);
|
||||
|
||||
self.config.style_components.clear();
|
||||
let mut style_components = vec![];
|
||||
if self.active_style_components.grid {
|
||||
self.config.style_components.insert(StyleComponent::Grid);
|
||||
style_components.push(StyleComponent::Grid);
|
||||
}
|
||||
if self.active_style_components.rule {
|
||||
self.config.style_components.insert(StyleComponent::Rule);
|
||||
style_components.push(StyleComponent::Rule);
|
||||
}
|
||||
if self.active_style_components.header_filename {
|
||||
self.config
|
||||
.style_components
|
||||
.insert(StyleComponent::HeaderFilename);
|
||||
if self.active_style_components.header {
|
||||
style_components.push(StyleComponent::Header);
|
||||
}
|
||||
if self.active_style_components.line_numbers {
|
||||
self.config
|
||||
.style_components
|
||||
.insert(StyleComponent::LineNumbers);
|
||||
style_components.push(StyleComponent::LineNumbers);
|
||||
}
|
||||
if self.active_style_components.snip {
|
||||
self.config.style_components.insert(StyleComponent::Snip);
|
||||
style_components.push(StyleComponent::Snip);
|
||||
}
|
||||
#[cfg(feature = "git")]
|
||||
if self.active_style_components.vcs_modification_markers {
|
||||
self.config.style_components.insert(StyleComponent::Changes);
|
||||
#[cfg(feature = "git")]
|
||||
style_components.push(StyleComponent::Changes);
|
||||
}
|
||||
self.config.style_components = StyleComponents::new(&style_components);
|
||||
|
||||
// Collect the inputs to print
|
||||
let inputs = std::mem::take(&mut self.inputs);
|
||||
let mut inputs: Vec<Input> = vec![];
|
||||
std::mem::swap(&mut inputs, &mut self.inputs);
|
||||
|
||||
// Run the controller
|
||||
let controller = Controller::new(&self.config, &self.assets);
|
||||
controller.run(inputs.into_iter().map(|i| i.into()).collect(), None)
|
||||
controller.run(inputs.into_iter().map(|i| i.into()).collect())
|
||||
}
|
||||
}
|
||||
|
||||
|
109
src/printer.rs
109
src/printer.rs
@@ -1,9 +1,8 @@
|
||||
use std::fmt;
|
||||
use std::io;
|
||||
use std::io::Write;
|
||||
use std::vec::Vec;
|
||||
|
||||
use nu_ansi_term::Color::{Fixed, Green, Red, Yellow};
|
||||
use nu_ansi_term::Style;
|
||||
use ansi_term::Colour::{Fixed, Green, Red, Yellow};
|
||||
use ansi_term::Style;
|
||||
|
||||
use bytesize::ByteSize;
|
||||
|
||||
@@ -16,7 +15,8 @@ use syntect::parsing::SyntaxSet;
|
||||
|
||||
use content_inspector::ContentType;
|
||||
|
||||
use encoding_rs::{UTF_16BE, UTF_16LE};
|
||||
use encoding::all::{UTF_16BE, UTF_16LE};
|
||||
use encoding::{DecoderTrap, Encoding};
|
||||
|
||||
use unicode_width::UnicodeWidthChar;
|
||||
|
||||
@@ -36,35 +36,21 @@ use crate::terminal::{as_terminal_escaped, to_ansi_color};
|
||||
use crate::vscreen::AnsiStyle;
|
||||
use crate::wrapping::WrappingMode;
|
||||
|
||||
pub enum OutputHandle<'a> {
|
||||
IoWrite(&'a mut dyn io::Write),
|
||||
FmtWrite(&'a mut dyn fmt::Write),
|
||||
}
|
||||
|
||||
impl<'a> OutputHandle<'a> {
|
||||
fn write_fmt(&mut self, args: fmt::Arguments<'_>) -> Result<()> {
|
||||
match self {
|
||||
Self::IoWrite(handle) => handle.write_fmt(args).map_err(Into::into),
|
||||
Self::FmtWrite(handle) => handle.write_fmt(args).map_err(Into::into),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) trait Printer {
|
||||
fn print_header(
|
||||
&mut self,
|
||||
handle: &mut OutputHandle,
|
||||
handle: &mut dyn Write,
|
||||
input: &OpenedInput,
|
||||
add_header_padding: bool,
|
||||
) -> Result<()>;
|
||||
fn print_footer(&mut self, handle: &mut OutputHandle, input: &OpenedInput) -> Result<()>;
|
||||
fn print_footer(&mut self, handle: &mut dyn Write, input: &OpenedInput) -> Result<()>;
|
||||
|
||||
fn print_snip(&mut self, handle: &mut OutputHandle) -> Result<()>;
|
||||
fn print_snip(&mut self, handle: &mut dyn Write) -> Result<()>;
|
||||
|
||||
fn print_line(
|
||||
&mut self,
|
||||
out_of_range: bool,
|
||||
handle: &mut OutputHandle,
|
||||
handle: &mut dyn Write,
|
||||
line_number: usize,
|
||||
line_buffer: &[u8],
|
||||
) -> Result<()>;
|
||||
@@ -83,50 +69,34 @@ impl<'a> SimplePrinter<'a> {
|
||||
impl<'a> Printer for SimplePrinter<'a> {
|
||||
fn print_header(
|
||||
&mut self,
|
||||
_handle: &mut OutputHandle,
|
||||
_handle: &mut dyn Write,
|
||||
_input: &OpenedInput,
|
||||
_add_header_padding: bool,
|
||||
) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn print_footer(&mut self, _handle: &mut OutputHandle, _input: &OpenedInput) -> Result<()> {
|
||||
fn print_footer(&mut self, _handle: &mut dyn Write, _input: &OpenedInput) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn print_snip(&mut self, _handle: &mut OutputHandle) -> Result<()> {
|
||||
fn print_snip(&mut self, _handle: &mut dyn Write) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn print_line(
|
||||
&mut self,
|
||||
out_of_range: bool,
|
||||
handle: &mut OutputHandle,
|
||||
handle: &mut dyn Write,
|
||||
_line_number: usize,
|
||||
line_buffer: &[u8],
|
||||
) -> Result<()> {
|
||||
if !out_of_range {
|
||||
if self.config.show_nonprintable {
|
||||
let line = replace_nonprintable(
|
||||
line_buffer,
|
||||
self.config.tab_width,
|
||||
self.config.nonprintable_notation,
|
||||
);
|
||||
let line = replace_nonprintable(line_buffer, self.config.tab_width);
|
||||
write!(handle, "{}", line)?;
|
||||
} else {
|
||||
match handle {
|
||||
OutputHandle::IoWrite(handle) => handle.write_all(line_buffer)?,
|
||||
OutputHandle::FmtWrite(handle) => {
|
||||
write!(
|
||||
handle,
|
||||
"{}",
|
||||
std::str::from_utf8(line_buffer).map_err(|_| Error::Msg(
|
||||
"encountered invalid utf8 while printing to non-io buffer"
|
||||
.to_string()
|
||||
))?
|
||||
)?;
|
||||
}
|
||||
}
|
||||
handle.write_all(line_buffer)?
|
||||
};
|
||||
}
|
||||
Ok(())
|
||||
@@ -244,11 +214,7 @@ impl<'a> InteractivePrinter<'a> {
|
||||
})
|
||||
}
|
||||
|
||||
fn print_horizontal_line_term(
|
||||
&mut self,
|
||||
handle: &mut OutputHandle,
|
||||
style: Style,
|
||||
) -> Result<()> {
|
||||
fn print_horizontal_line_term(&mut self, handle: &mut dyn Write, style: Style) -> Result<()> {
|
||||
writeln!(
|
||||
handle,
|
||||
"{}",
|
||||
@@ -257,7 +223,7 @@ impl<'a> InteractivePrinter<'a> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn print_horizontal_line(&mut self, handle: &mut OutputHandle, grid_char: char) -> Result<()> {
|
||||
fn print_horizontal_line(&mut self, handle: &mut dyn Write, grid_char: char) -> Result<()> {
|
||||
if self.panel_width == 0 {
|
||||
self.print_horizontal_line_term(handle, self.colors.grid)?;
|
||||
} else {
|
||||
@@ -287,7 +253,7 @@ impl<'a> InteractivePrinter<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
fn print_header_component_indent(&mut self, handle: &mut OutputHandle) -> Result<()> {
|
||||
fn print_header_component_indent(&mut self, handle: &mut dyn Write) -> std::io::Result<()> {
|
||||
if self.config.style_components.grid() {
|
||||
write!(
|
||||
handle,
|
||||
@@ -315,7 +281,7 @@ impl<'a> InteractivePrinter<'a> {
|
||||
impl<'a> Printer for InteractivePrinter<'a> {
|
||||
fn print_header(
|
||||
&mut self,
|
||||
handle: &mut OutputHandle,
|
||||
handle: &mut dyn Write,
|
||||
input: &OpenedInput,
|
||||
add_header_padding: bool,
|
||||
) -> Result<()> {
|
||||
@@ -414,7 +380,7 @@ impl<'a> Printer for InteractivePrinter<'a> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn print_footer(&mut self, handle: &mut OutputHandle, _input: &OpenedInput) -> Result<()> {
|
||||
fn print_footer(&mut self, handle: &mut dyn Write, _input: &OpenedInput) -> Result<()> {
|
||||
if self.config.style_components.grid()
|
||||
&& (self.content_type.map_or(false, |c| c.is_text()) || self.config.show_nonprintable)
|
||||
{
|
||||
@@ -424,7 +390,7 @@ impl<'a> Printer for InteractivePrinter<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
fn print_snip(&mut self, handle: &mut OutputHandle) -> Result<()> {
|
||||
fn print_snip(&mut self, handle: &mut dyn Write) -> Result<()> {
|
||||
let panel = self.create_fake_panel(" ...");
|
||||
let panel_count = panel.chars().count();
|
||||
|
||||
@@ -451,35 +417,24 @@ impl<'a> Printer for InteractivePrinter<'a> {
|
||||
fn print_line(
|
||||
&mut self,
|
||||
out_of_range: bool,
|
||||
handle: &mut OutputHandle,
|
||||
handle: &mut dyn Write,
|
||||
line_number: usize,
|
||||
line_buffer: &[u8],
|
||||
) -> Result<()> {
|
||||
let line = if self.config.show_nonprintable {
|
||||
replace_nonprintable(
|
||||
line_buffer,
|
||||
self.config.tab_width,
|
||||
self.config.nonprintable_notation,
|
||||
)
|
||||
.into()
|
||||
replace_nonprintable(line_buffer, self.config.tab_width)
|
||||
} else {
|
||||
match self.content_type {
|
||||
Some(ContentType::BINARY) | None => {
|
||||
return Ok(());
|
||||
}
|
||||
Some(ContentType::UTF_16LE) => UTF_16LE.decode_with_bom_removal(line_buffer).0,
|
||||
Some(ContentType::UTF_16BE) => UTF_16BE.decode_with_bom_removal(line_buffer).0,
|
||||
_ => {
|
||||
let line = String::from_utf8_lossy(line_buffer);
|
||||
if line_number == 1 {
|
||||
match line.strip_prefix('\u{feff}') {
|
||||
Some(stripped) => stripped.to_string().into(),
|
||||
None => line,
|
||||
}
|
||||
} else {
|
||||
line
|
||||
}
|
||||
}
|
||||
Some(ContentType::UTF_16LE) => UTF_16LE
|
||||
.decode(line_buffer, DecoderTrap::Replace)
|
||||
.map_err(|_| "Invalid UTF-16LE")?,
|
||||
Some(ContentType::UTF_16BE) => UTF_16BE
|
||||
.decode(line_buffer, DecoderTrap::Replace)
|
||||
.map_err(|_| "Invalid UTF-16BE")?,
|
||||
_ => String::from_utf8_lossy(line_buffer).to_string(),
|
||||
}
|
||||
};
|
||||
|
||||
@@ -657,7 +612,7 @@ impl<'a> Printer for InteractivePrinter<'a> {
|
||||
"{}\n{}",
|
||||
as_terminal_escaped(
|
||||
style,
|
||||
&format!("{}{}", self.ansi_style, line_buf),
|
||||
&*format!("{}{}", self.ansi_style, line_buf),
|
||||
self.config.true_color,
|
||||
self.config.colored_output,
|
||||
self.config.use_italic_text,
|
||||
@@ -683,7 +638,7 @@ impl<'a> Printer for InteractivePrinter<'a> {
|
||||
"{}",
|
||||
as_terminal_escaped(
|
||||
style,
|
||||
&format!("{}{}", self.ansi_style, line_buf),
|
||||
&*format!("{}{}", self.ansi_style, line_buf),
|
||||
self.config.true_color,
|
||||
self.config.colored_output,
|
||||
self.config.use_italic_text,
|
||||
|
@@ -129,12 +129,4 @@ impl StyleComponents {
|
||||
pub fn plain(&self) -> bool {
|
||||
self.0.iter().all(|c| c == &StyleComponent::Plain)
|
||||
}
|
||||
|
||||
pub fn insert(&mut self, component: StyleComponent) {
|
||||
self.0.insert(component);
|
||||
}
|
||||
|
||||
pub fn clear(&mut self) {
|
||||
self.0.clear();
|
||||
}
|
||||
}
|
||||
|
@@ -7,7 +7,7 @@ use globset::{Candidate, GlobBuilder, GlobMatcher};
|
||||
|
||||
pub mod ignored_suffixes;
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||
#[non_exhaustive]
|
||||
pub enum MappingTarget<'a> {
|
||||
/// For mapping a path to a specific syntax.
|
||||
@@ -63,41 +63,15 @@ impl<'a> SyntaxMapping<'a> {
|
||||
MappingTarget::MapTo("Bourne Again Shell (bash)"),
|
||||
)
|
||||
.unwrap();
|
||||
mapping
|
||||
.insert(
|
||||
"os-release",
|
||||
MappingTarget::MapTo("Bourne Again Shell (bash)"),
|
||||
)
|
||||
.unwrap();
|
||||
mapping
|
||||
.insert("*.pac", MappingTarget::MapTo("JavaScript (Babel)"))
|
||||
.unwrap();
|
||||
mapping
|
||||
.insert("fish_history", MappingTarget::MapTo("YAML"))
|
||||
.unwrap();
|
||||
|
||||
for glob in ["*.jsonl", "*.sarif"] {
|
||||
mapping.insert(glob, MappingTarget::MapTo("JSON")).unwrap();
|
||||
}
|
||||
|
||||
// See #2151, https://nmap.org/book/nse-language.html
|
||||
mapping
|
||||
.insert("*.nse", MappingTarget::MapTo("Lua"))
|
||||
.unwrap();
|
||||
|
||||
// See #1008
|
||||
mapping
|
||||
.insert("rails", MappingTarget::MapToUnknown)
|
||||
.unwrap();
|
||||
|
||||
mapping
|
||||
.insert("Containerfile", MappingTarget::MapTo("Dockerfile"))
|
||||
.unwrap();
|
||||
|
||||
mapping
|
||||
.insert("*.ksh", MappingTarget::MapTo("Bourne Again Shell (bash)"))
|
||||
.unwrap();
|
||||
|
||||
// Nginx and Apache syntax files both want to style all ".conf" files
|
||||
// see #1131 and #1137
|
||||
mapping
|
||||
@@ -156,30 +130,19 @@ impl<'a> SyntaxMapping<'a> {
|
||||
.insert("*.hook", MappingTarget::MapTo("INI"))
|
||||
.unwrap();
|
||||
|
||||
mapping
|
||||
.insert("*.ron", MappingTarget::MapTo("Rust"))
|
||||
.unwrap();
|
||||
|
||||
// Global git config files rooted in `$XDG_CONFIG_HOME/git/` or `$HOME/.config/git/`
|
||||
// See e.g. https://git-scm.com/docs/git-config#FILES
|
||||
match (
|
||||
std::env::var_os("XDG_CONFIG_HOME").filter(|val| !val.is_empty()),
|
||||
std::env::var_os("HOME")
|
||||
.filter(|val| !val.is_empty())
|
||||
.map(|home| Path::new(&home).join(".config")),
|
||||
) {
|
||||
(Some(xdg_config_home), Some(default_config_home))
|
||||
if xdg_config_home == default_config_home => {
|
||||
insert_git_config_global(&mut mapping, &xdg_config_home)
|
||||
}
|
||||
(Some(xdg_config_home), Some(default_config_home)) /* else guard */ => {
|
||||
if let Some(xdg_config_home) =
|
||||
std::env::var_os("XDG_CONFIG_HOME").filter(|val| !val.is_empty())
|
||||
{
|
||||
insert_git_config_global(&mut mapping, &xdg_config_home);
|
||||
insert_git_config_global(&mut mapping, &default_config_home)
|
||||
}
|
||||
(Some(config_home), None) => insert_git_config_global(&mut mapping, &config_home),
|
||||
(None, Some(config_home)) => insert_git_config_global(&mut mapping, &config_home),
|
||||
(None, None) => (),
|
||||
};
|
||||
if let Some(default_config_home) = std::env::var_os("HOME")
|
||||
.filter(|val| !val.is_empty())
|
||||
.map(|home| Path::new(&home).join(".config"))
|
||||
{
|
||||
insert_git_config_global(&mut mapping, &default_config_home);
|
||||
}
|
||||
|
||||
fn insert_git_config_global(mapping: &mut SyntaxMapping, config_home: impl AsRef<Path>) {
|
||||
let git_config_path = config_home.as_ref().join("git");
|
||||
@@ -211,7 +174,7 @@ impl<'a> SyntaxMapping<'a> {
|
||||
|
||||
pub fn insert(&mut self, from: &str, to: MappingTarget<'a>) -> Result<()> {
|
||||
let glob = GlobBuilder::new(from)
|
||||
.case_insensitive(true)
|
||||
.case_insensitive(false)
|
||||
.literal_separator(true)
|
||||
.build()?;
|
||||
self.mappings.push((glob.compile_matcher(), to));
|
||||
@@ -223,7 +186,6 @@ impl<'a> SyntaxMapping<'a> {
|
||||
}
|
||||
|
||||
pub(crate) fn get_syntax_for(&self, path: impl AsRef<Path>) -> Option<MappingTarget<'a>> {
|
||||
// Try matching on the file name as-is.
|
||||
let candidate = Candidate::new(&path);
|
||||
let candidate_filename = path.as_ref().file_name().map(Candidate::new);
|
||||
for (ref glob, ref syntax) in self.mappings.iter().rev() {
|
||||
@@ -235,13 +197,7 @@ impl<'a> SyntaxMapping<'a> {
|
||||
return Some(*syntax);
|
||||
}
|
||||
}
|
||||
// Try matching on the file name after removing an ignored suffix.
|
||||
let file_name = path.as_ref().file_name()?;
|
||||
self.ignored_suffixes
|
||||
.try_with_stripped_suffix(file_name, |stripped_file_name| {
|
||||
Ok(self.get_syntax_for(stripped_file_name))
|
||||
})
|
||||
.ok()?
|
||||
None
|
||||
}
|
||||
|
||||
pub fn insert_ignored_suffix(&mut self, suffix: &'a str) {
|
||||
@@ -249,9 +205,6 @@ impl<'a> SyntaxMapping<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
#[test]
|
||||
fn basic() {
|
||||
let mut map = SyntaxMapping::empty();
|
||||
@@ -297,28 +250,3 @@ mod tests {
|
||||
Some(MappingTarget::MapToUnknown)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
/// verifies that SyntaxMapping::builtin() doesn't repeat `Glob`-based keys
|
||||
fn no_duplicate_builtin_keys() {
|
||||
let mappings = SyntaxMapping::builtin().mappings;
|
||||
for i in 0..mappings.len() {
|
||||
let tail = mappings[i + 1..].into_iter();
|
||||
let (dupl, _): (Vec<_>, Vec<_>) =
|
||||
tail.partition(|item| item.0.glob() == mappings[i].0.glob());
|
||||
|
||||
// emit repeats on failure
|
||||
assert_eq!(
|
||||
dupl.len(),
|
||||
0,
|
||||
"Glob pattern `{}` mapped to multiple: {:?}",
|
||||
mappings[i].0.glob().glob(),
|
||||
{
|
||||
let (_, mut dupl_targets): (Vec<GlobMatcher>, Vec<MappingTarget>) =
|
||||
dupl.into_iter().cloned().unzip();
|
||||
dupl_targets.push(mappings[i].1)
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -20,9 +20,7 @@ impl Default for IgnoredSuffixes<'_> {
|
||||
".orig",
|
||||
// Debian and derivatives apt/dpkg/ucf backups
|
||||
".dpkg-dist",
|
||||
".dpkg-new",
|
||||
".dpkg-old",
|
||||
".dpkg-tmp",
|
||||
".ucf-dist",
|
||||
".ucf-new",
|
||||
".ucf-old",
|
||||
|
@@ -1,9 +1,9 @@
|
||||
use nu_ansi_term::Color::{self, Fixed, Rgb};
|
||||
use nu_ansi_term::{self, Style};
|
||||
use ansi_term::Color::{self, Fixed, RGB};
|
||||
use ansi_term::{self, Style};
|
||||
|
||||
use syntect::highlighting::{self, FontStyle};
|
||||
|
||||
pub fn to_ansi_color(color: highlighting::Color, true_color: bool) -> Option<nu_ansi_term::Color> {
|
||||
pub fn to_ansi_color(color: highlighting::Color, true_color: bool) -> Option<ansi_term::Color> {
|
||||
if color.a == 0 {
|
||||
// Themes can specify one of the user-configurable terminal colors by
|
||||
// encoding them as #RRGGBBAA with AA set to 00 (transparent) and RR set
|
||||
@@ -38,7 +38,7 @@ pub fn to_ansi_color(color: highlighting::Color, true_color: bool) -> Option<nu_
|
||||
// 01. The built-in theme ansi uses this.
|
||||
None
|
||||
} else if true_color {
|
||||
Some(Rgb(color.r, color.g, color.b))
|
||||
Some(RGB(color.r, color.g, color.b))
|
||||
} else {
|
||||
Some(Fixed(ansi_colours::ansi256_from_rgb((
|
||||
color.r, color.g, color.b,
|
||||
|
1
tests/examples/bat-tabs.conf
vendored
1
tests/examples/bat-tabs.conf
vendored
@@ -1 +0,0 @@
|
||||
--tabs=8
|
1
tests/examples/bat-theme.conf
vendored
1
tests/examples/bat-theme.conf
vendored
@@ -1 +0,0 @@
|
||||
--theme=TwoDark
|
5
tests/examples/bat-windows.conf
vendored
5
tests/examples/bat-windows.conf
vendored
@@ -1,5 +0,0 @@
|
||||
# Make sure that the pager gets executed
|
||||
--paging=always
|
||||
|
||||
# Output a dummy message for the integration test and system wide config test.
|
||||
--pager="echo.bat dummy-pager-from-config"
|
2
tests/examples/bat.conf
vendored
2
tests/examples/bat.conf
vendored
@@ -1,5 +1,5 @@
|
||||
# Make sure that the pager gets executed
|
||||
--paging=always
|
||||
|
||||
# Output a dummy message for the integration test and system wide config test.
|
||||
# Output a dummy message for the integration test.
|
||||
--pager="echo dummy-pager-from-config"
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user