diff --git a/packages/bib-generator/1.0.0/README.md b/packages/bib-generator/1.0.0/README.md new file mode 100644 index 0000000..8756a6e --- /dev/null +++ b/packages/bib-generator/1.0.0/README.md @@ -0,0 +1,9 @@ +# bib-generator +Generates a bib entry from a matching regex using espanso. + +Requires Python 3 installed on your system. + +## Usage +Just write `:cite::` anywhere, it will show 5 results in a form and then replace your text with the .bib entry you selected in the form. It uses the [DBLP](https://dblp.org/) API under the hood, which is restricted to computer science papers only. I highly recommend searching with ` ` to improve the search results, as `` often results in irrelevant results. + +Note: Espanso limits the regex matches to 30 characters ([Source](https://github.com/espanso/espanso/security)), so you must limit your query. \ No newline at end of file diff --git a/packages/bib-generator/1.0.0/_manifest.yml b/packages/bib-generator/1.0.0/_manifest.yml new file mode 100644 index 0000000..1146a09 --- /dev/null +++ b/packages/bib-generator/1.0.0/_manifest.yml @@ -0,0 +1,7 @@ +name: "bib-generator" +title: "Bib Generator" +homepage: https://github.com/Xeophon/hub/tree/main/packages/bib-generator +description: Generate a BibTex entry by searching through DBLP +version: 1.0.0 +author: Xeophon +tags: ["bib", "academia", "research"] diff --git a/packages/bib-generator/1.0.0/bib_generator.py b/packages/bib-generator/1.0.0/bib_generator.py new file mode 100644 index 0000000..5e16882 --- /dev/null +++ b/packages/bib-generator/1.0.0/bib_generator.py @@ -0,0 +1,55 @@ +import sys +import urllib.request +import urllib.parse +import re + + +def get_bib_info(bib): + """Extracts author, title, and year from a given bib entry.""" + author = re.search(r"author\s*=\s*{(.*?)}", bib, re.DOTALL) + if author is None: + author = re.search(r"editor\s*=\s*{(.*?)}", bib, re.DOTALL) + author = author.group(1) if author is not None else "Unknown" + title = re.search(r"title\s*=\s*{(.*?)}", bib, re.DOTALL).group(1) + year = re.search(r"year\s*=\s*{(.*?)}", bib).group(1) + return author, title, year + + +def format_bib_key(author, title, year): + """Formats the bib key using author's last name, first three words of the title, and the year.""" + author_lastname = author.split(" and")[0].split()[-1].lower() + first_three_words = "".join( + re.sub(r"[^a-zA-Z]", "", word) for word in title.split()[:3] + ) + key = f"{author_lastname}{first_three_words}{year}" + return key + + +def extract_url(selected_entry): + """Extracts the URL part from the selected entry in the espanso form""" + pattern = r"\(([^()]*\/.*\/[^()]*)\)$" + match = re.search(pattern, selected_entry) + if match: + return match.group(1) + else: + return None + + +def get_bib(selected_entry): + """Gets the bib from the selected entry in the espanso form""" + full_url = f"https://dblp.org/rec/{extract_url(selected_entry)}.bib" + with urllib.request.urlopen(full_url) as bib_response: + bib = bib_response.read().decode() + if "not found" not in bib: + author, title, year = get_bib_info(bib) + key = format_bib_key(author, title, year) + output = re.sub(r"\{DBLP:.*?\,", "{" + key + ",", bib) + else: + output = "Not found in DBLP" + print(output) + + +try: + get_bib(sys.argv[1]) +except Exception as e: + output = str(e) diff --git a/packages/bib-generator/1.0.0/dblp_multi_search.py b/packages/bib-generator/1.0.0/dblp_multi_search.py new file mode 100644 index 0000000..cc17dd0 --- /dev/null +++ b/packages/bib-generator/1.0.0/dblp_multi_search.py @@ -0,0 +1,29 @@ +import urllib.request +import urllib.parse +import json +import sys + + +def search(query): + """Searches for a publication and retrieves the top 5 matches.""" + options = {"q": query, "format": "json", "h": 5} + output = "" + url = f"https://dblp.org/search/publ/api?{urllib.parse.urlencode(options)}" + with urllib.request.urlopen(url) as response: + data = json.loads(response.read().decode()) + hit = data.get("result", {}).get("hits", {}).get("hit", []) + + if hit: + for item in hit: + info = item.get("info", {}) + title = info.get("title", "No title found") + output += f"{title} ({info.get('url').replace("https://dblp.org/rec/", "")})\n" + else: + print("No results found in DBLP") + print(output.strip()) + + +try: + search(sys.argv[1]) +except Exception as e: + output = str(e) diff --git a/packages/bib-generator/1.0.0/package.yml b/packages/bib-generator/1.0.0/package.yml new file mode 100644 index 0000000..ceb621b --- /dev/null +++ b/packages/bib-generator/1.0.0/package.yml @@ -0,0 +1,28 @@ +matches: + - regex: ":cite:(?P.*?):" + replace: "{{final}}" + vars: + - name: dblp_search_results + type: script + params: + args: + - python + - "%CONFIG%/match/packages/bib-generator/dblp_multi_search.py" + - "{{citation}}" + - name: form1 + type: form + params: + layout: | + Select bib entry: + [[entries]] + fields: + entries: + type: list + values: "{{dblp_search_results}}" + - name: final + type: script + params: + args: + - python + - "%CONFIG%/match/packages/bib-generator/bib_generator.py" + - "{{form1.entries}}" \ No newline at end of file