Skip to content

Commit

Permalink
Wrap lines based on indent length and only apply indentation after wr…
Browse files Browse the repository at this point in the history
…apping
  • Loading branch information
cdesaintguilhem committed Oct 14, 2024
1 parent 9bc0a3b commit b4e2130
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 14 deletions.
23 changes: 17 additions & 6 deletions src/format.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ pub fn format_file(
line = this_line.to_string();
}

// Apply indent based on the current state and the patterns in the line.
// Calculate the indent based on the current state and the patterns in the line.
let indent = calculate_indent(
&line,
&mut temp_state,
Expand All @@ -71,12 +71,20 @@ pub fn format_file(
args,
&pattern,
);
line = apply_indent(&line, indent, args, indent_char);

// Wrap the line after indenting, and add the wrap to the queue.
if needs_wrap(&line, &temp_state, args) {
let wrapped_lines =
apply_wrap(&line, &temp_state, file, args, logs);
let indent_length = usize::try_from(indent.visual * args.tab)
.expect("Visual indent is non-negative.");

// Wrap the line before applying the indent, and loop back if the line needed wrapping.
if needs_wrap(&line.trim_start(), indent_length, args) {
let wrapped_lines = apply_wrap(
&line.trim_start(),
indent_length,
&temp_state,
file,
args,
logs,
);
if let Some([this_line, next_line_start, next_line]) =
wrapped_lines
{
Expand All @@ -88,6 +96,9 @@ pub fn format_file(
continue;
}
}

// Lastly, apply the indent if the line didn't need wrapping.
line = apply_indent(&line, indent, args, indent_char);
}

// Add line to new text
Expand Down
21 changes: 13 additions & 8 deletions src/wrap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,25 +13,29 @@ pub const TEXT_LINE_START: &str = "";
pub const COMMENT_LINE_START: &str = "% ";

/// Check if a line needs wrapping
pub fn needs_wrap(line: &str, state: &State, args: &Cli) -> bool {
!args.keep
&& !state.verbatim.visual
&& !state.ignore.visual
&& (line.chars().count() > args.wrap.into())
pub fn needs_wrap(line: &str, indent_length: usize, args: &Cli) -> bool {
!args.keep && (line.chars().count() + indent_length > args.wrap.into())
}

/// Find the best place to break a long line
fn find_wrap_point(line: &str, args: &Cli) -> Option<usize> {
fn find_wrap_point(
line: &str,
indent_length: usize,
args: &Cli,
) -> Option<usize> {
let mut wrap_point: Option<usize> = None;
let mut after_char = false;
let mut prev_char: Option<char> = None;

let mut line_width = 0;

let wrap_boundary = usize::from(args.wrap_min) - indent_length;

// Return *byte* index rather than *char* index.
for (i, c) in line.char_indices() {
line_width += c.width().expect("No control characters in text.");
if line_width > args.wrap_min.into() && wrap_point.is_some() {

if line_width > wrap_boundary && wrap_point.is_some() {
break;
}
if c == ' ' && prev_char != Some('\\') {
Expand All @@ -49,6 +53,7 @@ fn find_wrap_point(line: &str, args: &Cli) -> Option<usize> {
/// Wrap a long line into a short prefix and a suffix
pub fn apply_wrap<'a>(
line: &'a str,
indent_length: usize,
state: &State,
file: &str,
args: &Cli,
Expand All @@ -65,7 +70,7 @@ pub fn apply_wrap<'a>(
"Wrapping long line.",
);
}
let wrap_point = find_wrap_point(line, args);
let wrap_point = find_wrap_point(line, indent_length, args);
let comment_index = find_comment_index(line);

match wrap_point {
Expand Down

0 comments on commit b4e2130

Please sign in to comment.