mirror of
				https://github.com/sharkdp/bat.git
				synced 2025-11-04 00:51:56 +00:00 
			
		
		
		
	update line-ranges
This commit is contained in:
		
				
					committed by
					
						
						David Peter
					
				
			
			
				
	
			
			
			
						parent
						
							6691786d82
						
					
				
				
					commit
					26dbdf4fa0
				
			
							
								
								
									
										83
									
								
								src/app.rs
									
									
									
									
									
								
							
							
						
						
									
										83
									
								
								src/app.rs
									
									
									
									
									
								
							@@ -148,8 +148,10 @@ impl App {
 | 
			
		||||
                    .takes_value(true)
 | 
			
		||||
                    .help("Print range of lines")
 | 
			
		||||
                    .long_help(
 | 
			
		||||
                        "Print a specified range of lines from the files \
 | 
			
		||||
                         --line-range 30-40 or --line-range 30-",
 | 
			
		||||
                        "Print a specified range or ranges of lines from the files. \
 | 
			
		||||
                         For example: '--line-range 30:40' will print lines 30 to 40 \n\
 | 
			
		||||
                                      '--line-range :40' will print lines 1 to 40 \n\
 | 
			
		||||
                                      '--line-range 40:' will print lines 40 to the end of the file",
 | 
			
		||||
                    ),
 | 
			
		||||
            )
 | 
			
		||||
            .arg(
 | 
			
		||||
@@ -280,7 +282,7 @@ impl App {
 | 
			
		||||
            term_width: Term::stdout().size().1 as usize,
 | 
			
		||||
            files,
 | 
			
		||||
            theme: self.matches.value_of("theme"),
 | 
			
		||||
            line_range: get_ranges(self.matches.value_of("line-range")),
 | 
			
		||||
            line_range: LineRange::from(self.matches.value_of("line-range")),
 | 
			
		||||
        })
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -334,7 +336,7 @@ pub struct Config<'a> {
 | 
			
		||||
    pub term_width: usize,
 | 
			
		||||
    pub files: Vec<Option<&'a str>>,
 | 
			
		||||
    pub theme: Option<&'a str>,
 | 
			
		||||
    pub line_range: Option<(usize, usize)>,
 | 
			
		||||
    pub line_range: Option<LineRange>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn is_truecolor_terminal() -> bool {
 | 
			
		||||
@@ -343,28 +345,61 @@ fn is_truecolor_terminal() -> bool {
 | 
			
		||||
        .unwrap_or(false)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn get_ranges(value: Option<&str>) -> Option<(usize, usize)> {
 | 
			
		||||
    match value {
 | 
			
		||||
        None => None,
 | 
			
		||||
        Some(str_range) => {
 | 
			
		||||
            let mut new_range = (usize::min_value(), usize::max_value());
 | 
			
		||||
            if str_range.bytes().nth(0).expect("Something should be here!") == b':' {
 | 
			
		||||
                new_range.1 = str_range[1..].parse().expect("This should be a number!");
 | 
			
		||||
                return Some(new_range);
 | 
			
		||||
            } else if str_range.bytes().last().expect("There should be a last!") == b':' {
 | 
			
		||||
                new_range.0 = str_range[..str_range.len() - 1]
 | 
			
		||||
                    .parse()
 | 
			
		||||
                    .expect("This should be a number!");
 | 
			
		||||
                return Some(new_range);
 | 
			
		||||
            }
 | 
			
		||||
pub struct LineRange {
 | 
			
		||||
    pub lower: usize,
 | 
			
		||||
    pub upper: usize,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
            let line_numbers: Vec<&str> = str_range.split(':').collect();
 | 
			
		||||
            if line_numbers.len() == 2 {
 | 
			
		||||
                new_range.0 = line_numbers[0].parse().expect("Should be a number!");
 | 
			
		||||
                new_range.1 = line_numbers[1].parse().expect("Should be a number!");
 | 
			
		||||
impl LineRange {
 | 
			
		||||
    pub fn from(value: Option<&str>) -> Option<LineRange> {
 | 
			
		||||
        match value {
 | 
			
		||||
            None => None,
 | 
			
		||||
            Some(range_raw) => {
 | 
			
		||||
                return LineRange::parse_range(range_raw).ok();
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            Some(new_range)
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub fn parse_range(range_raw: &str) -> Result<LineRange> {
 | 
			
		||||
        let mut new_range = LineRange{
 | 
			
		||||
            lower: usize::min_value(),
 | 
			
		||||
            upper: usize::max_value(),
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        if range_raw.bytes().nth(0).ok_or("No first byte")? == b':' {
 | 
			
		||||
            new_range.upper = range_raw[1..].parse()?;
 | 
			
		||||
            return Ok(new_range);
 | 
			
		||||
        } else if range_raw.bytes().last().ok_or("No last byte")? == b':' {
 | 
			
		||||
            new_range.lower = range_raw[..range_raw.len() - 1].parse()?;
 | 
			
		||||
            return Ok(new_range);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        let line_numbers: Vec<&str> = range_raw.split(':').collect();
 | 
			
		||||
        if line_numbers.len() == 2 {
 | 
			
		||||
            new_range.lower = line_numbers[0].parse()?;
 | 
			
		||||
            new_range.upper = line_numbers[1].parse()?;
 | 
			
		||||
        }
 | 
			
		||||
        Ok(new_range)                
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[test]
 | 
			
		||||
fn test_parse_line_range_full() {
 | 
			
		||||
    let range = LineRange::from(Some("40:50")).expect("Shouldn't fail on test!");
 | 
			
		||||
    assert_eq!(40, range.lower);
 | 
			
		||||
    assert_eq!(50, range.upper);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[test]
 | 
			
		||||
fn test_parse_line_range_partial_min() {
 | 
			
		||||
    let range = LineRange::from(Some(":50")).expect("Shouldn't fail on test!");
 | 
			
		||||
    assert_eq!(usize::min_value(), range.lower);
 | 
			
		||||
    assert_eq!(50, range.upper);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[test]
 | 
			
		||||
fn test_parse_line_range_partial_max() {
 | 
			
		||||
    let range = LineRange::from(Some("40:")).expect("Shouldn't fail on test!");
 | 
			
		||||
    assert_eq!(40, range.lower);
 | 
			
		||||
    assert_eq!(usize::max_value(), range.upper);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,5 @@
 | 
			
		||||
use ansi_term::Colour::Green;
 | 
			
		||||
use app::Config;
 | 
			
		||||
use app::{Config,LineRange};
 | 
			
		||||
use assets::HighlightingAssets;
 | 
			
		||||
use diff::get_git_diff;
 | 
			
		||||
use errors::*;
 | 
			
		||||
@@ -85,16 +85,35 @@ fn print_file(
 | 
			
		||||
    filename: Option<&str>,
 | 
			
		||||
) -> Result<()> {
 | 
			
		||||
    let stdin = io::stdin(); // TODO: this is not always needed
 | 
			
		||||
    {
 | 
			
		||||
        let reader: Box<BufRead> = match filename {
 | 
			
		||||
            None => Box::new(stdin.lock()),
 | 
			
		||||
            Some(filename) => Box::new(BufReader::new(File::open(filename)?)),
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
    let mut reader: Box<BufRead> = match filename {
 | 
			
		||||
        None => Box::new(stdin.lock()),
 | 
			
		||||
        Some(filename) => Box::new(BufReader::new(File::open(filename)?)),
 | 
			
		||||
    };
 | 
			
		||||
        let highlighter = HighlightLines::new(syntax, theme);
 | 
			
		||||
 | 
			
		||||
    let mut highlighter = HighlightLines::new(syntax, theme);
 | 
			
		||||
        printer.print_header(filename)?;
 | 
			
		||||
 | 
			
		||||
    printer.print_header(filename)?;
 | 
			
		||||
        match printer.config.line_range.as_ref() {
 | 
			
		||||
            Some(range) => {
 | 
			
		||||
                print_file_ranges(printer, reader, highlighter, range)?;
 | 
			
		||||
            },
 | 
			
		||||
            None => {
 | 
			
		||||
                print_file_no_ranges(printer, reader, highlighter)?;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        printer.print_footer()?;
 | 
			
		||||
    }
 | 
			
		||||
    Ok(())
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn print_file_ranges<'a>(
 | 
			
		||||
    printer: &mut Printer,
 | 
			
		||||
    mut reader: Box<BufRead + 'a>,
 | 
			
		||||
    mut highlighter: HighlightLines,
 | 
			
		||||
    ranges: &LineRange
 | 
			
		||||
) -> Result<()>{
 | 
			
		||||
    let mut buffer = Vec::new();
 | 
			
		||||
 | 
			
		||||
    while reader.read_until(b'\n', &mut buffer)? > 0 {
 | 
			
		||||
@@ -102,24 +121,36 @@ fn print_file(
 | 
			
		||||
            let line = String::from_utf8_lossy(&buffer);
 | 
			
		||||
            let regions = highlighter.highlight(line.as_ref());
 | 
			
		||||
 | 
			
		||||
            if printer.config.line_range.is_some() {
 | 
			
		||||
                if printer.line_number + 1 < printer.config.line_range.unwrap().0 {
 | 
			
		||||
                    // skip line
 | 
			
		||||
                    printer.line_number += 1;
 | 
			
		||||
                } else if printer.line_number >= printer.config.line_range.unwrap().1 {
 | 
			
		||||
                    // no more lines in range
 | 
			
		||||
                    break;
 | 
			
		||||
                } else {
 | 
			
		||||
                    printer.print_line(®ions)?;
 | 
			
		||||
                }
 | 
			
		||||
            if printer.line_number + 1 < ranges.lower {
 | 
			
		||||
                // skip line
 | 
			
		||||
                printer.line_number += 1;
 | 
			
		||||
            } else if printer.line_number >= ranges.upper {
 | 
			
		||||
                // no more lines in range
 | 
			
		||||
                break;
 | 
			
		||||
            } else {
 | 
			
		||||
                printer.print_line(®ions)?;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        buffer.clear();
 | 
			
		||||
    }
 | 
			
		||||
    Ok(())
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
    printer.print_footer()?;
 | 
			
		||||
fn print_file_no_ranges<'a>(
 | 
			
		||||
    printer: &mut Printer,
 | 
			
		||||
    mut reader: Box<BufRead + 'a>,
 | 
			
		||||
    mut highlighter: HighlightLines
 | 
			
		||||
) -> Result<()>{
 | 
			
		||||
    let mut buffer = Vec::new();
 | 
			
		||||
 | 
			
		||||
    while reader.read_until(b'\n', &mut buffer)? > 0 {
 | 
			
		||||
        {
 | 
			
		||||
            let line = String::from_utf8_lossy(&buffer);
 | 
			
		||||
            let regions = highlighter.highlight(line.as_ref());
 | 
			
		||||
            printer.print_line(®ions)?;
 | 
			
		||||
        }
 | 
			
		||||
        buffer.clear();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    Ok(())
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -41,6 +41,7 @@ mod errors {
 | 
			
		||||
            Clap(::clap::Error);
 | 
			
		||||
            Io(::std::io::Error);
 | 
			
		||||
            SyntectError(::syntect::LoadingError);
 | 
			
		||||
            ParseIntError(::std::num::ParseIntError);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user