Skip to content

Commit

Permalink
Merge pull request #102 from eth-p/master
Browse files Browse the repository at this point in the history
Added text wrapping. (Fixes #54)
  • Loading branch information
sharkdp authored May 16, 2018
2 parents 54b33c8 + d569693 commit 2eee685
Show file tree
Hide file tree
Showing 12 changed files with 493 additions and 243 deletions.
21 changes: 20 additions & 1 deletion src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use console::Term;
use errors::*;
use std::collections::HashSet;
use std::env;
use style::{OutputComponent, OutputComponents};
use style::{OutputComponent, OutputComponents, OutputWrap};

#[cfg(windows)]
use ansi_term;
Expand Down Expand Up @@ -86,6 +86,14 @@ impl App {
.default_value("auto")
.help("When to use the pager"),
)
.arg(
Arg::with_name("wrap")
.long("wrap")
.takes_value(true)
.possible_values(&["character", "never"])
.default_value("character")
.help("When to wrap text"),
)
.arg(
Arg::with_name("list-languages")
.long("list-languages")
Expand Down Expand Up @@ -141,6 +149,16 @@ impl App {
true_color: is_truecolor_terminal(),
output_components: self.output_components()?,
language: self.matches.value_of("language"),
output_wrap: if !self.interactive_output {
// We don't have the tty width when piping to another program.
// There's no point in wrapping when this is the case.
OutputWrap::None
} else {
match self.matches.value_of("wrap") {
Some("character") => OutputWrap::Character,
Some("never") | _ => OutputWrap::None,
}
},
colored_output: match self.matches.value_of("color") {
Some("always") => true,
Some("never") => false,
Expand Down Expand Up @@ -197,6 +215,7 @@ impl App {

pub struct Config<'a> {
pub true_color: bool,
pub output_wrap: OutputWrap,
pub output_components: OutputComponents,
pub language: Option<&'a str>,
pub colored_output: bool,
Expand Down
154 changes: 154 additions & 0 deletions src/decorations.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
use ansi_term::Style;
use diff::LineChange;
use printer::Printer;
use Colors;

#[derive(Clone)]
pub struct DecorationText {
pub width: usize,
pub text: String,
}

pub trait Decoration {
fn generate(&self, line_number: usize, continuation: bool, printer: &Printer)
-> DecorationText;
fn width(&self) -> usize;
}

// Line number decoration.
pub struct LineNumberDecoration {
color: Style,
cached_wrap: DecorationText,
cached_wrap_invalid_at: usize,
}

impl LineNumberDecoration {
pub fn new(colors: &Colors) -> Self {
LineNumberDecoration {
color: colors.line_number,
cached_wrap_invalid_at: 10000,
cached_wrap: DecorationText {
text: colors.line_number.paint(" ".repeat(4)).to_string(),
width: 4,
},
}
}
}

impl Decoration for LineNumberDecoration {
fn generate(
&self,
line_number: usize,
continuation: bool,
_printer: &Printer,
) -> DecorationText {
if continuation {
if line_number > self.cached_wrap_invalid_at {
let new_width = self.cached_wrap.width + 1;
return DecorationText {
text: self.color.paint(" ".repeat(new_width)).to_string(),
width: new_width,
};
}

self.cached_wrap.clone()
} else {
let plain: String = format!("{:4}", line_number);
DecorationText {
width: plain.len(),
text: self.color.paint(plain).to_string(),
}
}
}

fn width(&self) -> usize {
4
}
}

// Line changes decoration.
pub struct LineChangesDecoration {
cached_none: DecorationText,
cached_added: DecorationText,
cached_removed_above: DecorationText,
cached_removed_below: DecorationText,
cached_modified: DecorationText,
}

impl LineChangesDecoration {
#[inline]
fn generate_cached(style: Style, text: &str) -> DecorationText {
DecorationText {
text: style.paint(text).to_string(),
width: text.chars().count(),
}
}

pub fn new(colors: &Colors) -> Self {
LineChangesDecoration {
cached_none: Self::generate_cached(Style::default(), " "),
cached_added: Self::generate_cached(colors.git_added, "+"),
cached_removed_above: Self::generate_cached(colors.git_removed, "‾"),
cached_removed_below: Self::generate_cached(colors.git_removed, "_"),
cached_modified: Self::generate_cached(colors.git_modified, "~"),
}
}
}

impl Decoration for LineChangesDecoration {
fn generate(
&self,
line_number: usize,
continuation: bool,
printer: &Printer,
) -> DecorationText {
if !continuation {
if let Some(ref changes) = printer.line_changes {
return match changes.get(&(line_number as u32)) {
Some(&LineChange::Added) => self.cached_added.clone(),
Some(&LineChange::RemovedAbove) => self.cached_removed_above.clone(),
Some(&LineChange::RemovedBelow) => self.cached_removed_below.clone(),
Some(&LineChange::Modified) => self.cached_modified.clone(),
_ => self.cached_none.clone(),
};
}
}

self.cached_none.clone()
}

fn width(&self) -> usize {
self.cached_none.width
}
}

// Grid border decoration.
pub struct GridBorderDecoration {
cached: DecorationText,
}

impl GridBorderDecoration {
pub fn new(colors: &Colors) -> Self {
GridBorderDecoration {
cached: DecorationText {
text: colors.grid.paint("│").to_string(),
width: 1,
},
}
}
}

impl Decoration for GridBorderDecoration {
fn generate(
&self,
_line_number: usize,
_continuation: bool,
_printer: &Printer,
) -> DecorationText {
self.cached.clone()
}

fn width(&self) -> usize {
self.cached.width
}
}
1 change: 1 addition & 0 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ extern crate syntect;

mod app;
mod assets;
mod decorations;
mod diff;
mod printer;
mod style;
Expand Down
Loading

0 comments on commit 2eee685

Please sign in to comment.