pyeasyphd 0.0.2__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 pyeasyphd might be problematic. Click here for more details.
- pyeasyphd/.python-version +1 -0
- pyeasyphd/Main.sublime-menu +43 -0
- pyeasyphd/__init__.py +0 -0
- pyeasyphd/bib/__init__.py +1 -0
- pyeasyphd/bib/bibtexbase/__init__.py +7 -0
- pyeasyphd/bib/bibtexbase/standardize/_base.py +36 -0
- pyeasyphd/bib/bibtexbase/standardize/default_data.py +97 -0
- pyeasyphd/bib/bibtexbase/standardize/do_on_bib.py +54 -0
- pyeasyphd/bib/bibtexbase/standardize/do_on_comment_block.py +38 -0
- pyeasyphd/bib/bibtexbase/standardize/do_on_entry_block.py +310 -0
- pyeasyphd/bib/bibtexbase/standardize/do_on_preamble_block.py +35 -0
- pyeasyphd/bib/bibtexbase/standardize/do_on_string_block.py +34 -0
- pyeasyphd/bib/bibtexbase/standardize_bib.py +75 -0
- pyeasyphd/bib/bibtexparser/__init__.py +47 -0
- pyeasyphd/bib/bibtexparser/bibtex_format.py +87 -0
- pyeasyphd/bib/bibtexparser/exceptions.py +64 -0
- pyeasyphd/bib/bibtexparser/library.py +207 -0
- pyeasyphd/bib/bibtexparser/middlewares/block/add.py +94 -0
- pyeasyphd/bib/bibtexparser/middlewares/block/authors.py +22 -0
- pyeasyphd/bib/bibtexparser/middlewares/block/doi_url.py +62 -0
- pyeasyphd/bib/bibtexparser/middlewares/block/entry_field_keys_normalize.py +47 -0
- pyeasyphd/bib/bibtexparser/middlewares/block/entry_field_keys_replace.py +31 -0
- pyeasyphd/bib/bibtexparser/middlewares/block/entry_field_values_normalize.py +222 -0
- pyeasyphd/bib/bibtexparser/middlewares/block/entry_fields_delete.py +34 -0
- pyeasyphd/bib/bibtexparser/middlewares/block/entry_fields_keep.py +33 -0
- pyeasyphd/bib/bibtexparser/middlewares/block/entry_fields_sort.py +70 -0
- pyeasyphd/bib/bibtexparser/middlewares/block/entry_types.py +15 -0
- pyeasyphd/bib/bibtexparser/middlewares/block/journal_booktitle.py +113 -0
- pyeasyphd/bib/bibtexparser/middlewares/block/month_year.py +34 -0
- pyeasyphd/bib/bibtexparser/middlewares/block/number_volume.py +21 -0
- pyeasyphd/bib/bibtexparser/middlewares/block/pages.py +28 -0
- pyeasyphd/bib/bibtexparser/middlewares/block/title.py +20 -0
- pyeasyphd/bib/bibtexparser/middlewares/library/generating_entrykeys.py +98 -0
- pyeasyphd/bib/bibtexparser/middlewares/library/keeping_blocks.py +29 -0
- pyeasyphd/bib/bibtexparser/middlewares/library/sorting_blocks.py +124 -0
- pyeasyphd/bib/bibtexparser/middlewares/middleware.py +222 -0
- pyeasyphd/bib/bibtexparser/middlewares/parsestack.py +13 -0
- pyeasyphd/bib/bibtexparser/middlewares/utils.py +226 -0
- pyeasyphd/bib/bibtexparser/middlewares_library_to_library.py +414 -0
- pyeasyphd/bib/bibtexparser/middlewares_library_to_str.py +42 -0
- pyeasyphd/bib/bibtexparser/middlewares_str_to_library.py +35 -0
- pyeasyphd/bib/bibtexparser/middlewares_str_to_str.py +29 -0
- pyeasyphd/bib/bibtexparser/model.py +481 -0
- pyeasyphd/bib/bibtexparser/splitter.py +151 -0
- pyeasyphd/bib/core/__init__.py +18 -0
- pyeasyphd/bib/core/convert_library_to_library.py +31 -0
- pyeasyphd/bib/core/convert_library_to_str.py +199 -0
- pyeasyphd/bib/core/convert_str_to_library.py +34 -0
- pyeasyphd/bib/core/convert_str_to_str.py +27 -0
- pyeasyphd/main/__init__.py +17 -0
- pyeasyphd/main/basic_input.py +149 -0
- pyeasyphd/main/pandoc_md_to.py +361 -0
- pyeasyphd/main/python_run_bib.py +73 -0
- pyeasyphd/main/python_run_md.py +235 -0
- pyeasyphd/main/python_run_tex.py +149 -0
- pyeasyphd/main/python_writers.py +212 -0
- pyeasyphd/pyeasyphd.py +72 -0
- pyeasyphd/pyeasyphd.sublime-settings +235 -0
- pyeasyphd/pyeasyphd.sublime-syntax +5 -0
- pyeasyphd/tools/__init__.py +30 -0
- pyeasyphd/tools/compare/compare_bibs.py +234 -0
- pyeasyphd/tools/experiments_base.py +203 -0
- pyeasyphd/tools/format_save_bibs.py +178 -0
- pyeasyphd/tools/generate/generate_from_bibs.py +447 -0
- pyeasyphd/tools/generate/generate_links.py +356 -0
- pyeasyphd/tools/py_run_bib_md_tex.py +378 -0
- pyeasyphd/tools/replace/replace.py +81 -0
- pyeasyphd/tools/search/data.py +318 -0
- pyeasyphd/tools/search/search_base.py +118 -0
- pyeasyphd/tools/search/search_core.py +326 -0
- pyeasyphd/tools/search/search_keywords.py +227 -0
- pyeasyphd/tools/search/search_writers.py +288 -0
- pyeasyphd/tools/search/utils.py +152 -0
- pyeasyphd/tools/spider/process_spider_bib.py +247 -0
- pyeasyphd/tools/spider/process_spider_url.py +74 -0
- pyeasyphd/tools/spider/process_spider_url_bib.py +62 -0
- pyeasyphd/utils/utils.py +62 -0
- pyeasyphd-0.0.2.dist-info/METADATA +27 -0
- pyeasyphd-0.0.2.dist-info/RECORD +80 -0
- pyeasyphd-0.0.2.dist-info/WHEEL +4 -0
|
@@ -0,0 +1,361 @@
|
|
|
1
|
+
import copy
|
|
2
|
+
import os
|
|
3
|
+
import re
|
|
4
|
+
import time
|
|
5
|
+
from typing import Dict, List, Optional, Tuple
|
|
6
|
+
|
|
7
|
+
from pyadvtools import (
|
|
8
|
+
combine_content_in_list,
|
|
9
|
+
delete_empty_lines_last_occur_add_new_line,
|
|
10
|
+
insert_list_in_list,
|
|
11
|
+
read_list,
|
|
12
|
+
substitute_in_list,
|
|
13
|
+
write_list,
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
from ..utils.utils import operate_on_generate_html
|
|
17
|
+
from .basic_input import BasicInput
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class PandocMdTo(BasicInput):
|
|
21
|
+
"""Pandoc md to md, tex, html, pdf and so on.
|
|
22
|
+
|
|
23
|
+
Args:
|
|
24
|
+
options (dict): Options.
|
|
25
|
+
|
|
26
|
+
Attributes:
|
|
27
|
+
markdown_name (str = "multi-markdown"): Markdown name.
|
|
28
|
+
markdown_citation (str = "markdown_mmd"): Markdown citation.
|
|
29
|
+
columns_in_md (int = 120): Columns in md.
|
|
30
|
+
google_connected_paper_scite (bool = True): Google connected paper scite.
|
|
31
|
+
display_one_line_reference_note (bool = False): Display one line reference note.
|
|
32
|
+
cite_flag_in_tex (str = "cite"): Cite flag in tex.
|
|
33
|
+
"""
|
|
34
|
+
|
|
35
|
+
def __init__(self, options: dict) -> None:
|
|
36
|
+
super().__init__(options)
|
|
37
|
+
|
|
38
|
+
self.markdown_name: str = "multi-markdown"
|
|
39
|
+
self.markdown_citation: str = "markdown_mmd"
|
|
40
|
+
if self.markdown_name == "pandoc-markdown":
|
|
41
|
+
self.markdown_citation = "markdown-citations"
|
|
42
|
+
|
|
43
|
+
self.columns_in_md: int = options.get("columns_in_md", 120)
|
|
44
|
+
self.google_connected_paper_scite: bool = options.get("google_connected_paper_scite", True)
|
|
45
|
+
self.display_one_line_reference_note: bool = options.get("display_one_line_reference_note", False)
|
|
46
|
+
# tex
|
|
47
|
+
self.cite_flag_in_tex: str = options.get("cite_flag_in_tex", "cite")
|
|
48
|
+
|
|
49
|
+
# for pandoc markdown files to markdown files
|
|
50
|
+
def pandoc_md_to_md(
|
|
51
|
+
self,
|
|
52
|
+
path_bib: str,
|
|
53
|
+
path_md_one: str,
|
|
54
|
+
path_md_two: str,
|
|
55
|
+
name_md_one: Optional[str],
|
|
56
|
+
name_md_two: Optional[str],
|
|
57
|
+
) -> List[str]:
|
|
58
|
+
full_one = path_md_one if name_md_one is None else os.path.join(path_md_one, name_md_one)
|
|
59
|
+
full_two = path_md_two if name_md_two is None else os.path.join(path_md_two, name_md_two)
|
|
60
|
+
return self._pandoc_md_to_md(full_one, full_two, path_bib)
|
|
61
|
+
|
|
62
|
+
def _pandoc_md_to_md(self, full_md_one: str, full_md_two: str, path_bib: str) -> List[str]:
|
|
63
|
+
"""Pandoc."""
|
|
64
|
+
if not os.path.exists(path_two := os.path.dirname(full_md_two)):
|
|
65
|
+
os.makedirs(path_two)
|
|
66
|
+
|
|
67
|
+
if os.path.exists(self.full_csl_style_pandoc):
|
|
68
|
+
cmd = (
|
|
69
|
+
f"pandoc {full_md_one} -t {self.markdown_citation} "
|
|
70
|
+
f'-o {full_md_two} -M reference-section-title="References" '
|
|
71
|
+
f"-C --bibliography={path_bib} --csl={self.full_csl_style_pandoc} --columns {self.columns_in_md}"
|
|
72
|
+
)
|
|
73
|
+
else:
|
|
74
|
+
cmd = (
|
|
75
|
+
f"pandoc {full_md_one} -t {self.markdown_citation} "
|
|
76
|
+
f'-o {full_md_two} -M reference-section-title="References" '
|
|
77
|
+
f"-C --bibliography={path_bib} --columns {self.columns_in_md}"
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
try:
|
|
81
|
+
os.system(cmd)
|
|
82
|
+
except Exception as e:
|
|
83
|
+
print("pandoc md to md:", e)
|
|
84
|
+
|
|
85
|
+
if not os.path.exists(full_md_two):
|
|
86
|
+
print(f"- pandoc false from md to md: {os.path.basename(full_md_two)}\n")
|
|
87
|
+
return []
|
|
88
|
+
|
|
89
|
+
return self._standardize_markdown_content(full_md_two)
|
|
90
|
+
|
|
91
|
+
@staticmethod
|
|
92
|
+
def _standardize_markdown_content(full_md: str) -> List[str]:
|
|
93
|
+
regex = re.compile(r"(\s*>*\s*[-+*]+)\s\s\s(.*)")
|
|
94
|
+
for i in range(len(data_list := read_list(full_md, "r"))):
|
|
95
|
+
if mch := regex.match(data_list[i]):
|
|
96
|
+
data_list[i] = data_list[i].replace(mch.group(), mch.group(1) + " " + mch.group(2))
|
|
97
|
+
return data_list
|
|
98
|
+
|
|
99
|
+
# for pandoc markdown files to tex files
|
|
100
|
+
def pandoc_md_to_tex(
|
|
101
|
+
self,
|
|
102
|
+
template_name: str,
|
|
103
|
+
path_md: str,
|
|
104
|
+
path_tex: str,
|
|
105
|
+
name_md: Optional[str],
|
|
106
|
+
name_tex: Optional[str],
|
|
107
|
+
) -> List[str]:
|
|
108
|
+
full_one = path_md if name_md is None else os.path.join(path_md, name_md)
|
|
109
|
+
full_two = path_tex if name_tex is None else os.path.join(path_tex, name_tex)
|
|
110
|
+
return self._pandoc_md_to_tex(full_one, full_two, template_name)
|
|
111
|
+
|
|
112
|
+
def _pandoc_md_to_tex(self, full_md: str, full_tex: str, template_name: str) -> List[str]:
|
|
113
|
+
"""Pandoc."""
|
|
114
|
+
if not os.path.exists(path_tex := os.path.dirname(full_tex)):
|
|
115
|
+
os.makedirs(path_tex)
|
|
116
|
+
|
|
117
|
+
try:
|
|
118
|
+
if template_name.lower() == "beamer":
|
|
119
|
+
os.system(f"pandoc {full_md} -t beamer -o {full_tex} --from markdown ")
|
|
120
|
+
else:
|
|
121
|
+
os.system(f"pandoc {full_md} -o {full_tex} --from markdown ")
|
|
122
|
+
except Exception as e:
|
|
123
|
+
print("pandoc md to tex:", e)
|
|
124
|
+
|
|
125
|
+
if not os.path.exists(full_tex):
|
|
126
|
+
print(f"- pandoc false from md to tex: {os.path.basename(full_md)}\n")
|
|
127
|
+
return []
|
|
128
|
+
|
|
129
|
+
return self._substitute_in_tex_from_md(read_list(full_tex, "r", None))
|
|
130
|
+
|
|
131
|
+
def _substitute_in_tex_from_md(self, data_list: List[str]) -> List[str]:
|
|
132
|
+
old_str_list = [r"{\[}@", r"{\[}-@", r"{\[}", r"{\]}", r"\\_"]
|
|
133
|
+
new_str_list = [rf"\\{self.cite_flag_in_tex}" + "{", rf"\\{self.cite_flag_in_tex}" + "{", "{", "}", "_"]
|
|
134
|
+
old_str_list.extend([r"\\footnote<.->{", r";", r"@"])
|
|
135
|
+
new_str_list.extend([r"\\footnote{", ",", ""])
|
|
136
|
+
return substitute_in_list(old_str_list, new_str_list, data_list)
|
|
137
|
+
|
|
138
|
+
# for pandoc markdown files to html files
|
|
139
|
+
def pandoc_md_to_html(
|
|
140
|
+
self, path_md: str, path_html: str, name_md: Optional[str], name_html: Optional[str], operate: bool = False
|
|
141
|
+
) -> str:
|
|
142
|
+
full_one = path_md if name_md is None else os.path.join(path_md, name_md)
|
|
143
|
+
full_two = path_html if name_html is None else os.path.join(path_html, name_html)
|
|
144
|
+
return self._pandoc_md_to_html(full_one, full_two, operate)
|
|
145
|
+
|
|
146
|
+
@staticmethod
|
|
147
|
+
def _pandoc_md_to_html(full_md: str, full_html: str, operate: bool = False) -> str:
|
|
148
|
+
"""Pandoc."""
|
|
149
|
+
if not os.path.exists(path_html := os.path.dirname(full_html)):
|
|
150
|
+
os.makedirs(path_html)
|
|
151
|
+
|
|
152
|
+
cmd = f"pandoc {full_md} -o {full_html} --from markdown "
|
|
153
|
+
|
|
154
|
+
try:
|
|
155
|
+
os.system(cmd)
|
|
156
|
+
except Exception as e:
|
|
157
|
+
print("pandoc md to html:", e)
|
|
158
|
+
|
|
159
|
+
if not os.path.exists(full_html):
|
|
160
|
+
return f"- pandoc false from md to html: {os.path.basename(full_md)}\n"
|
|
161
|
+
|
|
162
|
+
if operate:
|
|
163
|
+
operate_on_generate_html(full_html)
|
|
164
|
+
return ""
|
|
165
|
+
|
|
166
|
+
# for pandoc markdown files to pdf files
|
|
167
|
+
def pandoc_md_to_pdf(
|
|
168
|
+
self,
|
|
169
|
+
path_md: str,
|
|
170
|
+
path_pdf: str,
|
|
171
|
+
name_md: Optional[str],
|
|
172
|
+
name_pdf: Optional[str],
|
|
173
|
+
) -> str:
|
|
174
|
+
full_one = path_md if name_md is None else os.path.join(path_md, name_md)
|
|
175
|
+
full_two = path_pdf if name_pdf is None else os.path.join(path_pdf, name_pdf)
|
|
176
|
+
return self._pandoc_md_to_pdf(full_one, full_two)
|
|
177
|
+
|
|
178
|
+
def _pandoc_md_to_pdf(self, full_md: str, full_pdf: str) -> str:
|
|
179
|
+
"""Pandoc."""
|
|
180
|
+
if not os.path.exists(path_pdf := os.path.dirname(full_pdf)):
|
|
181
|
+
os.makedirs(path_pdf)
|
|
182
|
+
|
|
183
|
+
if os.path.exists(self.full_tex_article_template_pandoc):
|
|
184
|
+
cmd = (
|
|
185
|
+
f"pandoc {full_md} -o {full_pdf} --from markdown "
|
|
186
|
+
f"--template {self.full_tex_article_template_pandoc} --listings --pdf-engine=xelatex"
|
|
187
|
+
)
|
|
188
|
+
else:
|
|
189
|
+
cmd = f"pandoc {full_md} -o {full_pdf} --from markdown --listings --pdf-engine=xelatex"
|
|
190
|
+
|
|
191
|
+
try:
|
|
192
|
+
os.system(cmd)
|
|
193
|
+
except Exception as e:
|
|
194
|
+
print("pandoc md to pdf:", e)
|
|
195
|
+
|
|
196
|
+
if not os.path.exists(full_pdf):
|
|
197
|
+
return f"- pandoc false from md to pdf: {os.path.basename(full_md)}\n"
|
|
198
|
+
return ""
|
|
199
|
+
|
|
200
|
+
# --------- --------- --------- --------- --------- --------- --------- --------- --------- #
|
|
201
|
+
# md
|
|
202
|
+
def generate_key_data_dict(
|
|
203
|
+
self,
|
|
204
|
+
pandoc_md_data_list: List[str],
|
|
205
|
+
key_url_http_bib_dict: Dict[str, List[List[str]]],
|
|
206
|
+
) -> Tuple[Dict[str, List[str]], Dict[str, List[str]], Dict[str, List[str]]]:
|
|
207
|
+
"""Generate."""
|
|
208
|
+
key_reference_dict = self._generate_citation_key_reference_dict_from_pandoc_md(pandoc_md_data_list)
|
|
209
|
+
(
|
|
210
|
+
key_basic_dict,
|
|
211
|
+
key_beauty_dict,
|
|
212
|
+
key_complex_dict,
|
|
213
|
+
) = self._generate_basic_beauty_complex_dict(key_url_http_bib_dict, key_reference_dict)
|
|
214
|
+
return key_basic_dict, key_beauty_dict, key_complex_dict
|
|
215
|
+
|
|
216
|
+
def _generate_citation_key_reference_dict_from_pandoc_md(
|
|
217
|
+
self, pandoc_md_data_list: List[str]
|
|
218
|
+
) -> Dict[str, List[str]]:
|
|
219
|
+
"""Generate."""
|
|
220
|
+
pandoc_md_data_list = self.__append_pandoc_md_reference_part(pandoc_md_data_list)
|
|
221
|
+
|
|
222
|
+
line_index, len_data = 0, len(pandoc_md_data_list)
|
|
223
|
+
if self.markdown_name == "pandoc-markdown":
|
|
224
|
+
a_flag, b_flag = r"^:::\s{#ref-(.*)\s\.csl-entry}", r"^:::"
|
|
225
|
+
else: # multi-markdown
|
|
226
|
+
a_flag, b_flag = r'^<div\sid="ref-(.*?)"', r"^</div>"
|
|
227
|
+
|
|
228
|
+
regex_one, regex_two = re.compile(a_flag), re.compile(b_flag)
|
|
229
|
+
key_reference_dict = {}
|
|
230
|
+
while line_index < len_data:
|
|
231
|
+
match_one = regex_one.search(pandoc_md_data_list[line_index])
|
|
232
|
+
line_index += 1
|
|
233
|
+
if not match_one:
|
|
234
|
+
continue
|
|
235
|
+
citation_key = match_one.group(1).strip()
|
|
236
|
+
|
|
237
|
+
content = []
|
|
238
|
+
while line_index < len_data:
|
|
239
|
+
line = pandoc_md_data_list[line_index]
|
|
240
|
+
if regex_two.search(line):
|
|
241
|
+
break
|
|
242
|
+
|
|
243
|
+
line_index += 1
|
|
244
|
+
if mch := re.search(r"([<\[]https?://)", line):
|
|
245
|
+
content.append(line.split(mch.group(1))[0][:-1])
|
|
246
|
+
break
|
|
247
|
+
else:
|
|
248
|
+
if line.strip():
|
|
249
|
+
content.append(line)
|
|
250
|
+
|
|
251
|
+
key_reference_dict.update({citation_key: delete_empty_lines_last_occur_add_new_line(content)})
|
|
252
|
+
return key_reference_dict
|
|
253
|
+
|
|
254
|
+
def __append_pandoc_md_reference_part(self, pandoc_md_data_list: List[str]) -> List[str]:
|
|
255
|
+
"""Append the line which starts with '::: {#'."""
|
|
256
|
+
line_index, len_data = 0, len(pandoc_md_data_list)
|
|
257
|
+
if self.markdown_name == "pandoc-markdown":
|
|
258
|
+
a_flag, b_flag = r":::\s{#", r"}"
|
|
259
|
+
else: # multi-markdown
|
|
260
|
+
a_flag, b_flag = r'<div\sid="ref', r">"
|
|
261
|
+
regex = re.compile(a_flag)
|
|
262
|
+
new_list = []
|
|
263
|
+
while line_index < len_data:
|
|
264
|
+
line = pandoc_md_data_list[line_index]
|
|
265
|
+
line_index += 1
|
|
266
|
+
if regex.search(line):
|
|
267
|
+
while line_index < len_data:
|
|
268
|
+
if b_flag != line.rstrip()[-1]:
|
|
269
|
+
line = line.rstrip() + " " + pandoc_md_data_list[line_index].lstrip()
|
|
270
|
+
line_index += 1
|
|
271
|
+
else:
|
|
272
|
+
new_list.append(line)
|
|
273
|
+
break
|
|
274
|
+
if line_index == len_data:
|
|
275
|
+
new_list.append(line)
|
|
276
|
+
else:
|
|
277
|
+
new_list.append(line)
|
|
278
|
+
return delete_empty_lines_last_occur_add_new_line(new_list)
|
|
279
|
+
|
|
280
|
+
def _generate_basic_beauty_complex_dict(
|
|
281
|
+
self,
|
|
282
|
+
key_url_http_bib_dict: Dict[str, List[List[str]]],
|
|
283
|
+
key_reference_dict: Dict[str, list],
|
|
284
|
+
) -> Tuple[Dict[str, List[str]], Dict[str, List[str]], Dict[str, List[str]]]:
|
|
285
|
+
"""Generate."""
|
|
286
|
+
header_list = ["<details>\n", "```\n"]
|
|
287
|
+
tail_list = ["```\n", "</details>\n"]
|
|
288
|
+
|
|
289
|
+
key_basic_dict: Dict[str, List[str]] = {}
|
|
290
|
+
key_beauty_dict: Dict[str, List[str]] = {}
|
|
291
|
+
key_complex_dict: Dict[str, List[str]] = {}
|
|
292
|
+
|
|
293
|
+
key_list_http = list(key_url_http_bib_dict.keys())
|
|
294
|
+
key_list_md = list(key_reference_dict.keys())
|
|
295
|
+
if set(key_list_http) != set(key_list_md):
|
|
296
|
+
print(f"`key_list_md`: set({key_list_md}) should be the same with `key_list_http`: set({key_list_http}).")
|
|
297
|
+
return key_basic_dict, key_beauty_dict, key_complex_dict
|
|
298
|
+
|
|
299
|
+
for k in key_list_http:
|
|
300
|
+
a: List[str] = copy.deepcopy(key_reference_dict[k])
|
|
301
|
+
b: List[str] = copy.deepcopy(key_reference_dict[k])
|
|
302
|
+
aa: List[str] = key_url_http_bib_dict[k][0]
|
|
303
|
+
bb: List[str] = key_url_http_bib_dict[k][1]
|
|
304
|
+
|
|
305
|
+
if (not self.google_connected_paper_scite) and aa:
|
|
306
|
+
bb = [f"([www]({aa[0].strip()}))\n"]
|
|
307
|
+
|
|
308
|
+
a.extend(aa)
|
|
309
|
+
b.extend(bb)
|
|
310
|
+
|
|
311
|
+
if self.display_one_line_reference_note:
|
|
312
|
+
a = ["".join(a).replace("\n", " ").strip() + "\n"]
|
|
313
|
+
b = ["".join(b).replace("\n", " ").strip() + "\n"]
|
|
314
|
+
|
|
315
|
+
c = combine_content_in_list([b, header_list, key_url_http_bib_dict[k][2], tail_list])
|
|
316
|
+
key_basic_dict.update({k: a})
|
|
317
|
+
key_beauty_dict.update({k: b})
|
|
318
|
+
key_complex_dict.update({k: c})
|
|
319
|
+
return key_basic_dict, key_beauty_dict, key_complex_dict
|
|
320
|
+
|
|
321
|
+
# --------- --------- --------- --------- --------- --------- --------- --------- --------- #
|
|
322
|
+
# tex
|
|
323
|
+
def generate_tex_content(self, file_prefix: str, path_subsection: str, path_bib: str, path_combine: str) -> None:
|
|
324
|
+
# for latex
|
|
325
|
+
# add template for tex file
|
|
326
|
+
add_bib_name = "{}/{}-abbr.bib".format(os.path.basename(path_bib), file_prefix)
|
|
327
|
+
add_tex_name = "{}/{}.tex".format(os.path.basename(path_subsection), file_prefix)
|
|
328
|
+
insert_part_one, insert_part_two = self._generate_tex_content(file_prefix, add_tex_name, add_bib_name)
|
|
329
|
+
|
|
330
|
+
# write tex
|
|
331
|
+
data_temp = insert_list_in_list(
|
|
332
|
+
self.article_template_tex, insert_part_one, r"\\begin{document}", "before"
|
|
333
|
+
)
|
|
334
|
+
data_temp = insert_list_in_list(data_temp, insert_part_two, r"\\begin{document}", "after")
|
|
335
|
+
write_list(data_temp, f"{file_prefix}.tex", "w", os.path.join(path_combine, "tex"))
|
|
336
|
+
return None
|
|
337
|
+
|
|
338
|
+
@staticmethod
|
|
339
|
+
def _generate_tex_content(file_prefix: str, add_tex_name: str, add_bib_name: str) -> Tuple[List[str], List[str]]:
|
|
340
|
+
if len(file_prefix) == 0:
|
|
341
|
+
file_prefix = "file_prefix"
|
|
342
|
+
|
|
343
|
+
part_one = [
|
|
344
|
+
"\\date{" + "{}".format(time.strftime("%B %d, %Y")) + "}\n\n",
|
|
345
|
+
"\\ifx \\fullpath \\undefined\n",
|
|
346
|
+
" \\addbibresource{" + "../{}".format(add_bib_name) + "}\n",
|
|
347
|
+
"\\else\n",
|
|
348
|
+
" \\addbibresource{" + "\\fullpath/{}".format(add_bib_name) + "}\n",
|
|
349
|
+
"\\fi\n\n",
|
|
350
|
+
]
|
|
351
|
+
part_two = [
|
|
352
|
+
"\n",
|
|
353
|
+
"% \\maketitle\n",
|
|
354
|
+
"\\tableofcontents\n\n",
|
|
355
|
+
"\\ifx \\fullpath \\undefined\n",
|
|
356
|
+
" \\input{" + "../{}".format(add_tex_name) + "}\n",
|
|
357
|
+
"\\else\n",
|
|
358
|
+
" \\input{" + "\\fullpath/{}".format(add_tex_name) + "}\n",
|
|
359
|
+
"\\fi\n",
|
|
360
|
+
]
|
|
361
|
+
return part_one, part_two
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
from typing import Any, Dict, List, Tuple, Union
|
|
2
|
+
|
|
3
|
+
from pyadvtools import (
|
|
4
|
+
transform_to_data_list,
|
|
5
|
+
)
|
|
6
|
+
|
|
7
|
+
from ..bib.bibtexparser import Entry, Library
|
|
8
|
+
from ..bib.core import ConvertLibrayToLibrary, ConvertStrToLibrary
|
|
9
|
+
from .basic_input import BasicInput
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class PythonRunBib(BasicInput):
|
|
13
|
+
"""Python bib.
|
|
14
|
+
|
|
15
|
+
Args:
|
|
16
|
+
options (Dict[str, Any]): Options.
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
def __init__(self, options: Dict[str, Any]) -> None:
|
|
20
|
+
super().__init__(options)
|
|
21
|
+
|
|
22
|
+
def parse_to_single_standard_library(
|
|
23
|
+
self,
|
|
24
|
+
original_data: Union[List[str], str, Library],
|
|
25
|
+
given_cite_keys: List[str] = [],
|
|
26
|
+
**kwargs,
|
|
27
|
+
) -> Library:
|
|
28
|
+
# update
|
|
29
|
+
self.options["keep_entries_by_cite_keys"] = given_cite_keys
|
|
30
|
+
|
|
31
|
+
if not isinstance(original_data, Library):
|
|
32
|
+
original_data = transform_to_data_list(original_data, extension=".bib", **kwargs)
|
|
33
|
+
original_data = ConvertStrToLibrary(self.options).generate_library(original_data)
|
|
34
|
+
|
|
35
|
+
library = ConvertLibrayToLibrary(self.options).generate_single_library(original_data)
|
|
36
|
+
return library
|
|
37
|
+
|
|
38
|
+
def parse_to_multi_standard_library(
|
|
39
|
+
self,
|
|
40
|
+
original_data: Union[List[str], str, Library],
|
|
41
|
+
given_cite_keys: List[str] = [],
|
|
42
|
+
**kwargs,
|
|
43
|
+
) -> Tuple[Library, Library, Library]:
|
|
44
|
+
# update
|
|
45
|
+
self.options["keep_entries_by_cite_keys"] = given_cite_keys
|
|
46
|
+
|
|
47
|
+
if not isinstance(original_data, Library):
|
|
48
|
+
original_data = transform_to_data_list(original_data, extension=".bib", **kwargs)
|
|
49
|
+
original_data = ConvertStrToLibrary(self.options).generate_library(original_data)
|
|
50
|
+
|
|
51
|
+
libraries = ConvertLibrayToLibrary(self.options).generate_multi_libraries(original_data)
|
|
52
|
+
abbr_library, zotero_library, save_library = libraries
|
|
53
|
+
return abbr_library, zotero_library, save_library
|
|
54
|
+
|
|
55
|
+
def parse_to_nested_entries_dict(
|
|
56
|
+
self,
|
|
57
|
+
original_data: Union[List[str], str, Library],
|
|
58
|
+
given_cite_keys: List[str] = [],
|
|
59
|
+
**kwargs,
|
|
60
|
+
) -> Dict[str, Dict[str, Dict[str, Dict[str, Dict[str, List[Entry]]]]]]:
|
|
61
|
+
library = self.parse_to_single_standard_library(original_data, given_cite_keys, **kwargs)
|
|
62
|
+
|
|
63
|
+
entry_type_year_volume_number_month_entry_dict = {}
|
|
64
|
+
for entry in library.entries:
|
|
65
|
+
entry_type = entry.entry_type
|
|
66
|
+
year = entry["year"] if "year" in entry else "year"
|
|
67
|
+
volume = entry["volume"] if "volume" in entry else "volume"
|
|
68
|
+
number = entry["number"] if "number" in entry else "number"
|
|
69
|
+
month = entry["month"] if "month" in entry else "month"
|
|
70
|
+
entry_type_year_volume_number_month_entry_dict.setdefault(entry_type, {}).setdefault(year, {}).setdefault(
|
|
71
|
+
volume, {}
|
|
72
|
+
).setdefault(number, {}).setdefault(month, []).append(entry)
|
|
73
|
+
return entry_type_year_volume_number_month_entry_dict
|
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
import copy
|
|
2
|
+
import os
|
|
3
|
+
import re
|
|
4
|
+
import shutil
|
|
5
|
+
import time
|
|
6
|
+
from typing import Any, Dict, List, Tuple
|
|
7
|
+
|
|
8
|
+
from pyadvtools import (
|
|
9
|
+
combine_content_in_list,
|
|
10
|
+
delete_empty_lines_last_occur_add_new_line,
|
|
11
|
+
read_list,
|
|
12
|
+
write_list,
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
from ..bib.core import ConvertStrToLibrary
|
|
16
|
+
from .basic_input import BasicInput
|
|
17
|
+
from .pandoc_md_to import PandocMdTo
|
|
18
|
+
from .python_writers import PythonWriters
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class PythonRunMd(BasicInput):
|
|
22
|
+
"""Python markdown.
|
|
23
|
+
|
|
24
|
+
Args:
|
|
25
|
+
options (Dict[str, Any]): Options.
|
|
26
|
+
|
|
27
|
+
Attributes:
|
|
28
|
+
delete_temp_generate_md (bool = True): Whether to delete temp generate md.
|
|
29
|
+
add_reference_in_md (bool = True): Whether to add reference in md.
|
|
30
|
+
add_bib_in_md (bool = False): Whether to add bib in md.
|
|
31
|
+
replace_cite_to_fullcite_in_md (bool = False): Whether to replace cite to fullcite in md.
|
|
32
|
+
replace_by_basic_beauty_complex_in_md (str = "beauty"): Replace by basic, beauty, or complex.
|
|
33
|
+
display_basic_beauty_complex_references_in_md (str = "beauty"): Display basic, beauty, or complex references.
|
|
34
|
+
"""
|
|
35
|
+
|
|
36
|
+
def __init__(self, options: Dict[str, Any]) -> None:
|
|
37
|
+
super().__init__(options)
|
|
38
|
+
|
|
39
|
+
# for md
|
|
40
|
+
self.final_output_main_md_name: str = options.get("final_output_main_md_name", "")
|
|
41
|
+
self.delete_temp_generate_md: bool = options.get("delete_temp_generate_md", True)
|
|
42
|
+
self.add_reference_in_md: bool = options.get("add_reference_in_md", True)
|
|
43
|
+
self.add_bib_in_md: bool = options.get("add_bib_in_md", False)
|
|
44
|
+
self.replace_cite_to_fullcite_in_md: bool = options.get("replace_cite_to_fullcite_in_md", False)
|
|
45
|
+
self.replace_by_basic_beauty_complex_in_md: str = options.get("replace_by_basic_beauty_complex_in_md", "beauty")
|
|
46
|
+
self.display_basic_beauty_complex_references_in_md: str = options.get(
|
|
47
|
+
"display_basic_beauty_complex_references_in_md", "beauty"
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
# for md
|
|
51
|
+
self._pandoc_md_to = PandocMdTo(self.options)
|
|
52
|
+
|
|
53
|
+
_options = {}
|
|
54
|
+
_options["is_standardize_bib"] = False
|
|
55
|
+
_options["is_display_implicit_comments"] = False
|
|
56
|
+
_options.update(options)
|
|
57
|
+
self._generate_library = ConvertStrToLibrary(_options)
|
|
58
|
+
|
|
59
|
+
# for markdown files
|
|
60
|
+
def special_operate_for_md(
|
|
61
|
+
self,
|
|
62
|
+
path_output: str,
|
|
63
|
+
data_list_md: List[str],
|
|
64
|
+
output_md_name: str,
|
|
65
|
+
full_bib_for_abbr: str,
|
|
66
|
+
full_bib_for_zotero: str,
|
|
67
|
+
template_name: str = "article",
|
|
68
|
+
generate_html: bool = False,
|
|
69
|
+
generate_tex: bool = True
|
|
70
|
+
) -> Tuple[List[str], List[str]]:
|
|
71
|
+
"""Markdown."""
|
|
72
|
+
path_temp = os.path.join(path_output, "{}".format(time.strftime("%Y_%m_%d_%H_%M_%S")))
|
|
73
|
+
if not os.path.exists(path_temp):
|
|
74
|
+
os.makedirs(path_temp)
|
|
75
|
+
|
|
76
|
+
# write original md content to temp file
|
|
77
|
+
full_temp_md = os.path.join(path_temp, output_md_name)
|
|
78
|
+
write_list(data_list_md, full_temp_md, "w", None, False)
|
|
79
|
+
|
|
80
|
+
# pandoc md to md to update md content
|
|
81
|
+
if read_list(full_bib_for_abbr, "r") and read_list(full_bib_for_zotero, "r"):
|
|
82
|
+
data_list_md = self._special_operate_for_md(
|
|
83
|
+
output_md_name, path_temp, full_bib_for_abbr, full_bib_for_zotero
|
|
84
|
+
)
|
|
85
|
+
elif os.path.exists(full_bib_for_abbr) and os.path.exists(full_bib_for_zotero):
|
|
86
|
+
print(f"The content of bib: {full_bib_for_abbr} or {full_bib_for_zotero} is empty.")
|
|
87
|
+
else:
|
|
88
|
+
pass
|
|
89
|
+
|
|
90
|
+
# main name
|
|
91
|
+
main_name = self.final_output_main_md_name
|
|
92
|
+
if len(main_name) == 0:
|
|
93
|
+
main_name = output_md_name.split(".md")[0] + "_" + self.replace_by_basic_beauty_complex_in_md
|
|
94
|
+
main_name = main_name + "_" + self.display_basic_beauty_complex_references_in_md + ".md"
|
|
95
|
+
if main_name.lower() == output_md_name.lower():
|
|
96
|
+
main_name = main_name.split(".md")[0] + "_.md"
|
|
97
|
+
if main_name[-3:] != ".md":
|
|
98
|
+
main_name = main_name + ".md"
|
|
99
|
+
|
|
100
|
+
# write new generated md content to given file
|
|
101
|
+
write_list(data_list_md, main_name, "w", path_output, False)
|
|
102
|
+
|
|
103
|
+
# for generating html file from md file
|
|
104
|
+
if data_list_md and generate_html:
|
|
105
|
+
self._pandoc_md_to.pandoc_md_to_html(
|
|
106
|
+
path_output, path_output, main_name, f'{main_name.split(".md")[0]}.html', True
|
|
107
|
+
)
|
|
108
|
+
|
|
109
|
+
# pandoc md to latex
|
|
110
|
+
data_list_tex = []
|
|
111
|
+
if generate_tex:
|
|
112
|
+
n5 = "5_pandoc" + ".tex"
|
|
113
|
+
data_list_tex = self._pandoc_md_to.pandoc_md_to_tex(template_name, path_temp, path_temp, output_md_name, n5)
|
|
114
|
+
|
|
115
|
+
# delete temp path
|
|
116
|
+
if self.delete_temp_generate_md:
|
|
117
|
+
shutil.rmtree(path_temp)
|
|
118
|
+
return data_list_md, data_list_tex
|
|
119
|
+
|
|
120
|
+
def _special_operate_for_md(
|
|
121
|
+
self,
|
|
122
|
+
output_md_name: str,
|
|
123
|
+
path_temp: str,
|
|
124
|
+
full_bib_for_abbr: str,
|
|
125
|
+
full_bib_for_zotero: str,
|
|
126
|
+
) -> List[str]:
|
|
127
|
+
# pandoc markdown to markdown
|
|
128
|
+
n1 = "1_pandoc" + ".md"
|
|
129
|
+
data_list_md = self._pandoc_md_to.pandoc_md_to_md(full_bib_for_abbr, path_temp, path_temp, output_md_name, n1)
|
|
130
|
+
|
|
131
|
+
# use zotero bib to generate library
|
|
132
|
+
bib_for_zotero = read_list(full_bib_for_zotero, "r")
|
|
133
|
+
library = self._generate_library.generate_library(bib_for_zotero)
|
|
134
|
+
|
|
135
|
+
_options = {}
|
|
136
|
+
_options.update(self.options)
|
|
137
|
+
_options["add_index_to_enties"] = False
|
|
138
|
+
_python_writers = PythonWriters(_options)
|
|
139
|
+
key_url_http_bib_dict = _python_writers.output_key_url_http_bib_dict(library)
|
|
140
|
+
|
|
141
|
+
content_md = []
|
|
142
|
+
if data_list_md and key_url_http_bib_dict:
|
|
143
|
+
key_basic_dict, key_beauty_dict, key_complex_dict = self._pandoc_md_to.generate_key_data_dict(
|
|
144
|
+
data_list_md, key_url_http_bib_dict
|
|
145
|
+
)
|
|
146
|
+
|
|
147
|
+
key_in_md = list(key_url_http_bib_dict.keys())
|
|
148
|
+
|
|
149
|
+
# generate by replacing `- [@citation_key]` to `- [citation_key]`
|
|
150
|
+
content = read_list(output_md_name, "r", path_temp)
|
|
151
|
+
if self.replace_cite_to_fullcite_in_md:
|
|
152
|
+
regex = re.compile(r"(\s*[-\+\*]\s*)\[@({})\]".format("|".join(key_in_md)))
|
|
153
|
+
for i in range(len(content)):
|
|
154
|
+
if not (mch := regex.match(content[i])):
|
|
155
|
+
continue
|
|
156
|
+
|
|
157
|
+
content[i] = content[i].replace(mch.group(), mch.group(1) + "[" + mch.group(2) + "]")
|
|
158
|
+
n2 = "2_generate" + ".md"
|
|
159
|
+
write_list(content, n2, "w", path_temp)
|
|
160
|
+
|
|
161
|
+
# pandoc markdown to markdown
|
|
162
|
+
n3 = "3_pandoc" + ".md"
|
|
163
|
+
data_list_md = self._pandoc_md_to.pandoc_md_to_md(full_bib_for_abbr, path_temp, path_temp, n2, n3)
|
|
164
|
+
|
|
165
|
+
# generate by replacing `- [citation_key]` to `- reference`
|
|
166
|
+
if self.replace_cite_to_fullcite_in_md:
|
|
167
|
+
regex = re.compile(r"(\s*)([-\+\*])(\s*)[\\]*\[({})[\\]*\]".format("|".join(key_in_md)))
|
|
168
|
+
for i in range(len(data_list_md)):
|
|
169
|
+
if not (mch := regex.search(data_list_md[i])):
|
|
170
|
+
continue
|
|
171
|
+
|
|
172
|
+
space_one, b, space_two, cite_key = mch.groups()
|
|
173
|
+
if self.replace_by_basic_beauty_complex_in_md.lower() == "basic":
|
|
174
|
+
temp_list = copy.deepcopy(key_basic_dict[cite_key])
|
|
175
|
+
elif self.replace_by_basic_beauty_complex_in_md.lower() == "complex":
|
|
176
|
+
temp_list = copy.deepcopy(key_complex_dict[cite_key])
|
|
177
|
+
else:
|
|
178
|
+
temp_list = copy.deepcopy(key_beauty_dict[cite_key])
|
|
179
|
+
|
|
180
|
+
temp = "".join(self._special_format(temp_list, space_one, space_two))
|
|
181
|
+
data_list_md[i] = data_list_md[i].replace(mch.group(), space_one + b + space_two + temp.strip())
|
|
182
|
+
n4 = "4_generate" + ".md"
|
|
183
|
+
write_list(data_list_md, os.path.join(path_temp, n4), "w")
|
|
184
|
+
|
|
185
|
+
# obtain footnote part (in the last part of the contents)
|
|
186
|
+
main_part, last_part = [], []
|
|
187
|
+
main_part_flag, last_part_flag = True, True
|
|
188
|
+
for line_index in range(len(data_list_md)):
|
|
189
|
+
if main_part_flag and re.match(r"#+ References\s[\[{]", data_list_md[line_index]):
|
|
190
|
+
main_part_flag = False
|
|
191
|
+
main_part = delete_empty_lines_last_occur_add_new_line(data_list_md[:line_index])
|
|
192
|
+
if last_part_flag and re.match(r"^\[\^1]: ", data_list_md[line_index]):
|
|
193
|
+
last_part_flag = False
|
|
194
|
+
last_part = delete_empty_lines_last_occur_add_new_line(data_list_md[line_index:])
|
|
195
|
+
|
|
196
|
+
if main_part_flag:
|
|
197
|
+
main_part = delete_empty_lines_last_occur_add_new_line(data_list_md)
|
|
198
|
+
if self.add_reference_in_md:
|
|
199
|
+
main_part.append("\n## References\n")
|
|
200
|
+
if len(last_part) > 0:
|
|
201
|
+
last_part.insert(0, "[//]: (Footnotes)\n\n")
|
|
202
|
+
last_part.append("\n")
|
|
203
|
+
|
|
204
|
+
# for bib
|
|
205
|
+
bib_in_md = []
|
|
206
|
+
if self.add_bib_in_md:
|
|
207
|
+
temp_c = combine_content_in_list([key_url_http_bib_dict[k][2] for k in key_in_md])
|
|
208
|
+
bib_in_md = combine_content_in_list([["<details>\n```\n"], temp_c, ["```\n</details>\n"]])
|
|
209
|
+
|
|
210
|
+
# Generate basic/beauty/complex markdown content
|
|
211
|
+
if dct := eval(f"key_{self.display_basic_beauty_complex_references_in_md}_dict"):
|
|
212
|
+
content_md = self._generate_content_md(dct, key_in_md, main_part, last_part, bib_in_md)
|
|
213
|
+
return content_md
|
|
214
|
+
|
|
215
|
+
@staticmethod
|
|
216
|
+
def _special_format(temp_list: List[str], space_one: str, space_two: str) -> List[str]:
|
|
217
|
+
# special format for alignment
|
|
218
|
+
for j in range(len(temp_list) - 1):
|
|
219
|
+
if temp_list[j][-1] == "\n":
|
|
220
|
+
temp_list[j + 1] = (space_one + " " + space_two) + temp_list[j + 1]
|
|
221
|
+
return temp_list
|
|
222
|
+
|
|
223
|
+
def _generate_content_md(
|
|
224
|
+
self,
|
|
225
|
+
key_basic_beauty_complex_dict: Dict[str, List[str]],
|
|
226
|
+
key_in_md_tex: List[str],
|
|
227
|
+
main_part: List[str],
|
|
228
|
+
last_part: List[str],
|
|
229
|
+
bib_in_md: List[str],
|
|
230
|
+
) -> List[str]:
|
|
231
|
+
temp_b = []
|
|
232
|
+
if self.add_reference_in_md:
|
|
233
|
+
temp_b = combine_content_in_list([key_basic_beauty_complex_dict[k] for k in key_in_md_tex], ["\n"])
|
|
234
|
+
content_md = combine_content_in_list([main_part, ["\n"], temp_b, last_part, bib_in_md])
|
|
235
|
+
return content_md
|