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. 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.) (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. 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), 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 ## limitations
Currently, the following features are missing: Currently, the following features are missing compared to Castel's version:
- ArXiv support - ArXiv support
- LaTeX output - LaTeX output
- Support for other PDF readers (e.g. Evince) - Support for other PDF readers (e.g. Evince)
@ -58,3 +58,9 @@ Currently, the following features are missing:
Feel free to send pull requests, Feel free to send pull requests,
although this project is primarily for my own usage although this project is primarily for my own usage
and I can not make any guarantees. 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 #!/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 datatypes import *
from enum import Enum, auto from enum import Enum, auto
from util import notify
import subprocess import subprocess
import pydbus
import argparse import argparse
import formatter.typst as typst_fmt import formatter.typst as typst_fmt
@ -32,21 +32,19 @@ def copy_ref(ref: Reference, format: LinkFormat) -> None:
clip_copy(link_txt) 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__": if __name__ == "__main__":
args = parser.parse_args() args = parser.parse_args()
if args.section: if args.section:
raise NotImplementedError("--section isn't implemented") ref = get_section_pdf()
else:
ref = get_page_pdf() ref = get_page_pdf()
format = LinkFormat.TYPST format = LinkFormat.TYPST
copy_ref(ref, format) copy_ref(ref, format)
notify("Copied ref", f"{ref.filepath.name} p. {ref.page}")
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 # for now no other format is implemented
# replace this with an union if that happens # replace this with an union if that happens
Reference = PDFReference Reference = PDFReference
# PyMuPDF type
@dataclass
class FitzBookmark:
level: int
title: SectionTitle
page: PageNumber

View File

@ -1,7 +1,24 @@
from pathlib import Path from pathlib import Path
from datatypes import * from datatypes import *
from typing import cast, Any
from util import rofi
import pydbus import pydbus
import subprocess 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: def get_page_pdf() -> PDFPage:

View File

@ -1,15 +1,31 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# pdfref:// URL handler # pdfref:// URL handler
import subprocess
from urllib.parse import urlparse, parse_qs from urllib.parse import urlparse, parse_qs
from sys import argv from sys import argv
from datatypes import *
from datatypes import PageNumber from typing import cast, Any
from util import notify
import subprocess
import fitz
url = urlparse(argv[1]) url = urlparse(argv[1])
query = parse_qs(url.query) query = parse_qs(url.query)
page: PageNumber = PageNumber(int(query.get("page", ["0"])[0])) 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) subprocess.run(["zathura", "--page", str(page), url.path], text=True)

View File

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

View File

@ -1,4 +1,5 @@
import subprocess import subprocess
import pydbus
from dataclasses import dataclass from dataclasses import dataclass
from typing import Optional from typing import Optional
@ -56,3 +57,10 @@ def rofi(entries: list[str], prompt: str="> ", fuzzy=True, extra_args=[]) -> Opt
pass pass
return ret 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)