Skip to content
This repository was archived by the owner on Sep 9, 2025. It is now read-only.

Add CLI options to control output files#76

Merged
hendrikvanantwerpen merged 10 commits intomainfrom
output-control
Apr 21, 2022
Merged

Add CLI options to control output files#76
hendrikvanantwerpen merged 10 commits intomainfrom
output-control

Conversation

@hendrikvanantwerpen
Copy link
Contributor

@hendrikvanantwerpen hendrikvanantwerpen commented Apr 6, 2022

Currently any file output produced by the CLI is put next to the input file it relates to. This PR adds optional arguments to the --save-* flags to specify the filename. Placeholders can be used that are substituted based on the input path.

The default changed to saving the file in the current directory, using the same name as the test file, but excluding directories. For example, %n.html for visualization.

One notable change is that --save-* take their argument with equals signs instead of using a separate argument. So, --save-graph=%n.html instead of --save-graph %n.html. This is to prevent accidental overwriting of user files when a user issues a command such as tree-sitter-stack-graphs test --save-graph first.py second.py where first.py would unintentionally be interpreted as the path to use for saving the visualization, instead of the first test path.

Fixes https://github.com/github/semantic-code/issues/299.

Output of `tree-sitter-stack-graphs test --help`
tree-sitter-stack-graphs-test
Run tests

USAGE:
    tree-sitter-stack-graphs test [OPTIONS] <TEST_PATH>...

ARGS:
    <TEST_PATH>...    Test file or directory paths

OPTIONS:
    -G, --save-graph[=<PATH_SPEC>...]
            Save graph for tests matching output mode. Takes an optional path specification argument
            for the output file. [default: %n.graph.json]

        --grammar <GRAMMAR_PATH>
            The path to look for tree-sitter grammars. Can be specified multiple times

    -h, --help
            Print help information

        --hide-failure-errors
            Hide failure error details

        --hide-passing
            Hide passing tests

        --output-mode <OUTPUT_MODE>
            Controls when graphs, paths, or visualization are saved [default: on-failure] [possible
            values: always, on-failure]

    -P, --save-paths[=<PATH_SPEC>...]
            Save paths for tests matching output mode. Takes an optional path specification argument
            for the output file. [default: %n.paths.json]

        --scope <SCOPE>
            The scope of the tree-sitter grammar. See https://tree-sitter.github.io/tree-
            sitter/syntax-highlighting#basics for details

        --show-ignored
            Show ignored files in output

        --tsg <TSG_PATH>
            The TSG file to use for stack graph construction

    -V, --save-visualization[=<PATH_SPEC>...]
            Save visualization for tests matching output mode. Takes an optional path specification
            argument for the output file. [default: %n.html]

PATH SPECIFICATIONS:
    Output filenames can be specified using placeholders based on the input file. The
    following placeholders are supported:
         %r   the root path, which is the directory argument which contains the file,
              or the directory of the file argument
         %d   the path directories relative to the root
         %n   the name of the file
         %e   the file extension (including the preceding dot)
         %%   a literal percentage sign
    Empty directory placeholders (%r and %d) are replaced by "." so that the shape of
    the path is not accidently changed. For example, "test -V %d/%n.html mytest.py"
    results in "./mytest.html" instead of the unintented "/mytest.html".

@hendrikvanantwerpen hendrikvanantwerpen self-assigned this Apr 6, 2022
@hendrikvanantwerpen hendrikvanantwerpen requested a review from a team April 6, 2022 17:13
@hendrikvanantwerpen hendrikvanantwerpen marked this pull request as ready for review April 6, 2022 17:14
Copy link
Contributor

@robrix robrix left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Coupla thoughts you can address or not at your option. Nice one 👍🏻

Comment on lines -20 to +21
/// The TSG file to use for stack graph construction
#[clap(long)]
#[clap(name = "TSG_PATH")]
/// The TSG file to use for stack graph construction.
#[clap(long, value_name = "TSG_PATH")]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you give me a quick explanation of these annotations? I'm pretty sure I follow what they're doing, but I'm uncertain what they are, if that makes any sense.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Of course! The clap(...) annotation says this is a command-line argument. long means that it is a long form argument (--XYZ), and because no name is provided, the field name is used. So, the argument is --tsg in this case. You can also use long = "the-tsg" to have a different flag name than field name. The value_name specifies the placeholder that is displayed in the help. So, it'll show something like --tsg TSG_PATH there. If omitted, it derives something from either the type or the field name. I think it was the field name, so it would have been displayed as --tsg TSG.

output_mode: OutputMode,
}

fn validate_path(path: &str) -> Result<PathBuf, String> {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we intend to support Windows? If so, @patrickt tells me that paths there can contain byte sequences which are generally invalid in strings, which could (I am unsure!) make str the wrong representation for this argument.

Personally I'm in favour of explicitly either treating Windows as unsupported or at least paths like that.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for catching that! I have used Path already in most places, so that Windows paths should be supported. I'll change this validator to also work on OsStr and accepts all valid Windows path.

I'll also add something to the help that explains how path specifiers and non-Unicode paths work together.

Comment on lines 152 to 154
total_failure_count += self
.run_test(test_root, test_path, &mut loader)
.with_context(|| format!("Error running test {}", test_path.display()))?;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wouldn't mind seeing this extracted into a separate function and called here and below, but it needn't block this PR.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm on the fence, since the factored out function is so small. But, it does improve readability of this code a bit, so I'll do it.

Hendrik van Antwerpen added 2 commits April 21, 2022 12:35
- Accept all valid paths for the tests argument, by changing the
  validator to accept OsStr.
- Add not about path specifications and the handling of non-Unicode
  paths on Windows.
@hendrikvanantwerpen hendrikvanantwerpen merged commit 2ee3ebe into main Apr 21, 2022
@hendrikvanantwerpen hendrikvanantwerpen deleted the output-control branch April 21, 2022 10:56
@robrix
Copy link
Contributor

robrix commented Apr 21, 2022

🎉

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants