diff options
author | Alejandro Gallo <aamsgallo@gmail.com> | 2021-10-03 23:39:33 +0200 |
---|---|---|
committer | Alejandro Gallo <aamsgallo@gmail.com> | 2021-10-03 23:39:33 +0200 |
commit | 6fdeec3ec0492a104022ac17a870bc060baa4c02 (patch) | |
tree | aa210547567c2293a52994d5d72874b39b09512e | |
parent | 8c981d2edbe9473b21a34de51ff5e42bd76bc187 (diff) |
Add papis merge to address request #340
-rw-r--r-- | CHANGELOG.md | 2 | ||||
-rw-r--r-- | papis/commands/merge.py | 137 | ||||
-rw-r--r-- | setup.py | 5 |
3 files changed, 142 insertions, 2 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index 33520e72..a4e66cf8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,8 @@ use emacs-like hooks for some commands. ## papis picker - You can now pick several elements with the key binding `c-t` +## `papis merge` +- Add the command `papis merge` to merge documents in pairs. VERSION v0.11 ============= diff --git a/papis/commands/merge.py b/papis/commands/merge.py new file mode 100644 index 00000000..48056228 --- /dev/null +++ b/papis/commands/merge.py @@ -0,0 +1,137 @@ +""" +Merge two documents that might be potentially repeated. + +If your papis picker do not support selecting two items, then +pass the ``--pick`` flag to pick twice for the documents. + +TODO: Write more documentation + +Cli +^^^ +.. click:: papis.commands.merge:cli + :prog: papis open +""" +import os +import os.path +import logging +from typing import Optional, List, Dict, Any +import click +import shutil + +import papis +import papis.api +import papis.pick +import papis.utils +import papis.config +import papis.cli +import papis.database +from papis.document import Document, to_dict +import papis.format +import papis.strings +import papis.commands.rm as rm +import papis.commands.update as update + + +def run(keep: Document, + erase: Document, + data: Dict[str, Any], + files: List[str], + keep_both: bool, + git: bool = False) -> None: + + logger = logging.getLogger('merge:run') + files_to_move = set(files) - set(keep.get_files()) + for f in files_to_move: + to_folder = keep.get_main_folder() + if to_folder: + logger.info("Moving %s", f) + shutil.copy(f, to_folder) + keep["files"] += [os.path.basename(f)] + update.run(keep, data, git=git) + if not keep_both: + logger.info("removing {}".format(erase)) + rm.run(erase, git=git) + else: + logger.info("keeping both documents") + + +@click.command("merge") +@click.help_option('-h', '--help') +@papis.cli.query_option() +@papis.cli.sort_option() +@click.option("-s", + "--second", + help="Keep the second document after merge and erase the first," + "the default is keep the first", + default=False, + is_flag=True) +@click.option("-p", + "--pick", + help="If your picker does not support picking two documents" + " at once, call twice the picker to get two documents", + default=False, + is_flag=True) +@click.option("-k", + "--keep", + "keep_both", + help="Do not erase any document", + default=False, + is_flag=True) +@papis.cli.git_option(help="Merge in git") +def cli(query: str, + sort_field: Optional[str], + second: bool, + git: bool, + keep_both: bool, + sort_reverse: bool, + pick: bool) -> None: + """Merge two documents from a given library""" + logger = logging.getLogger('cli:merge') + + documents = papis.database.get().query(query) + + if sort_field: + documents = papis.document.sort(documents, sort_field, sort_reverse) + + if not documents: + logger.warning(papis.strings.no_documents_retrieved_message) + return + + documents = [d for d in papis.pick.pick_doc(documents)] + + if pick: + other_documents = [d for d in papis.pick.pick_doc(documents)] + documents += other_documents + + if len(documents) != 2: + logger.error("You have to pick exactly two documents!") + return + + a = documents[0] + data_a = to_dict(a) + data_a.pop("ref") + data_a.pop("files") + b = documents[1] + data_b = to_dict(b) + data_b.pop("ref") + data_b.pop("files") + papis.utils.update_doc_from_data_interactively(data_a, + data_b, + papis.document.describe(b)) + + files = [] # type: List[str] + for doc in documents: + indices = papis.tui.utils.select_range( + doc.get_files(), + "Documents from A to keep", + accept_none=True, + bottom_toolbar=papis.document.describe(a)) + files += [doc.get_files()[i] for i in indices] + + if not papis.tui.utils.confirm("Are you sure you want to merge?"): + logger.info("Exiting safely") + return + + keep = b if second else a + erase = a if second else b + run(keep, erase, data_a, files, keep_both, git) @@ -167,21 +167,22 @@ setup( 'papis.command': [ "add=papis.commands.add:cli", "addto=papis.commands.addto:cli", + "bibtex=papis.commands.bibtex:cli", "browse=papis.commands.browse:cli", "config=papis.commands.config:cli", "edit=papis.commands.edit:cli", + "exec=papis.commands.exec:cli", "explore=papis.commands.explore:cli", "export=papis.commands.export:cli", "git=papis.commands.git:cli", "list=papis.commands.list:cli", + "merge=papis.commands.merge:cli", "mv=papis.commands.mv:cli", - "bibtex=papis.commands.bibtex:cli", "open=papis.commands.open:cli", "rename=papis.commands.rename:cli", "rm=papis.commands.rm:cli", "run=papis.commands.run:cli", "update=papis.commands.update:cli", - "exec=papis.commands.exec:cli", ], 'papis.downloader': [ "acs=papis.downloaders.acs:Downloader", |