Skip to content

Add the option to not print the filename #57

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

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
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
10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,16 @@ This will output the contents of every file, with each file preceded by its rela
...
```

- `--filename/--no-filename`: Control whether to show or hide filenames in the output (shown by default).

```bash
# Hide filenames in the output
files-to-prompt path/to/directory --no-filename

# Explicitly show filenames (default behavior)
files-to-prompt path/to/directory --filename
```

- `-0/--null`: Use NUL character as separator when reading paths from stdin. Useful when filenames may contain spaces.

```bash
Expand Down
49 changes: 35 additions & 14 deletions files_to_prompt/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,17 +52,18 @@ def add_line_numbers(content):
return "\n".join(numbered_lines)


def print_path(writer, path, content, cxml, markdown, line_numbers):
def print_path(writer, path, content, cxml, markdown, line_numbers, show_filename):
if cxml:
print_as_xml(writer, path, content, line_numbers)
print_as_xml(writer, path, content, line_numbers, show_filename)
elif markdown:
print_as_markdown(writer, path, content, line_numbers)
print_as_markdown(writer, path, content, line_numbers, show_filename)
else:
print_default(writer, path, content, line_numbers)
print_default(writer, path, content, line_numbers, show_filename)


def print_default(writer, path, content, line_numbers):
writer(path)
def print_default(writer, path, content, line_numbers, show_filename):
if show_filename:
writer(path)
writer("---")
if line_numbers:
content = add_line_numbers(content)
Expand All @@ -71,10 +72,11 @@ def print_default(writer, path, content, line_numbers):
writer("---")


def print_as_xml(writer, path, content, line_numbers):
def print_as_xml(writer, path, content, line_numbers, show_filename):
global global_index
writer(f'<document index="{global_index}">')
writer(f"<source>{path}</source>")
if show_filename:
writer(f"<source>{path}</source>")
writer("<document_content>")
if line_numbers:
content = add_line_numbers(content)
Expand All @@ -84,13 +86,14 @@ def print_as_xml(writer, path, content, line_numbers):
global_index += 1


def print_as_markdown(writer, path, content, line_numbers):
def print_as_markdown(writer, path, content, line_numbers, show_filename):
lang = EXT_TO_LANG.get(path.split(".")[-1], "")
# Figure out how many backticks to use
backticks = "```"
while backticks in content:
backticks += "`"
writer(path)
if show_filename:
writer(path)
writer(f"{backticks}{lang}")
if line_numbers:
content = add_line_numbers(content)
Expand All @@ -110,11 +113,12 @@ def process_path(
claude_xml,
markdown,
line_numbers=False,
show_filename=False,
):
if os.path.isfile(path):
try:
with open(path, "r") as f:
print_path(writer, path, f.read(), claude_xml, markdown, line_numbers)
print_path(writer, path, f.read(), claude_xml, markdown, line_numbers, show_filename)
except UnicodeDecodeError:
warning_message = f"Warning: Skipping file {path} due to UnicodeDecodeError"
click.echo(click.style(warning_message, fg="red"), err=True)
Expand Down Expand Up @@ -164,6 +168,7 @@ def process_path(
claude_xml,
markdown,
line_numbers,
show_filename,
)
except UnicodeDecodeError:
warning_message = (
Expand Down Expand Up @@ -244,6 +249,12 @@ def read_paths_from_stdin(use_null_separator):
is_flag=True,
help="Use NUL character as separator when reading from stdin",
)
@click.option(
"show_filename",
"--filename/--no-filename",
default=True,
help="Show or hide filename in the output (shown by default)",
)
@click.version_option()
def cli(
paths,
Expand All @@ -257,10 +268,11 @@ def cli(
markdown,
line_numbers,
null,
show_filename,
):
"""
Takes one or more paths to files or directories and outputs every file,
recursively, each one preceded with its filename like this:
recursively, each one preceded with its filename by default:

\b
path/to/file.py
Expand All @@ -271,15 +283,23 @@ def cli(
---
...

Use `--no-filename` to hide the filenames in the output.

If the `--cxml` flag is provided, the output will be structured as follows:

\b
<documents>
<document path="path/to/file1.txt">
<document index="1">
Copy link
Author

Choose a reason for hiding this comment

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

💬 This was updated because the documentation didn't follow what the implementation currently does.

<source>path/to/file1.txt</source> <!-- Unless --no-filename is used -->
<document_content>
Contents of file1.txt
</document_content>
</document>
<document path="path/to/file2.txt">
<document index="2">
<source>path/to/file2.txt</source> <!-- Unless --no-filename is used -->
<document_content>
Contents of file2.txt
</document_content>
</document>
...
</documents>
Expand Down Expand Up @@ -327,6 +347,7 @@ def cli(
claude_xml,
markdown,
line_numbers,
show_filename,
)
if claude_xml:
writer("</documents>")
Expand Down
63 changes: 63 additions & 0 deletions tests/test_files_to_prompt.py
Original file line number Diff line number Diff line change
Expand Up @@ -439,3 +439,66 @@ def test_markdown(tmpdir, option):
"`````\n"
)
assert expected.strip() == actual.strip()


@pytest.mark.parametrize(
"args,should_contain_filename",
[
([], True), # Default behavior (show filename)
(["--filename"], True), # Explicit flag to show filename
(["--no-filename"], False), # Explicit flag to hide filename
],
)
def test_filename_option(tmpdir, args, should_contain_filename):
runner = CliRunner()
with tmpdir.as_cwd():
os.makedirs("test_dir")
with open("test_dir/file1.txt", "w") as f:
f.write("Contents of file1")

result = runner.invoke(cli, ["test_dir"] + args)
assert result.exit_code == 0

if should_contain_filename:
assert "test_dir/file1.txt" in result.output
assert "---" in result.output
else:
assert "test_dir/file1.txt" not in result.output
# The content should still be there
assert "Contents of file1" in result.output


@pytest.mark.parametrize(
"args,should_contain_filename",
[
(["--cxml"], True), # Default with CXML
(["--cxml", "--filename"], True), # CXML with filename
(["--cxml", "--no-filename"], False), # CXML without filename
(["--markdown"], True), # Default with markdown
(["--markdown", "--filename"], True), # Markdown with filename
(["--markdown", "--no-filename"], False), # Markdown without filename
],
)
def test_filename_option_with_formats(tmpdir, args, should_contain_filename):
runner = CliRunner()
with tmpdir.as_cwd():
os.makedirs("test_dir")
with open("test_dir/file1.txt", "w") as f:
f.write("Contents of file1")

result = runner.invoke(cli, ["test_dir"] + args)
assert result.exit_code == 0

if should_contain_filename:
if "--cxml" in args:
assert "<source>test_dir/file1.txt</source>" in result.output
else:
assert "test_dir/file1.txt" in result.output
else:
if "--cxml" in args:
assert "<source>test_dir/file1.txt</source>" not in result.output
else:
assert "test_dir/file1.txt" not in result.output

# The content should always be there
assert "Contents of file1" in result.output