Skip to content

Commit

Permalink
Squashed commit for alternative format processing
Browse files Browse the repository at this point in the history
Squashed commit of the following:

commit ccbc433
Author: Cyprien de Saint Guilhem <cyprien.desaintguilhem@3milabs.tech>
Date:   Tue Oct 15 14:13:35 2024 +0200

    Fix typo

commit 0e4ec8c
Merge: 52fe1f7 3f658fd
Author: Cyprien de Saint Guilhem <cyprien.desaintguilhem@3milabs.tech>
Date:   Tue Oct 15 14:07:14 2024 +0200

    Merge remote-tracking branch 'upstream/main' into pr-refactor-logic

commit 52fe1f7
Author: Cyprien de Saint Guilhem <cyprien.desaintguilhem@3milabs.tech>
Date:   Mon Oct 14 22:19:16 2024 +0200

    Document added regex

commit 1418812
Author: Cyprien de Saint Guilhem <cyprien.desaintguilhem@3milabs.tech>
Date:   Mon Oct 14 18:15:44 2024 +0200

    Fix Clippy warnings

commit 6c248db
Author: Cyprien de Saint Guilhem <cyprien.desaintguilhem@3milabs.tech>
Date:   Mon Oct 14 18:04:11 2024 +0200

    Use `char::width()` for checking wrapping need

commit 3f658fd
Author: William G Underwood <42812654+WGUNDERWOOD@users.noreply.github.com>
Date:   Mon Oct 14 15:28:00 2024 +0100

    Clippy

commit 0dcbc93
Author: William G Underwood <42812654+WGUNDERWOOD@users.noreply.github.com>
Date:   Mon Oct 14 15:03:15 2024 +0100

    Split cli and read files

commit 3ca0fd2
Author: Cyprien de Saint Guilhem <cyprien.desaintguilhem@3milabs.tech>
Date:   Mon Oct 14 14:09:18 2024 +0200

    Remove unused function

commit b4e2130
Author: Cyprien de Saint Guilhem <cyprien.desaintguilhem@3milabs.tech>
Date:   Mon Oct 14 14:08:45 2024 +0200

    Wrap lines based on indent length and only apply indentation after wrapping

commit 9bc0a3b
Author: Cyprien de Saint Guilhem <cyprien.desaintguilhem@3milabs.tech>
Date:   Sun Oct 13 20:12:44 2024 +0200

    Move allocation outside of wrap application

commit 76d9ef0
Author: Cyprien de Saint Guilhem <cyprien.desaintguilhem@3milabs.tech>
Date:   Sat Oct 12 11:17:43 2024 +0200

    Separate indent calculation from application

commit eb7971e
Author: Cyprien de Saint Guilhem <cyprien.desaintguilhem@3milabs.tech>
Date:   Sat Oct 12 10:46:56 2024 +0200

    Extract indent calculation into function

commit e41a66d
Author: Cyprien de Saint Guilhem <cyprien.desaintguilhem@3milabs.tech>
Date:   Sat Oct 12 10:31:58 2024 +0200

    Apply clippy suggestions

commit 21bb908
Author: Cyprien de Saint Guilhem <cyprien.desaintguilhem@3milabs.tech>
Date:   Fri Oct 11 17:43:14 2024 +0200

    Rename ignore check and document

commit ac164ad
Author: Cyprien de Saint Guilhem <cyprien.desaintguilhem@3milabs.tech>
Date:   Fri Oct 11 17:13:31 2024 +0200

    Simplify Option matching

commit 8a6e868
Author: Cyprien de Saint Guilhem <cyprien.desaintguilhem@3milabs.tech>
Date:   Fri Oct 11 12:58:12 2024 +0200

    Remove unnecessary comment check and `Option` in return type when splitting lines

commit 1d15b86
Author: Cyprien de Saint Guilhem <cyprien.desaintguilhem@3milabs.tech>
Date:   Fri Oct 11 12:57:17 2024 +0200

    Change comments around

commit e77b629
Author: Cyprien de Saint Guilhem <cyprien.desaintguilhem@3milabs.tech>
Date:   Fri Oct 11 12:56:46 2024 +0200

    Refactor ignoring check as function

commit b10b010
Author: Cyprien de Saint Guilhem <cyprien.desaintguilhem@3milabs.tech>
Date:   Fri Oct 11 11:37:18 2024 +0200

    Move environment line splitting before indenting

    This avoids re-adding the start of the split line to the queue.

commit 0424d0a
Author: Cyprien de Saint Guilhem <cyprien.desaintguilhem@3milabs.tech>
Date:   Fri Oct 11 11:23:01 2024 +0200

    Move check for ignore outside of `apply_indent()`

commit 70ac614
Author: Cyprien de Saint Guilhem <cyprien.desaintguilhem@3milabs.tech>
Date:   Fri Oct 11 09:29:55 2024 +0200

    Use new return type for `put_env_new_line`

commit fdea16b
Author: Cyprien de Saint Guilhem <cyprien.desaintguilhem@3milabs.tech>
Date:   Fri Oct 11 09:28:54 2024 +0200

    Fix infinite loop issue when split points are in comments

commit 791c7f1
Author: Cyprien de Saint Guilhem <cyprien.desaintguilhem@3milabs.tech>
Date:   Fri Oct 11 09:27:23 2024 +0200

    Correct to not expect `{` after `\item` but only after `\begin` and `\end`

commit 6e5ce6c
Author: Cyprien de Saint Guilhem <cyprien.desaintguilhem@3milabs.tech>
Date:   Fri Oct 11 09:26:06 2024 +0200

    Match target tex file to source file

commit 9562af1
Author: Cyprien de Saint Guilhem <cyprien.desaintguilhem@3milabs.tech>
Date:   Thu Oct 10 22:27:53 2024 +0200

    Remove debug print statement

commit 0f48547
Author: Cyprien de Saint Guilhem <cyprien.desaintguilhem@3milabs.tech>
Date:   Thu Oct 10 18:10:00 2024 +0200

    Split environment and item lines without allocating

    This does not compile because the `format` function cannot yet deal with the new return type.

commit c49a08c
Author: Cyprien de Saint Guilhem <cyprien.desaintguilhem@3milabs.tech>
Date:   Thu Oct 10 13:27:48 2024 +0200

    Check indentation return to 0 on `state` instead of `new_text`

commit 1b90f21
Author: Cyprien de Saint Guilhem <cyprien.desaintguilhem@3milabs.tech>
Date:   Thu Oct 10 13:11:57 2024 +0200

    Split condition tree into distinct blocks with `continue`

commit e974225
Author: Cyprien de Saint Guilhem <cyprien.desaintguilhem@3milabs.tech>
Date:   Thu Oct 10 11:07:08 2024 +0200

    Plan line formatting logic steps

commit 4bf802a
Author: Cyprien de Saint Guilhem <cyprien.desaintguilhem@3milabs.tech>
Date:   Thu Oct 10 10:53:42 2024 +0200

    Group lines to clean text into one function

commit 380380d
Author: William G Underwood <42812654+WGUNDERWOOD@users.noreply.github.com>
Date:   Thu Oct 10 14:33:04 2024 +0100

    Release process notes
  • Loading branch information
cdesaintguilhem committed Oct 15, 2024
1 parent 945637b commit db634ec
Show file tree
Hide file tree
Showing 16 changed files with 358 additions and 230 deletions.
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 @@ -18,6 +18,7 @@ lazy_static = "1.5.0"
log = "0.4.22"
regex = "1.11.0"
similar = "2.6.0"
unicode-width = "0.2.0"

[profile.release]
codegen-units = 1
Expand Down
10 changes: 10 additions & 0 deletions notes.org
Original file line number Diff line number Diff line change
@@ -1 +1,11 @@
#+title: tex-fmt
* Release process
** Update version number in Cargo.toml
** Push to GitHub and check tests pass
** Create a git tag
*** git tag vX.X.X
*** git push --tags
** Publish to crates.io with cargo publish
** Publish GitHub release with notes
*** GitHub binaries published automatically with actions
** Publish in nixpkgs when bot makes pull request
50 changes: 1 addition & 49 deletions src/parse.rs → src/cli.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,9 @@
//! Utilities for reading the command line arguments
use crate::logging::*;
use crate::regexes::*;
use clap::Parser;
use log::Level::{Error, Trace};
use log::Level::Error;
use log::LevelFilter;
use std::fs;
use std::io::Read;

/// Command line arguments
#[allow(missing_docs)]
Expand Down Expand Up @@ -112,48 +109,3 @@ impl Cli {
}
}
}

/// Add a missing extension and read the file
pub fn read(file: &str, logs: &mut Vec<Log>) -> Option<(String, String)> {
// check if file has an accepted extension
let has_ext = EXTENSIONS.iter().any(|e| file.ends_with(e));
// if no valid extension, try adding .tex
let mut new_file = file.to_owned();
if !has_ext {
new_file.push_str(".tex");
};
if let Ok(text) = fs::read_to_string(&new_file) {
return Some((new_file, text));
}
if has_ext {
record_file_log(logs, Error, file, "Could not open file.");
} else {
record_file_log(logs, Error, file, "File type invalid.");
}
None
}

/// Attempt to read from STDIN, return filename `<STDIN>` and text
pub fn read_stdin(logs: &mut Vec<Log>) -> Option<(String, String)> {
let mut text = String::new();
match std::io::stdin().read_to_string(&mut text) {
Ok(bytes) => {
record_file_log(
logs,
Trace,
"<STDIN>",
&format!("Read {bytes} bytes."),
);
Some((String::from("<STDIN>"), text))
}
Err(e) => {
record_file_log(
logs,
Error,
"<STDIN>",
&format!("Could not read from STDIN: {e}"),
);
None
}
}
}
5 changes: 0 additions & 5 deletions src/comments.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,3 @@ pub fn find_comment_index(line: &str) -> Option<usize> {
pub fn remove_comment(line: &str, comment: Option<usize>) -> &str {
comment.map_or_else(|| line, |c| &line[0..c])
}

/// Extract a comment from the end of a line
pub fn get_comment(line: &str, comment: Option<usize>) -> &str {
comment.map_or_else(|| "", |c| &line[c..])
}
157 changes: 108 additions & 49 deletions src/format.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
//! Core methodology for formatting a file
use crate::cli::*;
use crate::ignore::*;
use crate::indent::*;
use crate::logging::*;
use crate::parse::*;
use crate::regexes::{ENV_BEGIN, ENV_END, ITEM};
use crate::subs::*;
use crate::verbatim::*;
Expand All @@ -14,77 +14,106 @@ use std::iter::zip;

/// Central function to format a file
pub fn format_file(
text: &str,
old_text: &str,
file: &str,
args: &Cli,
logs: &mut Vec<Log>,
) -> String {
record_file_log(logs, Info, file, "Formatting started.");
let mut old_text = remove_extra_newlines(text);
if !args.usetabs {
old_text = remove_tabs(&old_text, args);
}
old_text = remove_trailing_spaces(&old_text);

// Clean the source file and zip its lines with line numbers
let old_text = clean_text(old_text, args);
let mut old_lines = zip(1.., old_text.lines());

// Initialise
let mut state = State::new();
let old_lines = old_text.lines();
let mut old_lines = zip(1.., old_lines);
let mut queue: Vec<(usize, String)> = vec![];
let mut new_text = String::with_capacity(2 * text.len());
let mut new_text = String::with_capacity(2 * old_text.len());

// Select the character used for indentation.
let indent_char = if args.usetabs { "\t" } else { " " };

loop {
if let Some((linum_old, mut line)) = queue.pop() {
// Read the patterns present on this line.
let pattern = Pattern::new(&line);
let temp_state: State;
(line, temp_state) = apply_indent(

// Temporary state for working on this line.
let mut temp_state = state.clone();

// Update the state with the line number from the queue.
temp_state.linum_old = linum_old;

// If the line should not be ignored ...
if !set_ignore_and_report(
&line,
linum_old,
&state,
&mut temp_state,
logs,
file,
args,
&pattern,
indent_char,
);
if needs_env_new_line(&line, &temp_state, &pattern) {
let env_lines =
put_env_new_line(&line, &temp_state, file, args, logs);
if env_lines.is_some() {
queue.push((linum_old, env_lines.clone().unwrap().1));
queue.push((linum_old, env_lines.clone().unwrap().0));
} else {
state = temp_state;
new_text.push_str(&line);
new_text.push_str(LINE_END);
state.linum_new += 1;
};
} else if needs_wrap(&line, &temp_state, args) {
let wrapped_lines =
apply_wrap(&line, &temp_state, file, args, logs);
if wrapped_lines.is_some() {
queue.push((linum_old, wrapped_lines.clone().unwrap().1));
queue.push((linum_old, wrapped_lines.clone().unwrap().0));
} else {
state = temp_state;
new_text.push_str(&line);
new_text.push_str(LINE_END);
state.linum_new += 1;
};
} else {
state = temp_state;
new_text.push_str(&line);
new_text.push_str(LINE_END);
state.linum_new += 1;
) {
// Check if the line should be split because of a pattern that should begin on a new line.
if needs_env_new_line(&line, &temp_state, &pattern) {
// Split the line into two ...
let (this_line, next_line) =
put_env_new_line(&line, &temp_state, file, args, logs);
// ... and queue the second part for formatting.
queue.push((linum_old, next_line.to_string()));
line = this_line.to_string();
}

// Calculate the indent based on the current state and the patterns in the line.
let indent = calculate_indent(
&line,
&mut temp_state,
logs,
file,
args,
&pattern,
);

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
{
queue.push((
linum_old,
[next_line_start, next_line].concat(),
));
queue.push((linum_old, this_line.to_string()));
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
state = temp_state;
new_text.push_str(&line);
new_text.push_str(LINE_END);
state.linum_new += 1;
} else if let Some((linum_old, line)) = old_lines.next() {
queue.push((linum_old, line.to_string()));
} else {
break;
}
}

if !indents_return_to_zero(&new_text) {
if !indents_return_to_zero(&state) {
record_file_log(logs, Warn, file, "Indent does not return to zero.");
}

Expand All @@ -93,6 +122,35 @@ pub fn format_file(
new_text
}

/// Sets the `ignore` and `verbatim` flags in the given [State] based on `line` and returns whether `line` should be
/// ignored by formatting.
fn set_ignore_and_report(
line: &str,
temp_state: &mut State,
logs: &mut Vec<Log>,
file: &str,
pattern: &Pattern,
) -> bool {
temp_state.ignore = get_ignore(line, temp_state, logs, file, true);
temp_state.verbatim =
get_verbatim(line, temp_state, logs, file, true, pattern);

temp_state.verbatim.visual || temp_state.ignore.visual
}

/// Cleans the given text by removing extra line breaks and trailing spaces, and tabs if they shouldn't be used.
fn clean_text(text: &str, args: &Cli) -> String {
let mut text = remove_extra_newlines(text);

if !args.usetabs {
text = remove_tabs(&text, args);
}

text = remove_trailing_spaces(&text);

text
}

/// Information on the current state during formatting
#[derive(Clone, Debug)]
pub struct State {
Expand Down Expand Up @@ -143,6 +201,7 @@ impl Pattern {
}

/// Ensure that the indentation returns to zero at the end of the file
fn indents_return_to_zero(text: &str) -> bool {
!text.lines().last().unwrap_or_default().starts_with(' ')
fn indents_return_to_zero(state: &State) -> bool {
#![allow(clippy::missing_const_for_fn)]
state.indent.actual == 0
}
Loading

0 comments on commit db634ec

Please sign in to comment.