mirror of
https://github.com/simonw/files-to-prompt.git
synced 2025-10-23 00:02:47 +03:00
--code output to produce triple backtick markdown, closes #42
This commit is contained in:
40
README.md
40
README.md
@@ -64,6 +64,12 @@ This will output the contents of every file, with each file preceded by its rela
|
||||
files-to-prompt path/to/directory --cxml
|
||||
```
|
||||
|
||||
- `--code`: Output as fenced code blocks.
|
||||
|
||||
```bash
|
||||
files-to-prompt path/to/directory --code
|
||||
```
|
||||
|
||||
- `-o/--output <file>`: Write the output to a file instead of printing it to the console.
|
||||
|
||||
```bash
|
||||
@@ -208,6 +214,40 @@ Contents of file2.txt
|
||||
</documents>
|
||||
```
|
||||
|
||||
## --code fenced code block output
|
||||
|
||||
The `--code` option will output the files as fenced code blocks, which can be useful for pasting into Markdown documents.
|
||||
|
||||
```bash
|
||||
files-to-prompt path/to/directory --code
|
||||
```
|
||||
The language tag will be guessed based on the filename.
|
||||
|
||||
If the code itself contains triple backticks the wrapper around it will use one additional backtick.
|
||||
|
||||
Example output:
|
||||
`````
|
||||
myfile.py
|
||||
```python
|
||||
def my_function():
|
||||
return "Hello, world!"
|
||||
```
|
||||
other.js
|
||||
```javascript
|
||||
function myFunction() {
|
||||
return "Hello, world!";
|
||||
}
|
||||
```
|
||||
file_with_triple_backticks.md
|
||||
````markdown
|
||||
This file has its own
|
||||
```
|
||||
fenced code blocks
|
||||
```
|
||||
Inside it.
|
||||
````
|
||||
`````
|
||||
|
||||
## Development
|
||||
|
||||
To contribute to this tool, first checkout the code. Then create a new virtual environment:
|
||||
|
||||
@@ -6,6 +6,23 @@ import click
|
||||
|
||||
global_index = 1
|
||||
|
||||
EXT_TO_LANG = {
|
||||
"py": "python",
|
||||
"c": "c",
|
||||
"cpp": "cpp",
|
||||
"java": "java",
|
||||
"js": "javascript",
|
||||
"ts": "typescript",
|
||||
"html": "html",
|
||||
"css": "css",
|
||||
"xml": "xml",
|
||||
"json": "json",
|
||||
"yaml": "yaml",
|
||||
"yml": "yaml",
|
||||
"sh": "bash",
|
||||
"rb": "ruby",
|
||||
}
|
||||
|
||||
|
||||
def should_ignore(path, gitignore_rules):
|
||||
for rule in gitignore_rules:
|
||||
@@ -35,9 +52,11 @@ def add_line_numbers(content):
|
||||
return "\n".join(numbered_lines)
|
||||
|
||||
|
||||
def print_path(writer, path, content, xml, line_numbers):
|
||||
if xml:
|
||||
def print_path(writer, path, content, cxml, code, line_numbers):
|
||||
if cxml:
|
||||
print_as_xml(writer, path, content, line_numbers)
|
||||
elif code:
|
||||
print_as_code(writer, path, content, line_numbers)
|
||||
else:
|
||||
print_default(writer, path, content, line_numbers)
|
||||
|
||||
@@ -65,6 +84,20 @@ def print_as_xml(writer, path, content, line_numbers):
|
||||
global_index += 1
|
||||
|
||||
|
||||
def print_as_code(writer, path, content, line_numbers):
|
||||
lang = EXT_TO_LANG.get(path.split(".")[-1], "")
|
||||
# Figure out how many backticks to use
|
||||
backticks = "```"
|
||||
while backticks in content:
|
||||
backticks += "`"
|
||||
writer(path)
|
||||
writer(f"{backticks}{lang}")
|
||||
if line_numbers:
|
||||
content = add_line_numbers(content)
|
||||
writer(content)
|
||||
writer(f"{backticks}")
|
||||
|
||||
|
||||
def process_path(
|
||||
path,
|
||||
extensions,
|
||||
@@ -75,12 +108,13 @@ def process_path(
|
||||
ignore_patterns,
|
||||
writer,
|
||||
claude_xml,
|
||||
code,
|
||||
line_numbers=False,
|
||||
):
|
||||
if os.path.isfile(path):
|
||||
try:
|
||||
with open(path, "r") as f:
|
||||
print_path(writer, path, f.read(), claude_xml, line_numbers)
|
||||
print_path(writer, path, f.read(), claude_xml, code, line_numbers)
|
||||
except UnicodeDecodeError:
|
||||
warning_message = f"Warning: Skipping file {path} due to UnicodeDecodeError"
|
||||
click.echo(click.style(warning_message, fg="red"), err=True)
|
||||
@@ -124,7 +158,7 @@ def process_path(
|
||||
try:
|
||||
with open(file_path, "r") as f:
|
||||
print_path(
|
||||
writer, file_path, f.read(), claude_xml, line_numbers
|
||||
writer, file_path, f.read(), claude_xml, code, line_numbers
|
||||
)
|
||||
except UnicodeDecodeError:
|
||||
warning_message = (
|
||||
@@ -185,6 +219,9 @@ def read_paths_from_stdin(use_null_separator):
|
||||
is_flag=True,
|
||||
help="Output in XML-ish format suitable for Claude's long context window.",
|
||||
)
|
||||
@click.option(
|
||||
"--code", is_flag=True, help="Output in triple backtick fenced code blocks"
|
||||
)
|
||||
@click.option(
|
||||
"line_numbers",
|
||||
"-n",
|
||||
@@ -208,6 +245,7 @@ def cli(
|
||||
ignore_patterns,
|
||||
output_file,
|
||||
claude_xml,
|
||||
code,
|
||||
line_numbers,
|
||||
null,
|
||||
):
|
||||
@@ -236,6 +274,14 @@ def cli(
|
||||
</document>
|
||||
...
|
||||
</documents>
|
||||
|
||||
If the `--code` flag is provided, the output will be structured as follows:
|
||||
|
||||
\b
|
||||
path/to/file1.py
|
||||
```python
|
||||
Contents of file1.py
|
||||
```
|
||||
"""
|
||||
# Reset global_index for pytest
|
||||
global global_index
|
||||
@@ -270,6 +316,7 @@ def cli(
|
||||
ignore_patterns,
|
||||
writer,
|
||||
claude_xml,
|
||||
code,
|
||||
line_numbers,
|
||||
)
|
||||
if claude_xml:
|
||||
|
||||
@@ -375,3 +375,39 @@ def test_paths_from_arguments_and_stdin(tmpdir):
|
||||
assert "Contents of file1" in result.output
|
||||
assert "test_dir2/file2.txt" in result.output
|
||||
assert "Contents of file2" in result.output
|
||||
|
||||
|
||||
def test_code(tmpdir):
|
||||
runner = CliRunner()
|
||||
with tmpdir.as_cwd():
|
||||
os.makedirs("test_dir")
|
||||
with open("test_dir/python.py", "w") as f:
|
||||
f.write("This is python")
|
||||
with open("test_dir/python_with_quad_backticks.py", "w") as f:
|
||||
f.write("This is python with ```` in it already")
|
||||
with open("test_dir/code.js", "w") as f:
|
||||
f.write("This is javascript")
|
||||
with open("test_dir/code.unknown", "w") as f:
|
||||
f.write("This is an unknown file type")
|
||||
result = runner.invoke(cli, ["test_dir", "--code"])
|
||||
assert result.exit_code == 0
|
||||
actual = result.output
|
||||
expected = (
|
||||
"test_dir/code.js\n"
|
||||
"```javascript\n"
|
||||
"This is javascript\n"
|
||||
"```\n"
|
||||
"test_dir/code.unknown\n"
|
||||
"```\n"
|
||||
"This is an unknown file type\n"
|
||||
"```\n"
|
||||
"test_dir/python.py\n"
|
||||
"```python\n"
|
||||
"This is python\n"
|
||||
"```\n"
|
||||
"test_dir/python_with_quad_backticks.py\n"
|
||||
"`````python\n"
|
||||
"This is python with ```` in it already\n"
|
||||
"`````\n"
|
||||
)
|
||||
assert expected.strip() == actual.strip()
|
||||
|
||||
Reference in New Issue
Block a user