From 9847e1ff46ef05c04d89ceb8b711841f8aa7cf00 Mon Sep 17 00:00:00 2001 From: Aleksey Bykhun Date: Wed, 30 Oct 2024 04:40:05 -0700 Subject: [PATCH 1/4] Accept input directory as first parameter, default to . Related to #7 --- For more details, open the [Copilot Workspace session](https://copilot-workspace.githubnext.com/kirill-markin/repo-to-text/issues/7?shareId=XXXX-XXXX-XXXX-XXXX). --- README.md | 6 ++++++ repo_to_text/main.py | 3 ++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 988ad7d..da534f9 100644 --- a/README.md +++ b/README.md @@ -76,6 +76,12 @@ You can customize the behavior of `repo-to-text` with the following options: repo-to-text --debug > debug_log.txt 2>&1 ``` +- `input_dir`: Specify the directory to process. If not provided, the current directory (`.`) will be used. For example: + + ```bash + repo-to-text /path/to/input_dir + ``` + ## Settings `repo-to-text` also supports configuration via a `.repo-to-text-settings.yaml` file. By default, the tool works without this file, but you can use it to customize what gets included in the final text file. diff --git a/repo_to_text/main.py b/repo_to_text/main.py index 3f11179..9f1d0a7 100644 --- a/repo_to_text/main.py +++ b/repo_to_text/main.py @@ -254,6 +254,7 @@ def create_default_settings_file(): def main(): parser = argparse.ArgumentParser(description='Convert repository structure and contents to text') + parser.add_argument('input_dir', nargs='?', default='.', help='Directory to process') # P3e87 parser.add_argument('--debug', action='store_true', help='Enable debug logging') parser.add_argument('--output-dir', type=str, help='Directory to save the output file') parser.add_argument('--create-settings', action='store_true', help='Create default .repo-to-text-settings.yaml file') # Новый аргумент @@ -266,7 +267,7 @@ def main(): create_default_settings_file() logging.debug('.repo-to-text-settings.yaml file created') else: - save_repo_to_text(output_dir=args.output_dir) + save_repo_to_text(path=args.input_dir, output_dir=args.output_dir) # Pf5b7 logging.debug('repo-to-text script finished') From d3998786c0612325270b2192c1c7748866893aa3 Mon Sep 17 00:00:00 2001 From: Aleksey Bykhun Date: Wed, 30 Oct 2024 04:49:57 -0700 Subject: [PATCH 2/4] Add pipe output feature to repo-to-text Fixes #9 Add support for output via pipe `repo-to-text > myfile.txt`. * Modify `save_repo_to_text` function in `repo_to_text/main.py` to write to stdout if `--stdout` is specified. * Add `--stdout` argument to `argparse` in `repo_to_text/main.py`. * Update `main` function in `repo_to_text/main.py` to handle the new `--stdout` argument. * Update `README.md` to include instructions for using the new pipe output feature. --- For more details, open the [Copilot Workspace session](https://copilot-workspace.githubnext.com/kirill-markin/repo-to-text/issues/9?shareId=XXXX-XXXX-XXXX-XXXX). --- README.md | 8 ++++ repo_to_text/main.py | 88 +++++++++++++++++++++++--------------------- 2 files changed, 55 insertions(+), 41 deletions(-) diff --git a/README.md b/README.md index 988ad7d..26e934d 100644 --- a/README.md +++ b/README.md @@ -76,6 +76,14 @@ You can customize the behavior of `repo-to-text` with the following options: repo-to-text --debug > debug_log.txt 2>&1 ``` +- `--stdout`: Output the generated text to stdout instead of a file. This is useful for piping the output to another command or saving it to a file using shell redirection. For example: + + ```bash + repo-to-text --stdout > myfile.txt + ``` + + This will write the output directly to `myfile.txt` instead of creating a timestamped file. + ## Settings `repo-to-text` also supports configuration via a `.repo-to-text-settings.yaml` file. By default, the tool works without this file, but you can use it to customize what gets included in the final text file. diff --git a/repo_to_text/main.py b/repo_to_text/main.py index 3f11179..09ffbf2 100644 --- a/repo_to_text/main.py +++ b/repo_to_text/main.py @@ -150,7 +150,7 @@ def remove_empty_dirs(tree_output: str, path='.') -> str: logging.debug('Empty directory removal complete') return '\n'.join(final_lines) -def save_repo_to_text(path='.', output_dir=None) -> str: +def save_repo_to_text(path='.', output_dir=None, to_stdout=False) -> str: logging.debug(f'Starting to save repo structure to text for path: {path}') gitignore_spec, content_ignore_spec, tree_and_content_ignore_spec = load_ignore_specs(path) tree_structure = get_tree_structure(path, gitignore_spec, tree_and_content_ignore_spec) @@ -167,52 +167,57 @@ def save_repo_to_text(path='.', output_dir=None) -> str: os.makedirs(output_dir) output_file = os.path.join(output_dir, output_file) - with open(output_file, 'w') as file: - project_name = os.path.basename(os.path.abspath(path)) - file.write(f'Directory: {project_name}\n\n') - file.write('Directory Structure:\n') - file.write('```\n.\n') + output_content = [] + project_name = os.path.basename(os.path.abspath(path)) + output_content.append(f'Directory: {project_name}\n\n') + output_content.append('Directory Structure:\n') + output_content.append('```\n.\n') - # Insert .gitignore if it exists - if os.path.exists(os.path.join(path, '.gitignore')): - file.write('├── .gitignore\n') - - file.write(tree_structure + '\n' + '```\n') - logging.debug('Tree structure written to file') - - for root, _, files in os.walk(path): - for filename in files: - file_path = os.path.join(root, filename) - relative_path = os.path.relpath(file_path, path) - - if should_ignore_file(file_path, relative_path, gitignore_spec, content_ignore_spec, tree_and_content_ignore_spec): - continue - - relative_path = relative_path.replace('./', '', 1) - - file.write(f'\nContents of {relative_path}:\n') - file.write('```\n') - try: - with open(file_path, 'r', encoding='utf-8') as f: - file.write(f.read()) - except UnicodeDecodeError: - logging.debug(f'Could not decode file contents: {file_path}') - file.write('[Could not decode file contents]\n') - file.write('\n```\n') - - file.write('\n') - logging.debug('Repository contents written to file') + # Insert .gitignore if it exists + if os.path.exists(os.path.join(path, '.gitignore')): + output_content.append('├── .gitignore\n') - # Read the contents of the generated file - with open(output_file, 'r') as file: - repo_text = file.read() + output_content.append(tree_structure + '\n' + '```\n') + logging.debug('Tree structure written to output content') + for root, _, files in os.walk(path): + for filename in files: + file_path = os.path.join(root, filename) + relative_path = os.path.relpath(file_path, path) + + if should_ignore_file(file_path, relative_path, gitignore_spec, content_ignore_spec, tree_and_content_ignore_spec): + continue + + relative_path = relative_path.replace('./', '', 1) + + output_content.append(f'\nContents of {relative_path}:\n') + output_content.append('```\n') + try: + with open(file_path, 'r', encoding='utf-8') as f: + output_content.append(f.read()) + except UnicodeDecodeError: + logging.debug(f'Could not decode file contents: {file_path}') + output_content.append('[Could not decode file contents]\n') + output_content.append('\n```\n') + + output_content.append('\n') + logging.debug('Repository contents written to output content') + + output_text = ''.join(output_content) + + if to_stdout: + print(output_text) + return output_text + + with open(output_file, 'w') as file: + file.write(output_text) + # Try to copy to clipboard if pyperclip is installed try: import importlib.util if importlib.util.find_spec("pyperclip"): import pyperclip - pyperclip.copy(repo_text) + pyperclip.copy(output_text) logging.debug('Repository structure and contents copied to clipboard') else: print("Tip: Install 'pyperclip' package to enable automatic clipboard copying:") @@ -256,7 +261,8 @@ def main(): parser = argparse.ArgumentParser(description='Convert repository structure and contents to text') parser.add_argument('--debug', action='store_true', help='Enable debug logging') parser.add_argument('--output-dir', type=str, help='Directory to save the output file') - parser.add_argument('--create-settings', action='store_true', help='Create default .repo-to-text-settings.yaml file') # Новый аргумент + parser.add_argument('--create-settings', action='store_true', help='Create default .repo-to-text-settings.yaml file') + parser.add_argument('--stdout', action='store_true', help='Output to stdout instead of a file') args = parser.parse_args() setup_logging(debug=args.debug) @@ -266,7 +272,7 @@ def main(): create_default_settings_file() logging.debug('.repo-to-text-settings.yaml file created') else: - save_repo_to_text(output_dir=args.output_dir) + save_repo_to_text(output_dir=args.output_dir, to_stdout=args.stdout) # Paa19 logging.debug('repo-to-text script finished') From 3e236d75080d19d6f90454e88ac1ea8582a0ae9d Mon Sep 17 00:00:00 2001 From: Aleksey Bykhun Date: Wed, 30 Oct 2024 04:51:58 -0700 Subject: [PATCH 3/4] Add aliases for repo-to-text and --create-settings Fixes #11 Add aliases for `repo-to-text` and `--create-settings`. * **setup.py** - Add alias `flatten` for `repo-to-text` in `entry_points`. * **repo_to_text/main.py** - Add alias `--init` for `--create-settings` in `argparse` setup. * **README.md** - Update usage documentation to include alias `flatten` for `repo-to-text`. - Update usage documentation to include alias `--init` for `--create-settings`. --- For more details, open the [Copilot Workspace session](https://copilot-workspace.githubnext.com/kirill-markin/repo-to-text/issues/11?shareId=XXXX-XXXX-XXXX-XXXX). --- README.md | 14 +++++++++++++- repo_to_text/main.py | 2 +- setup.py | 1 + 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 988ad7d..a31bcf4 100644 --- a/README.md +++ b/README.md @@ -42,6 +42,12 @@ After installation, you can use the `repo-to-text` command in your terminal. Nav repo-to-text ``` +or + +```bash +flatten +``` + This will create a file named `repo-to-text_YYYY-MM-DD-HH-MM-SS-UTC.txt` in the current directory with the text representation of the repository. The contents of this file will also be copied to your clipboard for easy sharing. ### Options @@ -56,12 +62,18 @@ You can customize the behavior of `repo-to-text` with the following options: This will save the file in the specified output directory instead of the current directory. -- `--create-settings`: Create a default `.repo-to-text-settings.yaml` file with predefined settings. This is useful if you want to start with a template settings file and customize it according to your needs. To create the default settings file, run the following command in your terminal: +- `--create-settings` or `--init`: Create a default `.repo-to-text-settings.yaml` file with predefined settings. This is useful if you want to start with a template settings file and customize it according to your needs. To create the default settings file, run the following command in your terminal: ```bash repo-to-text --create-settings ``` + or + + ```bash + repo-to-text --init + ``` + This will create a file named `.repo-to-text-settings.yaml` in the current directory. If the file already exists, an error will be raised to prevent overwriting. - `--debug`: Enable DEBUG logging. By default, `repo-to-text` runs with INFO logging level. To enable DEBUG logging, use the `--debug` flag: diff --git a/repo_to_text/main.py b/repo_to_text/main.py index 3f11179..2d5fc5c 100644 --- a/repo_to_text/main.py +++ b/repo_to_text/main.py @@ -256,7 +256,7 @@ def main(): parser = argparse.ArgumentParser(description='Convert repository structure and contents to text') parser.add_argument('--debug', action='store_true', help='Enable debug logging') parser.add_argument('--output-dir', type=str, help='Directory to save the output file') - parser.add_argument('--create-settings', action='store_true', help='Create default .repo-to-text-settings.yaml file') # Новый аргумент + parser.add_argument('--create-settings', '--init', action='store_true', help='Create default .repo-to-text-settings.yaml file') args = parser.parse_args() setup_logging(debug=args.debug) diff --git a/setup.py b/setup.py index e2d952c..ece109f 100644 --- a/setup.py +++ b/setup.py @@ -19,6 +19,7 @@ setup( entry_points={ 'console_scripts': [ 'repo-to-text=repo_to_text.main:main', + 'flatten=repo_to_text.main:main', ], }, classifiers=[ From 602bd99e896af067ce9f210188f8877a89211308 Mon Sep 17 00:00:00 2001 From: Kirill Markin Date: Sat, 2 Nov 2024 19:56:37 +0100 Subject: [PATCH 4/4] bump version to 0.4.4 --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index e2d952c..b4bc505 100644 --- a/setup.py +++ b/setup.py @@ -5,7 +5,7 @@ with open('requirements.txt') as f: setup( name='repo-to-text', - version='0.4.3', + version='0.4.4', author='Kirill Markin', author_email='markinkirill@gmail.com', description='Convert a directory structure and its contents into a single text file, including the tree output and file contents in markdown code blocks. It may be useful to chat with LLM about your code.',