From bda8a3d6f6cd1a696a0da33f6ff6a344b6ebf067 Mon Sep 17 00:00:00 2001 From: Marty Oehme Date: Fri, 25 Aug 2023 16:25:54 +0200 Subject: [PATCH] papis: Extend papis-show to use rich output Papis show can now show output styled by python-rich if it is in the environment. Otherwise falls back to normal console printing. Added more information to output (journal, volume, issue, type, doi) but also added `-s` switch which returns to old single-line behavior for copying to other programs. --- writing/.config/papis/scripts/papis-show | 116 ++++++++++++++++++++++- 1 file changed, 113 insertions(+), 3 deletions(-) diff --git a/writing/.config/papis/scripts/papis-show b/writing/.config/papis/scripts/papis-show index 7c6779d..2c41828 100755 --- a/writing/.config/papis/scripts/papis-show +++ b/writing/.config/papis/scripts/papis-show @@ -1,6 +1,116 @@ -#!/usr/bin/env bash +#!/usr/bin/env python # papis-short-help: Display pretty human-readable document overview # -# TODO strip {} from bibtex entries to really pretty print +# Takes a query and displays the metadata of the results. Uses +# python-rich to display pretty panels if it exists in the environment, +# otherwise displays regular text. +# Can be invoked with -s to display single-line results better for +# pasting into other documents. -papis -l "${PAPIS_LIB}" list --format "{doc[author]} ({doc[year]}). {doc[title]}." "$@" +import argparse +from importlib.util import find_spec +from papis import database +from papis.database.base import Database +from papis.document import Document +from dataclasses import dataclass, field + +parser = argparse.ArgumentParser() +parser.add_argument( + "--short", "-s", help="only display single-line quick info", action="store_true" +) +parser.add_argument( + "--url", + dest="identifier", + help="display identifier (doi, isbn, url) or not", + action=argparse.BooleanOptionalAction, + default=True, +) +parser.add_argument("query", nargs="*", help="the query to search for") +args = parser.parse_args() + + +@dataclass +class DocInfo: + author: str = "" + title: str = "" + year: str = "" + journal: str = "" + volume: str = "" + issue: str = "" + pages: str = "" + publisher: str = "" + tags: list = field(default_factory=lambda: []) + dtype: str = "" + identifier: str = "" + doi: str = "" + + @staticmethod + def from_Document(doc: Document): + t: list[str] | str = doc.get("tags", "") + tags = ( + t.replace(";", ",").replace(" ", "").split(",") if isinstance(t, str) else t + ) + return DocInfo( + author=doc.get("author", ""), + title=doc.get("title", ""), + year=doc.get("year", ""), + journal=doc.get("journal", ""), + volume=doc.get("volume", ""), + issue=doc.get("issue", ""), + pages=doc.get("pages", ""), + publisher=doc.get("publisher", ""), + tags=tags, + dtype=doc.get("type", ""), + identifier=doc.get("doi", doc.get("isbn", doc.get("url", ""))), + ) + + +def main(db: Database, args) -> None: + query = " ".join(args.query) + docs: list[Document] = db.query(query) + for doc in docs: + info = DocInfo.from_Document(doc) + if args.short: + print_short(info, with_identifier=args.identifier) + else: + print_info(info, with_identifier=args.identifier) + + +def print_short(doc: DocInfo, with_identifier: bool = True) -> None: + print( + f"{doc.author} ({doc.year}). {doc.title}. " + f"{doc.identifier if with_identifier else ''}\n" + ) + + +def print_info(doc: DocInfo, with_identifier: bool = True) -> None: + if find_spec("rich"): + from rich import print as richprint + from rich.panel import Panel + + info: str = ( + f"[red]{doc.author}[/red] ({doc.year}) " + f"[steel_blue]\\[{doc.dtype}][/steel_blue]\n" + f"[bold]{doc.title}[/bold]\n" + f"{doc.journal} ({doc.volume}/{doc.issue}){doc.pages} - {doc.publisher}\n" + f"[grey69]{[tag for tag in doc.tags]} " + ) + if with_identifier: + info += f"[link={doc.identifier}]{doc.identifier}[/link][/grey69]" + richprint(Panel(info, expand=False)) + else: + info: str = ( + f"{doc.author} ({doc.year}) " + f"[{doc.dtype}]\n" + f"{doc.title}\n" + f"{doc.journal} ({doc.volume}/{doc.issue}){doc.pages} - {doc.publisher}\n" + f"{[tag for tag in doc.tags]} " + f"{doc.identifier}" + if with_identifier + else "" + ) + print(f"{info}\n---") + + +if __name__ == "__main__": + main(database.get(), args)