onepaste 1.3.0__tar.gz → 1.3.2__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.
- {onepaste-1.3.0 → onepaste-1.3.2}/.github/workflows/publish.yml +7 -0
- {onepaste-1.3.0 → onepaste-1.3.2}/.gitignore +22 -20
- {onepaste-1.3.0 → onepaste-1.3.2}/PKG-INFO +37 -32
- {onepaste-1.3.0 → onepaste-1.3.2}/PUBLISHING.md +5 -4
- {onepaste-1.3.0 → onepaste-1.3.2}/README.md +36 -31
- onepaste-1.3.2/onepaste/__init__.py +10 -0
- onepaste-1.3.2/onepaste/__main__.py +6 -0
- {onepaste-1.3.0/codecollector → onepaste-1.3.2/onepaste}/cli.py +20 -20
- {onepaste-1.3.0/codecollector → onepaste-1.3.2/onepaste}/collector.py +21 -9
- {onepaste-1.3.0/codecollector → onepaste-1.3.2/onepaste}/config.py +3 -3
- {onepaste-1.3.0/codecollector → onepaste-1.3.2/onepaste}/formatter.py +3 -3
- {onepaste-1.3.0/codecollector → onepaste-1.3.2/onepaste}/selector.py +1 -1
- {onepaste-1.3.0/codecollector → onepaste-1.3.2/onepaste}/splitter.py +4 -4
- {onepaste-1.3.0/codecollector → onepaste-1.3.2/onepaste}/uninstall.py +3 -3
- {onepaste-1.3.0 → onepaste-1.3.2}/pyproject.toml +3 -3
- {onepaste-1.3.0 → onepaste-1.3.2}/tests/conftest.py +2 -2
- {onepaste-1.3.0 → onepaste-1.3.2}/tests/test_cli.py +5 -5
- {onepaste-1.3.0 → onepaste-1.3.2}/tests/test_collector.py +26 -4
- {onepaste-1.3.0 → onepaste-1.3.2}/tests/test_config.py +3 -3
- {onepaste-1.3.0 → onepaste-1.3.2}/tests/test_formatter.py +3 -3
- {onepaste-1.3.0 → onepaste-1.3.2}/tests/test_output.py +2 -2
- {onepaste-1.3.0 → onepaste-1.3.2}/tests/test_splitter.py +4 -4
- {onepaste-1.3.0 → onepaste-1.3.2}/tests/test_tokens.py +2 -2
- onepaste-1.3.2/website/package-lock.json +1062 -0
- onepaste-1.3.0/codecollector/__init__.py +0 -10
- onepaste-1.3.0/codecollector/__main__.py +0 -6
- {onepaste-1.3.0 → onepaste-1.3.2}/LICENSE +0 -0
- {onepaste-1.3.0/codecollector → onepaste-1.3.2/onepaste}/gitignore.py +0 -0
- {onepaste-1.3.0/codecollector → onepaste-1.3.2/onepaste}/output.py +0 -0
- {onepaste-1.3.0/codecollector → onepaste-1.3.2/onepaste}/tokens.py +0 -0
|
@@ -3,6 +3,8 @@ name: Publish to PyPI
|
|
|
3
3
|
on:
|
|
4
4
|
release:
|
|
5
5
|
types: [published]
|
|
6
|
+
push:
|
|
7
|
+
tags: ["v*"]
|
|
6
8
|
workflow_dispatch:
|
|
7
9
|
|
|
8
10
|
jobs:
|
|
@@ -35,3 +37,8 @@ jobs:
|
|
|
35
37
|
|
|
36
38
|
- name: Publish to PyPI
|
|
37
39
|
uses: pypa/gh-action-pypi-publish@release/v1
|
|
40
|
+
with:
|
|
41
|
+
# Primary path: OIDC trusted publishing (no secret needed).
|
|
42
|
+
# Optional fallback: add a repo secret named PYPI_API_TOKEN and it
|
|
43
|
+
# takes precedence automatically; leave it unset for pure OIDC.
|
|
44
|
+
password: ${{ secrets.PYPI_API_TOKEN }}
|
|
@@ -13,13 +13,13 @@ __pycache__/
|
|
|
13
13
|
|
|
14
14
|
# Distribution / packaging
|
|
15
15
|
.Python
|
|
16
|
-
build/
|
|
16
|
+
/build/
|
|
17
17
|
develop-eggs/
|
|
18
|
-
dist/
|
|
18
|
+
/dist/
|
|
19
19
|
downloads/
|
|
20
20
|
eggs/
|
|
21
21
|
.eggs/
|
|
22
|
-
lib/
|
|
22
|
+
/lib/
|
|
23
23
|
lib64/
|
|
24
24
|
parts/
|
|
25
25
|
sdist/
|
|
@@ -52,7 +52,7 @@ coverage.xml
|
|
|
52
52
|
*.py,cover
|
|
53
53
|
.hypothesis/
|
|
54
54
|
.pytest_cache/
|
|
55
|
-
cover/
|
|
55
|
+
/cover/
|
|
56
56
|
|
|
57
57
|
# Translations
|
|
58
58
|
*.mo
|
|
@@ -76,7 +76,7 @@ docs/_build/
|
|
|
76
76
|
|
|
77
77
|
# PyBuilder
|
|
78
78
|
.pybuilder/
|
|
79
|
-
target/
|
|
79
|
+
/target/
|
|
80
80
|
|
|
81
81
|
# Jupyter Notebook
|
|
82
82
|
.ipynb_checkpoints
|
|
@@ -111,9 +111,9 @@ celerybeat.pid
|
|
|
111
111
|
# Environments
|
|
112
112
|
.env
|
|
113
113
|
.venv
|
|
114
|
-
env/
|
|
115
|
-
venv/
|
|
116
|
-
ENV/
|
|
114
|
+
/env/
|
|
115
|
+
/venv/
|
|
116
|
+
/ENV/
|
|
117
117
|
env.bak/
|
|
118
118
|
venv.bak/
|
|
119
119
|
|
|
@@ -225,12 +225,12 @@ code_collection*.md
|
|
|
225
225
|
code_collection*.manifest.json
|
|
226
226
|
*.collection.txt
|
|
227
227
|
*.collection.md
|
|
228
|
-
output/
|
|
229
|
-
collected_code/
|
|
228
|
+
/output/
|
|
229
|
+
/collected_code/
|
|
230
230
|
|
|
231
231
|
# 临时文件
|
|
232
|
-
tmp/
|
|
233
|
-
temp/
|
|
232
|
+
/tmp/
|
|
233
|
+
/temp/
|
|
234
234
|
*.tmp
|
|
235
235
|
*.temp
|
|
236
236
|
|
|
@@ -251,7 +251,7 @@ config.local.json
|
|
|
251
251
|
|
|
252
252
|
# 日志文件
|
|
253
253
|
*.log
|
|
254
|
-
logs/
|
|
254
|
+
/logs/
|
|
255
255
|
|
|
256
256
|
# --- Environment ---
|
|
257
257
|
# Conda
|
|
@@ -262,10 +262,10 @@ Anaconda*/
|
|
|
262
262
|
|
|
263
263
|
# NPM (如果项目中有前端部分)
|
|
264
264
|
node_modules/
|
|
265
|
-
package-lock.json
|
|
266
|
-
yarn.lock
|
|
265
|
+
/package-lock.json/
|
|
266
|
+
/yarn.lock/
|
|
267
267
|
.npm
|
|
268
|
-
|
|
268
|
+
/.npmrc/
|
|
269
269
|
|
|
270
270
|
# --- Docker ---
|
|
271
271
|
# (如果将来添加 Docker 支持)
|
|
@@ -274,7 +274,7 @@ docker-compose.override.yml
|
|
|
274
274
|
|
|
275
275
|
# --- Documentation ---
|
|
276
276
|
# 生成的文档
|
|
277
|
-
site/
|
|
277
|
+
/site/
|
|
278
278
|
docs/_build/
|
|
279
279
|
|
|
280
280
|
# --- Security ---
|
|
@@ -302,8 +302,8 @@ collected_*.txt
|
|
|
302
302
|
!collected_example.txt
|
|
303
303
|
|
|
304
304
|
# 测试输出
|
|
305
|
-
test_output/
|
|
306
|
-
test_results/
|
|
305
|
+
/test_output/
|
|
306
|
+
/test_results/
|
|
307
307
|
|
|
308
308
|
# 性能分析
|
|
309
309
|
*.prof
|
|
@@ -312,4 +312,6 @@ test_results/
|
|
|
312
312
|
# 数据库
|
|
313
313
|
*.db
|
|
314
314
|
*.sqlite
|
|
315
|
-
*.sqlite3
|
|
315
|
+
*.sqlite3
|
|
316
|
+
# Website lockfile MUST be tracked (reproducible Vercel builds)
|
|
317
|
+
!website/package-lock.json
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: onepaste
|
|
3
|
-
Version: 1.3.
|
|
3
|
+
Version: 1.3.2
|
|
4
4
|
Summary: Collect project code files into a single output for AI assistants
|
|
5
5
|
Project-URL: Homepage, https://github.com/emVisible/codecollector
|
|
6
6
|
Project-URL: Repository, https://github.com/emVisible/codecollector.git
|
|
@@ -35,7 +35,12 @@ Provides-Extra: tokens
|
|
|
35
35
|
Requires-Dist: tiktoken>=0.5; extra == 'tokens'
|
|
36
36
|
Description-Content-Type: text/markdown
|
|
37
37
|
|
|
38
|
-
#
|
|
38
|
+
# OnePaste
|
|
39
|
+
|
|
40
|
+
[](https://pypi.org/project/onepaste/)
|
|
41
|
+
[](https://pypi.org/project/onepaste/)
|
|
42
|
+
[](LICENSE)
|
|
43
|
+
[](https://github.com/emVisible/onepaste/actions/workflows/publish.yml)
|
|
39
44
|
|
|
40
45
|
Collect project code into LLM-ready Markdown. Select a directory, press Enter, copy and paste.
|
|
41
46
|
|
|
@@ -57,8 +62,8 @@ Without the `tokens` extra, token counts use a fast characters/4 estimate.
|
|
|
57
62
|
### From source (for development)
|
|
58
63
|
|
|
59
64
|
```bash
|
|
60
|
-
git clone https://github.com/emVisible/
|
|
61
|
-
cd
|
|
65
|
+
git clone https://github.com/emVisible/onepaste.git
|
|
66
|
+
cd onepaste
|
|
62
67
|
pipx install -e .
|
|
63
68
|
```
|
|
64
69
|
|
|
@@ -66,13 +71,13 @@ pipx install -e .
|
|
|
66
71
|
|
|
67
72
|
```bash
|
|
68
73
|
# Uninstall package
|
|
69
|
-
|
|
74
|
+
onepaste --uninstall
|
|
70
75
|
|
|
71
|
-
# Uninstall and remove ~/.config/
|
|
72
|
-
|
|
76
|
+
# Uninstall and remove ~/.config/onepaste
|
|
77
|
+
onepaste --uninstall --purge-config
|
|
73
78
|
|
|
74
79
|
# Reinstall editable from local source
|
|
75
|
-
cd /path/to/
|
|
80
|
+
cd /path/to/OnePaste
|
|
76
81
|
pipx install -e .
|
|
77
82
|
```
|
|
78
83
|
|
|
@@ -80,16 +85,16 @@ pipx install -e .
|
|
|
80
85
|
|
|
81
86
|
```bash
|
|
82
87
|
# Interactive: navigate to folder → select "Collect this directory" → Enter
|
|
83
|
-
|
|
88
|
+
onepaste
|
|
84
89
|
|
|
85
90
|
# Collect current directory (.gitignore filtering on automatically inside git repos)
|
|
86
|
-
|
|
91
|
+
onepaste .
|
|
87
92
|
|
|
88
93
|
# Pipe straight into another tool — no file written
|
|
89
|
-
|
|
94
|
+
onepaste . --stdout | llm "Explain what this project does"
|
|
90
95
|
|
|
91
96
|
# Only TypeScript sources, skip tests
|
|
92
|
-
|
|
97
|
+
onepaste . --include "src/**/*.ts" --exclude-pattern "*.test.ts"
|
|
93
98
|
```
|
|
94
99
|
|
|
95
100
|
Output is a single Markdown file (`code_collection.md`) ready to copy-paste into any LLM.
|
|
@@ -98,40 +103,40 @@ Output is a single Markdown file (`code_collection.md`) ready to copy-paste into
|
|
|
98
103
|
|
|
99
104
|
```bash
|
|
100
105
|
# Interactive mode
|
|
101
|
-
|
|
102
|
-
|
|
106
|
+
onepaste
|
|
107
|
+
onepaste -i # force .gitignore filter (deprecated: auto inside git)
|
|
103
108
|
|
|
104
109
|
# Collect a specific directory
|
|
105
|
-
|
|
106
|
-
|
|
110
|
+
onepaste /path/to/project
|
|
111
|
+
onepaste . --no-gitignore # include gitignored files too
|
|
107
112
|
|
|
108
113
|
# Non-recursive (current directory only)
|
|
109
|
-
|
|
114
|
+
onepaste . -n
|
|
110
115
|
|
|
111
116
|
# Custom output
|
|
112
|
-
|
|
113
|
-
|
|
117
|
+
onepaste . -o my_project.md
|
|
118
|
+
onepaste . -d ./collected
|
|
114
119
|
|
|
115
120
|
# Glob filtering (repeatable)
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
121
|
+
onepaste . --include "src/**"
|
|
122
|
+
onepaste . --include "*.py" --include "*.md"
|
|
123
|
+
onepaste . --exclude-pattern "*.min.js" --exclude-pattern "tests/*"
|
|
119
124
|
|
|
120
125
|
# Split large output (default: 2MB per part)
|
|
121
|
-
|
|
126
|
+
onepaste . --max-output-size 5
|
|
122
127
|
|
|
123
128
|
# Preview without writing
|
|
124
|
-
|
|
129
|
+
onepaste . --dry-run
|
|
125
130
|
|
|
126
131
|
# Extra exclusions
|
|
127
|
-
|
|
132
|
+
onepaste . --exclude vendor --exclude tmp
|
|
128
133
|
```
|
|
129
134
|
|
|
130
135
|
## Options
|
|
131
136
|
|
|
132
137
|
| Option | Description |
|
|
133
138
|
| ---------------------------- | ---------------------------------------------------------------------------------- |
|
|
134
|
-
| `path` | Directory to
|
|
139
|
+
| `path` | Directory to onepaste (default: interactive picker) |
|
|
135
140
|
| `-i` | Force-enable `.gitignore` filtering (deprecated alias; see below) |
|
|
136
141
|
| `--no-gitignore` | Disable `.gitignore` filtering |
|
|
137
142
|
| `-n, --non-recursive` | Only current directory, skip subdirectories |
|
|
@@ -139,15 +144,15 @@ collect . --exclude vendor --exclude tmp
|
|
|
139
144
|
| `-d, --output-dir` | Output directory (default: current working directory) |
|
|
140
145
|
| `--max-output-size MB` | Max output size per file; auto-split when exceeded (default: 2) |
|
|
141
146
|
| `--exclude DIR` | Extra directory to exclude (repeatable) |
|
|
142
|
-
| `--include GLOB` | Only
|
|
147
|
+
| `--include GLOB` | Only onepaste files matching glob (repeatable; overrides extension whitelist) |
|
|
143
148
|
| `--exclude-pattern GLOB` | Skip files matching glob (repeatable) |
|
|
144
149
|
| `--stdout` | Write collection to stdout; progress goes to stderr; no file written |
|
|
145
150
|
| `--dry-run` | Preview collection without writing output |
|
|
146
151
|
| `--force` | Overwrite existing output instead of auto-incrementing |
|
|
147
152
|
| `--config` | Path to config file (merged with global config) |
|
|
148
|
-
| `--init-config` | Generate default config at `~/.config/
|
|
149
|
-
| `--uninstall` | Uninstall
|
|
150
|
-
| `--purge-config` | Also remove `~/.config/
|
|
153
|
+
| `--init-config` | Generate default config at `~/.config/onepaste/config.json` |
|
|
154
|
+
| `--uninstall` | Uninstall onepaste via pipx and/or pip |
|
|
155
|
+
| `--purge-config` | Also remove `~/.config/onepaste` (with `--uninstall`) |
|
|
151
156
|
| `-v, --version` | Show version |
|
|
152
157
|
| `-h, --help` | Show help |
|
|
153
158
|
|
|
@@ -206,10 +211,10 @@ own output into the piped stream.
|
|
|
206
211
|
## Configuration
|
|
207
212
|
|
|
208
213
|
```bash
|
|
209
|
-
|
|
214
|
+
onepaste --init-config
|
|
210
215
|
```
|
|
211
216
|
|
|
212
|
-
Edit `~/.config/
|
|
217
|
+
Edit `~/.config/onepaste/config.json`:
|
|
213
218
|
|
|
214
219
|
```json
|
|
215
220
|
{
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Publishing to PyPI
|
|
2
2
|
|
|
3
|
-
Package name: **onepaste** (import name stays `
|
|
3
|
+
Package name: **onepaste** (import name stays `onepaste`, command stays `onepaste`).
|
|
4
4
|
|
|
5
5
|
## One-time setup (manual first release)
|
|
6
6
|
|
|
@@ -19,7 +19,7 @@ Package name: **onepaste** (import name stays `codecollector`, command stays `co
|
|
|
19
19
|
|
|
20
20
|
```bash
|
|
21
21
|
pipx install onepaste
|
|
22
|
-
|
|
22
|
+
onepaste --version # OnePaste v1.3.0
|
|
23
23
|
```
|
|
24
24
|
|
|
25
25
|
## Subsequent releases (GitHub Actions, zero tokens)
|
|
@@ -27,15 +27,16 @@ Package name: **onepaste** (import name stays `codecollector`, command stays `co
|
|
|
27
27
|
Uses PyPI Trusted Publishing (OIDC) — no secrets stored in GitHub.
|
|
28
28
|
|
|
29
29
|
1. On PyPI: your project → *Settings* → *Publishing* → add a **Trusted Publisher**:
|
|
30
|
-
- Owner: `emVisible` Repo: `
|
|
30
|
+
- Owner: `emVisible` Repo: `OnePaste`
|
|
31
31
|
- Workflow filename: `publish.yml`
|
|
32
32
|
- Environment name: `pypi`
|
|
33
33
|
2. Release: create a GitHub *Release* (or run the workflow manually via `workflow_dispatch`).
|
|
34
|
+
Alternatively: `git tag vX.Y.Z && git push origin vX.Y.Z` triggers the same workflow.
|
|
34
35
|
|
|
35
36
|
The workflow runs tests, builds, twine-checks, then publishes.
|
|
36
37
|
|
|
37
38
|
## Bump a version
|
|
38
39
|
|
|
39
40
|
1. `pyproject.toml` → `version`
|
|
40
|
-
2. `
|
|
41
|
+
2. `onepaste/__init__.py` → `__version__` (a test enforces both match)
|
|
41
42
|
3. Commit + GitHub Release with tag `vX.Y.Z`
|
|
@@ -1,4 +1,9 @@
|
|
|
1
|
-
#
|
|
1
|
+
# OnePaste
|
|
2
|
+
|
|
3
|
+
[](https://pypi.org/project/onepaste/)
|
|
4
|
+
[](https://pypi.org/project/onepaste/)
|
|
5
|
+
[](LICENSE)
|
|
6
|
+
[](https://github.com/emVisible/onepaste/actions/workflows/publish.yml)
|
|
2
7
|
|
|
3
8
|
Collect project code into LLM-ready Markdown. Select a directory, press Enter, copy and paste.
|
|
4
9
|
|
|
@@ -20,8 +25,8 @@ Without the `tokens` extra, token counts use a fast characters/4 estimate.
|
|
|
20
25
|
### From source (for development)
|
|
21
26
|
|
|
22
27
|
```bash
|
|
23
|
-
git clone https://github.com/emVisible/
|
|
24
|
-
cd
|
|
28
|
+
git clone https://github.com/emVisible/onepaste.git
|
|
29
|
+
cd onepaste
|
|
25
30
|
pipx install -e .
|
|
26
31
|
```
|
|
27
32
|
|
|
@@ -29,13 +34,13 @@ pipx install -e .
|
|
|
29
34
|
|
|
30
35
|
```bash
|
|
31
36
|
# Uninstall package
|
|
32
|
-
|
|
37
|
+
onepaste --uninstall
|
|
33
38
|
|
|
34
|
-
# Uninstall and remove ~/.config/
|
|
35
|
-
|
|
39
|
+
# Uninstall and remove ~/.config/onepaste
|
|
40
|
+
onepaste --uninstall --purge-config
|
|
36
41
|
|
|
37
42
|
# Reinstall editable from local source
|
|
38
|
-
cd /path/to/
|
|
43
|
+
cd /path/to/OnePaste
|
|
39
44
|
pipx install -e .
|
|
40
45
|
```
|
|
41
46
|
|
|
@@ -43,16 +48,16 @@ pipx install -e .
|
|
|
43
48
|
|
|
44
49
|
```bash
|
|
45
50
|
# Interactive: navigate to folder → select "Collect this directory" → Enter
|
|
46
|
-
|
|
51
|
+
onepaste
|
|
47
52
|
|
|
48
53
|
# Collect current directory (.gitignore filtering on automatically inside git repos)
|
|
49
|
-
|
|
54
|
+
onepaste .
|
|
50
55
|
|
|
51
56
|
# Pipe straight into another tool — no file written
|
|
52
|
-
|
|
57
|
+
onepaste . --stdout | llm "Explain what this project does"
|
|
53
58
|
|
|
54
59
|
# Only TypeScript sources, skip tests
|
|
55
|
-
|
|
60
|
+
onepaste . --include "src/**/*.ts" --exclude-pattern "*.test.ts"
|
|
56
61
|
```
|
|
57
62
|
|
|
58
63
|
Output is a single Markdown file (`code_collection.md`) ready to copy-paste into any LLM.
|
|
@@ -61,40 +66,40 @@ Output is a single Markdown file (`code_collection.md`) ready to copy-paste into
|
|
|
61
66
|
|
|
62
67
|
```bash
|
|
63
68
|
# Interactive mode
|
|
64
|
-
|
|
65
|
-
|
|
69
|
+
onepaste
|
|
70
|
+
onepaste -i # force .gitignore filter (deprecated: auto inside git)
|
|
66
71
|
|
|
67
72
|
# Collect a specific directory
|
|
68
|
-
|
|
69
|
-
|
|
73
|
+
onepaste /path/to/project
|
|
74
|
+
onepaste . --no-gitignore # include gitignored files too
|
|
70
75
|
|
|
71
76
|
# Non-recursive (current directory only)
|
|
72
|
-
|
|
77
|
+
onepaste . -n
|
|
73
78
|
|
|
74
79
|
# Custom output
|
|
75
|
-
|
|
76
|
-
|
|
80
|
+
onepaste . -o my_project.md
|
|
81
|
+
onepaste . -d ./collected
|
|
77
82
|
|
|
78
83
|
# Glob filtering (repeatable)
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
84
|
+
onepaste . --include "src/**"
|
|
85
|
+
onepaste . --include "*.py" --include "*.md"
|
|
86
|
+
onepaste . --exclude-pattern "*.min.js" --exclude-pattern "tests/*"
|
|
82
87
|
|
|
83
88
|
# Split large output (default: 2MB per part)
|
|
84
|
-
|
|
89
|
+
onepaste . --max-output-size 5
|
|
85
90
|
|
|
86
91
|
# Preview without writing
|
|
87
|
-
|
|
92
|
+
onepaste . --dry-run
|
|
88
93
|
|
|
89
94
|
# Extra exclusions
|
|
90
|
-
|
|
95
|
+
onepaste . --exclude vendor --exclude tmp
|
|
91
96
|
```
|
|
92
97
|
|
|
93
98
|
## Options
|
|
94
99
|
|
|
95
100
|
| Option | Description |
|
|
96
101
|
| ---------------------------- | ---------------------------------------------------------------------------------- |
|
|
97
|
-
| `path` | Directory to
|
|
102
|
+
| `path` | Directory to onepaste (default: interactive picker) |
|
|
98
103
|
| `-i` | Force-enable `.gitignore` filtering (deprecated alias; see below) |
|
|
99
104
|
| `--no-gitignore` | Disable `.gitignore` filtering |
|
|
100
105
|
| `-n, --non-recursive` | Only current directory, skip subdirectories |
|
|
@@ -102,15 +107,15 @@ collect . --exclude vendor --exclude tmp
|
|
|
102
107
|
| `-d, --output-dir` | Output directory (default: current working directory) |
|
|
103
108
|
| `--max-output-size MB` | Max output size per file; auto-split when exceeded (default: 2) |
|
|
104
109
|
| `--exclude DIR` | Extra directory to exclude (repeatable) |
|
|
105
|
-
| `--include GLOB` | Only
|
|
110
|
+
| `--include GLOB` | Only onepaste files matching glob (repeatable; overrides extension whitelist) |
|
|
106
111
|
| `--exclude-pattern GLOB` | Skip files matching glob (repeatable) |
|
|
107
112
|
| `--stdout` | Write collection to stdout; progress goes to stderr; no file written |
|
|
108
113
|
| `--dry-run` | Preview collection without writing output |
|
|
109
114
|
| `--force` | Overwrite existing output instead of auto-incrementing |
|
|
110
115
|
| `--config` | Path to config file (merged with global config) |
|
|
111
|
-
| `--init-config` | Generate default config at `~/.config/
|
|
112
|
-
| `--uninstall` | Uninstall
|
|
113
|
-
| `--purge-config` | Also remove `~/.config/
|
|
116
|
+
| `--init-config` | Generate default config at `~/.config/onepaste/config.json` |
|
|
117
|
+
| `--uninstall` | Uninstall onepaste via pipx and/or pip |
|
|
118
|
+
| `--purge-config` | Also remove `~/.config/onepaste` (with `--uninstall`) |
|
|
114
119
|
| `-v, --version` | Show version |
|
|
115
120
|
| `-h, --help` | Show help |
|
|
116
121
|
|
|
@@ -169,10 +174,10 @@ own output into the piped stream.
|
|
|
169
174
|
## Configuration
|
|
170
175
|
|
|
171
176
|
```bash
|
|
172
|
-
|
|
177
|
+
onepaste --init-config
|
|
173
178
|
```
|
|
174
179
|
|
|
175
|
-
Edit `~/.config/
|
|
180
|
+
Edit `~/.config/onepaste/config.json`:
|
|
176
181
|
|
|
177
182
|
```json
|
|
178
183
|
{
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"""OnePaste - Collect project code files for AI assistants."""
|
|
2
|
+
|
|
3
|
+
__version__ = "1.3.2"
|
|
4
|
+
__author__ = "thawn"
|
|
5
|
+
__license__ = "MIT"
|
|
6
|
+
|
|
7
|
+
from onepaste.collector import FileCollector
|
|
8
|
+
from onepaste.config import CollectorConfig
|
|
9
|
+
|
|
10
|
+
__all__ = ["FileCollector", "CollectorConfig", "__version__"]
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"""Command-line interface for
|
|
1
|
+
"""Command-line interface for OnePaste."""
|
|
2
2
|
|
|
3
3
|
import sys
|
|
4
4
|
from pathlib import Path
|
|
@@ -9,15 +9,15 @@ from rich.panel import Panel
|
|
|
9
9
|
from rich.table import Table
|
|
10
10
|
from rich.theme import Theme
|
|
11
11
|
|
|
12
|
-
from
|
|
13
|
-
from
|
|
14
|
-
from
|
|
15
|
-
from
|
|
16
|
-
from
|
|
17
|
-
from
|
|
18
|
-
from
|
|
19
|
-
from
|
|
20
|
-
from
|
|
12
|
+
from onepaste import __version__
|
|
13
|
+
from onepaste.collector import FileCollector
|
|
14
|
+
from onepaste.config import CONFIG_FILE, CollectorConfig, ensure_config_dir
|
|
15
|
+
from onepaste.formatter import OutputFormatter
|
|
16
|
+
from onepaste.output import output_files_exist, write_manifest
|
|
17
|
+
from onepaste.selector import InteractiveSelector
|
|
18
|
+
from onepaste.splitter import write_collection_output
|
|
19
|
+
from onepaste.tokens import count_tokens, method_label
|
|
20
|
+
from onepaste.uninstall import uninstall_package
|
|
21
21
|
|
|
22
22
|
custom_theme = Theme({
|
|
23
23
|
"info": "cyan",
|
|
@@ -35,8 +35,8 @@ console = Console(theme=custom_theme)
|
|
|
35
35
|
err_console = Console(file=sys.stderr, theme=custom_theme)
|
|
36
36
|
|
|
37
37
|
|
|
38
|
-
class
|
|
39
|
-
"""Main application class for
|
|
38
|
+
class OnePasteApp:
|
|
39
|
+
"""Main application class for OnePaste."""
|
|
40
40
|
|
|
41
41
|
def __init__(self):
|
|
42
42
|
self.config: Optional[CollectorConfig] = None
|
|
@@ -377,7 +377,7 @@ class CodeCollectorApp:
|
|
|
377
377
|
console.print()
|
|
378
378
|
console.print(
|
|
379
379
|
Panel(
|
|
380
|
-
"[title]
|
|
380
|
+
"[title]OnePaste[/title]\n"
|
|
381
381
|
"[subtitle]Select a directory → Enter → ready for LLM[/subtitle]\n"
|
|
382
382
|
f"[dim]v{__version__}[/dim]",
|
|
383
383
|
border_style="cyan",
|
|
@@ -391,7 +391,7 @@ def main() -> None:
|
|
|
391
391
|
import argparse
|
|
392
392
|
|
|
393
393
|
parser = argparse.ArgumentParser(
|
|
394
|
-
description="
|
|
394
|
+
description="OnePaste - Collect project code for AI assistants",
|
|
395
395
|
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
396
396
|
epilog=f"""
|
|
397
397
|
Examples:
|
|
@@ -410,8 +410,8 @@ Examples:
|
|
|
410
410
|
collect . --include "src/**" Only include files matching glob (repeatable)
|
|
411
411
|
collect . --exclude-pattern "*_test.go" Skip files matching glob (repeatable)
|
|
412
412
|
collect --init-config Initialize default configuration
|
|
413
|
-
collect --uninstall Uninstall
|
|
414
|
-
collect --uninstall --purge-config Uninstall and remove ~/.config/
|
|
413
|
+
collect --uninstall Uninstall onepaste (pipx/pip)
|
|
414
|
+
collect --uninstall --purge-config Uninstall and remove ~/.config/onepaste
|
|
415
415
|
|
|
416
416
|
Version: {__version__}
|
|
417
417
|
""",
|
|
@@ -478,14 +478,14 @@ Version: {__version__}
|
|
|
478
478
|
parser.add_argument(
|
|
479
479
|
"--uninstall",
|
|
480
480
|
action="store_true",
|
|
481
|
-
help="Uninstall
|
|
481
|
+
help="Uninstall onepaste (via pipx and/or pip)",
|
|
482
482
|
)
|
|
483
483
|
parser.add_argument(
|
|
484
484
|
"--purge-config",
|
|
485
485
|
action="store_true",
|
|
486
|
-
help="Also remove ~/.config/
|
|
486
|
+
help="Also remove ~/.config/onepaste (use with --uninstall)",
|
|
487
487
|
)
|
|
488
|
-
parser.add_argument("-v", "--version", action="version", version=f"
|
|
488
|
+
parser.add_argument("-v", "--version", action="version", version=f"OnePaste v{__version__}")
|
|
489
489
|
|
|
490
490
|
args = parser.parse_args()
|
|
491
491
|
|
|
@@ -535,7 +535,7 @@ Version: {__version__}
|
|
|
535
535
|
return
|
|
536
536
|
|
|
537
537
|
try:
|
|
538
|
-
app =
|
|
538
|
+
app = OnePasteApp()
|
|
539
539
|
|
|
540
540
|
if not args.path and not args.config:
|
|
541
541
|
respect = True if args.i else (False if args.no_gitignore else None)
|
|
@@ -6,8 +6,8 @@ import re
|
|
|
6
6
|
from pathlib import Path
|
|
7
7
|
from typing import Iterable, List, Optional, Set, Tuple
|
|
8
8
|
|
|
9
|
-
from
|
|
10
|
-
from
|
|
9
|
+
from onepaste.config import CollectorConfig
|
|
10
|
+
from onepaste.gitignore import GitignoreMatcher, list_git_visible_files
|
|
11
11
|
|
|
12
12
|
# Own outputs should never be re-collected (prevents runaway growth).
|
|
13
13
|
_OUTPUT_ARTIFACT_RE = re.compile(
|
|
@@ -150,16 +150,28 @@ class FileCollector:
|
|
|
150
150
|
|
|
151
151
|
def _path_in_excluded_dir(self, file_path: Path) -> bool:
|
|
152
152
|
try:
|
|
153
|
-
|
|
153
|
+
rel = file_path.relative_to(self.config.root_path)
|
|
154
154
|
except ValueError:
|
|
155
|
-
|
|
156
|
-
|
|
155
|
+
try:
|
|
156
|
+
rel = file_path.resolve().relative_to(self.config.root_path.resolve())
|
|
157
|
+
except ValueError:
|
|
158
|
+
return False
|
|
159
|
+
return any(part in self.config.all_exclude_dirs for part in rel.parts[:-1])
|
|
157
160
|
|
|
158
161
|
def _should_exclude_dir(self, dir_path: Path) -> bool:
|
|
159
|
-
"""Check if a directory should be excluded.
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
162
|
+
"""Check if a directory should be excluded.
|
|
163
|
+
|
|
164
|
+
Exclusion names match path segments *relative to the collection root*
|
|
165
|
+
only — never absolute ancestors (e.g. a /tmp-based temp dir must not
|
|
166
|
+
trip the "tmp" rule).
|
|
167
|
+
"""
|
|
168
|
+
try:
|
|
169
|
+
segments = dir_path.relative_to(self.config.root_path).parts
|
|
170
|
+
except ValueError:
|
|
171
|
+
segments = (dir_path.name,)
|
|
172
|
+
|
|
173
|
+
if any(part in self.config.all_exclude_dirs for part in segments):
|
|
174
|
+
return True
|
|
163
175
|
|
|
164
176
|
if self._git_files is None and self._gitignore:
|
|
165
177
|
if self._gitignore.is_ignored(dir_path, is_dir=True):
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
"""Configuration management for
|
|
1
|
+
"""Configuration management for OnePaste."""
|
|
2
2
|
|
|
3
3
|
import json
|
|
4
4
|
from dataclasses import dataclass, field, fields
|
|
5
5
|
from pathlib import Path
|
|
6
6
|
from typing import Any, Dict, List, Optional, Set
|
|
7
7
|
|
|
8
|
-
from
|
|
8
|
+
from onepaste.gitignore import is_inside_git_work_tree
|
|
9
9
|
|
|
10
|
-
CONFIG_DIR = Path.home() / ".config" / "
|
|
10
|
+
CONFIG_DIR = Path.home() / ".config" / "onepaste"
|
|
11
11
|
CONFIG_FILE = CONFIG_DIR / "config.json"
|
|
12
12
|
|
|
13
13
|
|