Add a --width CLI argument

html_output
Wilfred Hughes 2022-01-29 12:13:21 +07:00
parent d37a233b39
commit c0ba12bf68
3 changed files with 51 additions and 24 deletions

@ -15,6 +15,11 @@ visible.
Improved colours on terminals with light coloured backgrounds. Improved colours on terminals with light coloured backgrounds.
### Command Line Interface
Added a `--width` option which allows overriding `DFT_WIDTH`, and is
more discoverable.
## 0.17 (released 25 January 2022) ## 0.17 (released 25 January 2022)
### Diffing ### Diffing

@ -64,6 +64,12 @@ use crate::{
extern crate pretty_env_logger; extern crate pretty_env_logger;
/// Choose the display width: try to autodetect, or fall back to a
/// sensible default.
fn detect_display_width() -> usize {
term_size::dimensions().map(|(w, _)| w).unwrap_or(80)
}
fn configure_color() { fn configure_color() {
if atty::is(Stream::Stdout) || env::var("GIT_PAGER_IN_USE").is_ok() { if atty::is(Stream::Stdout) || env::var("GIT_PAGER_IN_USE").is_ok() {
// Always enable colour if stdout is a TTY or if the git pager is active. // Always enable colour if stdout is a TTY or if the git pager is active.
@ -76,6 +82,7 @@ fn configure_color() {
enum Mode { enum Mode {
Diff { Diff {
display_width: usize,
display_path: String, display_path: String,
lhs_path: String, lhs_path: String,
rhs_path: String, rhs_path: String,
@ -111,6 +118,15 @@ fn app() -> clap::App<'static> {
"Parse a single file with tree-sitter and display the tree-sitter parse tree.", "Parse a single file with tree-sitter and display the tree-sitter parse tree.",
), ),
) )
.arg(
Arg::new("width")
.long("width")
.takes_value(true)
.value_name("COLUMNS")
.help("Use this many columns when calculating line wrapping. Overrides $DFT_WIDTH if present. If not specified, difftastic will detect the terminal width.")
.validator(|s| s.parse::<usize>())
.required(false),
)
.arg( .arg(
Arg::new("paths") Arg::new("paths")
.multiple_values(true) .multiple_values(true)
@ -171,7 +187,22 @@ fn parse_args() -> Mode {
), ),
}; };
let display_width = if let Some(arg_width) = matches.value_of("width") {
let width = arg_width
.parse::<usize>()
.expect("Already validated by clap");
width
} else {
let env_width = if let Ok(env_width) = env::var("DFT_WIDTH") {
env_width.parse::<usize>().ok()
} else {
None
};
env_width.unwrap_or_else(detect_display_width)
};
Mode::Diff { Mode::Diff {
display_width,
display_path, display_path,
lhs_path, lhs_path,
rhs_path, rhs_path,
@ -233,20 +264,22 @@ fn main() {
} }
} }
Mode::Diff { Mode::Diff {
display_width,
display_path, display_path,
lhs_path, lhs_path,
rhs_path, rhs_path,
..
} => { } => {
let lhs_path = Path::new(&lhs_path); let lhs_path = Path::new(&lhs_path);
let rhs_path = Path::new(&rhs_path); let rhs_path = Path::new(&rhs_path);
if lhs_path.is_dir() && rhs_path.is_dir() { if lhs_path.is_dir() && rhs_path.is_dir() {
for diff_result in diff_directories(lhs_path, rhs_path) { for diff_result in diff_directories(lhs_path, rhs_path) {
print_diff_result(&diff_result); print_diff_result(display_width, &diff_result);
} }
} else { } else {
let diff_result = diff_file(&display_path, lhs_path, rhs_path); let diff_result = diff_file(&display_path, lhs_path, rhs_path);
print_diff_result(&diff_result); print_diff_result(display_width, &diff_result);
} }
} }
}; };
@ -368,7 +401,7 @@ fn diff_directories(lhs_dir: &Path, rhs_dir: &Path) -> Vec<DiffResult> {
res res
} }
fn print_diff_result(summary: &DiffResult) { fn print_diff_result(display_width: usize, summary: &DiffResult) {
if summary.binary { if summary.binary {
println!("{}", style::header(&summary.path, 1, 1, "binary")); println!("{}", style::header(&summary.path, 1, 1, "binary"));
return; return;
@ -415,6 +448,7 @@ fn print_diff_result(summary: &DiffResult) {
"{}", "{}",
side_by_side::display_hunks( side_by_side::display_hunks(
&hunks, &hunks,
display_width,
&summary.path, &summary.path,
&lang_name, &lang_name,
&summary.lhs_src, &summary.lhs_src,
@ -444,4 +478,10 @@ mod tests {
fn test_app() { fn test_app() {
app().debug_assert(); app().debug_assert();
} }
#[test]
fn test_detect_display_width() {
// Basic smoke test.
assert!(detect_display_width() > 10);
}
} }

@ -4,7 +4,6 @@ use colored::{Color, Colorize};
use std::{ use std::{
cmp::max, cmp::max,
collections::{HashMap, HashSet}, collections::{HashMap, HashSet},
env,
}; };
use crate::{ use crate::{
@ -18,19 +17,6 @@ use crate::{
const SPACER: &str = " "; const SPACER: &str = " ";
/// Choose the display width: honour environment variables, then try
/// to autodetect, or fall back to a sensible default.
fn display_width() -> usize {
// TODO: document in manual.
if let Ok(s) = env::var("DFT_WIDTH") {
if let Ok(i) = s.parse::<usize>() {
return i;
}
}
term_size::dimensions().map(|(w, _)| w).unwrap_or(80)
}
/// Split `s` by newlines. Always returns a non-empty vec. /// Split `s` by newlines. Always returns a non-empty vec.
/// ///
/// This differs from `str::lines`, which considers `""` to be zero /// This differs from `str::lines`, which considers `""` to be zero
@ -241,6 +227,7 @@ fn highlight_as_novel(
pub fn display_hunks( pub fn display_hunks(
hunks: &[Hunk], hunks: &[Hunk],
display_width: usize,
display_path: &str, display_path: &str,
lang_name: &str, lang_name: &str,
lhs_src: &str, lhs_src: &str,
@ -282,7 +269,7 @@ pub fn display_hunks(
let no_rhs_changes = hunk.lines.iter().all(|(_, r)| r.is_none()); let no_rhs_changes = hunk.lines.iter().all(|(_, r)| r.is_none());
let same_lines = aligned_lines.iter().all(|(l, r)| l == r); let same_lines = aligned_lines.iter().all(|(l, r)| l == r);
let widths = Widths::new(display_width(), &aligned_lines, &lhs_lines, &rhs_lines); let widths = Widths::new(display_width, &aligned_lines, &lhs_lines, &rhs_lines);
for (lhs_line_num, rhs_line_num) in aligned_lines { for (lhs_line_num, rhs_line_num) in aligned_lines {
let lhs_line_novel = highlight_as_novel( let lhs_line_novel = highlight_as_novel(
lhs_line_num, lhs_line_num,
@ -440,12 +427,6 @@ mod tests {
assert_eq!(widths.rhs_line_nums, 3); assert_eq!(widths.rhs_line_nums, 3);
} }
#[test]
fn test_display_width() {
// Basic smoke test.
assert!(display_width() > 10);
}
#[test] #[test]
fn test_display_single_column() { fn test_display_single_column() {
// Basic smoke test. // Basic smoke test.
@ -511,6 +492,7 @@ mod tests {
// Simple smoke test. // Simple smoke test.
display_hunks( display_hunks(
&hunks, &hunks,
80,
"foo.el", "foo.el",
"Emacs Lisp", "Emacs Lisp",
"foo", "foo",