summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlejandro Gallo <aamsgallo@gmail.com>2021-10-03 23:39:33 +0200
committerAlejandro Gallo <aamsgallo@gmail.com>2021-10-03 23:39:33 +0200
commit6fdeec3ec0492a104022ac17a870bc060baa4c02 (patch)
treeaa210547567c2293a52994d5d72874b39b09512e
parent8c981d2edbe9473b21a34de51ff5e42bd76bc187 (diff)
Add papis merge to address request #340
-rw-r--r--CHANGELOG.md2
-rw-r--r--papis/commands/merge.py137
-rw-r--r--setup.py5
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)
diff --git a/setup.py b/setup.py
index 8b0b7f70..a159c1a6 100644
--- a/setup.py
+++ b/setup.py
@@ -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",