Use pub(crate) everywhere for visibility

This isn't strictly necessary since difftastic is a binary-only
crate. However, it improves compiler warnings (see next commit) and
potentially helps future changes to make difftastic available as a
library.
pull/593/head^2
Wilfred Hughes 2023-11-18 16:25:08 +07:00
parent 60d0f61cbd
commit f2b3b34bec
29 changed files with 198 additions and 198 deletions

@ -12,22 +12,22 @@ enum ConflictState {
Right,
}
pub const START_LHS_MARKER: &str = "<<<<<<<";
pub(crate) const START_LHS_MARKER: &str = "<<<<<<<";
const START_BASE_MARKER: &str = "|||||||";
const START_RHS_MARKER: &str = "=======";
const END_RHS_MARKER: &str = ">>>>>>>";
pub struct ConflictFiles {
pub lhs_name: Option<String>,
pub lhs_content: String,
pub rhs_name: Option<String>,
pub rhs_content: String,
pub num_conflicts: usize,
pub(crate) struct ConflictFiles {
pub(crate) lhs_name: Option<String>,
pub(crate) lhs_content: String,
pub(crate) rhs_name: Option<String>,
pub(crate) rhs_content: String,
pub(crate) num_conflicts: usize,
}
/// Convert a string with conflict markers into the two conflicting
/// file contents.
pub fn apply_conflict_markers(s: &str) -> Result<ConflictFiles, String> {
pub(crate) fn apply_conflict_markers(s: &str) -> Result<ConflictFiles, String> {
let mut lhs_name: Option<String> = None;
let mut rhs_name: Option<String> = None;

@ -1,5 +1,5 @@
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum Side {
pub(crate) enum Side {
/// The left-hand side, or the 'before' file. Often abbreviated to
/// LHS.
Left,

@ -6,7 +6,7 @@ use crate::{
};
#[derive(PartialEq, Eq, Clone, Copy)]
pub enum ChangeKind<'a> {
pub(crate) enum ChangeKind<'a> {
Unchanged(&'a Syntax<'a>),
ReplacedComment(&'a Syntax<'a>, &'a Syntax<'a>),
ReplacedString(&'a Syntax<'a>, &'a Syntax<'a>),
@ -14,21 +14,21 @@ pub enum ChangeKind<'a> {
}
#[derive(Debug, Default)]
pub struct ChangeMap<'a> {
pub(crate) struct ChangeMap<'a> {
changes: DftHashMap<SyntaxId, ChangeKind<'a>>,
}
impl<'a> ChangeMap<'a> {
pub fn insert(&mut self, node: &'a Syntax<'a>, ck: ChangeKind<'a>) {
pub(crate) fn insert(&mut self, node: &'a Syntax<'a>, ck: ChangeKind<'a>) {
self.changes.insert(node.id(), ck);
}
pub fn get(&self, node: &Syntax<'a>) -> Option<ChangeKind<'a>> {
pub(crate) fn get(&self, node: &Syntax<'a>) -> Option<ChangeKind<'a>> {
self.changes.get(&node.id()).copied()
}
}
pub fn insert_deep_unchanged<'a>(
pub(crate) fn insert_deep_unchanged<'a>(
node: &'a Syntax<'a>,
opposite_node: &'a Syntax<'a>,
change_map: &mut ChangeMap<'a>,
@ -55,7 +55,7 @@ pub fn insert_deep_unchanged<'a>(
}
}
pub fn insert_deep_novel<'a>(node: &'a Syntax<'a>, change_map: &mut ChangeMap<'a>) {
pub(crate) fn insert_deep_novel<'a>(node: &'a Syntax<'a>, change_map: &mut ChangeMap<'a>) {
change_map.insert(node, ChangeKind::Novel);
if let Syntax::List { children, .. } = node {

@ -15,7 +15,7 @@ use crate::{
};
#[derive(Debug)]
pub struct ExceededGraphLimit {}
pub(crate) struct ExceededGraphLimit {}
/// Return the shortest route from `start` to the end vertex.
fn shortest_vertex_path<'s, 'b>(
@ -186,7 +186,7 @@ fn tree_count(root: Option<&Syntax>) -> u32 {
count
}
pub fn mark_syntax<'a>(
pub(crate) fn mark_syntax<'a>(
lhs_syntax: Option<&'a Syntax<'a>>,
rhs_syntax: Option<&'a Syntax<'a>>,
change_map: &mut ChangeMap<'a>,

@ -50,13 +50,13 @@ use crate::{
/// ^ ^
/// ```
#[derive(Debug, Clone)]
pub struct Vertex<'s, 'b> {
pub neighbours: RefCell<Option<Vec<(Edge, &'b Vertex<'s, 'b>)>>>,
pub predecessor: Cell<Option<(u32, &'b Vertex<'s, 'b>)>>,
pub(crate) struct Vertex<'s, 'b> {
pub(crate) neighbours: RefCell<Option<Vec<(Edge, &'b Vertex<'s, 'b>)>>>,
pub(crate) predecessor: Cell<Option<(u32, &'b Vertex<'s, 'b>)>>,
// TODO: experiment with storing SyntaxId only, and have a HashMap
// from SyntaxId to &Syntax.
pub lhs_syntax: Option<&'s Syntax<'s>>,
pub rhs_syntax: Option<&'s Syntax<'s>>,
pub(crate) lhs_syntax: Option<&'s Syntax<'s>>,
pub(crate) rhs_syntax: Option<&'s Syntax<'s>>,
parents: Stack<EnteredDelimiter<'s>>,
lhs_parent_id: Option<SyntaxId>,
rhs_parent_id: Option<SyntaxId>,
@ -249,11 +249,11 @@ fn push_rhs_delimiter<'s>(
}
impl<'s, 'b> Vertex<'s, 'b> {
pub fn is_end(&self) -> bool {
pub(crate) fn is_end(&self) -> bool {
self.lhs_syntax.is_none() && self.rhs_syntax.is_none() && self.parents.is_empty()
}
pub fn new(lhs_syntax: Option<&'s Syntax<'s>>, rhs_syntax: Option<&'s Syntax<'s>>) -> Self {
pub(crate) fn new(lhs_syntax: Option<&'s Syntax<'s>>, rhs_syntax: Option<&'s Syntax<'s>>) -> Self {
let parents = Stack::new();
Vertex {
neighbours: RefCell::new(None),
@ -275,7 +275,7 @@ impl<'s, 'b> Vertex<'s, 'b> {
///
/// See [`set_neighbours`] for all the edges available for a given `Vertex`.
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum Edge {
pub(crate) enum Edge {
UnchangedNode {
depth_difference: u32,
/// Is this node just punctuation? We penalise this case,
@ -301,7 +301,7 @@ pub enum Edge {
}
impl Edge {
pub fn cost(self) -> u32 {
pub(crate) fn cost(self) -> u32 {
match self {
// Matching nodes is always best.
UnchangedNode {
@ -478,7 +478,7 @@ fn pop_all_parents<'s>(
/// Compute the neighbours of `v` if we haven't previously done so,
/// and write them to the .neighbours cell inside `v`.
pub fn set_neighbours<'s, 'b>(
pub(crate) fn set_neighbours<'s, 'b>(
v: &Vertex<'s, 'b>,
alloc: &'b Bump,
seen: &mut DftHashMap<&Vertex<'s, 'b>, Vec<&'b Vertex<'s, 'b>>>,
@ -773,7 +773,7 @@ pub fn set_neighbours<'s, 'b>(
v.neighbours.replace(Some(res));
}
pub fn populate_change_map<'s, 'b>(
pub(crate) fn populate_change_map<'s, 'b>(
route: &[(Edge, &'b Vertex<'s, 'b>)],
change_map: &mut ChangeMap<'s>,
) {

@ -1,7 +1,7 @@
pub mod changes;
pub mod dijkstra;
pub(crate) mod changes;
pub(crate) mod dijkstra;
mod graph;
pub mod myers_diff;
pub mod sliders;
pub(crate) mod myers_diff;
pub(crate) mod sliders;
mod stack;
pub mod unchanged;
pub(crate) mod unchanged;

@ -7,7 +7,7 @@ use rustc_hash::FxHashSet;
use crate::hash::DftHashMap;
#[derive(Debug, PartialEq)]
pub enum DiffResult<T> {
pub(crate) enum DiffResult<T> {
Left(T),
Both(T, T),
Right(T),
@ -15,7 +15,7 @@ pub enum DiffResult<T> {
/// Compute a linear diff between `lhs` and `rhs`. This is the
/// traditional Myer's diff algorithm.
pub fn slice<'a, T: PartialEq + Clone>(lhs: &'a [T], rhs: &'a [T]) -> Vec<DiffResult<&'a T>> {
pub(crate) fn slice<'a, T: PartialEq + Clone>(lhs: &'a [T], rhs: &'a [T]) -> Vec<DiffResult<&'a T>> {
wu_diff::diff(lhs, rhs)
.into_iter()
.map(|result| match result {
@ -35,7 +35,7 @@ pub fn slice<'a, T: PartialEq + Clone>(lhs: &'a [T], rhs: &'a [T]) -> Vec<DiffRe
///
/// This is faster when equality checks on `T` are expensive, such as
/// large strings.
pub fn slice_by_hash<'a, T: Eq + Hash>(lhs: &'a [T], rhs: &'a [T]) -> Vec<DiffResult<&'a T>> {
pub(crate) fn slice_by_hash<'a, T: Eq + Hash>(lhs: &'a [T], rhs: &'a [T]) -> Vec<DiffResult<&'a T>> {
// Compute a unique numeric value for each item, use that for
// diffing, then return diff results in terms of the original
// type.
@ -95,7 +95,7 @@ pub fn slice_by_hash<'a, T: Eq + Hash>(lhs: &'a [T], rhs: &'a [T]) -> Vec<DiffRe
///
/// (This heuristic is used in traditional diff tools too, such as GNU
/// diff.)
pub fn slice_unique_by_hash<'a, T: Eq + Clone + Hash>(
pub(crate) fn slice_unique_by_hash<'a, T: Eq + Clone + Hash>(
lhs: &'a [T],
rhs: &'a [T],
) -> Vec<DiffResult<&'a T>> {

@ -37,7 +37,7 @@ use crate::{
parse::syntax::Syntax::{self, *},
};
pub fn fix_all_sliders<'a>(
pub(crate) fn fix_all_sliders<'a>(
language: guess_language::Language,
nodes: &[&'a Syntax<'a>],
change_map: &mut ChangeMap<'a>,

@ -13,7 +13,7 @@ const MOSTLY_UNCHANGED_MIN_COMMON_CHILDREN: usize = 4;
/// Set [`ChangeKind`] on nodes that have exactly the same structure
/// on both sides, and return a vec of pairs that need proper diffing.
pub fn mark_unchanged<'a>(
pub(crate) fn mark_unchanged<'a>(
lhs_nodes: &[&'a Syntax<'a>],
rhs_nodes: &[&'a Syntax<'a>],
change_map: &mut ChangeMap<'a>,

@ -11,7 +11,7 @@ use crate::{
parse::syntax::{zip_repeat_shorter, MatchKind, MatchedPos},
};
pub fn all_matched_lines_filled(
pub(crate) fn all_matched_lines_filled(
lhs_mps: &[MatchedPos],
rhs_mps: &[MatchedPos],
lhs_lines: &[&str],
@ -327,7 +327,7 @@ fn match_preceding_blanks(
res
}
pub fn opposite_positions(mps: &[MatchedPos]) -> DftHashMap<LineNumber, HashSet<LineNumber>> {
pub(crate) fn opposite_positions(mps: &[MatchedPos]) -> DftHashMap<LineNumber, HashSet<LineNumber>> {
let mut res: DftHashMap<LineNumber, HashSet<LineNumber>> = DftHashMap::default();
for mp in mps {
@ -452,12 +452,12 @@ fn pad_after(ln: LineNumber, max_line: LineNumber, num_context_lines: usize) ->
res
}
pub fn flip_tuple<Tx: Copy, Ty: Copy>(pair: (Tx, Ty)) -> (Ty, Tx) {
pub(crate) fn flip_tuple<Tx: Copy, Ty: Copy>(pair: (Tx, Ty)) -> (Ty, Tx) {
let (x, y) = pair;
(y, x)
}
pub fn flip_tuples<Tx: Copy, Ty: Copy>(items: &[(Tx, Ty)]) -> Vec<(Ty, Tx)> {
pub(crate) fn flip_tuples<Tx: Copy, Ty: Copy>(items: &[(Tx, Ty)]) -> Vec<(Ty, Tx)> {
items.iter().copied().map(flip_tuple).collect()
}
@ -513,7 +513,7 @@ fn after_with_opposites(
res
}
pub fn calculate_before_context(
pub(crate) fn calculate_before_context(
lines: &[(Option<LineNumber>, Option<LineNumber>)],
opposite_to_lhs: &DftHashMap<LineNumber, HashSet<LineNumber>>,
opposite_to_rhs: &DftHashMap<LineNumber, HashSet<LineNumber>>,
@ -535,7 +535,7 @@ pub fn calculate_before_context(
}
}
pub fn calculate_after_context(
pub(crate) fn calculate_after_context(
lines: &[(Option<LineNumber>, Option<LineNumber>)],
opposite_to_lhs: &DftHashMap<LineNumber, HashSet<LineNumber>>,
opposite_to_rhs: &DftHashMap<LineNumber, HashSet<LineNumber>>,
@ -585,7 +585,7 @@ pub fn calculate_after_context(
}
}
pub fn add_context(
pub(crate) fn add_context(
lines: &[(Option<LineNumber>, Option<LineNumber>)],
opposite_to_lhs: &DftHashMap<LineNumber, HashSet<LineNumber>>,
opposite_to_rhs: &DftHashMap<LineNumber, HashSet<LineNumber>>,

@ -20,18 +20,18 @@ use crate::{
/// A hunk represents a series of modified lines that are displayed
/// together.
#[derive(Debug, Clone)]
pub struct Hunk {
pub(crate) struct Hunk {
/// The LHS line numbers that contain novel content.
pub novel_lhs: HashSet<LineNumber>,
pub(crate) novel_lhs: HashSet<LineNumber>,
/// The RHS line numbers that contain novel content.
pub novel_rhs: HashSet<LineNumber>,
pub(crate) novel_rhs: HashSet<LineNumber>,
/// Line pairs that contain modified lines. This does not include
/// padding, so at least one of the two lines has novel content.
pub lines: Vec<(Option<LineNumber>, Option<LineNumber>)>,
pub(crate) lines: Vec<(Option<LineNumber>, Option<LineNumber>)>,
}
impl Hunk {
pub fn merge(self, other: &Self) -> Self {
pub(crate) fn merge(self, other: &Self) -> Self {
let mut lines = self.lines;
lines.extend(other.lines.iter());
@ -130,7 +130,7 @@ fn extract_lines(hunk: &Hunk) -> Vec<(Option<LineNumber>, Option<LineNumber>)> {
relevant
}
pub fn merge_adjacent(
pub(crate) fn merge_adjacent(
hunks: &[Hunk],
opposite_to_lhs: &DftHashMap<LineNumber, HashSet<LineNumber>>,
opposite_to_rhs: &DftHashMap<LineNumber, HashSet<LineNumber>>,
@ -599,7 +599,7 @@ fn matched_novel_lines(
lines
}
pub fn matched_pos_to_hunks(lhs_mps: &[MatchedPos], rhs_mps: &[MatchedPos]) -> Vec<Hunk> {
pub(crate) fn matched_pos_to_hunks(lhs_mps: &[MatchedPos], rhs_mps: &[MatchedPos]) -> Vec<Hunk> {
lines_to_hunks(&matched_novel_lines(lhs_mps, rhs_mps), lhs_mps, rhs_mps)
}
@ -623,7 +623,7 @@ fn either_side_equal(
false
}
pub fn matched_lines_indexes_for_hunk(
pub(crate) fn matched_lines_indexes_for_hunk(
matched_lines: &[(Option<LineNumber>, Option<LineNumber>)],
hunk: &Hunk,
num_context_lines: usize,

@ -11,7 +11,7 @@ use crate::{
summary::FileFormat,
};
pub fn print(
pub(crate) fn print(
lhs_src: &str,
rhs_src: &str,
display_options: &DisplayOptions,

@ -273,7 +273,7 @@ impl Highlight {
}
}
pub fn print_directory(diffs: Vec<DiffResult>) {
pub(crate) fn print_directory(diffs: Vec<DiffResult>) {
let files = diffs.iter().map(File::from).collect::<Vec<File>>();
println!(
"{}",
@ -281,7 +281,7 @@ pub fn print_directory(diffs: Vec<DiffResult>) {
);
}
pub fn print(diff: &DiffResult) {
pub(crate) fn print(diff: &DiffResult) {
let file = File::from(diff);
println!(
"{}",

@ -1,6 +1,6 @@
pub mod context;
pub mod hunks;
pub mod inline;
pub mod json;
pub mod side_by_side;
pub mod style;
pub(crate) mod context;
pub(crate) mod hunks;
pub(crate) mod inline;
pub(crate) mod json;
pub(crate) mod side_by_side;
pub(crate) mod style;

@ -231,7 +231,7 @@ impl SourceDimensions {
}
}
pub fn lines_with_novel(
pub(crate) fn lines_with_novel(
lhs_mps: &[MatchedPos],
rhs_mps: &[MatchedPos],
) -> (HashSet<LineNumber>, HashSet<LineNumber>) {
@ -317,7 +317,7 @@ fn highlight_as_novel(
false
}
pub fn print(
pub(crate) fn print(
hunks: &[Hunk],
display_options: &DisplayOptions,
display_path: &str,

@ -18,13 +18,13 @@ use crate::{
};
#[derive(Clone, Copy, Debug)]
pub enum BackgroundColor {
pub(crate) enum BackgroundColor {
Dark,
Light,
}
impl BackgroundColor {
pub fn is_dark(self) -> bool {
pub(crate) fn is_dark(self) -> bool {
matches!(self, BackgroundColor::Dark)
}
}
@ -115,7 +115,7 @@ fn split_string_by_width(s: &str, max_width: usize, tab_width: usize) -> Vec<(&s
/// Return a copy of `src` with all the tab characters replaced by
/// `tab_width` strings.
pub fn replace_tabs(src: &str, tab_width: usize) -> String {
pub(crate) fn replace_tabs(src: &str, tab_width: usize) -> String {
let tab_as_spaces = " ".repeat(tab_width);
src.replace('\t', &tab_as_spaces)
}
@ -123,7 +123,7 @@ pub fn replace_tabs(src: &str, tab_width: usize) -> String {
/// Split `line` (from the source code) into multiple lines of
/// `max_len` (i.e. word wrapping), and apply `styles` to each part
/// according to its original position in `line`.
pub fn split_and_apply(
pub(crate) fn split_and_apply(
line: &str,
max_len: usize,
tab_width: usize,
@ -297,7 +297,7 @@ fn style_lines(lines: &[&str], styles: &[(SingleLineSpan, Style)]) -> Vec<String
res
}
pub fn novel_style(style: Style, side: Side, background: BackgroundColor) -> Style {
pub(crate) fn novel_style(style: Style, side: Side, background: BackgroundColor) -> Style {
if background.is_dark() {
match side {
Side::Left => style.bright_red(),
@ -311,7 +311,7 @@ pub fn novel_style(style: Style, side: Side, background: BackgroundColor) -> Sty
}
}
pub fn color_positions(
pub(crate) fn color_positions(
side: Side,
background: BackgroundColor,
syntax_highlight: bool,
@ -392,7 +392,7 @@ pub fn color_positions(
styles
}
pub fn apply_colors(
pub(crate) fn apply_colors(
s: &str,
side: Side,
syntax_highlight: bool,
@ -454,7 +454,7 @@ pub(crate) fn apply_line_number_color(
}
}
pub fn header(
pub(crate) fn header(
display_path: &str,
extra_info: Option<&String>,
hunk_num: usize,

@ -1,12 +1,12 @@
/// Successfully ran a diff, found no syntactic changes in text files
/// or byte changes in binary files.
pub const EXIT_SUCCESS: i32 = 0;
pub(crate) const EXIT_SUCCESS: i32 = 0;
/// Successfully ran a diff, found syntactic changes in text files or
/// byte changes in binary files.
pub const EXIT_FOUND_CHANGES: i32 = 1;
pub(crate) const EXIT_FOUND_CHANGES: i32 = 1;
/// Invalid arguments given to difftastic. This could be usage errors
/// (e.g. invalid numbers of arguments) or invalid paths (e.g. files
/// we don't have permission to read).
pub const EXIT_BAD_ARGUMENTS: i32 = 2;
pub(crate) const EXIT_BAD_ARGUMENTS: i32 = 2;

@ -13,7 +13,7 @@ use walkdir::WalkDir;
use crate::exit_codes::EXIT_BAD_ARGUMENTS;
use crate::options::FileArgument;
pub fn read_file_or_die(path: &FileArgument) -> Vec<u8> {
pub(crate) fn read_file_or_die(path: &FileArgument) -> Vec<u8> {
match read_file_arg(path) {
Ok(src) => src,
Err(e) => {
@ -23,7 +23,7 @@ pub fn read_file_or_die(path: &FileArgument) -> Vec<u8> {
}
}
pub fn read_files_or_die(
pub(crate) fn read_files_or_die(
lhs_path: &FileArgument,
rhs_path: &FileArgument,
missing_as_empty: bool,
@ -102,7 +102,7 @@ fn eprint_read_error(file_arg: &FileArgument, e: &std::io::Error) {
};
}
pub fn read_or_die(path: &Path) -> Vec<u8> {
pub(crate) fn read_or_die(path: &Path) -> Vec<u8> {
match fs::read(path) {
Ok(src) => src,
Err(e) => {
@ -139,13 +139,13 @@ fn u16_from_bytes(bytes: &[u8]) -> Vec<u16> {
}
#[derive(Debug, Eq, PartialEq)]
pub enum ProbableFileKind {
pub(crate) enum ProbableFileKind {
Text(String),
Binary,
}
/// Do these bytes look like a binary (non-textual) format?
pub fn guess_content(bytes: &[u8]) -> ProbableFileKind {
pub(crate) fn guess_content(bytes: &[u8]) -> ProbableFileKind {
// If the bytes are entirely valid UTF-8, treat them as a string.
if let Ok(valid_utf8_string) = std::str::from_utf8(bytes) {
return ProbableFileKind::Text(valid_utf8_string.to_string());
@ -248,7 +248,7 @@ fn relative_file_paths_in_dir(dir: &Path) -> Vec<PathBuf> {
/// that occur in at least one directory.
///
/// Attempts to preserve the ordering of files in both directories.
pub fn relative_paths_in_either(lhs_dir: &Path, rhs_dir: &Path) -> Vec<PathBuf> {
pub(crate) fn relative_paths_in_either(lhs_dir: &Path, rhs_dir: &Path) -> Vec<PathBuf> {
let lhs_paths = relative_file_paths_in_dir(lhs_dir);
let rhs_paths = relative_file_paths_in_dir(rhs_dir);

@ -9,4 +9,4 @@ use rustc_hash::FxHasher;
/// benchmarks) in a hashbrown::HashMap rather than std HashMap is a
/// little faster, and it also allows us to use the entry_ref API
/// which is unavailable in stable Rust.
pub type DftHashMap<K, V> = hashbrown::HashMap<K, V, BuildHasherDefault<FxHasher>>;
pub(crate) type DftHashMap<K, V> = hashbrown::HashMap<K, V, BuildHasherDefault<FxHasher>>;

@ -106,7 +106,7 @@ fn line_len_in_bytes(line: &str) -> usize {
}
// TODO: Prefer src/opposite_src nomenclature as this function is called from both sides.
pub fn change_positions(lhs_src: &str, rhs_src: &str) -> Vec<MatchedPos> {
pub(crate) fn change_positions(lhs_src: &str, rhs_src: &str) -> Vec<MatchedPos> {
// TODO: If either side is "", don't split each line by words
// pointlessly. This is common for file additions/removals.
let lhs_lp = LinePositions::from(lhs_src);

@ -4,7 +4,7 @@ use std::ops::Sub;
use line_numbers::LineNumber;
pub fn format_line_num(line_num: LineNumber) -> String {
pub(crate) fn format_line_num(line_num: LineNumber) -> String {
format!("{} ", line_num.display())
}
@ -12,13 +12,13 @@ pub fn format_line_num(line_num: LineNumber) -> String {
#[derive(Debug, PartialEq, Clone, Copy)]
struct LinePosition {
/// Both zero-indexed.
pub line: LineNumber,
pub(crate) line: LineNumber,
column: usize,
}
/// Return the length of `s` in codepoints. This is important when
/// finding character boundaries for slicing without errors.
pub fn codepoint_len(s: &str) -> usize {
pub(crate) fn codepoint_len(s: &str) -> usize {
s.chars().count()
}
@ -26,11 +26,11 @@ pub fn codepoint_len(s: &str) -> usize {
///
/// This is a trivial wrapper to make it clear when we want bytes not
/// codepoints.
pub fn byte_len(s: &str) -> usize {
pub(crate) fn byte_len(s: &str) -> usize {
s.len()
}
pub trait MaxLine {
pub(crate) trait MaxLine {
fn max_line(&self) -> LineNumber;
}
@ -46,7 +46,7 @@ impl<S: AsRef<str>> MaxLine for S {
}
}
pub fn is_all_whitespace(s: &str) -> bool {
pub(crate) fn is_all_whitespace(s: &str) -> bool {
s.chars().all(|c| c.is_whitespace())
}

@ -14,35 +14,35 @@ use crate::{
version::VERSION,
};
pub const DEFAULT_BYTE_LIMIT: usize = 1_000_000;
pub(crate) const DEFAULT_BYTE_LIMIT: usize = 1_000_000;
// Chosen experimentally: this is sufficiently many for all the sample
// files (the highest is slow_before/after.rs at 1.3M nodes), but
// small enough to terminate in ~5 seconds like the test file in #306.
pub const DEFAULT_GRAPH_LIMIT: usize = 3_000_000;
pub const DEFAULT_PARSE_ERROR_LIMIT: usize = 0;
pub(crate) const DEFAULT_GRAPH_LIMIT: usize = 3_000_000;
pub(crate) const DEFAULT_PARSE_ERROR_LIMIT: usize = 0;
pub const DEFAULT_TAB_WIDTH: usize = 8;
pub(crate) const DEFAULT_TAB_WIDTH: usize = 8;
const USAGE: &str = concat!(env!("CARGO_BIN_NAME"), " [OPTIONS] OLD-PATH NEW-PATH");
#[derive(Debug, Clone, Copy)]
pub enum ColorOutput {
pub(crate) enum ColorOutput {
Always,
Auto,
Never,
}
#[derive(Debug, Clone)]
pub struct DisplayOptions {
pub background_color: BackgroundColor,
pub use_color: bool,
pub display_mode: DisplayMode,
pub print_unchanged: bool,
pub tab_width: usize,
pub display_width: usize,
pub num_context_lines: u32,
pub in_vcs: bool,
pub syntax_highlight: bool,
pub(crate) struct DisplayOptions {
pub(crate) background_color: BackgroundColor,
pub(crate) use_color: bool,
pub(crate) display_mode: DisplayMode,
pub(crate) print_unchanged: bool,
pub(crate) tab_width: usize,
pub(crate) display_width: usize,
pub(crate) num_context_lines: u32,
pub(crate) in_vcs: bool,
pub(crate) syntax_highlight: bool,
}
impl Default for DisplayOptions {
@ -62,13 +62,13 @@ impl Default for DisplayOptions {
}
#[derive(Debug, Clone)]
pub struct DiffOptions {
pub graph_limit: usize,
pub byte_limit: usize,
pub parse_error_limit: usize,
pub check_only: bool,
pub ignore_comments: bool,
pub strip_cr: bool,
pub(crate) struct DiffOptions {
pub(crate) graph_limit: usize,
pub(crate) byte_limit: usize,
pub(crate) parse_error_limit: usize,
pub(crate) check_only: bool,
pub(crate) ignore_comments: bool,
pub(crate) strip_cr: bool,
}
impl Default for DiffOptions {
@ -293,7 +293,7 @@ When multiple overrides are specified, the first matching override wins."))
}
#[derive(Debug, Copy, Clone)]
pub enum DisplayMode {
pub(crate) enum DisplayMode {
Inline,
SideBySide,
SideBySideShowBoth,
@ -301,7 +301,7 @@ pub enum DisplayMode {
}
#[derive(Eq, PartialEq, Debug)]
pub enum FileArgument {
pub(crate) enum FileArgument {
NamedPath(std::path::PathBuf),
Stdin,
DevNull,
@ -327,7 +327,7 @@ fn relative_to_current(path: &Path) -> PathBuf {
impl FileArgument {
/// Return a `FileArgument` representing this command line
/// argument.
pub fn from_cli_argument(arg: &OsStr) -> Self {
pub(crate) fn from_cli_argument(arg: &OsStr) -> Self {
if arg == "/dev/null" {
FileArgument::DevNull
} else if arg == "-" {
@ -339,7 +339,7 @@ impl FileArgument {
/// Return a `FileArgument` that always represents a path that
/// exists, with the exception of `/dev/null`, which is turned into [FileArgument::DevNull].
pub fn from_path_argument(arg: &OsStr) -> Self {
pub(crate) fn from_path_argument(arg: &OsStr) -> Self {
// For new and deleted files, Git passes `/dev/null` as the reference file.
if arg == "/dev/null" {
FileArgument::DevNull
@ -348,7 +348,7 @@ impl FileArgument {
}
}
pub fn display(&self) -> String {
pub(crate) fn display(&self) -> String {
match self {
FileArgument::NamedPath(path) => relative_to_current(path).display().to_string(),
FileArgument::Stdin => "(stdin)".to_string(),
@ -357,7 +357,7 @@ impl FileArgument {
}
}
pub enum Mode {
pub(crate) enum Mode {
Diff {
diff_options: DiffOptions,
display_options: DisplayOptions,
@ -491,7 +491,7 @@ fn parse_overrides_or_die(raw_overrides: &[String]) -> Vec<(LanguageOverride, Ve
}
/// Parse CLI arguments passed to the binary.
pub fn parse_args() -> Mode {
pub(crate) fn parse_args() -> Mode {
let matches = app().get_matches();
let color_output = match matches.value_of("color").expect("color has a default") {
@ -733,7 +733,7 @@ fn detect_display_width() -> usize {
80
}
pub fn should_use_color(color_output: ColorOutput) -> bool {
pub(crate) fn should_use_color(color_output: ColorOutput) -> bool {
match color_output {
ColorOutput::Always => true,
ColorOutput::Auto => {

@ -17,7 +17,7 @@ use strum::{EnumIter, IntoEnumIterator};
/// Languages supported by difftastic. Each language here has a
/// corresponding tree-sitter parser.
#[derive(Debug, Clone, Copy, PartialEq, Eq, EnumIter)]
pub enum Language {
pub(crate) enum Language {
Ada,
Bash,
C,
@ -77,14 +77,14 @@ pub enum Language {
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum LanguageOverride {
pub(crate) enum LanguageOverride {
Language(Language),
PlainText,
}
/// If there is a language called `name` (comparing case
/// insensitively), return it. Treat `"text"` as an additional option.
pub fn language_override_from_name(name: &str) -> Option<LanguageOverride> {
pub(crate) fn language_override_from_name(name: &str) -> Option<LanguageOverride> {
let name = name.trim().to_lowercase();
if name == "text" {
@ -102,7 +102,7 @@ pub fn language_override_from_name(name: &str) -> Option<LanguageOverride> {
}
/// The language name shown to the user.
pub fn language_name(language: Language) -> &'static str {
pub(crate) fn language_name(language: Language) -> &'static str {
match language {
Ada => "Ada",
Bash => "Bash",
@ -166,7 +166,7 @@ pub fn language_name(language: Language) -> &'static str {
use Language::*;
/// File globs that identify languages based on the file path.
pub fn language_globs(language: Language) -> Vec<glob::Pattern> {
pub(crate) fn language_globs(language: Language) -> Vec<glob::Pattern> {
let glob_strs: &'static [&'static str] = match language {
Ada => &["*.ada", "*.adb", "*.ads"],
Bash => &[
@ -387,7 +387,7 @@ fn looks_like_hacklang(path: &Path, src: &str) -> bool {
false
}
pub fn guess(
pub(crate) fn guess(
path: &Path,
src: &str,
overrides: &[(LanguageOverride, Vec<glob::Pattern>)],

@ -1,3 +1,3 @@
pub mod guess_language;
pub mod syntax;
pub mod tree_sitter_parser;
pub(crate) mod guess_language;
pub(crate) mod syntax;
pub(crate) mod tree_sitter_parser;

@ -45,10 +45,10 @@ impl<'a> fmt::Debug for ChangeKind<'a> {
}
}
pub type SyntaxId = NonZeroU32;
pub(crate) type SyntaxId = NonZeroU32;
/// Fields that are common to both `Syntax::List` and `Syntax::Atom`.
pub struct SyntaxInfo<'a> {
pub(crate) struct SyntaxInfo<'a> {
/// The previous node with the same parent as this one.
previous_sibling: Cell<Option<&'a Syntax<'a>>>,
/// The next node with the same parent as this one.
@ -60,7 +60,7 @@ pub struct SyntaxInfo<'a> {
parent: Cell<Option<&'a Syntax<'a>>>,
/// The number of nodes that are ancestors of this one.
num_ancestors: Cell<u32>,
pub num_after: Cell<usize>,
pub(crate) num_after: Cell<usize>,
/// A number that uniquely identifies this syntax node.
unique_id: Cell<SyntaxId>,
/// A number that uniquely identifies the content of this syntax
@ -75,7 +75,7 @@ pub struct SyntaxInfo<'a> {
}
impl<'a> SyntaxInfo<'a> {
pub fn new() -> Self {
pub(crate) fn new() -> Self {
Self {
previous_sibling: Cell::new(None),
next_sibling: Cell::new(None),
@ -96,7 +96,7 @@ impl<'a> Default for SyntaxInfo<'a> {
}
}
pub enum Syntax<'a> {
pub(crate) enum Syntax<'a> {
List {
info: SyntaxInfo<'a>,
open_position: Vec<SingleLineSpan>,
@ -192,7 +192,7 @@ impl<'a> fmt::Debug for Syntax<'a> {
}
impl<'a> Syntax<'a> {
pub fn new_list(
pub(crate) fn new_list(
arena: &'a Arena<Syntax<'a>>,
open_content: &str,
open_position: Vec<SingleLineSpan>,
@ -245,7 +245,7 @@ impl<'a> Syntax<'a> {
})
}
pub fn new_atom(
pub(crate) fn new_atom(
arena: &'a Arena<Syntax<'a>>,
mut position: Vec<SingleLineSpan>,
mut content: &str,
@ -270,42 +270,42 @@ impl<'a> Syntax<'a> {
})
}
pub fn info(&self) -> &SyntaxInfo<'a> {
pub(crate) fn info(&self) -> &SyntaxInfo<'a> {
match self {
List { info, .. } | Atom { info, .. } => info,
}
}
pub fn parent(&self) -> Option<&'a Syntax<'a>> {
pub(crate) fn parent(&self) -> Option<&'a Syntax<'a>> {
self.info().parent.get()
}
pub fn next_sibling(&self) -> Option<&'a Syntax<'a>> {
pub(crate) fn next_sibling(&self) -> Option<&'a Syntax<'a>> {
self.info().next_sibling.get()
}
/// A unique ID of this syntax node. Every node is guaranteed to
/// have a different value.
pub fn id(&self) -> SyntaxId {
pub(crate) fn id(&self) -> SyntaxId {
self.info().unique_id.get()
}
/// A content ID of this syntax node. Two nodes have the same
/// content ID if they have the same content, regardless of
/// position.
pub fn content_id(&self) -> u32 {
pub(crate) fn content_id(&self) -> u32 {
self.info().content_id.get()
}
pub fn content_is_unique(&self) -> bool {
pub(crate) fn content_is_unique(&self) -> bool {
self.info().content_is_unique.get()
}
pub fn num_ancestors(&self) -> u32 {
pub(crate) fn num_ancestors(&self) -> u32 {
self.info().num_ancestors.get()
}
pub fn dbg_content(&self) -> String {
pub(crate) fn dbg_content(&self) -> String {
match self {
List {
open_content,
@ -333,7 +333,7 @@ impl<'a> Syntax<'a> {
}
}
pub fn comment_positions<'a>(nodes: &[&'a Syntax<'a>]) -> Vec<SingleLineSpan> {
pub(crate) fn comment_positions<'a>(nodes: &[&'a Syntax<'a>]) -> Vec<SingleLineSpan> {
fn walk_comment_positions(node: &Syntax<'_>, positions: &mut Vec<SingleLineSpan>) {
match node {
List { children, .. } => {
@ -358,7 +358,7 @@ pub fn comment_positions<'a>(nodes: &[&'a Syntax<'a>]) -> Vec<SingleLineSpan> {
}
/// Initialise all the fields in `SyntaxInfo`.
pub fn init_all_info<'a>(lhs_roots: &[&'a Syntax<'a>], rhs_roots: &[&'a Syntax<'a>]) {
pub(crate) fn init_all_info<'a>(lhs_roots: &[&'a Syntax<'a>], rhs_roots: &[&'a Syntax<'a>]) {
init_info(lhs_roots, rhs_roots);
init_next_prev(lhs_roots);
init_next_prev(rhs_roots);
@ -440,7 +440,7 @@ fn set_num_after(nodes: &[&Syntax], parent_num_after: usize) {
}
}
}
pub fn init_next_prev<'a>(roots: &[&'a Syntax<'a>]) {
pub(crate) fn init_next_prev<'a>(roots: &[&'a Syntax<'a>]) {
set_prev_sibling(roots);
set_next_sibling(roots);
set_prev(roots, None);
@ -563,7 +563,7 @@ impl<'a> Eq for Syntax<'a> {}
/// Different types of strings. We want to diff these the same way,
/// but highlight them differently.
#[derive(PartialEq, Eq, Debug, Clone, Copy, Hash)]
pub enum StringKind {
pub(crate) enum StringKind {
/// A string literal, such as `"foo"`.
StringLiteral,
/// Plain text, such as the content of `<p>foo</p>`.
@ -571,7 +571,7 @@ pub enum StringKind {
}
#[derive(PartialEq, Eq, Debug, Clone, Copy, Hash)]
pub enum AtomKind {
pub(crate) enum AtomKind {
Normal,
// TODO: We should either have a AtomWithWords(HighlightKind) or a
// separate String, Text and Comment kind.
@ -584,14 +584,14 @@ pub enum AtomKind {
/// Unlike atoms, tokens can be delimiters like `{`.
#[derive(PartialEq, Eq, Debug, Clone, Copy)]
pub enum TokenKind {
pub(crate) enum TokenKind {
Delimiter,
Atom(AtomKind),
}
/// A matched token (an atom, a delimiter, or a comment word).
#[derive(PartialEq, Eq, Debug, Clone)]
pub enum MatchKind {
pub(crate) enum MatchKind {
UnchangedToken {
highlight: TokenKind,
self_pos: Vec<SingleLineSpan>,
@ -614,7 +614,7 @@ pub enum MatchKind {
}
impl MatchKind {
pub fn is_novel(&self) -> bool {
pub(crate) fn is_novel(&self) -> bool {
matches!(
self,
MatchKind::Novel { .. } | MatchKind::NovelWord { .. } | MatchKind::NovelLinePart { .. }
@ -623,9 +623,9 @@ impl MatchKind {
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct MatchedPos {
pub kind: MatchKind,
pub pos: SingleLineSpan,
pub(crate) struct MatchedPos {
pub(crate) kind: MatchKind,
pub(crate) pos: SingleLineSpan,
}
/// Given the text `content` from a comment or strings, split it into
@ -867,7 +867,7 @@ impl MatchedPos {
}
/// Walk `nodes` and return a vec of all the changed positions.
pub fn change_positions<'a>(
pub(crate) fn change_positions<'a>(
nodes: &[&'a Syntax<'a>],
change_map: &ChangeMap<'a>,
) -> Vec<MatchedPos> {
@ -921,7 +921,7 @@ fn change_positions_<'a>(
}
}
pub fn zip_pad_shorter<Tx: Clone, Ty: Clone>(
pub(crate) fn zip_pad_shorter<Tx: Clone, Ty: Clone>(
lhs: &[Tx],
rhs: &[Ty],
) -> Vec<(Option<Tx>, Option<Ty>)> {
@ -941,7 +941,7 @@ pub fn zip_pad_shorter<Tx: Clone, Ty: Clone>(
/// Zip `lhs` with `rhs`, but repeat the last item from the shorter
/// slice.
pub fn zip_repeat_shorter<Tx: Clone, Ty: Clone>(lhs: &[Tx], rhs: &[Ty]) -> Vec<(Tx, Ty)> {
pub(crate) fn zip_repeat_shorter<Tx: Clone, Ty: Clone>(lhs: &[Tx], rhs: &[Ty]) -> Vec<(Tx, Ty)> {
let lhs_last: Tx = match lhs.last() {
Some(last) => last.clone(),
None => return vec![],

@ -19,7 +19,7 @@ use crate::parse::syntax::{AtomKind, Syntax};
/// languages we should parse them as.
///
/// Note that we don't support sub-languages more than one layer deep.
pub struct TreeSitterSubLanguage {
pub(crate) struct TreeSitterSubLanguage {
/// How to identify a node. The query must contain exactly one
/// capture group (the name is arbitrary).
query: ts::Query,
@ -29,9 +29,9 @@ pub struct TreeSitterSubLanguage {
}
/// Configuration for a tree-sitter parser.
pub struct TreeSitterConfig {
pub(crate) struct TreeSitterConfig {
/// The tree-sitter language parser.
pub language: ts::Language,
pub(crate) language: ts::Language,
/// Tree-sitter nodes that we treat as indivisible atoms.
///
@ -127,7 +127,7 @@ const OCAML_ATOM_NODES: [&str; 6] = [
"attribute_id",
];
pub fn from_language(language: guess::Language) -> TreeSitterConfig {
pub(crate) fn from_language(language: guess::Language) -> TreeSitterConfig {
use guess::Language::*;
match language {
Ada => {
@ -1079,7 +1079,7 @@ pub fn from_language(language: guess::Language) -> TreeSitterConfig {
}
/// Parse `src` with tree-sitter.
pub fn to_tree(src: &str, config: &TreeSitterConfig) -> tree_sitter::Tree {
pub(crate) fn to_tree(src: &str, config: &TreeSitterConfig) -> tree_sitter::Tree {
let mut parser = ts::Parser::new();
parser
.set_language(config.language)
@ -1089,9 +1089,9 @@ pub fn to_tree(src: &str, config: &TreeSitterConfig) -> tree_sitter::Tree {
}
#[derive(Debug)]
pub struct ExceededByteLimit(pub usize);
pub(crate) struct ExceededByteLimit(pub(crate) usize);
pub fn to_tree_with_limit(
pub(crate) fn to_tree_with_limit(
diff_options: &DiffOptions,
config: &TreeSitterConfig,
lhs_src: &str,
@ -1108,7 +1108,7 @@ pub fn to_tree_with_limit(
/// Find any nodes that can be parsed as other languages (e.g. JavaScript embedded in HTML),
/// and return a map of their node IDs mapped to parsed trees. Every time we see such a node,
/// we will ignore it and recurse into the root node of the given tree instead.
pub fn parse_subtrees(
pub(crate) fn parse_subtrees(
src: &str,
config: &TreeSitterConfig,
tree: &tree_sitter::Tree,
@ -1234,7 +1234,7 @@ fn tree_highlights(
}
}
pub fn print_tree(src: &str, tree: &tree_sitter::Tree) {
pub(crate) fn print_tree(src: &str, tree: &tree_sitter::Tree) {
let mut cursor = tree.walk();
print_cursor(src, &mut cursor, 0);
}
@ -1269,7 +1269,7 @@ fn print_cursor(src: &str, cursor: &mut ts::TreeCursor, depth: usize) {
}
}
pub fn comment_positions(
pub(crate) fn comment_positions(
tree: &tree_sitter::Tree,
src: &str,
config: &TreeSitterConfig,
@ -1292,9 +1292,9 @@ pub fn comment_positions(
}
#[derive(Debug)]
pub struct ExceededParseErrorLimit(pub usize);
pub(crate) struct ExceededParseErrorLimit(pub(crate) usize);
pub fn to_syntax_with_limit<'a>(
pub(crate) fn to_syntax_with_limit<'a>(
lhs_src: &str,
rhs_src: &str,
lhs_tree: &tree_sitter::Tree,
@ -1327,7 +1327,7 @@ pub fn to_syntax_with_limit<'a>(
Ok((lhs_nodes, rhs_nodes))
}
pub fn to_syntax<'a>(
pub(crate) fn to_syntax<'a>(
tree: &tree_sitter::Tree,
src: &str,
arena: &'a Arena<Syntax<'a>>,
@ -1374,7 +1374,7 @@ pub fn to_syntax<'a>(
}
/// Parse `src` with tree-sitter and convert to difftastic Syntax.
pub fn parse<'a>(
pub(crate) fn parse<'a>(
arena: &'a Arena<Syntax<'a>>,
src: &str,
config: &TreeSitterConfig,
@ -1433,7 +1433,7 @@ fn find_delim_positions(
None
}
pub struct HighlightedNodeIds {
pub(crate) struct HighlightedNodeIds {
keyword_ids: HashSet<usize>,
comment_ids: HashSet<usize>,
string_ids: HashSet<usize>,

@ -11,13 +11,13 @@ use crate::{
};
#[derive(Debug, PartialEq, Eq)]
pub enum FileContent {
pub(crate) enum FileContent {
Text(String),
Binary,
}
#[derive(Debug, Clone)]
pub enum FileFormat {
pub(crate) enum FileFormat {
SupportedLanguage(guess_language::Language),
PlainText,
TextFallback { reason: String },
@ -36,26 +36,26 @@ impl Display for FileFormat {
}
#[derive(Debug)]
pub struct DiffResult {
pub display_path: String,
pub(crate) struct DiffResult {
pub(crate) display_path: String,
/// Additional information to display about this file, such as
/// "Renamed from x.js to y.js".
pub extra_info: Option<String>,
pub(crate) extra_info: Option<String>,
pub file_format: FileFormat,
pub lhs_src: FileContent,
pub rhs_src: FileContent,
pub hunks: Vec<Hunk>,
pub(crate) file_format: FileFormat,
pub(crate) lhs_src: FileContent,
pub(crate) rhs_src: FileContent,
pub(crate) hunks: Vec<Hunk>,
pub lhs_positions: Vec<MatchedPos>,
pub rhs_positions: Vec<MatchedPos>,
pub(crate) lhs_positions: Vec<MatchedPos>,
pub(crate) rhs_positions: Vec<MatchedPos>,
pub has_byte_changes: bool,
pub has_syntactic_changes: bool,
pub(crate) has_byte_changes: bool,
pub(crate) has_syntactic_changes: bool,
}
impl DiffResult {
pub fn has_reportable_change(&self) -> bool {
pub(crate) fn has_reportable_change(&self) -> bool {
if matches!(self.lhs_src, FileContent::Binary)
|| matches!(self.rhs_src, FileContent::Binary)
{

@ -2,15 +2,15 @@ use std::fmt;
use lazy_static::lazy_static;
pub struct CommitInfo {
pub short_commit_hash: &'static str,
pub commit_hash: &'static str,
pub commit_date: &'static str,
pub(crate) struct CommitInfo {
pub(crate) short_commit_hash: &'static str,
pub(crate) commit_hash: &'static str,
pub(crate) commit_date: &'static str,
}
pub struct VersionInfo {
pub version: &'static str,
pub commit_info: Option<CommitInfo>,
pub(crate) struct VersionInfo {
pub(crate) version: &'static str,
pub(crate) commit_info: Option<CommitInfo>,
}
impl fmt::Display for VersionInfo {
@ -25,10 +25,10 @@ impl fmt::Display for VersionInfo {
}
lazy_static! {
pub static ref VERSION: String = version().to_string();
pub(crate) static ref VERSION: String = version().to_string();
}
pub const fn version() -> VersionInfo {
pub(crate) const fn version() -> VersionInfo {
let version = env!("CARGO_PKG_VERSION");
let commit_info = match (
option_env!("DFT_COMMIT_SHORT_HASH"),

@ -6,7 +6,7 @@
/// See also `split_words_and_numbers`. Both these functions are hot,
/// so they are separate implementations rather than passing a bool to
/// customise number handling.
pub fn split_words(s: &str) -> Vec<&str> {
pub(crate) fn split_words(s: &str) -> Vec<&str> {
let mut res = vec![];
let mut word_start: Option<usize> = None;
for (idx, c) in s.char_indices() {
@ -41,7 +41,7 @@ pub fn split_words(s: &str) -> Vec<&str> {
/// non-word characters.
///
/// "foo..bar23" -> vec!["foo", ".", ".", "bar23"]
pub fn split_words_and_numbers(s: &str) -> Vec<&str> {
pub(crate) fn split_words_and_numbers(s: &str) -> Vec<&str> {
let mut res = vec![];
let mut word_start: Option<(usize, char)> = None;
for (idx, c) in s.char_indices() {