2018-08-23 22:37:27 +02:00
|
|
|
use std::fs::File;
|
|
|
|
use std::io::{self, BufRead, BufReader, Write};
|
|
|
|
|
2018-08-28 20:12:45 +02:00
|
|
|
use app::{Config, InputFile};
|
2018-08-23 22:37:27 +02:00
|
|
|
use assets::HighlightingAssets;
|
|
|
|
use errors::*;
|
|
|
|
use line_range::LineRange;
|
|
|
|
use output::OutputType;
|
2018-08-23 23:13:24 +02:00
|
|
|
use printer::{InteractivePrinter, Printer, SimplePrinter};
|
2018-08-23 22:37:27 +02:00
|
|
|
|
2018-08-28 22:16:42 +02:00
|
|
|
const THEME_PREVIEW_FILE: &[u8] = include_bytes!("../assets/theme_preview.rs");
|
|
|
|
|
2018-08-23 22:37:27 +02:00
|
|
|
pub struct Controller<'a> {
|
|
|
|
config: &'a Config<'a>,
|
|
|
|
assets: &'a HighlightingAssets,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'b> Controller<'b> {
|
|
|
|
pub fn new<'a>(config: &'a Config, assets: &'a HighlightingAssets) -> Controller<'a> {
|
|
|
|
Controller { config, assets }
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn run(&self) -> Result<bool> {
|
|
|
|
let mut output_type = OutputType::from_mode(self.config.paging_mode);
|
|
|
|
let writer = output_type.handle()?;
|
|
|
|
let mut no_errors: bool = true;
|
|
|
|
|
2018-08-23 23:13:24 +02:00
|
|
|
for filename in &self.config.files {
|
|
|
|
let result = if self.config.loop_through {
|
|
|
|
let mut printer = SimplePrinter::new();
|
|
|
|
self.print_file(&mut printer, writer, *filename)
|
|
|
|
} else {
|
|
|
|
let mut printer = InteractivePrinter::new(&self.config, &self.assets, *filename);
|
|
|
|
self.print_file(&mut printer, writer, *filename)
|
|
|
|
};
|
2018-08-23 22:37:27 +02:00
|
|
|
|
|
|
|
if let Err(error) = result {
|
|
|
|
handle_error(&error);
|
|
|
|
no_errors = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Ok(no_errors)
|
|
|
|
}
|
|
|
|
|
2018-08-28 20:12:45 +02:00
|
|
|
fn print_file<'a, P: Printer>(
|
2018-08-23 23:13:24 +02:00
|
|
|
&self,
|
|
|
|
printer: &mut P,
|
|
|
|
writer: &mut Write,
|
2018-08-28 20:12:45 +02:00
|
|
|
filename: InputFile<'a>,
|
2018-08-23 23:13:24 +02:00
|
|
|
) -> Result<()> {
|
2018-08-23 22:37:27 +02:00
|
|
|
let stdin = io::stdin();
|
|
|
|
{
|
|
|
|
let reader: Box<BufRead> = match filename {
|
2018-08-28 20:12:45 +02:00
|
|
|
InputFile::StdIn => Box::new(stdin.lock()),
|
|
|
|
InputFile::Ordinary(filename) => Box::new(BufReader::new(File::open(filename)?)),
|
2018-08-28 22:16:42 +02:00
|
|
|
InputFile::ThemePreviewFile => Box::new(THEME_PREVIEW_FILE),
|
2018-08-23 22:37:27 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
printer.print_header(writer, filename)?;
|
2018-08-23 23:13:24 +02:00
|
|
|
self.print_file_ranges(printer, writer, reader, &self.config.line_range)?;
|
2018-08-23 22:37:27 +02:00
|
|
|
printer.print_footer(writer)?;
|
|
|
|
}
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
fn print_file_ranges<'a, P: Printer>(
|
|
|
|
&self,
|
|
|
|
printer: &mut P,
|
|
|
|
writer: &mut Write,
|
|
|
|
mut reader: Box<BufRead + 'a>,
|
|
|
|
line_ranges: &Option<LineRange>,
|
|
|
|
) -> Result<()> {
|
2018-08-23 23:13:24 +02:00
|
|
|
let mut line_buffer = Vec::new();
|
2018-08-23 22:37:27 +02:00
|
|
|
|
|
|
|
let mut line_number: usize = 1;
|
|
|
|
|
2018-08-23 23:13:24 +02:00
|
|
|
while reader.read_until(b'\n', &mut line_buffer)? > 0 {
|
2018-08-23 22:37:27 +02:00
|
|
|
{
|
|
|
|
match line_ranges {
|
|
|
|
&Some(ref range) => {
|
|
|
|
if line_number < range.lower {
|
2018-08-23 23:35:57 +02:00
|
|
|
// Call the printer in case we need to call the syntax highlighter
|
|
|
|
// for this line. However, set `out_of_range` to `true`.
|
|
|
|
printer.print_line(true, writer, line_number, &line_buffer)?;
|
2018-08-23 22:37:27 +02:00
|
|
|
} else if line_number > range.upper {
|
2018-08-23 23:35:57 +02:00
|
|
|
// no more lines in range, exit early
|
2018-08-23 22:37:27 +02:00
|
|
|
break;
|
|
|
|
} else {
|
2018-08-23 23:35:57 +02:00
|
|
|
printer.print_line(false, writer, line_number, &line_buffer)?;
|
2018-08-23 22:37:27 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
&None => {
|
2018-08-23 23:35:57 +02:00
|
|
|
printer.print_line(false, writer, line_number, &line_buffer)?;
|
2018-08-23 22:37:27 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
line_number += 1;
|
|
|
|
}
|
2018-08-23 23:13:24 +02:00
|
|
|
line_buffer.clear();
|
2018-08-23 22:37:27 +02:00
|
|
|
}
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
}
|