Skip to content

Commit

Permalink
Merge pull request #121 from Xeophon/main
Browse files Browse the repository at this point in the history
feat: Add bib-generator
  • Loading branch information
smeech authored Jul 20, 2024
2 parents 8a8d279 + 8e227cd commit bc7a306
Show file tree
Hide file tree
Showing 5 changed files with 128 additions and 0 deletions.
9 changes: 9 additions & 0 deletions packages/bib-generator/1.0.0/README.md
Original file line number Diff line number Diff line change
@@ -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:<your search>:` 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 `<Author> <Some parts of the title>` to improve the search results, as `<Some parts of the title>` 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.
7 changes: 7 additions & 0 deletions packages/bib-generator/1.0.0/_manifest.yml
Original file line number Diff line number Diff line change
@@ -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"]
55 changes: 55 additions & 0 deletions packages/bib-generator/1.0.0/bib_generator.py
Original file line number Diff line number Diff line change
@@ -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)
29 changes: 29 additions & 0 deletions packages/bib-generator/1.0.0/dblp_multi_search.py
Original file line number Diff line number Diff line change
@@ -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)
28 changes: 28 additions & 0 deletions packages/bib-generator/1.0.0/package.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
matches:
- regex: ":cite:(?P<citation>.*?):"
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}}"

0 comments on commit bc7a306

Please sign in to comment.