kopipasta 0.1.0__tar.gz

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.

File without changes
@@ -0,0 +1,3 @@
1
+ include README.md
2
+ include LICENSE
3
+ include requirements.txt
@@ -0,0 +1,64 @@
1
+ Metadata-Version: 2.1
2
+ Name: kopipasta
3
+ Version: 0.1.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
+
24
+ # kopipasta
25
+
26
+ A CLI tool to generate prompts with project structure and file contents.
27
+
28
+ ## Installation
29
+
30
+ You can install kopipasta using pipx (or pip):
31
+
32
+ ```
33
+ pipx install kopipasta
34
+ ```
35
+
36
+ ## Usage
37
+
38
+ To use kopipasta, run the following command in your terminal:
39
+
40
+ ```
41
+ kopipasta [files_or_directories]
42
+ ```
43
+
44
+ Replace `[files_or_directories]` with the paths to the files or directories you want to include in the prompt.
45
+
46
+ Example:
47
+ ```
48
+ kopipasta . src/ config.json
49
+ ```
50
+
51
+ This will generate a prompt including the project structure and contents of the specified files and directories, ignoring files and directories typically excluded in version control (based on common .gitignore patterns).
52
+
53
+ The generated prompt will be displayed in the console and automatically copied to your clipboard.
54
+
55
+ ## Features
56
+
57
+ - Generates a structured prompt with project overview, file contents, and task instructions
58
+ - Ignores files and directories based on common .gitignore patterns
59
+ - Allows interactive selection of files to include
60
+ - Automatically copies the generated prompt to the clipboard
61
+
62
+ ## License
63
+
64
+ This project is licensed under the MIT License.
@@ -0,0 +1,41 @@
1
+ # kopipasta
2
+
3
+ A CLI tool to generate prompts with project structure and file contents.
4
+
5
+ ## Installation
6
+
7
+ You can install kopipasta using pipx (or pip):
8
+
9
+ ```
10
+ pipx install kopipasta
11
+ ```
12
+
13
+ ## Usage
14
+
15
+ To use kopipasta, run the following command in your terminal:
16
+
17
+ ```
18
+ kopipasta [files_or_directories]
19
+ ```
20
+
21
+ Replace `[files_or_directories]` with the paths to the files or directories you want to include in the prompt.
22
+
23
+ Example:
24
+ ```
25
+ kopipasta . src/ config.json
26
+ ```
27
+
28
+ This will generate a prompt including the project structure and contents of the specified files and directories, ignoring files and directories typically excluded in version control (based on common .gitignore patterns).
29
+
30
+ The generated prompt will be displayed in the console and automatically copied to your clipboard.
31
+
32
+ ## Features
33
+
34
+ - Generates a structured prompt with project overview, file contents, and task instructions
35
+ - Ignores files and directories based on common .gitignore patterns
36
+ - Allows interactive selection of files to include
37
+ - Automatically copies the generated prompt to the clipboard
38
+
39
+ ## License
40
+
41
+ This project is licensed under the MIT License.
File without changes
@@ -0,0 +1,222 @@
1
+ #!/usr/bin/env python3
2
+ import os
3
+ import argparse
4
+ import pyperclip
5
+ import fnmatch
6
+
7
+ def read_gitignore():
8
+ default_ignore_patterns = [
9
+ '.git', 'node_modules', 'venv', '.venv', 'dist', '.idea', '__pycache__',
10
+ '*.pyc', '.ruff_cache', '.mypy_cache', '.pytest_cache', '.vscode', '.vite',
11
+ '.terraform', 'output', 'poetry.lock', 'package-lock.json', '.env',
12
+ '*.log', '*.bak', '*.swp', '*.swo', '*.tmp', 'tmp', 'temp', 'logs',
13
+ 'build', 'target', '.DS_Store', 'Thumbs.db', '*.class', '*.jar',
14
+ '*.war', '*.ear', '*.sqlite', '*.db', '.github', '.gitignore'
15
+ ]
16
+ gitignore_patterns = default_ignore_patterns.copy()
17
+
18
+ if os.path.exists('.gitignore'):
19
+ with open('.gitignore', 'r') as file:
20
+ for line in file:
21
+ line = line.strip()
22
+ if line and not line.startswith('#'):
23
+ gitignore_patterns.append(line)
24
+ return gitignore_patterns
25
+
26
+ def is_ignored(path, ignore_patterns):
27
+ path = os.path.normpath(path)
28
+ for pattern in ignore_patterns:
29
+ if fnmatch.fnmatch(os.path.basename(path), pattern) or fnmatch.fnmatch(path, pattern):
30
+ return True
31
+ return False
32
+
33
+ def get_project_structure(ignore_patterns):
34
+ tree = []
35
+ for root, dirs, files in os.walk('.'):
36
+ # Remove ignored directories
37
+ dirs[:] = [d for d in dirs if not is_ignored(os.path.join(root, d), ignore_patterns)]
38
+ # Remove ignored files
39
+ files = [f for f in files if not is_ignored(os.path.join(root, f), ignore_patterns)]
40
+ level = root.replace('.', '').count(os.sep)
41
+ indent = ' ' * 4 * level + '|-- '
42
+ tree.append(f"{indent}{os.path.basename(root)}/")
43
+ subindent = ' ' * 4 * (level + 1) + '|-- '
44
+ for f in files:
45
+ tree.append(f"{subindent}{f}")
46
+ return '\n'.join(tree)
47
+
48
+ def read_file_contents(file_path):
49
+ try:
50
+ with open(file_path, 'r') as file:
51
+ return file.read()
52
+ except Exception as e:
53
+ print(f"Error reading {file_path}: {e}")
54
+ return ""
55
+
56
+ def get_relative_path(file_path):
57
+ return os.path.relpath(file_path)
58
+
59
+ def get_language_for_file(file_path):
60
+ extension = os.path.splitext(file_path)[1].lower()
61
+ language_map = {
62
+ '.py': 'python',
63
+ '.js': 'javascript',
64
+ '.jsx': 'jsx',
65
+ '.ts': 'typescript',
66
+ '.tsx': 'tsx',
67
+ '.html': 'html',
68
+ '.css': 'css',
69
+ '.json': 'json',
70
+ '.md': 'markdown',
71
+ '.sql': 'sql',
72
+ '.sh': 'bash',
73
+ '.yml': 'yaml',
74
+ '.yaml': 'yaml',
75
+ '.go': 'go',
76
+ '.toml': 'toml'
77
+ }
78
+ return language_map.get(extension, '')
79
+
80
+ def select_files_in_directory(directory, ignore_patterns):
81
+ files = [f for f in os.listdir(directory)
82
+ if os.path.isfile(os.path.join(directory, f)) and not is_ignored(os.path.join(directory, f), ignore_patterns)]
83
+
84
+ if not files:
85
+ return []
86
+
87
+ print(f"\nDirectory: {directory}")
88
+ print("Files:")
89
+ for file in files:
90
+ print(f"- {file}")
91
+
92
+ while True:
93
+ choice = input("\n(y)es add all / (n)o ignore all / (s)elect individually / (q)uit? ").lower()
94
+ if choice == 'y':
95
+ print(f"Added all files from {directory}")
96
+ return files
97
+ elif choice == 'n':
98
+ print(f"Ignored all files from {directory}")
99
+ return []
100
+ elif choice == 's':
101
+ selected_files = []
102
+ for file in files:
103
+ while True:
104
+ file_choice = input(f"{file} (y/n/q)? ").lower()
105
+ if file_choice == 'y':
106
+ selected_files.append(file)
107
+ break
108
+ elif file_choice == 'n':
109
+ break
110
+ elif file_choice == 'q':
111
+ print(f"Quitting selection for {directory}")
112
+ return selected_files
113
+ else:
114
+ print("Invalid choice. Please enter 'y', 'n', or 'q'.")
115
+ print(f"Added {len(selected_files)} files from {directory}")
116
+ return selected_files
117
+ elif choice == 'q':
118
+ print(f"Quitting selection for {directory}")
119
+ return []
120
+ else:
121
+ print("Invalid choice. Please try again.")
122
+
123
+ def process_directory(directory, ignore_patterns):
124
+ files_to_include = []
125
+ processed_dirs = set()
126
+
127
+ for root, dirs, files in os.walk(directory):
128
+ # Remove ignored directories
129
+ dirs[:] = [d for d in dirs if not is_ignored(os.path.join(root, d), ignore_patterns)]
130
+ # Remove ignored files
131
+ files = [f for f in files if not is_ignored(os.path.join(root, f), ignore_patterns)]
132
+
133
+ if root in processed_dirs:
134
+ continue
135
+
136
+ selected_files = select_files_in_directory(root, ignore_patterns)
137
+ full_paths = [os.path.join(root, f) for f in selected_files]
138
+ files_to_include.extend(full_paths)
139
+ processed_dirs.add(root)
140
+
141
+ return files_to_include, processed_dirs
142
+
143
+ def generate_prompt(files_to_include, ignore_patterns):
144
+ prompt = "# Project Overview\n\n"
145
+ prompt += "## Summary of Included Files\n\n"
146
+ for file in files_to_include:
147
+ relative_path = get_relative_path(file)
148
+ prompt += f"- {relative_path}\n"
149
+ prompt += "\n"
150
+
151
+ prompt += "## Project Structure\n\n"
152
+ prompt += "```\n"
153
+ prompt += get_project_structure(ignore_patterns)
154
+ prompt += "\n```\n\n"
155
+
156
+ prompt += "## File Contents\n\n"
157
+ for file in files_to_include:
158
+ relative_path = get_relative_path(file)
159
+ language = get_language_for_file(file)
160
+ prompt += f"### {relative_path}\n\n"
161
+ prompt += f"```{language}\n"
162
+ prompt += read_file_contents(file)
163
+ prompt += "\n```\n\n"
164
+
165
+ prompt += "## Task Instructions\n\n"
166
+ task_instructions = input("Enter the task instructions: ")
167
+ prompt += f"{task_instructions}\n\n"
168
+
169
+ prompt += "## Task Analysis and Planning\n\n"
170
+ prompt += (
171
+ "Before starting, explain the task back to me in your own words. "
172
+ "Ask for any clarifications if needed. Once you're clear, ask to proceed.\n\n"
173
+ "Then, outline a plan for the task. Finally, use your plan to complete the task."
174
+ )
175
+
176
+ return prompt
177
+
178
+ def main():
179
+ parser = argparse.ArgumentParser(description="Generate a prompt with project structure and file contents.")
180
+ parser.add_argument('inputs', nargs='+', help='Files or directories to include in the prompt')
181
+ args = parser.parse_args()
182
+
183
+ ignore_patterns = read_gitignore()
184
+
185
+ files_to_include = []
186
+ processed_dirs = set()
187
+
188
+ for input_path in args.inputs:
189
+ if os.path.isfile(input_path):
190
+ if not is_ignored(input_path, ignore_patterns):
191
+ files_to_include.append(input_path)
192
+ print(f"Added file: {input_path}")
193
+ else:
194
+ print(f"Ignored file: {input_path}")
195
+ elif os.path.isdir(input_path):
196
+ dir_files, dir_processed = process_directory(input_path, ignore_patterns)
197
+ files_to_include.extend(dir_files)
198
+ processed_dirs.update(dir_processed)
199
+ else:
200
+ print(f"Warning: {input_path} is not a valid file or directory. Skipping.")
201
+
202
+ if not files_to_include:
203
+ print("No files were selected. Exiting.")
204
+ return
205
+
206
+ print("\nFile selection complete.")
207
+ print(f"Summary: Added {len(files_to_include)} files from {len(processed_dirs)} directories.")
208
+
209
+ prompt = generate_prompt(files_to_include, ignore_patterns)
210
+ print("\nGenerated prompt:")
211
+ print(prompt)
212
+
213
+ # Copy the prompt to clipboard
214
+ try:
215
+ pyperclip.copy(prompt)
216
+ print("\nPrompt has been copied to clipboard.")
217
+ except pyperclip.PyperclipException as e:
218
+ print(f"Failed to copy to clipboard: {e}")
219
+
220
+ if __name__ == "__main__":
221
+ main()
222
+
@@ -0,0 +1,64 @@
1
+ Metadata-Version: 2.1
2
+ Name: kopipasta
3
+ Version: 0.1.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
+
24
+ # kopipasta
25
+
26
+ A CLI tool to generate prompts with project structure and file contents.
27
+
28
+ ## Installation
29
+
30
+ You can install kopipasta using pipx (or pip):
31
+
32
+ ```
33
+ pipx install kopipasta
34
+ ```
35
+
36
+ ## Usage
37
+
38
+ To use kopipasta, run the following command in your terminal:
39
+
40
+ ```
41
+ kopipasta [files_or_directories]
42
+ ```
43
+
44
+ Replace `[files_or_directories]` with the paths to the files or directories you want to include in the prompt.
45
+
46
+ Example:
47
+ ```
48
+ kopipasta . src/ config.json
49
+ ```
50
+
51
+ This will generate a prompt including the project structure and contents of the specified files and directories, ignoring files and directories typically excluded in version control (based on common .gitignore patterns).
52
+
53
+ The generated prompt will be displayed in the console and automatically copied to your clipboard.
54
+
55
+ ## Features
56
+
57
+ - Generates a structured prompt with project overview, file contents, and task instructions
58
+ - Ignores files and directories based on common .gitignore patterns
59
+ - Allows interactive selection of files to include
60
+ - Automatically copies the generated prompt to the clipboard
61
+
62
+ ## License
63
+
64
+ This project is licensed under the MIT License.
@@ -0,0 +1,13 @@
1
+ LICENSE
2
+ MANIFEST.in
3
+ README.md
4
+ requirements.txt
5
+ setup.py
6
+ kopipasta/__init__.py
7
+ kopipasta/main.py
8
+ kopipasta.egg-info/PKG-INFO
9
+ kopipasta.egg-info/SOURCES.txt
10
+ kopipasta.egg-info/dependency_links.txt
11
+ kopipasta.egg-info/entry_points.txt
12
+ kopipasta.egg-info/requires.txt
13
+ kopipasta.egg-info/top_level.txt
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ kopipasta = kopipasta.main:main
@@ -0,0 +1 @@
1
+ pyperclip==1.9.0
@@ -0,0 +1 @@
1
+ kopipasta
@@ -0,0 +1 @@
1
+ pyperclip==1.9.0
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,38 @@
1
+ from setuptools import setup, find_packages
2
+
3
+ with open("README.md", "r", encoding="utf-8") as fh:
4
+ long_description = fh.read()
5
+
6
+ setup(
7
+ name="kopipasta",
8
+ version="0.1.0",
9
+ author="Mikko Korpela",
10
+ author_email="mikko.korpela@gmail.com",
11
+ description="A CLI tool to generate prompts with project structure and file contents",
12
+ long_description=long_description,
13
+ long_description_content_type="text/markdown",
14
+ url="https://github.com/mkorpela/kopipasta",
15
+ packages=find_packages(),
16
+ install_requires=[
17
+ "pyperclip==1.9.0",
18
+ ],
19
+ classifiers=[
20
+ "Development Status :: 3 - Alpha",
21
+ "Intended Audience :: Developers",
22
+ "License :: OSI Approved :: MIT License",
23
+ "Operating System :: OS Independent",
24
+ "Programming Language :: Python :: 3",
25
+ "Programming Language :: Python :: 3.8",
26
+ "Programming Language :: Python :: 3.9",
27
+ "Programming Language :: Python :: 3.10",
28
+ "Programming Language :: Python :: 3.11",
29
+ "Programming Language :: Python :: 3.12",
30
+ ],
31
+ python_requires=">=3.8",
32
+ license="MIT",
33
+ entry_points={
34
+ "console_scripts": [
35
+ "kopipasta=kopipasta.main:main",
36
+ ],
37
+ },
38
+ )