diff --git a/Cargo.toml b/Cargo.toml index 98a0fdc2..d7ba56b2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,14 +15,27 @@ exclude = [ build = "build.rs" edition = '2018' +[features] +default = ["application"] +# Feature required for bat the application. Should be disabled when depending on +# bat as a library. +application = [ + "atty", + "clap", + "dirs", + "lazy_static", + "liquid", + "wild", +] + [dependencies] -atty = "0.2.14" +atty = { version = "0.2.14", optional = true } ansi_term = "^0.12.1" ansi_colours = "^1.0" console = "0.10" -dirs = "2.0" -lazy_static = "1.4" -wild = "2.0" +dirs = { version = "2.0", optional = true } +lazy_static = { version = "1.4", optional = true } +wild = { version = "2.0", optional = true } content_inspector = "0.2.4" encoding = "0.2" shell-words = "0.1.0" @@ -32,7 +45,6 @@ globset = "0.4" [dependencies.git2] version = "0.13" default-features = false -features = [] [dependencies.syntect] version = "3.2.0" @@ -41,22 +53,22 @@ features = ["parsing", "yaml-load", "dump-load", "dump-create"] [dependencies.clap] version = "2.33" +optional = true default-features = false features = ["suggestions", "color", "wrap_help"] [dependencies.error-chain] version = "0.12" default-features = false -features = [] [dev-dependencies] tempdir = "0.3" assert_cmd = "0.12.0" [build-dependencies] -clap = "2.33" -liquid = "0.20" -lazy_static = "1.4" +clap = { version = "2.33", optional = true } +liquid = { version = "0.20", optional = true } +lazy_static = { version = "1.4", optional = true } [profile.release] lto = true diff --git a/build.rs b/build.rs index bff88e9f..074caaff 100644 --- a/build.rs +++ b/build.rs @@ -1,38 +1,42 @@ // TODO: Re-enable generation of shell completion files (below) when clap 3 is out. // For more details, see https://github.com/sharkdp/bat/issues/372 -#[macro_use] -extern crate lazy_static; -extern crate liquid; +// For bat-as-a-library, no build script is required. The build script is for +// the manpage and completions, which are only relevant to the bat application. +#[cfg(not(feature = "application"))] +fn main() {} -use std::error::Error; -use std::fs; -use std::path::Path; +#[cfg(feature = "application")] +fn main() -> Result<(), Box> { + use std::error::Error; + use std::fs; + use std::path::Path; -// Read environment variables. -lazy_static! { - pub static ref PROJECT_NAME: &'static str = option_env!("PROJECT_NAME").unwrap_or("bat"); - pub static ref PROJECT_VERSION: &'static str = option_env!("CARGO_PKG_VERSION").unwrap(); - pub static ref EXECUTABLE_NAME: &'static str = option_env!("PROJECT_EXECUTABLE") - .or(option_env!("PROJECT_NAME")) - .unwrap_or("bat"); -} + use lazy_static::lazy_static; -/// Generates a file from a liquid template. -fn template( - variables: &liquid::Object, - in_file: &str, - out_file: impl AsRef, -) -> Result<(), Box> { - let template = liquid::ParserBuilder::with_stdlib() - .build()? - .parse(&fs::read_to_string(in_file)?)?; + // Read environment variables. + lazy_static! { + static ref PROJECT_NAME: &'static str = option_env!("PROJECT_NAME").unwrap_or("bat"); + static ref PROJECT_VERSION: &'static str = option_env!("CARGO_PKG_VERSION").unwrap(); + static ref EXECUTABLE_NAME: &'static str = option_env!("PROJECT_EXECUTABLE") + .or(option_env!("PROJECT_NAME")) + .unwrap_or("bat"); + } - fs::write(out_file, template.render(variables)?)?; - Ok(()) -} + /// Generates a file from a liquid template. + fn template( + variables: &liquid::Object, + in_file: &str, + out_file: impl AsRef, + ) -> Result<(), Box> { + let template = liquid::ParserBuilder::with_stdlib() + .build()? + .parse(&fs::read_to_string(in_file)?)?; + + fs::write(out_file, template.render(variables)?)?; + Ok(()) + } -fn main() -> Result<(), Box> { let variables = liquid::object!({ "PROJECT_NAME": PROJECT_NAME.to_owned(), "PROJECT_EXECUTABLE": EXECUTABLE_NAME.to_owned(), diff --git a/ci/script.bash b/ci/script.bash index db608c16..7f72ed34 100755 --- a/ci/script.bash +++ b/ci/script.bash @@ -12,3 +12,6 @@ if [[ $TARGET != arm-unknown-linux-gnueabihf ]] && [[ $TARGET != aarch64-unknown # Run 'bat' on its own source code and the README cargo run --target "$TARGET" -- src/bin/bat/main.rs README.md --paging=never fi + +# Check bat-as-a-library, which has a smaller set of dependencies +cargo check --target "$TARGET" --verbose --lib --no-default-features diff --git a/src/bin/bat/app.rs b/src/bin/bat/app.rs index f1649b3f..56988b17 100644 --- a/src/bin/bat/app.rs +++ b/src/bin/bat/app.rs @@ -9,13 +9,9 @@ use crate::{ config::{get_args_from_config_file, get_args_from_env_var}, }; use clap::ArgMatches; -use wild; use console::Term; -#[cfg(windows)] -use ansi_term; - use bat::{ config::{ Config, HighlightedLineRanges, InputFile, LineRange, LineRanges, MappingTarget, OutputWrap, diff --git a/src/bin/bat/clap_app.rs b/src/bin/bat/clap_app.rs index c2505ca9..c7344991 100644 --- a/src/bin/bat/clap_app.rs +++ b/src/bin/bat/clap_app.rs @@ -1,4 +1,4 @@ -use clap::{App as ClapApp, AppSettings, Arg, ArgGroup, SubCommand}; +use clap::{crate_name, crate_version, App as ClapApp, AppSettings, Arg, ArgGroup, SubCommand}; use std::path::Path; pub fn build_app(interactive_output: bool) -> ClapApp<'static, 'static> { diff --git a/src/bin/bat/config.rs b/src/bin/bat/config.rs index 25c14d3b..8595ad5b 100644 --- a/src/bin/bat/config.rs +++ b/src/bin/bat/config.rs @@ -4,8 +4,6 @@ use std::fs; use std::io::{self, Write}; use std::path::PathBuf; -use shell_words; - use crate::directories::PROJECT_DIRS; pub fn config_file() -> PathBuf { diff --git a/src/bin/bat/directories.rs b/src/bin/bat/directories.rs index e57a58c0..8f0f261d 100644 --- a/src/bin/bat/directories.rs +++ b/src/bin/bat/directories.rs @@ -1,7 +1,6 @@ use std::env; use std::path::{Path, PathBuf}; -use dirs; use lazy_static::lazy_static; /// Wrapper for 'dirs' that treats MacOS more like Linux, by following the XDG specification. diff --git a/src/bin/bat/main.rs b/src/bin/bat/main.rs index 20130118..15cc37fa 100644 --- a/src/bin/bat/main.rs +++ b/src/bin/bat/main.rs @@ -1,11 +1,6 @@ // `error_chain!` can recurse deeply #![recursion_limit = "1024"] -#[macro_use] -extern crate clap; - -extern crate dirs as dirs_rs; - mod app; mod assets; mod clap_app; diff --git a/src/errors.rs b/src/errors.rs index a0f7e5eb..ff5682b9 100644 --- a/src/errors.rs +++ b/src/errors.rs @@ -2,20 +2,20 @@ use error_chain::error_chain; error_chain! { foreign_links { - Clap(::clap::Error); - Io(::std::io::Error); - SyntectError(::syntect::LoadingError); - ParseIntError(::std::num::ParseIntError); - GlobParsingError(::globset::Error); + Clap(clap::Error); + Io(std::io::Error); + SyntectError(syntect::LoadingError); + ParseIntError(std::num::ParseIntError); + GlobParsingError(globset::Error); } } pub fn default_error_handler(error: &Error) { match error { Error(ErrorKind::Io(ref io_error), _) - if io_error.kind() == ::std::io::ErrorKind::BrokenPipe => + if io_error.kind() == std::io::ErrorKind::BrokenPipe => { - ::std::process::exit(0); + std::process::exit(0); } _ => { use ansi_term::Colour::Red; @@ -23,3 +23,36 @@ pub fn default_error_handler(error: &Error) { } }; } + +// Mock out a type for clap::Error if we aren't pulling in a dependency on clap. +// +// This can be removed after migrating away from error_chain to some modern +// derive-based error library such as thiserror, in favor of: +// +// #[derive(Error)] +// pub enum Error { +// #[cfg(feature = "application")] +// Clap(clap::Error), +// ... +// } +// +#[cfg(not(feature = "application"))] +mod clap { + use std::fmt::{self, Debug, Display}; + + pub struct Error(()); + + impl Display for Error { + fn fmt(&self, _formatter: &mut fmt::Formatter) -> fmt::Result { + unreachable!() + } + } + + impl Debug for Error { + fn fmt(&self, _formatter: &mut fmt::Formatter) -> fmt::Result { + unreachable!() + } + } + + impl std::error::Error for Error {} +} diff --git a/src/lib.rs b/src/lib.rs index 8178f497..404ad49c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,17 +1,6 @@ // `error_chain!` can recurse deeply #![recursion_limit = "1024"] -extern crate ansi_term; -extern crate atty; -extern crate console; -extern crate content_inspector; -extern crate dirs as dirs_rs; -extern crate encoding; -extern crate git2; -extern crate shell_words; -extern crate syntect; -extern crate wild; - pub(crate) mod assets; pub mod config; pub(crate) mod controller; diff --git a/src/output.rs b/src/output.rs index 3bad301b..134ab7b5 100644 --- a/src/output.rs +++ b/src/output.rs @@ -4,8 +4,6 @@ use std::io::{self, Write}; use std::path::PathBuf; use std::process::{Child, Command, Stdio}; -use shell_words; - use crate::config::PagingMode; use crate::errors::*; use crate::less::retrieve_less_version; diff --git a/src/terminal.rs b/src/terminal.rs index 8c3766c5..981bf3b2 100644 --- a/src/terminal.rs +++ b/src/terminal.rs @@ -1,5 +1,3 @@ -extern crate ansi_colours; - use ansi_term::Colour::{Fixed, RGB}; use ansi_term::{self, Style}; diff --git a/tests/tester.rs b/tests/tester.rs index a761babe..9c52459f 100644 --- a/tests/tester.rs +++ b/tests/tester.rs @@ -4,13 +4,11 @@ use std::io::Read; use std::path::{Path, PathBuf}; use std::process::Command; -extern crate tempdir; -use self::tempdir::TempDir; +use tempdir::TempDir; -extern crate git2; -use self::git2::build::CheckoutBuilder; -use self::git2::Repository; -use self::git2::Signature; +use git2::build::CheckoutBuilder; +use git2::Repository; +use git2::Signature; pub struct BatTester { /// Temporary working directory