Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

support txtpp as second extension #8

Merged
merged 3 commits into from
Oct 30, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
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
284 changes: 121 additions & 163 deletions Cargo.lock

Large diffs are not rendered by default.

9 changes: 5 additions & 4 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "txtpp"
version = "0.2.2"
version = "0.2.3"
edition = "2021"
description = "A simple-to-use general purpose preprocessor for text files."
repository = "https://github.com/Pistonite/txtpp"
Expand All @@ -12,20 +12,21 @@ exclude = [
"tests/examples/**/*",
"docs/*",
".github/**/*",
"Justfile"
"Taskfile.yml"
]

[dependencies]
which = "^4.4.0"
which = "^5.0.0"
error-stack = "^0.3.1"
termcolor = "^1.2.0"
threadpool = "^1.8.1"
clap = { version = "^4.2.4", features = ["cargo", "derive"], optional = true }
clap = { version = "^4.4.7", features = ["cargo", "derive"], optional = true }
log = "^0.4.17"
env_logger = "^0.10.0"
derivative = "^2.2.0"

[features]
default = ["cli"]
cli = ["clap"]

[dev-dependencies]
Expand Down
26 changes: 0 additions & 26 deletions Justfile

This file was deleted.

1 change: 0 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
# txtpp
![Build Badge](https://img.shields.io/github/actions/workflow/status/Pistonite/txtpp/rust.yml)
![Version Badge](https://img.shields.io/crates/v/txtpp)
![Docs Badge](https://img.shields.io/docsrs/txtpp)
![License Badge](https://img.shields.io/github/license/Pistonite/txtpp)
![Issue Badge](https://img.shields.io/github/issues/Pistonite/txtpp)

Expand Down
30 changes: 30 additions & 0 deletions Taskfile.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
version: '3'

tasks:
install:
desc: Install dependencies
cmds:
- rustup update
- cargo install cargo-watch
clean:
desc: Clean example output
cmds:
- cargo run -- clean tests/examples docs -r
readme:
desc: Generate the readme
cmds:
- cargo run -- docs/README.md
- mv docs/README.md README.md
dev:
desc: Run tests in watch mode
cmds:
- cargo watch -x test
check:
desc: Pre-commit checks
cmds:
- cargo clippy --all-targets --all-features -- -D warnings -D clippy::todo
- cargo fmt
- cargo doc
- cargo test
- task: readme
- task: clean
3 changes: 2 additions & 1 deletion docs/README.md.txtpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
# txtpp
![Build Badge](https://img.shields.io/github/actions/workflow/status/Pistonite/txtpp/rust.yml)
![Version Badge](https://img.shields.io/crates/v/txtpp)
![Docs Badge](https://img.shields.io/docsrs/txtpp)
![License Badge](https://img.shields.io/github/license/Pistonite/txtpp)
![Issue Badge](https://img.shields.io/github/issues/Pistonite/txtpp)

Expand Down Expand Up @@ -60,7 +59,9 @@ TXTPP#include fiz.txt
- [Execution](#execution)
- [Directive Specification](#directive-specification)
- [Include Directive](#include-directive)
- [After Directive](#after-directive)
- [Run Directive](#run-directive)
- [Empty Directive](#empty-directive)
- [Temp Directive](#temp-directive)
- [Tag Directive](#tag-directive)
- [Write Directive](#write-directive)
Expand Down
5 changes: 1 addition & 4 deletions src/core/util/dependency.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,7 @@ impl DepManager {
if self.finished.contains(dependency) {
continue;
}
let dependers = self
.in_edges
.entry(dependency.clone())
.or_insert(HashSet::new());
let dependers = self.in_edges.entry(dependency.clone()).or_default();
// add depender -> dependency edge
if dependers.insert(depender.clone()) {
*dependency_count += 1;
Expand Down
2 changes: 1 addition & 1 deletion src/fs/io_context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ impl IOCtx {
.attach_printable(format!("could not open input file: `{input_path}`"))
})?;

let output_path = input_file.as_path_buf().trim_txtpp().map_err(|e| {
let output_path = input_file.as_path_buf().remove_txtpp().map_err(|e| {
e.change_context(Self::make_error_with_kind(
input_path.clone(),
PpErrorKind::OpenFile,
Expand Down
2 changes: 1 addition & 1 deletion src/fs/path/abs_path.rs
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ impl AbsPath {
}

pub fn trim_txtpp(&self) -> Result<String, PathError> {
let p = self.p.trim_txtpp()?;
let p = self.p.remove_txtpp()?;
Ok(path_string_from_base(&self.b, &p))
}
}
Expand Down
122 changes: 97 additions & 25 deletions src/fs/path/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,25 +21,42 @@ mod directory;
pub use directory::*;

pub trait TxtppPath: Sized {
/// Get the path with the txtpp extension,
/// Get the path to the txtpp file corresponding to the current path.
///
/// Return `.txtpp` added to self if:
/// - self does not end with `.txtpp`
/// - `{self}.txtpp` is a file
/// Otherwise, returns None.
/// For a file foo.bar, the txtpp file could be:
/// - foo.bar.txtpp, or
/// - foo.txtpp.bar
///
/// If the path is already a txtpp file, `None` will be returned.
/// Otherwise, if a corresponding txtpp file exists, that will be returned
fn get_txtpp_file(&self) -> Option<Self>;
/// Check if the path has the txtpp extension itself

/// Check if the path matches a txtpp file format. The path can be non-existent and this will
/// still return true as long as the format is correct.
fn is_txtpp_file(&self) -> bool;
/// Remove the txtpp extension from the path.

/// If current path is a txtpp file, return the path corresponding to the output of the txtpp
/// file. This is the reverse of [`TxtppPath::get_txtpp_file`].
///
/// If the path does not have the txtpp extension, an error will be returned.
fn trim_txtpp(&self) -> Result<Self, PathError>;
/// If the path is not a txtpp file, an error will be returned.
fn remove_txtpp(&self) -> Result<Self, PathError>;
}

impl TxtppPath for PathBuf {
fn is_txtpp_file(&self) -> bool {
match self.extension() {
Some(ext) => ext == TXTPP_EXT,
Some(ext) => {
if ext == TXTPP_EXT {
return true;
}
// check if the second extension is txtpp
let mut p = self.clone();
p.set_extension("");
match p.extension() {
Some(ext) => ext == TXTPP_EXT,
None => false,
}
}
None => false,
}
}
Expand All @@ -50,31 +67,57 @@ impl TxtppPath for PathBuf {
}

let mut p = self.clone();
let ext = match p.extension() {
match self.extension() {
Some(ext) => {
let mut ext = ext.to_os_string();
ext.push(".");
ext.push(TXTPP_EXT);
ext
// if there is extension, try .xxx.txtpp then .txtpp.xxx
let mut ext1 = ext.to_os_string();
ext1.push(".");
ext1.push(TXTPP_EXT);
p.set_extension(ext1);

if p.is_file() {
return Some(p);
}
p.set_extension(""); // restore p
let mut ext2 = OsString::from(TXTPP_EXT);
ext2.push(".");
ext2.push(ext);
p.set_extension(ext2);
if p.is_file() {
Some(p)
} else {
None
}
}
None => {
// if there's no extension, the only way is adding .txtpp at the end
let ext = OsString::from(TXTPP_EXT);
p.set_extension(ext);
if p.is_file() {
Some(p)
} else {
None
}
}
None => OsString::from(TXTPP_EXT),
};
p.set_extension(ext);

if p.is_file() {
Some(p)
} else {
None
}
}

fn trim_txtpp(&self) -> Result<Self, PathError> {
fn remove_txtpp(&self) -> Result<Self, PathError> {
if !self.is_txtpp_file() {
return Err(Report::new(PathError::from(self))
.attach_printable(format!("path does not {TXTPP_EXT} extension")));
.attach_printable(format!("path does not have {TXTPP_EXT} extension")));
}
let mut p = self.clone();
p.set_extension("");
if matches!(p.extension(), Some(ext) if ext == TXTPP_EXT) {
// remove the txtpp extension and add the original back
p.set_extension("");
let self_ext = self.extension().ok_or_else(|| {
Report::new(PathError::from(self))
.attach_printable(format!("path does not have {TXTPP_EXT} extension"))
})?;
p.set_extension(self_ext);
}

Ok(p)
}
Expand All @@ -95,3 +138,32 @@ pub fn normalize_path(p: &str) -> &str {
pub fn normalize_path(p: &str) -> &str {
p
}

#[cfg(test)]
mod test {
use super::*;

#[test]
fn test_is_txtpp_file() {
assert!(PathBuf::from("foo.txtpp").is_txtpp_file());
assert!(PathBuf::from("foo.bar.txtpp").is_txtpp_file());
assert!(PathBuf::from("foo.txtpp.bar").is_txtpp_file());
assert!(!PathBuf::from("foo.bar").is_txtpp_file());
assert!(!PathBuf::from("foo").is_txtpp_file());
assert!(!PathBuf::from("txtpp").is_txtpp_file());
}

#[test]
fn test_remove_txtpp() {
assert!(PathBuf::from("foo").remove_txtpp().is_err());
assert!(PathBuf::from("foo.bar").remove_txtpp().is_err());
assert_eq!(
PathBuf::from("foo.bar.txtpp").remove_txtpp().unwrap(),
PathBuf::from("foo.bar")
);
assert_eq!(
PathBuf::from("foo.txtpp.bar").remove_txtpp().unwrap(),
PathBuf::from("foo.bar")
);
}
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
hello
-TXTPP#include bar.txt
world
world