-
Notifications
You must be signed in to change notification settings - Fork 0
/
bibx
executable file
·146 lines (132 loc) · 4.54 KB
/
bibx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
#!/usr/bin/env python3
import argparse
import bibtexparser
import subprocess
import shlex
import os
from bibtexparser.bparser import BibTexParser, BibDatabase
from bibtexparser.bwriter import BibTexWriter
VERSION = "v1.1"
def get_parser():
parser = argparse.ArgumentParser(
description="""Extract bibliography entries from LaTeX sources
using a reference BibTeX file""",
epilog="""For reporting bugs, giving suggestions and contributing
to this project, visit https://github.com/CodePurble/bibextract""",
)
parser.add_argument(
"-v", "--version", help="Show version information and exit", action="store_true"
)
parser.add_argument(
"-o",
"--output",
default="ext.bib",
help="""File to which the extracted entries are output
to. Default is './ext.bib'""",
)
parser.add_argument(
"-e",
"--entries",
help="""Text file containing entries to extract from
the BibTeX file, each line in the file must have ONE
BibTeX label""",
)
parser.add_argument(
"-q",
"--quiet",
default=False,
help="Suppress output to stdout",
action="store_true",
)
parser.add_argument(
"-f",
"--files",
help="""LaTeX files to scan for citations whose BibTeX
entries need to be extracted""",
action="extend",
nargs="+",
)
parser.add_argument(
"-i",
"--indent",
help="""Indentation to be used in the generated BibTeX
file. Default is four spaces""",
default=" ",
)
parser.add_argument(
"-d",
"--dryrun",
help="""Perform a dry-run, i.e. do not output a file,
just print info messages. Ignores the -o option,
affected by -q""",
action="store_true",
)
parser.add_argument(
"-b",
"--bib",
help="BibTeX file(s) to look for entries in",
action="extend",
nargs="+",
)
return parser
def main():
parser = get_parser()
args = parser.parse_args()
if args.version:
parser.exit(0, f"{VERSION}\n")
else:
if (args.bib is None) or (args.files is None):
parser.print_usage()
parser.exit(
2, "Error: the following arguments are required: -b/--bib, -f/--files\n"
)
else:
# Scan LaTeX files for citations and generate set containing BibTeX entry
# labels
e_set = set()
for file in args.files:
output = subprocess.run(
[
os.path.dirname(os.path.realpath(__file__)) + "/ext.sh",
shlex.quote(file),
],
capture_output=True,
)
if output.returncode == 0:
e_set = e_set.union(
set(output.stdout.decode().rstrip().split("\n"))
)
# Merge custom BibTeX entry labels into main set if any
if args.entries is not None:
with open(args.entries, "r") as en:
while entry := en.readline():
e_set = e_set.union(entry)
e_dict = {}
for file in args.bib:
with open(file) as bibtex_file:
parser = BibTexParser()
parser.ignore_nonstandard_types = False
bib_database = bibtexparser.load(bibtex_file, parser)
curr_dict = bib_database.entries_dict
e_dict.update(curr_dict)
out_db = BibDatabase()
found = 0
for entry in e_set:
if entry in e_dict.keys():
if not args.quiet:
print(f"Found: {entry}")
found += 1
out_db.entries.append(e_dict[entry])
else:
if not args.quiet:
print(f"Not found: {entry}")
writer = BibTexWriter()
writer.indent = args.indent
writer.add_trailing_comma = True
if not args.dryrun:
with open(args.output, "w") as outfile:
bibtexparser.dump(out_db, outfile, writer)
if not args.quiet:
print(f"\nFound {found}/{len(e_set)} entries")
if __name__ == "__main__":
main()