@@ -1,15 +1,51 @@
1+use std::collections::HashSet;
2+use std::env;
3+
14use atty::{self, Stream};
5+
26use clap::{App as ClapApp, AppSettings, Arg, ArgGroup, ArgMatches, SubCommand};
7+
38use console::Term;
4−use errors::*;
5−use std::collections::HashSet;
6−use std::env;
7−use style::{OutputComponent, OutputComponents, OutputWrap};
89
910#[cfg(windows)]
1011use ansi_term;
1112
1213use assets::BAT_THEME_DEFAULT;
14+use errors::*;
15+use line_range::LineRange;
16+use style::{OutputComponent, OutputComponents, OutputWrap};
17+
18+#[derive(Debug, Clone, Copy)]
19+pub enum PagingMode {
20+ Always,
21+ QuitIfOneScreen,
22+ Never,
23+}
24+
25+pub struct Config<'a> {
26+ pub true_color: bool,
27+ pub output_wrap: OutputWrap,
28+ pub output_components: OutputComponents,
29+ pub language: Option<&'a str>,
30+ pub colored_output: bool,
31+ pub paging_mode: PagingMode,
32+ pub term_width: usize,
33+ pub files: Vec<Option<&'a str>>,
34+ pub theme: String,
35+ pub line_range: Option<LineRange>,
36+}
37+
38+fn is_truecolor_terminal() -> bool {
39+ env::var("COLORTERM")
40+ .map(|colorterm| colorterm == "truecolor" || colorterm == "24bit")
41+ .unwrap_or(false)
42+}
43+
44+/// Helper function that should might appear in Rust stable at some point
45+/// (https://doc.rust-lang.org/stable/std/option/enum.Option.html#method.transpose)
46+fn transpose<T>(opt: Option<Result<T>>) -> Result<Option<T>> {
47+ opt.map_or(Ok(None), |res| res.map(Some))
48+}
1349
1450pub struct App {
1551 pub matches: ArgMatches<'static>,
@@ -319,104 +355,3 @@ impl App {
319355 }))
320356 }
321357}
322−
323−#[derive(Debug, Clone, Copy)]
324−pub enum PagingMode {
325− Always,
326− QuitIfOneScreen,
327− Never,
328−}
329−
330−pub struct Config<'a> {
331− pub true_color: bool,
332− pub output_wrap: OutputWrap,
333− pub output_components: OutputComponents,
334− pub language: Option<&'a str>,
335− pub colored_output: bool,
336− pub paging_mode: PagingMode,
337− pub term_width: usize,
338− pub files: Vec<Option<&'a str>>,
339− pub theme: String,
340− pub line_range: Option<LineRange>,
341−}
342−
343−fn is_truecolor_terminal() -> bool {
344− env::var("COLORTERM")
345− .map(|colorterm| colorterm == "truecolor" || colorterm == "24bit")
346− .unwrap_or(false)
347−}
348−
349−pub struct LineRange {
350− pub lower: usize,
351− pub upper: usize,
352−}
353−
354−impl LineRange {
355− pub fn from(range_raw: &str) -> Result<LineRange> {
356− LineRange::parse_range(range_raw)
357− }
358−
359− pub fn new() -> LineRange {
360− LineRange {
361− lower: usize::min_value(),
362− upper: usize::max_value(),
363− }
364− }
365−
366− pub fn parse_range(range_raw: &str) -> Result<LineRange> {
367− let mut new_range = LineRange::new();
368−
369− if range_raw.bytes().nth(0).ok_or("Empty line range")? == b':' {
370− new_range.upper = range_raw[1..].parse()?;
371− return Ok(new_range);
372− } else if range_raw.bytes().last().ok_or("Empty line range")? == b':' {
373− new_range.lower = range_raw[..range_raw.len() - 1].parse()?;
374− return Ok(new_range);
375− }
376−
377− let line_numbers: Vec<&str> = range_raw.split(':').collect();
378− if line_numbers.len() == 2 {
379− new_range.lower = line_numbers[0].parse()?;
380− new_range.upper = line_numbers[1].parse()?;
381− return Ok(new_range);
382− }
383− Err("expected single ':' character".into())
384− }
385−}
386−
387−#[test]
388−fn test_parse_line_range_full() {
389− let range = LineRange::from("40:50").expect("Shouldn't fail on test!");
390− assert_eq!(40, range.lower);
391− assert_eq!(50, range.upper);
392−}
393−
394−#[test]
395−fn test_parse_line_range_partial_min() {
396− let range = LineRange::from(":50").expect("Shouldn't fail on test!");
397− assert_eq!(usize::min_value(), range.lower);
398− assert_eq!(50, range.upper);
399−}
400−
401−#[test]
402−fn test_parse_line_range_partial_max() {
403− let range = LineRange::from("40:").expect("Shouldn't fail on test!");
404− assert_eq!(40, range.lower);
405− assert_eq!(usize::max_value(), range.upper);
406−}
407−
408−#[test]
409−fn test_parse_line_range_fail() {
410− let range = LineRange::from("40:50:80");
411− assert!(range.is_err());
412− let range = LineRange::from("40::80");
413− assert!(range.is_err());
414− let range = LineRange::from(":40:");
415− assert!(range.is_err());
416− let range = LineRange::from("40");
417− assert!(range.is_err());
418−}
419−
420−fn transpose<T>(opt: Option<Result<T>>) -> Result<Option<T>> {
421− opt.map_or(Ok(None), |res| res.map(Some))
422−}