--ignore patterns now include directory names unless --ignore-files-only (#30)

* Option to --include-directories otherwise ignored by an ignore pattern
* --include-directories renamed to --ignore-files-only

Refs https://github.com/simonw/files-to-prompt/pull/30/#issuecomment-2658177542

---------

Co-authored-by: Simon Willison <swillison@gmail.com>
This commit is contained in:
Nick Powell
2025-02-14 03:28:32 +00:00
committed by GitHub
parent c4f6fbefd7
commit acbe107f49
3 changed files with 53 additions and 5 deletions

View File

@@ -41,13 +41,19 @@ This will output the contents of every file, with each file preceded by its rela
files-to-prompt path/to/directory --include-hidden
```
- `--ignore-files-only`: Include directory paths which would otherwise be ignored by an `--ignore` pattern.
```bash
files-to-prompt path/to/directory --ignore-files-only --ignore "*dir*"
```
- `--ignore-gitignore`: Ignore `.gitignore` files and include all files.
```bash
files-to-prompt path/to/directory --ignore-gitignore
```
- `--ignore <pattern>`: Specify one or more patterns to ignore. Can be used multiple times.
- `--ignore <pattern>`: Specify one or more patterns to ignore. Can be used multiple times. Patterns may match file names and directory names, unless you also specify `--ignore-files-only`.
```bash
files-to-prompt path/to/directory --ignore "*.log" --ignore "temp*"
```
@@ -138,6 +144,19 @@ Contents of file3.txt
---
```
If you run `files-to-prompt my_directory --ignore "sub*"`, the output will exclude all files in `subdirectory/` (unless you also specify `--ignore-files-only`):
```
my_directory/file1.txt
---
Contents of file1.txt
---
my_directory/file2.txt
---
Contents of file2.txt
---
```
### Claude XML Output
Anthropic has provided [specific guidelines](https://docs.anthropic.com/claude/docs/long-context-window-tips) for optimally structuring prompts to take advantage of Claude's extended context window.

View File

@@ -68,6 +68,7 @@ def process_path(
path,
extensions,
include_hidden,
ignore_files_only,
ignore_gitignore,
gitignore_rules,
ignore_patterns,
@@ -102,6 +103,12 @@ def process_path(
]
if ignore_patterns:
if not ignore_files_only:
dirs[:] = [
d
for d in dirs
if not any(fnmatch(d, pattern) for pattern in ignore_patterns)
]
files = [
f
for f in files
@@ -133,6 +140,11 @@ def process_path(
is_flag=True,
help="Include files and folders starting with .",
)
@click.option(
"--ignore-files-only",
is_flag=True,
help="--ignore option only ignores files",
)
@click.option(
"--ignore-gitignore",
is_flag=True,
@@ -171,6 +183,7 @@ def cli(
paths,
extensions,
include_hidden,
ignore_files_only,
ignore_gitignore,
ignore_patterns,
output_file,
@@ -223,6 +236,7 @@ def cli(
path,
extensions,
include_hidden,
ignore_files_only,
ignore_gitignore,
gitignore_rules,
ignore_patterns,

View File

@@ -88,7 +88,7 @@ def test_multiple_paths(tmpdir):
def test_ignore_patterns(tmpdir):
runner = CliRunner()
with tmpdir.as_cwd():
os.makedirs("test_dir")
os.makedirs("test_dir", exist_ok=True)
with open("test_dir/file_to_ignore.txt", "w") as f:
f.write("This file should be ignored due to ignore patterns")
with open("test_dir/file_to_include.txt", "w") as f:
@@ -100,12 +100,27 @@ def test_ignore_patterns(tmpdir):
assert "This file should be ignored due to ignore patterns" not in result.output
assert "test_dir/file_to_include.txt" not in result.output
result = runner.invoke(cli, ["test_dir", "--ignore", "file_to_ignore.*"])
os.makedirs("test_dir/test_subdir", exist_ok=True)
with open("test_dir/test_subdir/any_file.txt", "w") as f:
f.write("This entire subdirectory should be ignored due to ignore patterns")
result = runner.invoke(cli, ["test_dir", "--ignore", "*subdir*"])
assert result.exit_code == 0
assert "test_dir/file_to_ignore.txt" not in result.output
assert "This file should be ignored due to ignore patterns" not in result.output
assert "test_dir/test_subdir/any_file.txt" not in result.output
assert (
"This entire subdirectory should be ignored due to ignore patterns"
not in result.output
)
assert "test_dir/file_to_include.txt" in result.output
assert "This file should be included" in result.output
assert "This file should be included" in result.output
result = runner.invoke(
cli, ["test_dir", "--ignore", "*subdir*", "--ignore-files-only"]
)
assert result.exit_code == 0
assert "test_dir/test_subdir/any_file.txt" in result.output
result = runner.invoke(cli, ["test_dir", "--ignore", ""])
def test_specific_extensions(tmpdir):