Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ ignore = "0.4.1"
num_cpus = "1.8.0"
regex = "1.5.5"
rprompt = "1.0.3"
similar = "2.7.0"

[dev-dependencies]
assert_cmd = "2"
Expand Down
23 changes: 8 additions & 15 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,7 @@ mod terminal;

use rprompt::prompt_reply_stderr;
use rprompt::prompt_reply_stdout;

use crate::terminal::Color;
use crate::terminal::print_bolded_diff_to_terminal;

type Result<T> = ::std::result::Result<T, Error>;

Expand Down Expand Up @@ -524,19 +523,13 @@ impl Fastmod {
}

fn print_diff<'a>(&mut self, diffs: &[DiffResult<&'a str>]) {
for diff in diffs {
match diff {
DiffResult::Left(l) => {
terminal::fg(Color::Red);
println!("- {}", l);
terminal::reset();
}
DiffResult::Both(l, _) => println!(" {}", l),
DiffResult::Right(r) => {
terminal::fg(Color::Green);
println!("+ {}", r);
terminal::reset();
}
for window in diffs.windows(2) {
match window {
[DiffResult::Left(l), DiffResult::Right(r)] => {
let _ = print_bolded_diff_to_terminal(l, r);
},
[DiffResult::Both(l, _), _] => println!(" {}", l),
_ => (),
}
}
}
Expand Down
88 changes: 62 additions & 26 deletions src/terminal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,43 +14,79 @@
* limitations under the License.
*/

use std::io;
use std::io::stdout;

use crossterm::ExecutableCommand;
use anyhow::Result;
use crossterm::execute;
use crossterm::style::SetForegroundColor;
use crossterm::terminal::Clear;
use crossterm::terminal::ClearType;
use crossterm::style::SetAttribute;
use crossterm::style::ResetColor;
use crossterm::style::Color;
use crossterm::style::Attribute;
use crossterm::style::Print;
use crossterm::terminal::{Clear, ClearType};
use similar::{ChangeTag, TextDiff};

pub enum Color {
Red,
Green,
}

impl Color {
pub fn to_crossterm_color(self) -> crossterm::style::Color {
match self {
Color::Red => crossterm::style::Color::DarkRed,
Color::Green => crossterm::style::Color::DarkGreen,
}
}
}

pub fn clear() {
if io::stdout().execute(Clear(ClearType::All)).is_err() {
if execute!(stdout(), Clear(ClearType::All)).is_err() {
print!("{}", "\n".repeat(8));
}
}

pub fn fg(color: Color) {
let _ = io::stdout().execute(SetForegroundColor(color.to_crossterm_color()));
}

pub fn reset() {
let _ = io::stdout().execute(SetForegroundColor(crossterm::style::Color::Reset));
}

pub fn size() -> Option<(usize, usize)> {
crossterm::terminal::size()
.ok()
.map(|(w, h)| (w as usize, h as usize))
}

pub fn print_bolded_diff_to_terminal(before: &str, after: &str) -> Result<()> {
let mut stdout = stdout();
let diff = TextDiff::from_chars(before, after);

execute!(stdout, SetForegroundColor(Color::DarkRed), Print("- "))?;
for op in diff.ops() {
for change in diff.iter_changes(op) {
match change.tag() {
ChangeTag::Equal => {
execute!(stdout, Print(change.value()))?;
}
ChangeTag::Delete => {
execute!(
stdout,
SetAttribute(Attribute::Bold),
Print(change.value()),
SetAttribute(Attribute::Reset),
SetForegroundColor(Color::DarkRed),
)?;
}
ChangeTag::Insert => { /* Only show deleted chars for "before" line */ }
}
}
}
execute!(stdout, ResetColor, Print("\n"))?;

execute!(stdout, SetForegroundColor(Color::DarkGreen), Print("+ "))?;
for op in diff.ops() {
for change in diff.iter_changes(op) {
match change.tag() {
ChangeTag::Equal => {
execute!(stdout, Print(change.value()))?;
}
ChangeTag::Insert => {
execute!(
stdout,
SetAttribute(Attribute::Bold),
Print(change.value()),
SetAttribute(Attribute::Reset),
SetForegroundColor(Color::DarkGreen),
)?;
}
ChangeTag::Delete => { /* Only show added chars for "after" line */ }
}
}
}
execute!(stdout, ResetColor, Print("\n"))?;

Ok(())
}