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.

Files changed (80) hide show
  1. pyeasyphd/.python-version +1 -0
  2. pyeasyphd/Main.sublime-menu +43 -0
  3. pyeasyphd/__init__.py +0 -0
  4. pyeasyphd/bib/__init__.py +1 -0
  5. pyeasyphd/bib/bibtexbase/__init__.py +7 -0
  6. pyeasyphd/bib/bibtexbase/standardize/_base.py +36 -0
  7. pyeasyphd/bib/bibtexbase/standardize/default_data.py +97 -0
  8. pyeasyphd/bib/bibtexbase/standardize/do_on_bib.py +54 -0
  9. pyeasyphd/bib/bibtexbase/standardize/do_on_comment_block.py +38 -0
  10. pyeasyphd/bib/bibtexbase/standardize/do_on_entry_block.py +310 -0
  11. pyeasyphd/bib/bibtexbase/standardize/do_on_preamble_block.py +35 -0
  12. pyeasyphd/bib/bibtexbase/standardize/do_on_string_block.py +34 -0
  13. pyeasyphd/bib/bibtexbase/standardize_bib.py +75 -0
  14. pyeasyphd/bib/bibtexparser/__init__.py +47 -0
  15. pyeasyphd/bib/bibtexparser/bibtex_format.py +87 -0
  16. pyeasyphd/bib/bibtexparser/exceptions.py +64 -0
  17. pyeasyphd/bib/bibtexparser/library.py +207 -0
  18. pyeasyphd/bib/bibtexparser/middlewares/block/add.py +94 -0
  19. pyeasyphd/bib/bibtexparser/middlewares/block/authors.py +22 -0
  20. pyeasyphd/bib/bibtexparser/middlewares/block/doi_url.py +62 -0
  21. pyeasyphd/bib/bibtexparser/middlewares/block/entry_field_keys_normalize.py +47 -0
  22. pyeasyphd/bib/bibtexparser/middlewares/block/entry_field_keys_replace.py +31 -0
  23. pyeasyphd/bib/bibtexparser/middlewares/block/entry_field_values_normalize.py +222 -0
  24. pyeasyphd/bib/bibtexparser/middlewares/block/entry_fields_delete.py +34 -0
  25. pyeasyphd/bib/bibtexparser/middlewares/block/entry_fields_keep.py +33 -0
  26. pyeasyphd/bib/bibtexparser/middlewares/block/entry_fields_sort.py +70 -0
  27. pyeasyphd/bib/bibtexparser/middlewares/block/entry_types.py +15 -0
  28. pyeasyphd/bib/bibtexparser/middlewares/block/journal_booktitle.py +113 -0
  29. pyeasyphd/bib/bibtexparser/middlewares/block/month_year.py +34 -0
  30. pyeasyphd/bib/bibtexparser/middlewares/block/number_volume.py +21 -0
  31. pyeasyphd/bib/bibtexparser/middlewares/block/pages.py +28 -0
  32. pyeasyphd/bib/bibtexparser/middlewares/block/title.py +20 -0
  33. pyeasyphd/bib/bibtexparser/middlewares/library/generating_entrykeys.py +98 -0
  34. pyeasyphd/bib/bibtexparser/middlewares/library/keeping_blocks.py +29 -0
  35. pyeasyphd/bib/bibtexparser/middlewares/library/sorting_blocks.py +124 -0
  36. pyeasyphd/bib/bibtexparser/middlewares/middleware.py +222 -0
  37. pyeasyphd/bib/bibtexparser/middlewares/parsestack.py +13 -0
  38. pyeasyphd/bib/bibtexparser/middlewares/utils.py +226 -0
  39. pyeasyphd/bib/bibtexparser/middlewares_library_to_library.py +414 -0
  40. pyeasyphd/bib/bibtexparser/middlewares_library_to_str.py +42 -0
  41. pyeasyphd/bib/bibtexparser/middlewares_str_to_library.py +35 -0
  42. pyeasyphd/bib/bibtexparser/middlewares_str_to_str.py +29 -0
  43. pyeasyphd/bib/bibtexparser/model.py +481 -0
  44. pyeasyphd/bib/bibtexparser/splitter.py +151 -0
  45. pyeasyphd/bib/core/__init__.py +18 -0
  46. pyeasyphd/bib/core/convert_library_to_library.py +31 -0
  47. pyeasyphd/bib/core/convert_library_to_str.py +199 -0
  48. pyeasyphd/bib/core/convert_str_to_library.py +34 -0
  49. pyeasyphd/bib/core/convert_str_to_str.py +27 -0
  50. pyeasyphd/main/__init__.py +17 -0
  51. pyeasyphd/main/basic_input.py +149 -0
  52. pyeasyphd/main/pandoc_md_to.py +361 -0
  53. pyeasyphd/main/python_run_bib.py +73 -0
  54. pyeasyphd/main/python_run_md.py +235 -0
  55. pyeasyphd/main/python_run_tex.py +149 -0
  56. pyeasyphd/main/python_writers.py +212 -0
  57. pyeasyphd/pyeasyphd.py +72 -0
  58. pyeasyphd/pyeasyphd.sublime-settings +235 -0
  59. pyeasyphd/pyeasyphd.sublime-syntax +5 -0
  60. pyeasyphd/tools/__init__.py +30 -0
  61. pyeasyphd/tools/compare/compare_bibs.py +234 -0
  62. pyeasyphd/tools/experiments_base.py +203 -0
  63. pyeasyphd/tools/format_save_bibs.py +178 -0
  64. pyeasyphd/tools/generate/generate_from_bibs.py +447 -0
  65. pyeasyphd/tools/generate/generate_links.py +356 -0
  66. pyeasyphd/tools/py_run_bib_md_tex.py +378 -0
  67. pyeasyphd/tools/replace/replace.py +81 -0
  68. pyeasyphd/tools/search/data.py +318 -0
  69. pyeasyphd/tools/search/search_base.py +118 -0
  70. pyeasyphd/tools/search/search_core.py +326 -0
  71. pyeasyphd/tools/search/search_keywords.py +227 -0
  72. pyeasyphd/tools/search/search_writers.py +288 -0
  73. pyeasyphd/tools/search/utils.py +152 -0
  74. pyeasyphd/tools/spider/process_spider_bib.py +247 -0
  75. pyeasyphd/tools/spider/process_spider_url.py +74 -0
  76. pyeasyphd/tools/spider/process_spider_url_bib.py +62 -0
  77. pyeasyphd/utils/utils.py +62 -0
  78. pyeasyphd-0.0.2.dist-info/METADATA +27 -0
  79. pyeasyphd-0.0.2.dist-info/RECORD +80 -0
  80. 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