Skip to content

Commit cfc9fa5

Browse files
committed
--code output to produce triple backtick markdown, closes #42
1 parent 630bbf9 commit cfc9fa5

File tree

3 files changed

+127
-4
lines changed

3 files changed

+127
-4
lines changed

README.md

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,12 @@ This will output the contents of every file, with each file preceded by its rela
6464
files-to-prompt path/to/directory --cxml
6565
```
6666

67+
- `--code`: Output as fenced code blocks.
68+
69+
```bash
70+
files-to-prompt path/to/directory --code
71+
```
72+
6773
- `-o/--output <file>`: Write the output to a file instead of printing it to the console.
6874

6975
```bash
@@ -208,6 +214,40 @@ Contents of file2.txt
208214
</documents>
209215
```
210216

217+
## --code fenced code block output
218+
219+
The `--code` option will output the files as fenced code blocks, which can be useful for pasting into Markdown documents.
220+
221+
```bash
222+
files-to-prompt path/to/directory --code
223+
```
224+
The language tag will be guessed based on the filename.
225+
226+
If the code itself contains triple backticks the wrapper around it will use one additional backtick.
227+
228+
Example output:
229+
`````
230+
myfile.py
231+
```python
232+
def my_function():
233+
return "Hello, world!"
234+
```
235+
other.js
236+
```javascript
237+
function myFunction() {
238+
return "Hello, world!";
239+
}
240+
```
241+
file_with_triple_backticks.md
242+
````markdown
243+
This file has its own
244+
```
245+
fenced code blocks
246+
```
247+
Inside it.
248+
````
249+
`````
250+
211251
## Development
212252

213253
To contribute to this tool, first checkout the code. Then create a new virtual environment:

files_to_prompt/cli.py

Lines changed: 51 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,23 @@
66

77
global_index = 1
88

9+
EXT_TO_LANG = {
10+
"py": "python",
11+
"c": "c",
12+
"cpp": "cpp",
13+
"java": "java",
14+
"js": "javascript",
15+
"ts": "typescript",
16+
"html": "html",
17+
"css": "css",
18+
"xml": "xml",
19+
"json": "json",
20+
"yaml": "yaml",
21+
"yml": "yaml",
22+
"sh": "bash",
23+
"rb": "ruby",
24+
}
25+
926

1027
def should_ignore(path, gitignore_rules):
1128
for rule in gitignore_rules:
@@ -35,9 +52,11 @@ def add_line_numbers(content):
3552
return "\n".join(numbered_lines)
3653

3754

38-
def print_path(writer, path, content, xml, line_numbers):
39-
if xml:
55+
def print_path(writer, path, content, cxml, code, line_numbers):
56+
if cxml:
4057
print_as_xml(writer, path, content, line_numbers)
58+
elif code:
59+
print_as_code(writer, path, content, line_numbers)
4160
else:
4261
print_default(writer, path, content, line_numbers)
4362

@@ -65,6 +84,20 @@ def print_as_xml(writer, path, content, line_numbers):
6584
global_index += 1
6685

6786

87+
def print_as_code(writer, path, content, line_numbers):
88+
lang = EXT_TO_LANG.get(path.split(".")[-1], "")
89+
# Figure out how many backticks to use
90+
backticks = "```"
91+
while backticks in content:
92+
backticks += "`"
93+
writer(path)
94+
writer(f"{backticks}{lang}")
95+
if line_numbers:
96+
content = add_line_numbers(content)
97+
writer(content)
98+
writer(f"{backticks}")
99+
100+
68101
def process_path(
69102
path,
70103
extensions,
@@ -75,12 +108,13 @@ def process_path(
75108
ignore_patterns,
76109
writer,
77110
claude_xml,
111+
code,
78112
line_numbers=False,
79113
):
80114
if os.path.isfile(path):
81115
try:
82116
with open(path, "r") as f:
83-
print_path(writer, path, f.read(), claude_xml, line_numbers)
117+
print_path(writer, path, f.read(), claude_xml, code, line_numbers)
84118
except UnicodeDecodeError:
85119
warning_message = f"Warning: Skipping file {path} due to UnicodeDecodeError"
86120
click.echo(click.style(warning_message, fg="red"), err=True)
@@ -124,7 +158,7 @@ def process_path(
124158
try:
125159
with open(file_path, "r") as f:
126160
print_path(
127-
writer, file_path, f.read(), claude_xml, line_numbers
161+
writer, file_path, f.read(), claude_xml, code, line_numbers
128162
)
129163
except UnicodeDecodeError:
130164
warning_message = (
@@ -185,6 +219,9 @@ def read_paths_from_stdin(use_null_separator):
185219
is_flag=True,
186220
help="Output in XML-ish format suitable for Claude's long context window.",
187221
)
222+
@click.option(
223+
"--code", is_flag=True, help="Output in triple backtick fenced code blocks"
224+
)
188225
@click.option(
189226
"line_numbers",
190227
"-n",
@@ -208,6 +245,7 @@ def cli(
208245
ignore_patterns,
209246
output_file,
210247
claude_xml,
248+
code,
211249
line_numbers,
212250
null,
213251
):
@@ -236,6 +274,14 @@ def cli(
236274
</document>
237275
...
238276
</documents>
277+
278+
If the `--code` flag is provided, the output will be structured as follows:
279+
280+
\b
281+
path/to/file1.py
282+
```python
283+
Contents of file1.py
284+
```
239285
"""
240286
# Reset global_index for pytest
241287
global global_index
@@ -270,6 +316,7 @@ def cli(
270316
ignore_patterns,
271317
writer,
272318
claude_xml,
319+
code,
273320
line_numbers,
274321
)
275322
if claude_xml:

tests/test_files_to_prompt.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -375,3 +375,39 @@ def test_paths_from_arguments_and_stdin(tmpdir):
375375
assert "Contents of file1" in result.output
376376
assert "test_dir2/file2.txt" in result.output
377377
assert "Contents of file2" in result.output
378+
379+
380+
def test_code(tmpdir):
381+
runner = CliRunner()
382+
with tmpdir.as_cwd():
383+
os.makedirs("test_dir")
384+
with open("test_dir/python.py", "w") as f:
385+
f.write("This is python")
386+
with open("test_dir/python_with_quad_backticks.py", "w") as f:
387+
f.write("This is python with ```` in it already")
388+
with open("test_dir/code.js", "w") as f:
389+
f.write("This is javascript")
390+
with open("test_dir/code.unknown", "w") as f:
391+
f.write("This is an unknown file type")
392+
result = runner.invoke(cli, ["test_dir", "--code"])
393+
assert result.exit_code == 0
394+
actual = result.output
395+
expected = (
396+
"test_dir/code.js\n"
397+
"```javascript\n"
398+
"This is javascript\n"
399+
"```\n"
400+
"test_dir/code.unknown\n"
401+
"```\n"
402+
"This is an unknown file type\n"
403+
"```\n"
404+
"test_dir/python.py\n"
405+
"```python\n"
406+
"This is python\n"
407+
"```\n"
408+
"test_dir/python_with_quad_backticks.py\n"
409+
"`````python\n"
410+
"This is python with ```` in it already\n"
411+
"`````\n"
412+
)
413+
assert expected.strip() == actual.strip()

0 commit comments

Comments
 (0)