From 88e9c89741b6d01c0c9802a676b0a124fd6db146 Mon Sep 17 00:00:00 2001 From: Pistonight Date: Sat, 30 Sep 2023 14:50:06 -0700 Subject: [PATCH] add after directive --- .github/workflows/rust.yml | 18 +++++------------- CHANGELOG.md | 3 +++ Cargo.lock | 2 +- Cargo.toml | 2 +- Justfile | 2 +- README.md | 17 +++++++++++++++-- docs/README.md.txtpp | 18 ++++++++++++++++-- .../execute/pp/directive/directive_from.rs | 14 ++++++++++++++ src/core/execute/pp/directive/mod.rs | 9 ++++++++- src/core/execute/pp/mod.rs | 7 +++++-- tests/examples/after/example.expected | 3 +++ tests/examples/after/example.txtpp | 3 +++ tests/examples/after/foo.txtpp | 1 + tests/test.rs | 5 +++++ 14 files changed, 81 insertions(+), 23 deletions(-) create mode 100644 tests/examples/after/example.expected create mode 100644 tests/examples/after/example.txtpp create mode 100644 tests/examples/after/foo.txtpp diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 45b264c..b5ec06a 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -19,26 +19,18 @@ jobs: - name: Set git to not convert line endings run: | git config --global core.autocrlf false - - uses: actions/checkout@v3 - - name: Setup Rust - uses: ATiltedTree/setup-rust@v1 + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@stable with: - rust-version: stable components: clippy - - uses: actions/cache@v2 - with: - path: | - ~/.cargo/registry - ~/.cargo/git - target - key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }} + - uses: Swatinem/rust-cache@v2 - uses: actions/setup-python@v4 with: python-version: '3.10' - name: Show Compiler Version run: rustc --version --verbose - - name: Clippy - run: cargo clippy --all-targets --all-features -- -D warnings + - run: cargo fmt --check + - run: cargo clippy --all-targets --all-features -- -D warnings - name: Test run: cargo test --verbose - name: Make sure clean can run diff --git a/CHANGELOG.md b/CHANGELOG.md index 2eed211..54504b6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,8 @@ # CHANGELOG +## 0.2.2 +- New `after` directive to specify dependency explicitly + ## 0.2.1 - Temp files are no longer re-written if they are already up-to-date in both verify and build mode - New flag `--needed/-N` and corresponding mode `InMemoryBuild` that stores the fresh output in memory and only writes the file if different diff --git a/Cargo.lock b/Cargo.lock index fa722fa..32c173c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -424,7 +424,7 @@ dependencies = [ [[package]] name = "txtpp" -version = "0.2.1" +version = "0.2.2" dependencies = [ "clap", "copy_dir", diff --git a/Cargo.toml b/Cargo.toml index a00e636..dcf11c0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "txtpp" -version = "0.2.1" +version = "0.2.2" edition = "2021" description = "A simple-to-use general purpose preprocessor for text files." repository = "https://github.com/Pistonite/txtpp" diff --git a/Justfile b/Justfile index e7d179a..f9511ef 100644 --- a/Justfile +++ b/Justfile @@ -16,7 +16,7 @@ readme: # Pre-commit checks check: && readme clean - cargo clippy --all-targets --all-features -- -D warnings + cargo clippy --all-targets --all-features -- -D warnings -D clippy::todo cargo fmt cargo doc cargo test diff --git a/README.md b/README.md index 2578bd8..6c262dc 100644 --- a/README.md +++ b/README.md @@ -134,7 +134,7 @@ This will execute the command `echo "hello world"`. The `-` in the last line in ## Execution The directives are executed immediately after they are parsed. They may produce an output to be included in the output file and/or have side effects such as creating a temporary file. -If the directive has output (like `include` and `run`), it will be formated as: +If the directive has output (like `include` and `run`), it will be formatted as: - Every line in the output will be prepended with `{WHITESPACES}`, so that the indentation is consistent ``` // TXTPP#run echo 1; echo 2 @@ -159,7 +159,7 @@ If the directive has output (like `include` and `run`), it will be formated as: ``` -Note that normally, you will not be able to connect a directive output to the previous line, since directives always start on its own line. However, you can use `tag` (see [below](#tag-directive)) to achieve this. If there is currently an active `tag` directive that is listening for output, the output will be sent to the tag instead of the output file, without the indentation. and the directive will produce no output. +Note that normally, you will not be able to connect a directive output to the previous line, since directives always start on its own line. However, you can use `tag` (see [below](#tag-directive)) to achieve this. If there is currently an active `tag` directive that is listening for output, the output will be sent to the tag instead of the output file, without the indentation, and the directive will produce no output. # Directive Specification This section contains detailed specification of each directive. @@ -176,7 +176,20 @@ Single-line only. The argument is `FILE_PATH` ``` TXTPP#include foo.txt ``` +## After Directive +#### USAGE +This directive is to explicitly specify dependency. +#### ARGUMENTS +Single-line only. The argument is `FILE_PATH` +#### BEHAVIOR +This directive behaves exactly like `include`, except it only changes the dependency structure and doesn't affect the output. +This can be useful if there are implicit dependencies. For example, a `run` directive could execute a command that depends on a txtpp output. +#### EXAMPLE +``` +TXTPP#after foo.txt +TXTPP#run ./my-script.sh foo.txt +``` ## Run Directive #### USAGE This directive is used to run a command and include the output of the command into the current file. diff --git a/docs/README.md.txtpp b/docs/README.md.txtpp index 1495605..28f1d94 100644 --- a/docs/README.md.txtpp +++ b/docs/README.md.txtpp @@ -126,7 +126,7 @@ This will execute the command `echo "hello world"`. The `-` in the last line in ## Execution The directives are executed immediately after they are parsed. They may produce an output to be included in the output file and/or have side effects such as creating a temporary file. -If the directive has output (like `include` and `run`), it will be formated as: +If the directive has output (like `include` and `run`), it will be formatted as: - Every line in the output will be prepended with `{WHITESPACES}`, so that the indentation is consistent ``` TXTPP#include run1.txtpp @@ -149,7 +149,7 @@ If the directive has output (like `include` and `run`), it will be formated as: ``` -Note that normally, you will not be able to connect a directive output to the previous line, since directives always start on its own line. However, you can use `tag` (see [below](#tag-directive)) to achieve this. If there is currently an active `tag` directive that is listening for output, the output will be sent to the tag instead of the output file, without the indentation. and the directive will produce no output. +Note that normally, you will not be able to connect a directive output to the previous line, since directives always start on its own line. However, you can use `tag` (see [below](#tag-directive)) to achieve this. If there is currently an active `tag` directive that is listening for output, the output will be sent to the tag instead of the output file, without the indentation, and the directive will produce no output. # Directive Specification This section contains detailed specification of each directive. @@ -167,6 +167,20 @@ Single-line only. The argument is `FILE_PATH` ++TXTPP#include foo.txt ++``` +## After Directive +#### USAGE +This directive is to explicitly specify dependency. +#### ARGUMENTS +Single-line only. The argument is `FILE_PATH` +#### BEHAVIOR +This directive behaves exactly like `include`, except it only changes the dependency structure and doesn't affect the output. + +This can be useful if there are implicit dependencies. For example, a `run` directive could execute a command that depends on a txtpp output. +#### EXAMPLE +++TXTPP#write ``` +++TXTPP#after foo.txt +++TXTPP#run ./my-script.sh foo.txt +++``` ## Run Directive #### USAGE diff --git a/src/core/execute/pp/directive/directive_from.rs b/src/core/execute/pp/directive/directive_from.rs index 4f1c655..46595af 100644 --- a/src/core/execute/pp/directive/directive_from.rs +++ b/src/core/execute/pp/directive/directive_from.rs @@ -386,4 +386,18 @@ mod ut { assert_eq!(expected, actual); } + + #[test] + fn test_detect_after() { + let line = " random TXTPP#after stuff\t\t"; + let expected = Some(Directive::new( + " ", + "random ", + DirectiveType::After, + vec!["stuff".to_string()], + )); + let actual = Directive::detect_from(line); + + assert_eq!(expected, actual); + } } diff --git a/src/core/execute/pp/directive/mod.rs b/src/core/execute/pp/directive/mod.rs index fc4190c..858bfc5 100644 --- a/src/core/execute/pp/directive/mod.rs +++ b/src/core/execute/pp/directive/mod.rs @@ -60,6 +60,8 @@ pub enum DirectiveType { Empty, /// Include directive, argument is path to a file Include, + /// After directive, argument is path to a file + After, /// Run directive, argument is a command Run, /// Tag directive, argument is a string @@ -81,6 +83,7 @@ impl TryFrom<&str> for DirectiveType { "tag" => Ok(DirectiveType::Tag), "temp" => Ok(DirectiveType::Temp), "write" => Ok(DirectiveType::Write), + "after" => Ok(DirectiveType::After), _ => Err(()), } } @@ -89,7 +92,10 @@ impl TryFrom<&str> for DirectiveType { impl DirectiveType { /// Does directive support multi-line arguments pub fn supports_multi_line(&self) -> bool { - !matches!(self, DirectiveType::Include | DirectiveType::Tag) + !matches!( + self, + DirectiveType::After | DirectiveType::Include | DirectiveType::Tag + ) } } @@ -98,6 +104,7 @@ impl Display for DirectiveType { match self { DirectiveType::Empty => write!(f, ""), DirectiveType::Include => write!(f, "include"), + DirectiveType::After => write!(f, "after"), DirectiveType::Run => write!(f, "run"), DirectiveType::Tag => write!(f, "tag"), DirectiveType::Temp => write!(f, "temp"), diff --git a/src/core/execute/pp/mod.rs b/src/core/execute/pp/mod.rs index 79417b2..ebbc676 100644 --- a/src/core/execute/pp/mod.rs +++ b/src/core/execute/pp/mod.rs @@ -218,7 +218,7 @@ impl<'a> Pp<'a> { }; let raw_output = match d.directive_type { - DirectiveType::Empty => { + DirectiveType::Empty | DirectiveType::After => { // do nothing (consume the line) None } @@ -286,7 +286,10 @@ impl<'a> Pp<'a> { // never collect deps in execute mode return Ok(Some(d)); } - if let DirectiveType::Include = d.directive_type { + if matches!( + d.directive_type, + DirectiveType::Include | DirectiveType::After + ) { let arg = d.args.first().cloned().unwrap_or_default(); let include_path = PathBuf::from(&arg); // We use join instead of share_base because the dependency might not exist diff --git a/tests/examples/after/example.expected b/tests/examples/after/example.expected new file mode 100644 index 0000000..b0f969d --- /dev/null +++ b/tests/examples/after/example.expected @@ -0,0 +1,3 @@ +In this example, the run directive executes a command that depends on foo. The after directive is used to make sure foo is produced before this file +hello + diff --git a/tests/examples/after/example.txtpp b/tests/examples/after/example.txtpp new file mode 100644 index 0000000..08f07ee --- /dev/null +++ b/tests/examples/after/example.txtpp @@ -0,0 +1,3 @@ +In this example, the run directive executes a command that depends on foo. The after directive is used to make sure foo is produced before this file +TXTPP#after foo +-TXTPP#run cat foo diff --git a/tests/examples/after/foo.txtpp b/tests/examples/after/foo.txtpp new file mode 100644 index 0000000..ce01362 --- /dev/null +++ b/tests/examples/after/foo.txtpp @@ -0,0 +1 @@ +hello diff --git a/tests/test.rs b/tests/test.rs index fc11583..38dcdff 100644 --- a/tests/test.rs +++ b/tests/test.rs @@ -232,3 +232,8 @@ testit!(tests__examples__temp__no_rewrite, |env| { assert_eq!(modified, modified4); // temp file is always checked before re-written assert_ne!(modified_out, modified_out4); }); + +testit!(tests__examples__after, |env| { + assert!(env.run().is_ok()); + env.assert_file_eq("example", "example.expected"); +});