kopipasta 0.18.0__py3-none-any.whl → 0.20.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of kopipasta might be problematic. Click here for more details.

kopipasta/main.py CHANGED
@@ -5,6 +5,8 @@ import json
5
5
  import os
6
6
  import argparse
7
7
  import re
8
+ import subprocess
9
+ import tempfile
8
10
  from typing import Dict, List, Optional, Set, Tuple
9
11
  import pyperclip
10
12
  import fnmatch
@@ -434,6 +436,10 @@ def get_file_snippet(file_path, max_lines=50, max_bytes=4096):
434
436
  byte_count += len(line.encode('utf-8'))
435
437
  return snippet
436
438
 
439
+ def get_colored_file_snippet(file_path, max_lines=50, max_bytes=4096):
440
+ snippet = get_file_snippet(file_path, max_lines, max_bytes)
441
+ return get_colored_code(file_path, snippet)
442
+
437
443
  def print_char_count(count):
438
444
  token_estimate = count // 4
439
445
  print(f"\rCurrent prompt size: {count} characters (~ {token_estimate} tokens)", flush=True)
@@ -683,7 +689,7 @@ def handle_env_variables(content, env_vars):
683
689
 
684
690
  return content
685
691
 
686
- def generate_prompt(files_to_include: List[FileTuple], ignore_patterns: List[str], web_contents: Dict[str, Tuple[FileTuple, str]], env_vars: Dict[str, str]) -> str:
692
+ def generate_prompt_template(files_to_include: List[FileTuple], ignore_patterns: List[str], web_contents: Dict[str, Tuple[FileTuple, str]], env_vars: Dict[str, str]) -> Tuple[str, int]:
687
693
  prompt = "# Project Overview\n\n"
688
694
  prompt += "## Project Structure\n\n"
689
695
  prompt += "```\n"
@@ -716,8 +722,8 @@ def generate_prompt(files_to_include: List[FileTuple], ignore_patterns: List[str
716
722
  prompt += f"### {url}{' (snippet)' if is_snippet else ''}\n\n```{language}\n{content}\n```\n\n"
717
723
 
718
724
  prompt += "## Task Instructions\n\n"
719
- task_instructions = input("Enter the task instructions: ")
720
- prompt += f"{task_instructions}\n\n"
725
+ cursor_position = len(prompt)
726
+ prompt += "\n\n"
721
727
  prompt += "## Instructions for Achieving the Task\n\n"
722
728
  analysis_text = (
723
729
  "1. **Confirm and Understand the Task**:\n"
@@ -745,12 +751,38 @@ def generate_prompt(files_to_include: List[FileTuple], ignore_patterns: List[str
745
751
  " - Request the user to share any error messages or outputs from debugging to assist further.\n"
746
752
  )
747
753
  prompt += analysis_text
748
- return prompt
754
+ return prompt, cursor_position
749
755
 
756
+ def open_editor_for_input(template: str, cursor_position: int) -> str:
757
+ editor = os.environ.get('EDITOR', 'vim')
758
+ with tempfile.NamedTemporaryFile(mode='w+', suffix='.md', delete=False) as temp_file:
759
+ temp_file.write(template)
760
+ temp_file.flush()
761
+ temp_file_path = temp_file.name
762
+
763
+ try:
764
+ cursor_line = template[:cursor_position].count('\n') + 1
765
+ cursor_column = cursor_position - template.rfind('\n', 0, cursor_position)
766
+
767
+ if 'vim' in editor or 'nvim' in editor:
768
+ subprocess.call([editor, f'+call cursor({cursor_line}, {cursor_column})', '+startinsert', temp_file_path])
769
+ elif 'emacs' in editor:
770
+ subprocess.call([editor, f'+{cursor_line}:{cursor_column}', temp_file_path])
771
+ elif 'nano' in editor:
772
+ subprocess.call([editor, f'+{cursor_line},{cursor_column}', temp_file_path])
773
+ else:
774
+ subprocess.call([editor, temp_file_path])
775
+
776
+ with open(temp_file_path, 'r') as file:
777
+ content = file.read()
778
+ return content
779
+ finally:
780
+ os.unlink(temp_file_path)
750
781
 
751
782
  def main():
752
783
  parser = argparse.ArgumentParser(description="Generate a prompt with project structure, file contents, and web content.")
753
784
  parser.add_argument('inputs', nargs='+', help='Files, directories, or URLs to include in the prompt')
785
+ parser.add_argument('-t', '--task', help='Task description for the AI prompt')
754
786
  args = parser.parse_args()
755
787
 
756
788
  ignore_patterns = read_gitignore()
@@ -803,7 +835,9 @@ def main():
803
835
  use_snippet = is_large_file(input_path)
804
836
  files_to_include.append((input_path, use_snippet, None, get_language_for_file(input_path)))
805
837
  if use_snippet:
806
- current_char_count += len(get_file_snippet(input_path))
838
+ snippet = get_file_snippet(input_path)
839
+ current_char_count += len(snippet)
840
+ print(get_colored_code(input_path, snippet))
807
841
  else:
808
842
  current_char_count += os.path.getsize(input_path)
809
843
  print(f"Added file: {input_path}{' (snippet)' if use_snippet else ''}")
@@ -838,16 +872,23 @@ def main():
838
872
  print_char_count(current_char_count)
839
873
  print(f"Summary: Added {len(files_to_include)} files from {len(processed_dirs)} directories and {len(web_contents)} web sources.")
840
874
 
841
- prompt = generate_prompt(files_to_include, ignore_patterns, web_contents, env_vars)
875
+ prompt_template, cursor_position = generate_prompt_template(files_to_include, ignore_patterns, web_contents, env_vars)
876
+
877
+ if args.task:
878
+ task_description = args.task
879
+ final_prompt = prompt_template[:cursor_position] + task_description + prompt_template[cursor_position:]
880
+ else:
881
+ final_prompt = open_editor_for_input(prompt_template, cursor_position)
882
+
842
883
  print("\n\nGenerated prompt:")
843
- print(prompt)
884
+ print(final_prompt)
844
885
 
845
886
  # Copy the prompt to clipboard
846
887
  try:
847
- pyperclip.copy(prompt)
888
+ pyperclip.copy(final_prompt)
848
889
  separator = "\n" + "=" * 40 + "\n☕🍝 Kopipasta Complete! 🍝☕\n" + "=" * 40 + "\n"
849
890
  print(separator)
850
- final_char_count = len(prompt)
891
+ final_char_count = len(final_prompt)
851
892
  final_token_estimate = final_char_count // 4
852
893
  print(f"Prompt has been copied to clipboard. Final size: {final_char_count} characters (~ {final_token_estimate} tokens)")
853
894
  except pyperclip.PyperclipException as e:
@@ -0,0 +1,79 @@
1
+ Metadata-Version: 2.1
2
+ Name: kopipasta
3
+ Version: 0.20.0
4
+ Summary: A CLI tool to generate prompts with project structure and file contents
5
+ Home-page: https://github.com/mkorpela/kopipasta
6
+ Author: Mikko Korpela
7
+ Author-email: mikko.korpela@gmail.com
8
+ License: MIT
9
+ Classifier: Development Status :: 3 - Alpha
10
+ Classifier: Intended Audience :: Developers
11
+ Classifier: License :: OSI Approved :: MIT License
12
+ Classifier: Operating System :: OS Independent
13
+ Classifier: Programming Language :: Python :: 3
14
+ Classifier: Programming Language :: Python :: 3.8
15
+ Classifier: Programming Language :: Python :: 3.9
16
+ Classifier: Programming Language :: Python :: 3.10
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Requires-Python: >=3.8
20
+ Description-Content-Type: text/markdown
21
+ License-File: LICENSE
22
+ Requires-Dist: pyperclip==1.9.0
23
+ Requires-Dist: requests==2.32.3
24
+ Requires-Dist: Pygments==2.18.0
25
+
26
+ # kopipasta
27
+
28
+ [![Version](https://img.shields.io/pypi/v/kopipasta.svg)](https://pypi.python.org/pypi/kopipasta)
29
+ [![Downloads](http://pepy.tech/badge/kopipasta)](http://pepy.tech/project/kopipasta)
30
+
31
+ A CLI tool for generating AI-assisted code prompts with project structure and file contents, using an interactive editor-based workflow.
32
+
33
+ <img src="kopipasta.jpg" alt="kopipasta" width="300">
34
+
35
+ - An LLM told me that kopi means Coffee in some languages.. and a Diffusion model then made this delicious soup.
36
+
37
+ ## Installation
38
+
39
+ You can install kopipasta using pipx (or pip):
40
+
41
+ ```bash
42
+ pipx install kopipasta
43
+ ```
44
+
45
+ ## Usage
46
+
47
+ To use kopipasta, run the following command in your terminal:
48
+
49
+ ```bash
50
+ kopipasta [files_or_directories_or_urls]
51
+ ```
52
+
53
+ Replace `[files_or_directories_or_urls]` with the paths to the files or directories you want to include in the prompt, as well as any web URLs you want to fetch content from.
54
+
55
+ Example:
56
+ ```bash
57
+ kopipasta src/ config.json https://example.com/api-docs
58
+ ```
59
+
60
+ This will guide you through an interactive process to:
61
+ 1. Select files and directories to include in the prompt
62
+ 2. Choose between full content, snippets, or patches for large files
63
+ 3. Fetch and include content from provided URLs
64
+ 4. Open an editor for you to input the specific task or code generation instructions
65
+ 5. Generate a comprehensive prompt that includes project structure, selected file contents, and your task instructions
66
+
67
+ The generated prompt will be displayed in the console and automatically copied to your clipboard, ready to be used with an AI code generation tool.
68
+
69
+ ## Features
70
+
71
+ - Generates structured prompts with project overview, file contents, web content, and task instructions
72
+ - Interactive file selection process with options for full content, snippets, or specific patches
73
+ - Fetches and includes content from web URLs
74
+ - Opens your preferred editor (configurable via EDITOR environment variable) for task input
75
+ - Detects and securely handles environment variables from a `.env` file
76
+ - Ignores files and directories based on common .gitignore patterns
77
+ - Allows interactive selection of files to include
78
+ - Supports various file types with syntax highlighting in the selection process
79
+ - Automatically copies the generated prompt to the clipboard
@@ -0,0 +1,8 @@
1
+ kopipasta/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
+ kopipasta/main.py,sha256=zHCgL8dIZ4qMDzaN4EgUltH7wRT8UVvLn0Fq5ZgEZ8s,36904
3
+ kopipasta-0.20.0.dist-info/LICENSE,sha256=xw4C9TAU7LFu4r_MwSbky90uzkzNtRwAo3c51IWR8lk,1091
4
+ kopipasta-0.20.0.dist-info/METADATA,sha256=quUlS4S58ovXK3TG7iQn5Wvge-zfx7ZXI6YUNLd9m-Y,3179
5
+ kopipasta-0.20.0.dist-info/WHEEL,sha256=GV9aMThwP_4oNCtvEC2ec3qUYutgWeAzklro_0m4WJQ,91
6
+ kopipasta-0.20.0.dist-info/entry_points.txt,sha256=but54qDNz1-F8fVvGstq_QID5tHjczP7bO7rWLFkc6Y,50
7
+ kopipasta-0.20.0.dist-info/top_level.txt,sha256=iXohixMuCdw8UjGDUp0ouICLYBDrx207sgZIJ9lxn0o,10
8
+ kopipasta-0.20.0.dist-info/RECORD,,
@@ -1,200 +0,0 @@
1
- Metadata-Version: 2.1
2
- Name: kopipasta
3
- Version: 0.18.0
4
- Summary: A CLI tool to generate prompts with project structure and file contents
5
- Home-page: https://github.com/mkorpela/kopipasta
6
- Author: Mikko Korpela
7
- Author-email: mikko.korpela@gmail.com
8
- License: MIT
9
- Classifier: Development Status :: 3 - Alpha
10
- Classifier: Intended Audience :: Developers
11
- Classifier: License :: OSI Approved :: MIT License
12
- Classifier: Operating System :: OS Independent
13
- Classifier: Programming Language :: Python :: 3
14
- Classifier: Programming Language :: Python :: 3.8
15
- Classifier: Programming Language :: Python :: 3.9
16
- Classifier: Programming Language :: Python :: 3.10
17
- Classifier: Programming Language :: Python :: 3.11
18
- Classifier: Programming Language :: Python :: 3.12
19
- Requires-Python: >=3.8
20
- Description-Content-Type: text/markdown
21
- License-File: LICENSE
22
- Requires-Dist: pyperclip==1.9.0
23
- Requires-Dist: requests==2.32.3
24
-
25
- # kopipasta
26
-
27
- A CLI tool to generate prompts with project structure, file contents, and web content, while handling environment variables securely and offering snippets for large files also interactive patch selection, allowing you to include only the most relevant parts of your code.
28
-
29
- <img src="kopipasta.jpg" alt="kopipasta" width="300">
30
-
31
- - An LLM told me that kopi means Coffee in some languages.. and a Diffusion model then made this delicious soup.
32
-
33
- ## Installation
34
-
35
- You can install kopipasta using pipx (or pip):
36
-
37
- ```
38
- pipx install kopipasta
39
- ```
40
-
41
- ## Usage
42
-
43
- To use kopipasta, run the following command in your terminal:
44
-
45
- ```
46
- kopipasta [files_or_directories_or_urls]
47
- ```
48
-
49
- Replace `[files_or_directories_or_urls]` with the paths to the files or directories you want to include in the prompt, as well as any web URLs you want to fetch content from.
50
-
51
- Example:
52
- ```
53
- kopipasta src/ config.json https://example.com/api-docs
54
- ```
55
-
56
- This will generate a prompt including:
57
- - The project structure
58
- - Contents of the specified files and directories (with snippet options for large files)
59
- - Content fetched from the provided URLs (with snippet options for large content)
60
- - Handling of environment variables found in a `.env` file (if present)
61
-
62
- Files and directories typically excluded in version control (based on common .gitignore patterns) are ignored.
63
-
64
- The generated prompt will be displayed in the console and automatically copied to your clipboard.
65
-
66
- ## Features
67
-
68
- - Generates a structured prompt with project overview, file contents, web content, and task instructions
69
- - Offers snippet options for large files (>100 KB) and web content (>10,000 characters)
70
- - Fetches and includes content from web URLs
71
- - Detects and securely handles environment variables from a `.env` file
72
- - Ignores files and directories based on common .gitignore patterns
73
- - Allows interactive selection of files to include
74
- - Automatically copies the generated prompt to the clipboard
75
-
76
- ## Environment Variable Handling
77
-
78
- If a `.env` file is present in the current directory, kopipasta will:
79
- 1. Read and store the environment variables
80
- 2. Detect these variables in file contents and web content
81
- 3. Prompt you to choose how to handle each detected variable:
82
- - (m)ask: Replace the value with asterisks
83
- - (s)kip: Replace the value with "[REDACTED]"
84
- - (k)eep: Leave the value as-is
85
-
86
- This ensures sensitive information is handled securely in the generated prompt.
87
-
88
- ## Snippet Functionality
89
-
90
- For large files (>100 KB) and web content (>10,000 characters), kopipasta offers a snippet option:
91
-
92
- - For files: The first 50 lines or 4 KB (4,096 bytes), whichever comes first
93
- - For web content: The first 1,000 characters
94
-
95
- This helps manage the overall prompt size while still providing useful information about the content structure.
96
-
97
- ## Example output
98
-
99
- ```bash
100
- ❯ kopipasta . https://example.com/api-docs
101
-
102
- Directory: .
103
- Files:
104
- - __init__.py
105
- - main.py (120 KB, ~120000 chars, ~30000 tokens)
106
- - large_data.csv (5 MB, ~5000000 chars, ~1250000 tokens)
107
- - .env
108
-
109
- (y)es add all / (n)o ignore all / (s)elect individually / (q)uit? y
110
- main.py is large. Use (f)ull content or (s)nippet? s
111
- large_data.csv is large. Use (f)ull content or (s)nippet? s
112
- Added all files from .
113
- Added web content from: https://example.com/api-docs
114
-
115
- File and web content selection complete.
116
- Current prompt size: 10500 characters (~ 2625 tokens)
117
- Summary: Added 3 files from 1 directory and 1 web source.
118
-
119
- Detected environment variables:
120
- - API_KEY=12345abcde
121
-
122
- How would you like to handle API_KEY? (m)ask / (k)eep: m
123
-
124
- Enter the task instructions: Implement new API endpoint
125
-
126
- Generated prompt:
127
- # Project Overview
128
-
129
- ## Project Structure
130
-
131
- ```
132
- |-- ./
133
- |-- __init__.py
134
- |-- main.py
135
- |-- large_data.csv
136
- |-- .env
137
- ```
138
-
139
- ## File Contents
140
-
141
- ### __init__.py
142
-
143
- ```python
144
- # Initialize package
145
- ```
146
-
147
- ### main.py (snippet)
148
-
149
- ```python
150
- import os
151
- import pandas as pd
152
-
153
- API_KEY = os.getenv('API_KEY')
154
-
155
- def process_data(file_path):
156
- df = pd.read_csv(file_path)
157
- # Rest of the function...
158
-
159
- # More code...
160
- ```
161
-
162
- ### large_data.csv (snippet)
163
-
164
- ```
165
- id,name,value
166
- 1,John,100
167
- 2,Jane,200
168
- 3,Bob,150
169
- 4,Alice,300
170
- # ... (first 50 lines or 4 KB)
171
- ```
172
-
173
- ## Web Content
174
-
175
- ### https://example.com/api-docs (snippet)
176
-
177
- ```
178
- API Documentation
179
- Endpoint: /api/v1/data
180
- Method: GET
181
- Authorization: Bearer **********
182
- ...
183
- ```
184
-
185
- ## Task Instructions
186
-
187
- Implement new API endpoint
188
-
189
- ## Task Analysis and Planning
190
-
191
- Before starting, explain the task back to me in your own words. Ask for any clarifications if needed. Once you're clear, ask to proceed.
192
-
193
- Then, outline a plan for the task. Finally, use your plan to complete the task.
194
-
195
- Prompt has been copied to clipboard. Final size: 1500 characters (~ 375 tokens)
196
- ```
197
-
198
- ## License
199
-
200
- This project is licensed under the MIT License.
@@ -1,8 +0,0 @@
1
- kopipasta/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
- kopipasta/main.py,sha256=VuVUOjCL1XeAV9u7oo-hx2v42KgE0mFYWzfoDn2hL6E,35090
3
- kopipasta-0.18.0.dist-info/LICENSE,sha256=xw4C9TAU7LFu4r_MwSbky90uzkzNtRwAo3c51IWR8lk,1091
4
- kopipasta-0.18.0.dist-info/METADATA,sha256=be12_mfA2Ivg30CH8gIVrghmVzz71-56nAanX7ZsZhM,5646
5
- kopipasta-0.18.0.dist-info/WHEEL,sha256=GV9aMThwP_4oNCtvEC2ec3qUYutgWeAzklro_0m4WJQ,91
6
- kopipasta-0.18.0.dist-info/entry_points.txt,sha256=but54qDNz1-F8fVvGstq_QID5tHjczP7bO7rWLFkc6Y,50
7
- kopipasta-0.18.0.dist-info/top_level.txt,sha256=iXohixMuCdw8UjGDUp0ouICLYBDrx207sgZIJ9lxn0o,10
8
- kopipasta-0.18.0.dist-info/RECORD,,