#!/usr/bin/env python3 import sys import re import subprocess import argparse def parse_bibtex_entry(entry): """Extract title and year from a BibTeX entry.""" title = "" year = "" # Extract title title_match = re.search( r"title\s*=\s*\{(.+?)\}\s*,", entry, re.DOTALL | re.IGNORECASE ) if title_match: title = title_match.group(1) # Clean up title - remove extra braces and LaTeX commands title = re.sub(r"^\{+|\}+$", "", title) # Remove outer braces title = re.sub(r"\{\{|\}\}", "", title) # Remove double braces title = re.sub(r"\\textit\{([^}]+)\}", r"\1", title) # Remove \textit{} title = re.sub(r"\\emph\{([^}]+)\}", r"\1", title) # Remove \emph{} title = title.replace("â€", "-") # Fix encoding issues title = title.strip() # Extract year from date field date_match = re.search(r"date\s*=\s*\{(\d{4})", entry, re.IGNORECASE) if date_match: year = date_match.group(1) return title, year def create_task(title, year): """Create a TaskWarrior task for the paper.""" if not title: return False # Format: [title] ([year]) task_desc = title if year: task_desc += f" ({year})" # Create the task command cmd = ["task", "add", task_desc, "+reading", "project:thesis"] try: subprocess.run(cmd, check=True, capture_output=True, text=True) return True except subprocess.CalledProcessError as e: print(f"Error creating task: {e}") return False def main(): parser = argparse.ArgumentParser( description="Convert BibTeX entries to TaskWarrior reading tasks" ) parser.add_argument("bibtex_file", help="Path to the BibTeX file") args = parser.parse_args() # Check if file exists try: with open(args.bibtex_file, "r", encoding="utf-8") as f: content = f.read() except FileNotFoundError: print(f"Error: File '{args.bibtex_file}' not found.") sys.exit(1) except UnicodeDecodeError: # Try with different encoding if UTF-8 fails try: with open(args.bibtex_file, "r", encoding="latin-1") as f: content = f.read() except Exception as e: print(f"Error reading file: {e}") sys.exit(1) # Check if taskwarrior is available try: subprocess.run(["task", "--version"], check=True, capture_output=True) except (subprocess.CalledProcessError, FileNotFoundError): print("Error: TaskWarrior (task) is not installed or not in PATH.") sys.exit(1) print(f"Processing BibTeX file: {args.bibtex_file}") print("Creating reading tasks in TaskWarrior...") print() # Split content into individual entries # Look for @type{key, patterns entries = re.split(r"@\w+\{[^,]*,", content) # Remove the first empty split entries = [entry.strip() for entry in entries[1:] if entry.strip()] created_count = 0 for i, entry in enumerate(entries): title, year = parse_bibtex_entry(entry) if title: if create_task(title, year): created_count += 1 print( f"✓ Created task {created_count}: {title}" + (f" ({year})" if year else "") ) else: print(f"✗ Failed to create task for: {title}") print() print(f"Finished processing BibTeX file.") print( f"Created {created_count} reading tasks with tag 'reading' under project 'thesis'." ) print() print("To view your reading tasks, use:") print(" task +reading list") print(" task project:thesis list") if __name__ == "__main__": main()