diff --git a/jrnl/Entry.py b/jrnl/Entry.py index c6c29c6d..34503cd9 100755 --- a/jrnl/Entry.py +++ b/jrnl/Entry.py @@ -74,6 +74,9 @@ class Entry: def __repr__(self): return "".format(self.title.strip(), self.date.strftime("%Y-%m-%d %H:%M")) + def __hash__(self): + return hash(self.__repr__()) + def __eq__(self, other): if not isinstance(other, Entry) \ or self.title.strip() != other.title.strip() \ diff --git a/jrnl/Journal.py b/jrnl/Journal.py index 5fc92df4..a7b6521b 100644 --- a/jrnl/Journal.py +++ b/jrnl/Journal.py @@ -33,6 +33,10 @@ class Journal(object): """Returns the number of entries""" return len(self.entries) + def import_(self, other_journal_txt): + self.entries = list(frozenset(self.entries) | frozenset(self._parse(other_journal_txt))) + self.sort() + def open(self, filename=None): """Opens the journal file defined in the config and parses it into a list of Entries. Entries have the form (date, title, body).""" diff --git a/jrnl/cli.py b/jrnl/cli.py index 2229b664..a50c9965 100644 --- a/jrnl/cli.py +++ b/jrnl/cli.py @@ -40,6 +40,8 @@ def parse_args(args=None): exporting.add_argument('--tags', dest='tags', action="store_true", help='Returns a list of all tags and number of occurences') exporting.add_argument('--export', metavar='TYPE', dest='export', choices=plugins.BaseExporter.PLUGIN_NAMES, help='Export your journal. TYPE can be %s.' % plugins.BaseExporter.get_plugin_types_string(), default=False, const=None) exporting.add_argument('-o', metavar='OUTPUT', dest='output', help='Optionally specifies output file when using --export. If OUTPUT is a directory, exports each entry into an individual file instead.', default=False, const=None) + exporting.add_argument('--import', metavar='TYPE', dest='import_', choices=plugins.BaseImporter.PLUGIN_NAMES, help='Import entries into your journal. TYPE can be jrnl, and it defaults to jrnl if nothing else is specified.', default=False, const='jrnl', nargs='?') + exporting.add_argument('-i', metavar='INPUT', dest='input', help='Optionally specifies input file when using --import.', default=False, const=None) exporting.add_argument('--encrypt', metavar='FILENAME', dest='encrypt', help='Encrypts your existing journal with a new password', nargs='?', default=False, const=None) exporting.add_argument('--decrypt', metavar='FILENAME', dest='decrypt', help='Decrypts your journal and stores it in plain text', nargs='?', default=False, const=None) exporting.add_argument('--edit', dest='edit', help='Opens your editor to edit the selected entries.', action="store_true") @@ -51,7 +53,12 @@ def guess_mode(args, config): """Guesses the mode (compose, read or export) from the given arguments""" compose = True export = False - if args.decrypt is not False or args.encrypt is not False or args.export is not False or any((args.short, args.tags, args.edit)): + import_ = False + if args.import_ is not False: + compose = False + export = False + import_ = True + elif args.decrypt is not False or args.encrypt is not False or args.export is not False or any((args.short, args.tags, args.edit)): compose = False export = True elif any((args.start_date, args.end_date, args.on_date, args.limit, args.strict, args.starred)): @@ -61,7 +68,7 @@ def guess_mode(args, config): # No date and only tags? compose = False - return compose, export + return compose, export, import_ def encrypt(journal, filename=None): @@ -162,7 +169,7 @@ def run(manual_args=None): config['journal'] = journal_conf config['journal'] = os.path.expanduser(os.path.expandvars(config['journal'])) touch_journal(config['journal']) - mode_compose, mode_export = guess_mode(args, config) + mode_compose, mode_export, mode_import = guess_mode(args, config) # How to quit writing? if "win32" in sys.platform: @@ -189,15 +196,20 @@ def run(manual_args=None): journal = Journal.open_journal(journal_name, config) + # Import mode + if mode_import: + plugins.get_importer(args.import_).import_(journal, args.input) + # Writing mode - if mode_compose: + elif mode_compose: raw = " ".join(args.text).strip() if util.PY2 and type(raw) is not unicode: raw = raw.decode(sys.getfilesystemencoding()) journal.new_entry(raw) util.prompt("[Entry added to {0} journal]".format(journal_name)) journal.write() - else: + + if not mode_compose: old_entries = journal.entries if args.on_date: args.start_date = args.end_date = args.on_date @@ -209,7 +221,7 @@ def run(manual_args=None): journal.limit(args.limit) # Reading mode - if not mode_compose and not mode_export: + if not mode_compose and not mode_export and not mode_import: print(util.py2encode(journal.pprint())) # Various export modes diff --git a/jrnl/plugins/__init__.py b/jrnl/plugins/__init__.py index ecda8068..301ad76d 100644 --- a/jrnl/plugins/__init__.py +++ b/jrnl/plugins/__init__.py @@ -53,3 +53,10 @@ def get_exporter(format): if hasattr(exporter, "names") and format in exporter.names: return exporter return None + + +def get_importer(format): + for importer in BaseImporter.PLUGINS: + if hasattr(importer, "names") and format in importer.names: + return importer + return None diff --git a/jrnl/plugins/jrnl_importer.py b/jrnl/plugins/jrnl_importer.py new file mode 100644 index 00000000..6563233b --- /dev/null +++ b/jrnl/plugins/jrnl_importer.py @@ -0,0 +1,32 @@ +#!/usr/bin/env python +# encoding: utf-8 + +from __future__ import absolute_import, unicode_literals +import codecs +import sys +from . import BaseImporter +from .. import util + +class JRNLImporter(BaseImporter): + """This plugin imports entries from other jrnl files.""" + names = ["jrnl"] + + @staticmethod + def import_(journal, input=None): + """Imports from an existing file if input is specified, and + standard input otherwise.""" + old_cnt = len(journal.entries) + old_entries = journal.entries + if input: + with codecs.open(input, "r", "utf-8") as f: + other_journal_txt = f.read() + else: + try: + other_journal_txt = util.py23_read() + except KeyboardInterrupt: + util.prompt("[Entries NOT imported into journal.]") + sys.exit(0) + journal.import_(other_journal_txt) + new_cnt = len(journal.entries) + util.prompt("[{0} imported to {1} journal]".format(new_cnt - old_cnt, journal.name)) + journal.write()