implemented section references

This commit is contained in:
dogeystamp 2023-07-23 19:57:42 -04:00
parent 482d443314
commit 35267cfa34
Signed by: dogeystamp
GPG Key ID: 7225FE3592EFFA38
7 changed files with 71 additions and 18 deletions

View File

@ -3,7 +3,7 @@
This is a Python rewrite of Gilles Castel's [Instant Reference](https://github.com/gillescastel/instant-reference) tool.
(I was not a fan of needing NPM rather than the system package manager to install some dependencies.)
pyinstantref allows you to copy a link to a specific page in a PDF with a single keybind in Zathura.
pyinstantref allows you to copy a link to a specific page or header in a PDF with a single keybind in Zathura.
You can then paste this reference in your notes and other documents.
For now, it only works with my own [templates](https://github.com/dogeystamp/typst-templates) for [Typst](https://github.com/typst/typst),
@ -50,7 +50,7 @@ This will make Ctrl-L copy a reference to the current page in Zathura.
## limitations
Currently, the following features are missing:
Currently, the following features are missing compared to Castel's version:
- ArXiv support
- LaTeX output
- Support for other PDF readers (e.g. Evince)
@ -58,3 +58,9 @@ Currently, the following features are missing:
Feel free to send pull requests,
although this project is primarily for my own usage
and I can not make any guarantees.
Also:
- Section references are unreliable because titles might change,
and there might be sections with the same title.
Proper IDs for bookmarks are possible,
but not until Typst resolves [issue #1352](https://github.com/typst/typst/issues/1352).

View File

@ -1,10 +1,10 @@
#!/usr/bin/env python3
from pdf_data import get_page_pdf
from pdf_data import get_page_pdf, get_section_pdf
from datatypes import *
from enum import Enum, auto
from util import notify
import subprocess
import pydbus
import argparse
import formatter.typst as typst_fmt
@ -32,21 +32,19 @@ def copy_ref(ref: Reference, format: LinkFormat) -> None:
clip_copy(link_txt)
def notify(title:str, txt: str) -> None:
"""Send a text notification."""
bus = pydbus.SessionBus()
notifs = bus.get(".Notifications")
notifs.Notify("instantref", 0, "dialog-information", title, txt, [], {}, 5000)
if __name__ == "__main__":
args = parser.parse_args()
if args.section:
raise NotImplementedError("--section isn't implemented")
ref = get_section_pdf()
else:
ref = get_page_pdf()
format = LinkFormat.TYPST
copy_ref(ref, format)
match ref:
case PDFPage():
notify("Copied ref", f"{ref.filepath.name} p. {ref.page}")
case PDFSection():
notify("Copied ref", f"{ref.filepath.name} sec. {ref.title}")

View File

@ -63,3 +63,10 @@ PDFReference = Union[PDFPage, PDFSection]
# for now no other format is implemented
# replace this with an union if that happens
Reference = PDFReference
# PyMuPDF type
@dataclass
class FitzBookmark:
level: int
title: SectionTitle
page: PageNumber

View File

@ -1,7 +1,24 @@
from pathlib import Path
from datatypes import *
from typing import cast, Any
from util import rofi
import pydbus
import subprocess
import fitz
def get_section_pdf() -> PDFSection:
page_ref: PDFPage = get_page_pdf()
with fitz.Document(page_ref.filepath) as doc:
toc = [FitzBookmark(*x) for x in cast(Any, doc).get_toc()]
page_headers = [x for x in toc if x.page == page_ref.page]
rofi_res = rofi([f"{x.title}" for x in page_headers], prompt="Select header: ")
if rofi_res is None or rofi_res.index is None:
raise RuntimeError("No header was selected.")
selected_header = page_headers[rofi_res.index]
return PDFSection(filepath=page_ref.filepath, title=selected_header.title)
def get_page_pdf() -> PDFPage:

View File

@ -1,15 +1,31 @@
#!/usr/bin/env python3
# pdfref:// URL handler
import subprocess
from urllib.parse import urlparse, parse_qs
from sys import argv
from datatypes import PageNumber
from datatypes import *
from typing import cast, Any
from util import notify
import subprocess
import fitz
url = urlparse(argv[1])
query = parse_qs(url.query)
page: PageNumber = PageNumber(int(query.get("page", ["0"])[0]))
section: SectionTitle = SectionTitle(query.get("section", [])[0])
if section != []:
with fitz.Document(url.path) as doc:
toc = [FitzBookmark(*x) for x in cast(Any, doc).get_toc()]
headers = [x for x in toc if x.title == section]
if headers == []:
notify("", f"Failed to find section '{section}': did the title change?")
else:
if len(headers) > 1:
notify("", f"Multiple sections '{section}' found: page might be incorrect")
page = headers[0].page
subprocess.run(["zathura", "--page", str(page), url.path], text=True)

View File

@ -1,3 +1,4 @@
pycairo==1.24.0
pydbus==0.6.0
PyGObject==3.44.1
PyMuPDF==1.22.5

View File

@ -1,4 +1,5 @@
import subprocess
import pydbus
from dataclasses import dataclass
from typing import Optional
@ -56,3 +57,10 @@ def rofi(entries: list[str], prompt: str="> ", fuzzy=True, extra_args=[]) -> Opt
pass
return ret
def notify(title:str, txt: str) -> None:
"""Send a text notification."""
bus = pydbus.SessionBus()
notifs = bus.get(".Notifications")
notifs.Notify("instantref", 0, "dialog-information", title, txt, [], {}, 5000)