bib_optimizer 0.5.1__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.
- bib_optimizer-0.5.1/LICENSE +21 -0
- bib_optimizer-0.5.1/PKG-INFO +226 -0
- bib_optimizer-0.5.1/README.md +171 -0
- bib_optimizer-0.5.1/pyproject.toml +64 -0
- bib_optimizer-0.5.1/setup.cfg +4 -0
- bib_optimizer-0.5.1/src/bib_optimizer/__init__.py +2 -0
- bib_optimizer-0.5.1/src/bib_optimizer/__main__.py +23 -0
- bib_optimizer-0.5.1/src/bib_optimizer/helpers.py +74 -0
- bib_optimizer-0.5.1/src/bib_optimizer.egg-info/PKG-INFO +226 -0
- bib_optimizer-0.5.1/src/bib_optimizer.egg-info/SOURCES.txt +12 -0
- bib_optimizer-0.5.1/src/bib_optimizer.egg-info/dependency_links.txt +1 -0
- bib_optimizer-0.5.1/src/bib_optimizer.egg-info/entry_points.txt +2 -0
- bib_optimizer-0.5.1/src/bib_optimizer.egg-info/requires.txt +12 -0
- bib_optimizer-0.5.1/src/bib_optimizer.egg-info/top_level.txt +1 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Ka Wa Yip
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: bib_optimizer
|
|
3
|
+
Version: 0.5.1
|
|
4
|
+
Summary: Clean and optimize bib file.
|
|
5
|
+
Author-email: Ka Wa Yip <yipkawa@gmail.com>
|
|
6
|
+
License: MIT License
|
|
7
|
+
|
|
8
|
+
Copyright (c) 2025 Ka Wa Yip
|
|
9
|
+
|
|
10
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
11
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
12
|
+
in the Software without restriction, including without limitation the rights
|
|
13
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
14
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
15
|
+
furnished to do so, subject to the following conditions:
|
|
16
|
+
|
|
17
|
+
The above copyright notice and this permission notice shall be included in all
|
|
18
|
+
copies or substantial portions of the Software.
|
|
19
|
+
|
|
20
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
21
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
22
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
23
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
24
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
25
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
26
|
+
SOFTWARE.
|
|
27
|
+
|
|
28
|
+
Project-URL: Homepage, https://github.com/kwyip/bib_optimizer
|
|
29
|
+
Project-URL: Issues, https://github.com/kwyip/bib_optimizer/issues
|
|
30
|
+
Keywords: latex,bib,bibliography
|
|
31
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
32
|
+
Classifier: Programming Language :: Python
|
|
33
|
+
Classifier: Programming Language :: Python :: 3
|
|
34
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
35
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
36
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
37
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
38
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
39
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
40
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
41
|
+
Requires-Python: >=3.8
|
|
42
|
+
Description-Content-Type: text/markdown
|
|
43
|
+
License-File: LICENSE
|
|
44
|
+
Requires-Dist: bibtexparser<2,>=1.4.3
|
|
45
|
+
Provides-Extra: build
|
|
46
|
+
Requires-Dist: build; extra == "build"
|
|
47
|
+
Requires-Dist: twine; extra == "build"
|
|
48
|
+
Provides-Extra: dev
|
|
49
|
+
Requires-Dist: black; extra == "dev"
|
|
50
|
+
Requires-Dist: bumpver; extra == "dev"
|
|
51
|
+
Requires-Dist: isort; extra == "dev"
|
|
52
|
+
Requires-Dist: mypy; extra == "dev"
|
|
53
|
+
Requires-Dist: pytest; extra == "dev"
|
|
54
|
+
Dynamic: license-file
|
|
55
|
+
|
|
56
|
+
<figure>
|
|
57
|
+
<img src="https://github.com/kwyip/bib_optimizer/blob/main/logo.png?raw=True" alt="logo" height="143" />
|
|
58
|
+
<!-- <figcaption>An elephant at sunset</figcaption> -->
|
|
59
|
+
</figure>
|
|
60
|
+
|
|
61
|
+
[](https://github.com/kwyip/bib_optimizer/blob/main/LICENSE)
|
|
62
|
+
[](https://pypi.org/project/bib-optimizer/)
|
|
63
|
+
[](https://pypi.org/project/bib-optimizer)
|
|
64
|
+
[](https://pypi.org/project/bib-optimizer/#files)
|
|
65
|
+
[](https://pepy.tech/project/bib_optimizer)
|
|
66
|
+
|
|
67
|
+
[bib-optimizer](https://bibopt.github.io/)
|
|
68
|
+
==========================================
|
|
69
|
+
|
|
70
|
+
Oh, sure, because who doesn't love manually cleaning up messy `.bib` files? `bib_optimizer.py` heroically steps in to remove those lazy, _unused_ citations and _reorder_ the survivors exactly as they appear in the `.tex` file—because, clearly, chaos is the default setting for bibliographies.
|
|
71
|
+
|
|
72
|
+
In layman's terms, it automates bibliography management by:
|
|
73
|
+
|
|
74
|
+
1. removing unused citations,
|
|
75
|
+
2. reordering the remaining ones to match their order of appearance in the `.tex` file.
|
|
76
|
+
|
|
77
|
+
**Input Files:**
|
|
78
|
+
|
|
79
|
+
* `main.tex` – The LaTeX source file.
|
|
80
|
+
* `ref.bib` – The original bibliography file.
|
|
81
|
+
|
|
82
|
+
These input files will **remain unchanged**.
|
|
83
|
+
|
|
84
|
+
**Output File:**
|
|
85
|
+
|
|
86
|
+
* `ref_opt.bib` – A placeholder filename for the newly generated, cleaned, and ordered bibliography file.
|
|
87
|
+
|
|
88
|
+
* * *
|
|
89
|
+
|
|
90
|
+
Installation
|
|
91
|
+
------------
|
|
92
|
+
|
|
93
|
+
### Install from PyPI with pip
|
|
94
|
+
|
|
95
|
+
Create and activate a virtual environment, then install the latest release from PyPI:
|
|
96
|
+
|
|
97
|
+
```bash
|
|
98
|
+
python -m venv .venv
|
|
99
|
+
|
|
100
|
+
# Linux/macOS
|
|
101
|
+
source .venv/bin/activate
|
|
102
|
+
|
|
103
|
+
# Windows
|
|
104
|
+
.venv\Scripts\activate
|
|
105
|
+
|
|
106
|
+
python -m pip install --upgrade bib_optimizer
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
Alternatively, install the command in an isolated environment with [uv](https://docs.astral.sh/uv/):
|
|
110
|
+
|
|
111
|
+
```bash
|
|
112
|
+
uv tool install bib_optimizer
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
After either installation method, the `bibopt` command is available in your terminal.
|
|
116
|
+
|
|
117
|
+
### Install from source for development
|
|
118
|
+
|
|
119
|
+
This repository uses uv for project and dependency management.
|
|
120
|
+
|
|
121
|
+
1. **Clone the repository**
|
|
122
|
+
|
|
123
|
+
```bash
|
|
124
|
+
git clone https://github.com/kwyip/bib_optimizer.git
|
|
125
|
+
cd bib_optimizer
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
2. **Install environment**
|
|
129
|
+
|
|
130
|
+
```bash
|
|
131
|
+
# This creates the virtual environment and installs all dependencies
|
|
132
|
+
uv sync
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
3. **Activate environment**
|
|
136
|
+
|
|
137
|
+
```bash
|
|
138
|
+
# Linux/MacOS
|
|
139
|
+
source .venv/bin/activate
|
|
140
|
+
|
|
141
|
+
# Windows
|
|
142
|
+
.venv\Scripts\activate
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
_🐍 This requires Python 3.8 or newer versions_
|
|
146
|
+
|
|
147
|
+
* * *
|
|
148
|
+
|
|
149
|
+
### Steps to Clean Your Bibliography
|
|
150
|
+
|
|
151
|
+
1. **Prepare the input files (e.g., by downloading them from Overleaf)**.
|
|
152
|
+
2. **Run the command to generate a new `.bib` file (for example, you may name it `ref_opt.bib`)**:
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
`bibopt main.tex ref.bib ref_opt.bib`
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
3. **Use the Cleaned Bibliography**
|
|
160
|
+
Replace `ref.bib` with `ref_opt.bib` in your LaTeX project.
|
|
161
|
+
|
|
162
|
+
* * *
|
|
163
|
+
|
|
164
|
+
### Test
|
|
165
|
+
|
|
166
|
+
You may test the installation using the sample input files (`sample_main.tex` and `sample_ref.bib`) located in the test folder.
|
|
167
|
+
|
|
168
|
+
<img src="https://github.com/kwyip/bib_optimizer/blob/main/sample_main_shot.png?raw=True" alt="sample_main_shot" width="34.83%"/> <img src="https://github.com/kwyip/bib_optimizer/blob/main/sample_ref_shot.png?raw=True" alt="sample_ref_shot" width="43%" />
|
|
169
|
+
|
|
170
|
+
`sample_main.tex` _and_ `sample_ref.bib`
|
|
171
|
+
|
|
172
|
+
<img src="https://github.com/kwyip/bib_optimizer/blob/main/sample_ref_opt_shot.png?raw=True" alt="sample_ref_opt_shot" width="43%" />
|
|
173
|
+
|
|
174
|
+
_A sample_ `ref_opt.bib` _created after running_ `bibopt sample_main.tex sample_ref.bib ref_opt.bib`
|
|
175
|
+
|
|
176
|
+
* * *
|
|
177
|
+
|
|
178
|
+
## Code-free use with an AI agent
|
|
179
|
+
|
|
180
|
+
[**Download `SKILL.md`**](./SKILL.md), then upload these files to your AI agent:
|
|
181
|
+
|
|
182
|
+
- `SKILL.md`,
|
|
183
|
+
- the root `.tex` file,
|
|
184
|
+
- the source `.bib` file, and if any:
|
|
185
|
+
- every `.tex` file referenced through `\input` or `\include`.
|
|
186
|
+
|
|
187
|
+
> [!TIP]
|
|
188
|
+
> Use this prompt:
|
|
189
|
+
>
|
|
190
|
+
> ```text
|
|
191
|
+
> Use the attached `SKILL.md` to optimize the attached LaTeX and BibTeX files.
|
|
192
|
+
> Return only the optimized `.bib` file.
|
|
193
|
+
> ```
|
|
194
|
+
|
|
195
|
+
|
|
196
|
+
https://github.com/user-attachments/assets/2b4e3224-2aee-44c1-974c-812dead72e2f
|
|
197
|
+
|
|
198
|
+
|
|
199
|
+
* * *
|
|
200
|
+
|
|
201
|
+
#### New feature (version 0.4.0)
|
|
202
|
+
|
|
203
|
+
If the `main.tex` calls inputs from other `.tex` (e.g., with `\input{...}`), the newly generated `ref_opt.bib` will preserve the order of appearances in the `main.tex` with each inputted `.tex` as well. \
|
|
204
|
+
(The dependent `.tex` files need to be placed in the same directory as `main.tex`.)
|
|
205
|
+
|
|
206
|
+
---
|
|
207
|
+
#### New feature (version 0.4.1)
|
|
208
|
+
|
|
209
|
+
On top of version 0.4, skip any `\input` `.tex` file if not found.
|
|
210
|
+
|
|
211
|
+
---
|
|
212
|
+
#### New feature/Fix (version 0.4.2)
|
|
213
|
+
|
|
214
|
+
Added support for the `\include{...}` command in addition to `\input{...}`, fixing missing citations when a LaTeX project uses `\include` to split its content across files.
|
|
215
|
+
|
|
216
|
+
---
|
|
217
|
+
#### New feature/Fix (version 0.4.3)
|
|
218
|
+
|
|
219
|
+
Added Python 3.14 support and constrained `bibtexparser` to the compatible 1.x release series, fixing `ModuleNotFoundError: No module named 'bibtexparser.bwriter'` during fresh installations.
|
|
220
|
+
|
|
221
|
+
---
|
|
222
|
+
#### New feature/Fix (version 0.5.0)
|
|
223
|
+
|
|
224
|
+
Add code-free SKILL.md
|
|
225
|
+
|
|
226
|
+
♥ Lastly executed on Python `3.14` on 2026-09-29.
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
<figure>
|
|
2
|
+
<img src="https://github.com/kwyip/bib_optimizer/blob/main/logo.png?raw=True" alt="logo" height="143" />
|
|
3
|
+
<!-- <figcaption>An elephant at sunset</figcaption> -->
|
|
4
|
+
</figure>
|
|
5
|
+
|
|
6
|
+
[](https://github.com/kwyip/bib_optimizer/blob/main/LICENSE)
|
|
7
|
+
[](https://pypi.org/project/bib-optimizer/)
|
|
8
|
+
[](https://pypi.org/project/bib-optimizer)
|
|
9
|
+
[](https://pypi.org/project/bib-optimizer/#files)
|
|
10
|
+
[](https://pepy.tech/project/bib_optimizer)
|
|
11
|
+
|
|
12
|
+
[bib-optimizer](https://bibopt.github.io/)
|
|
13
|
+
==========================================
|
|
14
|
+
|
|
15
|
+
Oh, sure, because who doesn't love manually cleaning up messy `.bib` files? `bib_optimizer.py` heroically steps in to remove those lazy, _unused_ citations and _reorder_ the survivors exactly as they appear in the `.tex` file—because, clearly, chaos is the default setting for bibliographies.
|
|
16
|
+
|
|
17
|
+
In layman's terms, it automates bibliography management by:
|
|
18
|
+
|
|
19
|
+
1. removing unused citations,
|
|
20
|
+
2. reordering the remaining ones to match their order of appearance in the `.tex` file.
|
|
21
|
+
|
|
22
|
+
**Input Files:**
|
|
23
|
+
|
|
24
|
+
* `main.tex` – The LaTeX source file.
|
|
25
|
+
* `ref.bib` – The original bibliography file.
|
|
26
|
+
|
|
27
|
+
These input files will **remain unchanged**.
|
|
28
|
+
|
|
29
|
+
**Output File:**
|
|
30
|
+
|
|
31
|
+
* `ref_opt.bib` – A placeholder filename for the newly generated, cleaned, and ordered bibliography file.
|
|
32
|
+
|
|
33
|
+
* * *
|
|
34
|
+
|
|
35
|
+
Installation
|
|
36
|
+
------------
|
|
37
|
+
|
|
38
|
+
### Install from PyPI with pip
|
|
39
|
+
|
|
40
|
+
Create and activate a virtual environment, then install the latest release from PyPI:
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
python -m venv .venv
|
|
44
|
+
|
|
45
|
+
# Linux/macOS
|
|
46
|
+
source .venv/bin/activate
|
|
47
|
+
|
|
48
|
+
# Windows
|
|
49
|
+
.venv\Scripts\activate
|
|
50
|
+
|
|
51
|
+
python -m pip install --upgrade bib_optimizer
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
Alternatively, install the command in an isolated environment with [uv](https://docs.astral.sh/uv/):
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
uv tool install bib_optimizer
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
After either installation method, the `bibopt` command is available in your terminal.
|
|
61
|
+
|
|
62
|
+
### Install from source for development
|
|
63
|
+
|
|
64
|
+
This repository uses uv for project and dependency management.
|
|
65
|
+
|
|
66
|
+
1. **Clone the repository**
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
git clone https://github.com/kwyip/bib_optimizer.git
|
|
70
|
+
cd bib_optimizer
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
2. **Install environment**
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
# This creates the virtual environment and installs all dependencies
|
|
77
|
+
uv sync
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
3. **Activate environment**
|
|
81
|
+
|
|
82
|
+
```bash
|
|
83
|
+
# Linux/MacOS
|
|
84
|
+
source .venv/bin/activate
|
|
85
|
+
|
|
86
|
+
# Windows
|
|
87
|
+
.venv\Scripts\activate
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
_🐍 This requires Python 3.8 or newer versions_
|
|
91
|
+
|
|
92
|
+
* * *
|
|
93
|
+
|
|
94
|
+
### Steps to Clean Your Bibliography
|
|
95
|
+
|
|
96
|
+
1. **Prepare the input files (e.g., by downloading them from Overleaf)**.
|
|
97
|
+
2. **Run the command to generate a new `.bib` file (for example, you may name it `ref_opt.bib`)**:
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
`bibopt main.tex ref.bib ref_opt.bib`
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
3. **Use the Cleaned Bibliography**
|
|
105
|
+
Replace `ref.bib` with `ref_opt.bib` in your LaTeX project.
|
|
106
|
+
|
|
107
|
+
* * *
|
|
108
|
+
|
|
109
|
+
### Test
|
|
110
|
+
|
|
111
|
+
You may test the installation using the sample input files (`sample_main.tex` and `sample_ref.bib`) located in the test folder.
|
|
112
|
+
|
|
113
|
+
<img src="https://github.com/kwyip/bib_optimizer/blob/main/sample_main_shot.png?raw=True" alt="sample_main_shot" width="34.83%"/> <img src="https://github.com/kwyip/bib_optimizer/blob/main/sample_ref_shot.png?raw=True" alt="sample_ref_shot" width="43%" />
|
|
114
|
+
|
|
115
|
+
`sample_main.tex` _and_ `sample_ref.bib`
|
|
116
|
+
|
|
117
|
+
<img src="https://github.com/kwyip/bib_optimizer/blob/main/sample_ref_opt_shot.png?raw=True" alt="sample_ref_opt_shot" width="43%" />
|
|
118
|
+
|
|
119
|
+
_A sample_ `ref_opt.bib` _created after running_ `bibopt sample_main.tex sample_ref.bib ref_opt.bib`
|
|
120
|
+
|
|
121
|
+
* * *
|
|
122
|
+
|
|
123
|
+
## Code-free use with an AI agent
|
|
124
|
+
|
|
125
|
+
[**Download `SKILL.md`**](./SKILL.md), then upload these files to your AI agent:
|
|
126
|
+
|
|
127
|
+
- `SKILL.md`,
|
|
128
|
+
- the root `.tex` file,
|
|
129
|
+
- the source `.bib` file, and if any:
|
|
130
|
+
- every `.tex` file referenced through `\input` or `\include`.
|
|
131
|
+
|
|
132
|
+
> [!TIP]
|
|
133
|
+
> Use this prompt:
|
|
134
|
+
>
|
|
135
|
+
> ```text
|
|
136
|
+
> Use the attached `SKILL.md` to optimize the attached LaTeX and BibTeX files.
|
|
137
|
+
> Return only the optimized `.bib` file.
|
|
138
|
+
> ```
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
https://github.com/user-attachments/assets/2b4e3224-2aee-44c1-974c-812dead72e2f
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
* * *
|
|
145
|
+
|
|
146
|
+
#### New feature (version 0.4.0)
|
|
147
|
+
|
|
148
|
+
If the `main.tex` calls inputs from other `.tex` (e.g., with `\input{...}`), the newly generated `ref_opt.bib` will preserve the order of appearances in the `main.tex` with each inputted `.tex` as well. \
|
|
149
|
+
(The dependent `.tex` files need to be placed in the same directory as `main.tex`.)
|
|
150
|
+
|
|
151
|
+
---
|
|
152
|
+
#### New feature (version 0.4.1)
|
|
153
|
+
|
|
154
|
+
On top of version 0.4, skip any `\input` `.tex` file if not found.
|
|
155
|
+
|
|
156
|
+
---
|
|
157
|
+
#### New feature/Fix (version 0.4.2)
|
|
158
|
+
|
|
159
|
+
Added support for the `\include{...}` command in addition to `\input{...}`, fixing missing citations when a LaTeX project uses `\include` to split its content across files.
|
|
160
|
+
|
|
161
|
+
---
|
|
162
|
+
#### New feature/Fix (version 0.4.3)
|
|
163
|
+
|
|
164
|
+
Added Python 3.14 support and constrained `bibtexparser` to the compatible 1.x release series, fixing `ModuleNotFoundError: No module named 'bibtexparser.bwriter'` during fresh installations.
|
|
165
|
+
|
|
166
|
+
---
|
|
167
|
+
#### New feature/Fix (version 0.5.0)
|
|
168
|
+
|
|
169
|
+
Add code-free SKILL.md
|
|
170
|
+
|
|
171
|
+
♥ Lastly executed on Python `3.14` on 2026-09-29.
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# pyproject.toml
|
|
2
|
+
|
|
3
|
+
[build-system]
|
|
4
|
+
requires = ["setuptools>=75.3.0", "wheel"]
|
|
5
|
+
build-backend = "setuptools.build_meta"
|
|
6
|
+
|
|
7
|
+
[project]
|
|
8
|
+
name = "bib_optimizer"
|
|
9
|
+
version = "0.5.1"
|
|
10
|
+
description = "Clean and optimize bib file."
|
|
11
|
+
authors = [
|
|
12
|
+
{ name="Ka Wa Yip", email="yipkawa@gmail.com" },
|
|
13
|
+
]
|
|
14
|
+
license = { file = "LICENSE" }
|
|
15
|
+
readme = "README.md"
|
|
16
|
+
requires-python = ">=3.8"
|
|
17
|
+
dependencies = ["bibtexparser>=1.4.3,<2"]
|
|
18
|
+
classifiers = [
|
|
19
|
+
"License :: OSI Approved :: MIT License",
|
|
20
|
+
"Programming Language :: Python",
|
|
21
|
+
"Programming Language :: Python :: 3",
|
|
22
|
+
"Programming Language :: Python :: 3.8",
|
|
23
|
+
"Programming Language :: Python :: 3.9",
|
|
24
|
+
"Programming Language :: Python :: 3.10",
|
|
25
|
+
"Programming Language :: Python :: 3.11",
|
|
26
|
+
"Programming Language :: Python :: 3.12",
|
|
27
|
+
"Programming Language :: Python :: 3.13",
|
|
28
|
+
"Programming Language :: Python :: 3.14"
|
|
29
|
+
]
|
|
30
|
+
keywords = ["latex", "bib", "bibliography"]
|
|
31
|
+
|
|
32
|
+
[project.urls]
|
|
33
|
+
Homepage = "https://github.com/kwyip/bib_optimizer"
|
|
34
|
+
Issues = "https://github.com/kwyip/bib_optimizer/issues"
|
|
35
|
+
|
|
36
|
+
[project.optional-dependencies]
|
|
37
|
+
build = ["build", "twine"]
|
|
38
|
+
dev = ["black", "bumpver", "isort", "mypy", "pytest"]
|
|
39
|
+
|
|
40
|
+
[project.scripts]
|
|
41
|
+
bibopt = "bib_optimizer.__main__:main"
|
|
42
|
+
|
|
43
|
+
[tool.bumpver]
|
|
44
|
+
current_version = "0.5.1"
|
|
45
|
+
version_pattern = "MAJOR.MINOR.PATCH"
|
|
46
|
+
commit_message = "bump version {old_version} -> {new_version}"
|
|
47
|
+
commit = true
|
|
48
|
+
tag = true
|
|
49
|
+
push = false
|
|
50
|
+
|
|
51
|
+
[tool.bumpver.file_patterns]
|
|
52
|
+
"pyproject.toml" = [
|
|
53
|
+
'current_version = "{version}"',
|
|
54
|
+
'version = "{version}"',
|
|
55
|
+
]
|
|
56
|
+
"src/bib_optimizer/__init__.py" = ["{version}"]
|
|
57
|
+
"src/bib_optimizer/__main__.py" = ["- bib_optimizer v{version}"]
|
|
58
|
+
|
|
59
|
+
[tool.isort]
|
|
60
|
+
profile = "black"
|
|
61
|
+
import_heading_stdlib = "Standard library imports"
|
|
62
|
+
import_heading_thirdparty = "Third party imports"
|
|
63
|
+
import_heading_firstparty = "Reader imports"
|
|
64
|
+
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"""Version:
|
|
2
|
+
--------
|
|
3
|
+
|
|
4
|
+
- bib_optimizer v0.5.1
|
|
5
|
+
"""
|
|
6
|
+
import sys
|
|
7
|
+
from bib_optimizer import helpers
|
|
8
|
+
|
|
9
|
+
def main():
|
|
10
|
+
if len(sys.argv[1:]) != 3:
|
|
11
|
+
raise Exception("Sorry, please input three files: your tex filename, bib filename, and the desired new bib filename")
|
|
12
|
+
tex = sys.argv[1:][0]
|
|
13
|
+
old_bib = sys.argv[1:][1]
|
|
14
|
+
new_bib = sys.argv[1:][2]
|
|
15
|
+
|
|
16
|
+
helpers.bib_opt(tex, old_bib, new_bib)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
if __name__ == '__main__':
|
|
21
|
+
main()
|
|
22
|
+
|
|
23
|
+
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import bibtexparser
|
|
2
|
+
import re
|
|
3
|
+
from bibtexparser.bwriter import BibTexWriter
|
|
4
|
+
|
|
5
|
+
def _augment_func(filecontent, all_keys, temp_citations):
|
|
6
|
+
for e in re.findall(r'\\cite[tp]?\{([^}]+)\}', filecontent):
|
|
7
|
+
for c in e.split(','):
|
|
8
|
+
c = c.strip()
|
|
9
|
+
if c not in temp_citations:
|
|
10
|
+
all_keys.append(c)
|
|
11
|
+
temp_citations.add(c)
|
|
12
|
+
|
|
13
|
+
return all_keys, temp_citations
|
|
14
|
+
|
|
15
|
+
def bib_opt(filename, input_bib, output_bib):
|
|
16
|
+
with open(filename, 'r', encoding='utf-8') as file:
|
|
17
|
+
lines = file.readlines()
|
|
18
|
+
filtered_lines = [line for line in lines if not line.lstrip().startswith('%')]
|
|
19
|
+
filecontent = ''.join(filtered_lines)
|
|
20
|
+
|
|
21
|
+
with open(input_bib, 'r', encoding='utf-8') as bibfile:
|
|
22
|
+
bib_database = bibtexparser.load(bibfile)
|
|
23
|
+
|
|
24
|
+
allowed_keys = []
|
|
25
|
+
all_keys = []
|
|
26
|
+
temp_citations = set()
|
|
27
|
+
|
|
28
|
+
split_pattern = r'(.*?)(\\(?:input|include)[^\n]*\n)(.*?)((?=\\(?:input|include))|\Z)'
|
|
29
|
+
matches = re.findall(split_pattern, filecontent, flags=re.DOTALL)
|
|
30
|
+
split_results = [(before, after.strip()) for before, input_line, after, _ in matches]
|
|
31
|
+
|
|
32
|
+
input_pattern_extended = r'\\(?:input|include)\s*(?:{([^}]+)}|([^\s\n]+))'
|
|
33
|
+
matches = re.findall(input_pattern_extended, filecontent)
|
|
34
|
+
input_files_extended = [m[0] if m[0] else m[1] for m in matches]
|
|
35
|
+
|
|
36
|
+
if not split_results:
|
|
37
|
+
all_keys, temp_citations = _augment_func(filecontent, all_keys, temp_citations)
|
|
38
|
+
else:
|
|
39
|
+
for split_result, input_file_extended in zip(split_results, input_files_extended):
|
|
40
|
+
all_keys, temp_citations = _augment_func(split_result[0], all_keys, temp_citations)
|
|
41
|
+
|
|
42
|
+
if ".tex" not in input_file_extended:
|
|
43
|
+
input_file_extended += ".tex"
|
|
44
|
+
|
|
45
|
+
try:
|
|
46
|
+
with open(input_file_extended, 'r', encoding='utf-8') as file:
|
|
47
|
+
_lines = file.readlines()
|
|
48
|
+
|
|
49
|
+
_filtered_lines = [line for line in _lines if not line.lstrip().startswith('%')]
|
|
50
|
+
_filecontent = ''.join(_filtered_lines)
|
|
51
|
+
|
|
52
|
+
all_keys, temp_citations = _augment_func(_filecontent, all_keys, temp_citations)
|
|
53
|
+
except Exception as e:
|
|
54
|
+
print(f'{e}, skipped.')
|
|
55
|
+
|
|
56
|
+
all_keys, temp_citations = _augment_func(split_result[1], all_keys, temp_citations)
|
|
57
|
+
|
|
58
|
+
for k in all_keys:
|
|
59
|
+
allowed_keys.append(k)
|
|
60
|
+
|
|
61
|
+
entry_dict = {entry.get('ID'): entry for entry in bib_database.entries}
|
|
62
|
+
filtered_entries = [entry_dict[key] for key in allowed_keys if key in entry_dict]
|
|
63
|
+
|
|
64
|
+
writer = BibTexWriter()
|
|
65
|
+
writer.indent = ' '
|
|
66
|
+
writer.order_entries_by = None
|
|
67
|
+
|
|
68
|
+
new_bib_database = bibtexparser.bibdatabase.BibDatabase()
|
|
69
|
+
new_bib_database.entries = filtered_entries
|
|
70
|
+
|
|
71
|
+
with open(output_bib, 'w', encoding='utf-8') as bibfile:
|
|
72
|
+
bibfile.write(writer.write(new_bib_database))
|
|
73
|
+
|
|
74
|
+
print(f'successfully created {output_bib}')
|
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: bib_optimizer
|
|
3
|
+
Version: 0.5.1
|
|
4
|
+
Summary: Clean and optimize bib file.
|
|
5
|
+
Author-email: Ka Wa Yip <yipkawa@gmail.com>
|
|
6
|
+
License: MIT License
|
|
7
|
+
|
|
8
|
+
Copyright (c) 2025 Ka Wa Yip
|
|
9
|
+
|
|
10
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
11
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
12
|
+
in the Software without restriction, including without limitation the rights
|
|
13
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
14
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
15
|
+
furnished to do so, subject to the following conditions:
|
|
16
|
+
|
|
17
|
+
The above copyright notice and this permission notice shall be included in all
|
|
18
|
+
copies or substantial portions of the Software.
|
|
19
|
+
|
|
20
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
21
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
22
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
23
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
24
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
25
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
26
|
+
SOFTWARE.
|
|
27
|
+
|
|
28
|
+
Project-URL: Homepage, https://github.com/kwyip/bib_optimizer
|
|
29
|
+
Project-URL: Issues, https://github.com/kwyip/bib_optimizer/issues
|
|
30
|
+
Keywords: latex,bib,bibliography
|
|
31
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
32
|
+
Classifier: Programming Language :: Python
|
|
33
|
+
Classifier: Programming Language :: Python :: 3
|
|
34
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
35
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
36
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
37
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
38
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
39
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
40
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
41
|
+
Requires-Python: >=3.8
|
|
42
|
+
Description-Content-Type: text/markdown
|
|
43
|
+
License-File: LICENSE
|
|
44
|
+
Requires-Dist: bibtexparser<2,>=1.4.3
|
|
45
|
+
Provides-Extra: build
|
|
46
|
+
Requires-Dist: build; extra == "build"
|
|
47
|
+
Requires-Dist: twine; extra == "build"
|
|
48
|
+
Provides-Extra: dev
|
|
49
|
+
Requires-Dist: black; extra == "dev"
|
|
50
|
+
Requires-Dist: bumpver; extra == "dev"
|
|
51
|
+
Requires-Dist: isort; extra == "dev"
|
|
52
|
+
Requires-Dist: mypy; extra == "dev"
|
|
53
|
+
Requires-Dist: pytest; extra == "dev"
|
|
54
|
+
Dynamic: license-file
|
|
55
|
+
|
|
56
|
+
<figure>
|
|
57
|
+
<img src="https://github.com/kwyip/bib_optimizer/blob/main/logo.png?raw=True" alt="logo" height="143" />
|
|
58
|
+
<!-- <figcaption>An elephant at sunset</figcaption> -->
|
|
59
|
+
</figure>
|
|
60
|
+
|
|
61
|
+
[](https://github.com/kwyip/bib_optimizer/blob/main/LICENSE)
|
|
62
|
+
[](https://pypi.org/project/bib-optimizer/)
|
|
63
|
+
[](https://pypi.org/project/bib-optimizer)
|
|
64
|
+
[](https://pypi.org/project/bib-optimizer/#files)
|
|
65
|
+
[](https://pepy.tech/project/bib_optimizer)
|
|
66
|
+
|
|
67
|
+
[bib-optimizer](https://bibopt.github.io/)
|
|
68
|
+
==========================================
|
|
69
|
+
|
|
70
|
+
Oh, sure, because who doesn't love manually cleaning up messy `.bib` files? `bib_optimizer.py` heroically steps in to remove those lazy, _unused_ citations and _reorder_ the survivors exactly as they appear in the `.tex` file—because, clearly, chaos is the default setting for bibliographies.
|
|
71
|
+
|
|
72
|
+
In layman's terms, it automates bibliography management by:
|
|
73
|
+
|
|
74
|
+
1. removing unused citations,
|
|
75
|
+
2. reordering the remaining ones to match their order of appearance in the `.tex` file.
|
|
76
|
+
|
|
77
|
+
**Input Files:**
|
|
78
|
+
|
|
79
|
+
* `main.tex` – The LaTeX source file.
|
|
80
|
+
* `ref.bib` – The original bibliography file.
|
|
81
|
+
|
|
82
|
+
These input files will **remain unchanged**.
|
|
83
|
+
|
|
84
|
+
**Output File:**
|
|
85
|
+
|
|
86
|
+
* `ref_opt.bib` – A placeholder filename for the newly generated, cleaned, and ordered bibliography file.
|
|
87
|
+
|
|
88
|
+
* * *
|
|
89
|
+
|
|
90
|
+
Installation
|
|
91
|
+
------------
|
|
92
|
+
|
|
93
|
+
### Install from PyPI with pip
|
|
94
|
+
|
|
95
|
+
Create and activate a virtual environment, then install the latest release from PyPI:
|
|
96
|
+
|
|
97
|
+
```bash
|
|
98
|
+
python -m venv .venv
|
|
99
|
+
|
|
100
|
+
# Linux/macOS
|
|
101
|
+
source .venv/bin/activate
|
|
102
|
+
|
|
103
|
+
# Windows
|
|
104
|
+
.venv\Scripts\activate
|
|
105
|
+
|
|
106
|
+
python -m pip install --upgrade bib_optimizer
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
Alternatively, install the command in an isolated environment with [uv](https://docs.astral.sh/uv/):
|
|
110
|
+
|
|
111
|
+
```bash
|
|
112
|
+
uv tool install bib_optimizer
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
After either installation method, the `bibopt` command is available in your terminal.
|
|
116
|
+
|
|
117
|
+
### Install from source for development
|
|
118
|
+
|
|
119
|
+
This repository uses uv for project and dependency management.
|
|
120
|
+
|
|
121
|
+
1. **Clone the repository**
|
|
122
|
+
|
|
123
|
+
```bash
|
|
124
|
+
git clone https://github.com/kwyip/bib_optimizer.git
|
|
125
|
+
cd bib_optimizer
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
2. **Install environment**
|
|
129
|
+
|
|
130
|
+
```bash
|
|
131
|
+
# This creates the virtual environment and installs all dependencies
|
|
132
|
+
uv sync
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
3. **Activate environment**
|
|
136
|
+
|
|
137
|
+
```bash
|
|
138
|
+
# Linux/MacOS
|
|
139
|
+
source .venv/bin/activate
|
|
140
|
+
|
|
141
|
+
# Windows
|
|
142
|
+
.venv\Scripts\activate
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
_🐍 This requires Python 3.8 or newer versions_
|
|
146
|
+
|
|
147
|
+
* * *
|
|
148
|
+
|
|
149
|
+
### Steps to Clean Your Bibliography
|
|
150
|
+
|
|
151
|
+
1. **Prepare the input files (e.g., by downloading them from Overleaf)**.
|
|
152
|
+
2. **Run the command to generate a new `.bib` file (for example, you may name it `ref_opt.bib`)**:
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
`bibopt main.tex ref.bib ref_opt.bib`
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
3. **Use the Cleaned Bibliography**
|
|
160
|
+
Replace `ref.bib` with `ref_opt.bib` in your LaTeX project.
|
|
161
|
+
|
|
162
|
+
* * *
|
|
163
|
+
|
|
164
|
+
### Test
|
|
165
|
+
|
|
166
|
+
You may test the installation using the sample input files (`sample_main.tex` and `sample_ref.bib`) located in the test folder.
|
|
167
|
+
|
|
168
|
+
<img src="https://github.com/kwyip/bib_optimizer/blob/main/sample_main_shot.png?raw=True" alt="sample_main_shot" width="34.83%"/> <img src="https://github.com/kwyip/bib_optimizer/blob/main/sample_ref_shot.png?raw=True" alt="sample_ref_shot" width="43%" />
|
|
169
|
+
|
|
170
|
+
`sample_main.tex` _and_ `sample_ref.bib`
|
|
171
|
+
|
|
172
|
+
<img src="https://github.com/kwyip/bib_optimizer/blob/main/sample_ref_opt_shot.png?raw=True" alt="sample_ref_opt_shot" width="43%" />
|
|
173
|
+
|
|
174
|
+
_A sample_ `ref_opt.bib` _created after running_ `bibopt sample_main.tex sample_ref.bib ref_opt.bib`
|
|
175
|
+
|
|
176
|
+
* * *
|
|
177
|
+
|
|
178
|
+
## Code-free use with an AI agent
|
|
179
|
+
|
|
180
|
+
[**Download `SKILL.md`**](./SKILL.md), then upload these files to your AI agent:
|
|
181
|
+
|
|
182
|
+
- `SKILL.md`,
|
|
183
|
+
- the root `.tex` file,
|
|
184
|
+
- the source `.bib` file, and if any:
|
|
185
|
+
- every `.tex` file referenced through `\input` or `\include`.
|
|
186
|
+
|
|
187
|
+
> [!TIP]
|
|
188
|
+
> Use this prompt:
|
|
189
|
+
>
|
|
190
|
+
> ```text
|
|
191
|
+
> Use the attached `SKILL.md` to optimize the attached LaTeX and BibTeX files.
|
|
192
|
+
> Return only the optimized `.bib` file.
|
|
193
|
+
> ```
|
|
194
|
+
|
|
195
|
+
|
|
196
|
+
https://github.com/user-attachments/assets/2b4e3224-2aee-44c1-974c-812dead72e2f
|
|
197
|
+
|
|
198
|
+
|
|
199
|
+
* * *
|
|
200
|
+
|
|
201
|
+
#### New feature (version 0.4.0)
|
|
202
|
+
|
|
203
|
+
If the `main.tex` calls inputs from other `.tex` (e.g., with `\input{...}`), the newly generated `ref_opt.bib` will preserve the order of appearances in the `main.tex` with each inputted `.tex` as well. \
|
|
204
|
+
(The dependent `.tex` files need to be placed in the same directory as `main.tex`.)
|
|
205
|
+
|
|
206
|
+
---
|
|
207
|
+
#### New feature (version 0.4.1)
|
|
208
|
+
|
|
209
|
+
On top of version 0.4, skip any `\input` `.tex` file if not found.
|
|
210
|
+
|
|
211
|
+
---
|
|
212
|
+
#### New feature/Fix (version 0.4.2)
|
|
213
|
+
|
|
214
|
+
Added support for the `\include{...}` command in addition to `\input{...}`, fixing missing citations when a LaTeX project uses `\include` to split its content across files.
|
|
215
|
+
|
|
216
|
+
---
|
|
217
|
+
#### New feature/Fix (version 0.4.3)
|
|
218
|
+
|
|
219
|
+
Added Python 3.14 support and constrained `bibtexparser` to the compatible 1.x release series, fixing `ModuleNotFoundError: No module named 'bibtexparser.bwriter'` during fresh installations.
|
|
220
|
+
|
|
221
|
+
---
|
|
222
|
+
#### New feature/Fix (version 0.5.0)
|
|
223
|
+
|
|
224
|
+
Add code-free SKILL.md
|
|
225
|
+
|
|
226
|
+
♥ Lastly executed on Python `3.14` on 2026-09-29.
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
LICENSE
|
|
2
|
+
README.md
|
|
3
|
+
pyproject.toml
|
|
4
|
+
src/bib_optimizer/__init__.py
|
|
5
|
+
src/bib_optimizer/__main__.py
|
|
6
|
+
src/bib_optimizer/helpers.py
|
|
7
|
+
src/bib_optimizer.egg-info/PKG-INFO
|
|
8
|
+
src/bib_optimizer.egg-info/SOURCES.txt
|
|
9
|
+
src/bib_optimizer.egg-info/dependency_links.txt
|
|
10
|
+
src/bib_optimizer.egg-info/entry_points.txt
|
|
11
|
+
src/bib_optimizer.egg-info/requires.txt
|
|
12
|
+
src/bib_optimizer.egg-info/top_level.txt
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
bib_optimizer
|