repo_description: A cat(1) clone with wings.
repo_topics: cli command-line git hacktoberfest rust syntax-highlighting terminal tool
code: use crate::line_range::{HighlightedLineRanges, LineRanges};
  use crate::nonprintable_notation::{BinaryBehavior, NonprintableNotation};
  #[cfg(feature = "paging")]
  use crate::paging::PagingMode;
  use crate::style::StyleComponents;
  use crate::syntax_mapping::SyntaxMapping;
  use crate::wrapping::WrappingMode;
  use crate::StripAnsiMode;
  
  #[derive(Debug, Clone)]
  pub enum VisibleLines {
      /// Show all lines which are included in the line ranges
      Ranges(LineRanges),
  
      #[cfg(feature = "git")]
      /// Only show lines surrounding added/deleted/modified lines
      DiffContext(usize),
  }
  
  impl VisibleLines {
      pub fn diff_mode(&self) -> bool {
          match self {
              Self::Ranges(_) => false,
              #[cfg(feature = "git")]
              Self::DiffContext(_) => true,
          }
      }
  }
  
  impl Default for VisibleLines {
      fn default() -> Self {
          VisibleLines::Ranges(LineRanges::default())
      }
  }
  
  #[derive(Debug, Clone, Default)]
  pub struct Config<'a> {
      /// The explicitly configured language, if any
      pub language: Option<&'a str>,
  
      /// The fallback syntax used when auto-detection fails
      pub fallback_syntax: Option<&'a str>,
  
      /// 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,
  
      /// How to treat binary content
      pub binary: BinaryBehavior,
  
      /// The character width of the terminal
      pub term_width: usize,
  
      /// The width of tab characters.
      /// Currently, a value of 0 will cause tabs to be passed through without expanding them.
      pub tab_width: usize,
  
      /// Whether or not to simply loop through all input (`cat` mode)
      pub loop_through: bool,
  
      /// Whether or not the output should be colorized
      pub colored_output: bool,
  
      /// Whether or not the output terminal supports true color
      pub true_color: bool,
  
      /// Style elements (grid, line numbers, ...)
      pub style_components: StyleComponents,
  
      /// If and how text should be wrapped
      pub wrapping_mode: WrappingMode,
  
      /// Pager or STDOUT
      #[cfg(feature = "paging")]
      pub paging_mode: PagingMode,
  
      /// Specifies which lines should be printed
      pub visible_lines: VisibleLines,
  
      /// The syntax highlighting theme
      pub theme: String,
  
      /// File extension/name mappings
      pub syntax_mapping: SyntaxMapping<'a>,
  
      /// Command to start the pager
      pub pager: Option<&'a str>,
  
      /// Whether or not to use ANSI italics
      pub use_italic_text: bool,
  
      /// Ranges of lines which should be highlighted with a special background color
      pub highlighted_lines: HighlightedLineRanges,
  
      /// Whether or not to allow custom assets. If this is false or if custom assets (a.k.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,
  
      // Whether or not to set terminal title when using a pager
      pub set_terminal_title: bool,
  
      /// The maximum number of consecutive empty lines to display
      pub squeeze_lines: Option<usize>,
  
      // Whether or not to strip ANSI escape codes from the input
      pub strip_ansi: StripAnsiMode,
  
      /// Whether or not to produce no output when input is empty
      pub quiet_empty: bool,
  
      /// Whether or not to use unbuffered input reading for streaming use cases
      pub unbuffered: bool,
  }
  
  #[cfg(all(feature = "minimal-application", feature = "paging"))]
  pub fn get_pager_executable(config_pager: Option<&str>) -> Option<String> {
      crate::pager::get_pager(config_pager)
          .ok()
          .flatten()
          .and_then(|pager| {
              if pager.kind != crate::pager::PagerKind::Builtin {
                  Some(pager.bin)
              } else {
                  None
              }
          })
  }
  
  #[test]
  fn default_config_should_include_all_lines() {
      use crate::line_range::MaxBufferedLineNumber;
      use crate::line_range::RangeCheckResult;
  
      assert_eq!(
          LineRanges::default().check(17, MaxBufferedLineNumber::Tentative(17)),
          RangeCheckResult::InRange
      );
  }
  
  #[test]
  fn default_config_should_highlight_no_lines() {
      use crate::line_range::MaxBufferedLineNumber;
      use crate::line_range::RangeCheckResult;
  
      assert_ne!(
          Config::default()
              .highlighted_lines
              .0
              .check(17, MaxBufferedLineNumber::Tentative(17)),
          RangeCheckResult::InRange
      );
  }
  
  #[cfg(all(feature = "minimal-application", feature = "paging"))]
  #[test]
  fn get_pager_executable_with_config_pager_less() {
      let result = get_pager_executable(Some("less"));
      assert_eq!(result, Some("less".to_string()));
  }
  
  #[cfg(all(feature = "minimal-application", feature = "paging"))]
  #[test]
  fn get_pager_executable_with_config_pager_builtin() {
      let result = get_pager_executable(Some("builtin"));
      assert_eq!(result, None);
  }
  
  #[cfg(all(feature = "minimal-application", feature = "paging"))]
  #[test]
  fn get_pager_executable_with_config_pager_more() {
      let result = get_pager_executable(Some("more"));
      assert_eq!(result, Some("more".to_string()));
  }
  
  #[cfg(all(feature = "minimal-application", feature = "paging"))]
  #[test]
  fn get_pager_executable_with_bat_pager() {
      std::env::set_var("BAT_PAGER", "most");
      let result = get_pager_executable(None);
      assert_eq!(result, Some("most".to_string()));
      std::env::remove_var("BAT_PAGER");
  }
  
  #[cfg(all(feature = "minimal-application", feature = "paging"))]
  #[test]
  fn get_pager_executable_with_pager_more_switches_to_less() {
      std::env::set_var("PAGER", "more");
      let result = get_pager_executable(None);
      assert_eq!(result, Some("less".to_string()));
      std::env::remove_var("PAGER");
  }
  
  #[cfg(all(feature = "minimal-application", feature = "paging"))]
  #[test]
  fn get_pager_executable_default() {
      // Ensure no env vars
      std::env::remove_var("BAT_PAGER");
      std::env::remove_var("PAGER");
      let result = get_pager_executable(None);
      assert_eq!(result, Some("less".to_string()));
  }
  
  #[cfg(all(feature = "minimal-application", feature = "paging"))]
  #[test]
  fn get_pager_executable_name_ignoring_arguments() {
      let result = get_pager_executable(Some("foo --bar"));
      assert_eq!(result, Some("foo".to_string()));
  }
  
  #[cfg(all(feature = "minimal-application", feature = "paging"))]
  #[test]
  fn get_pager_executable_name_ignoring_path() {
      let result = get_pager_executable(Some("/bin/foo test"));
      assert_eq!(result, Some("/bin/foo".to_string()));
  }
  
  #[cfg(all(feature = "minimal-application", feature = "paging"))]
  #[test]
  fn get_pager_executable_invalid_command() {
      let result = get_pager_executable(Some("invalid ' command"));
      assert_eq!(result, None);
  }
  
  #[cfg(all(feature = "minimal-application", feature = "paging"))]
  #[test]
  fn get_pager_executable_empty_config() {
      let result = get_pager_executable(Some(""));
      assert_eq!(result, None);
  }
  