From e5ee4e3f97bfda28a7302937963b1932c6f220bf Mon Sep 17 00:00:00 2001 From: Manuel Ebert Date: Tue, 6 Aug 2013 17:57:21 -0700 Subject: [PATCH 1/4] Filters before exporting --- jrnl/Journal.py | 1 + jrnl/jrnl.py | 7 ++++--- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/jrnl/Journal.py b/jrnl/Journal.py index 7c680b21..9a7767e8 100644 --- a/jrnl/Journal.py +++ b/jrnl/Journal.py @@ -54,6 +54,7 @@ class Journal(object): consts.DOWParseStyle = -1 # "Monday" will be either today or the last Monday self.dateparse = pdt.Calendar(consts) self.key = None # used to decrypt and encrypt the journal + self.search_tags = None # Store tags we're highlighting journal_txt = self.open() self.entries = self.parse(journal_txt) diff --git a/jrnl/jrnl.py b/jrnl/jrnl.py index ef78840b..256075ce 100755 --- a/jrnl/jrnl.py +++ b/jrnl/jrnl.py @@ -176,14 +176,15 @@ def cli(manual_args=None): entry.starred = args.star util.prompt("[Entry added to {0} journal]".format(journal_name)) journal.write() - - # Reading mode - elif not mode_export: + else: journal.filter(tags=args.text, start_date=args.start_date, end_date=args.end_date, strict=args.strict, short=args.short) journal.limit(args.limit) + + # Reading mode + if not mode_export: print(journal.pprint()) # Various export modes From d4cb4e64f60ebb9822cc013b5e6260d3f9c27064 Mon Sep 17 00:00:00 2001 From: Manuel Ebert Date: Tue, 6 Aug 2013 17:57:31 -0700 Subject: [PATCH 2/4] Tests for filtering --- features/data/journals/tags.journal | 2 +- features/exporting.feature | 52 +++++++++++++++++++++++++++++ features/steps/core.py | 18 ++++++++-- features/tagging.feature | 10 ++++++ 4 files changed, 79 insertions(+), 3 deletions(-) create mode 100644 features/exporting.feature diff --git a/features/data/journals/tags.journal b/features/data/journals/tags.journal index 7b5cdf04..bfd49cf4 100644 --- a/features/data/journals/tags.journal +++ b/features/data/journals/tags.journal @@ -1,4 +1,4 @@ -2013-06-09 15:39 I have an @idea: +2013-04-09 15:39 I have an @idea: (1) write a command line @journal software (2) ??? (3) PROFIT! diff --git a/features/exporting.feature b/features/exporting.feature new file mode 100644 index 00000000..26a0f7b4 --- /dev/null +++ b/features/exporting.feature @@ -0,0 +1,52 @@ +Feature: Expoting a Journal + + Scenario: Exporting to json + Given we use the config "tags.json" + When we run "jrnl --export json" + Then we should get no error + and the output should be + """ + { + "entries": [ + { + "body": "(1) write a command line @journal software\n(2) ???\n(3) PROFIT!", + "date": "2013-04-09", + "time": "15:39", + "title": "I have an @idea:" + }, + { + "body": "As alway's he shared his latest @idea on how to rule the world with me.", + "date": "2013-06-10", + "time": "15:40", + "title": "I met with @dan." + } + ], + "tags": { + "@idea": 2, + "@journal": 1, + "@dan": 1 + } + } + """ + + Scenario: Exporting using filters should only export parts of the journal + Given we use the config "tags.json" + When we run "jrnl -to 'may 2013' --export json" + Then we should get no error + and the output should be + """ + { + "entries": [ + { + "body": "(1) write a command line @journal software\n(2) ???\n(3) PROFIT!", + "date": "2013-04-09", + "time": "15:39", + "title": "I have an @idea:" + } + ], + "tags": { + "@idea": 1, + "@journal": 1 + } + } + """ diff --git a/features/steps/core.py b/features/steps/core.py index b3675c1c..fc9e15ff 100644 --- a/features/steps/core.py +++ b/features/steps/core.py @@ -8,6 +8,20 @@ try: except ImportError: from cStringIO import StringIO +def _parse_args(command): + nargs=[] + concats = [] + for a in command.split()[1:]: + if a.startswith("'"): + concats.append(a.strip("'")) + elif a.endswith("'"): + concats.append(a.strip("'")) + nargs.append(u" ".join(concats)) + concats = [] + else: + nargs.append(a) + return nargs + def read_journal(journal_name="default"): with open(jrnl.CONFIG_PATH) as config_file: config = json.load(config_file) @@ -34,14 +48,14 @@ def set_config(context, config_file): @when('we run "{command}" and enter "{inputs}"') def run_with_input(context, command, inputs=None): text = inputs or context.text - args = command.split()[1:] + args = _parse_args(command) buffer = StringIO(text.strip()) jrnl.util.STDIN = buffer jrnl.cli(args) @when('we run "{command}"') def run(context, command): - args = command.split()[1:] + args = _parse_args(command) jrnl.cli(args or None) diff --git a/features/tagging.feature b/features/tagging.feature index a030d610..a30c1052 100644 --- a/features/tagging.feature +++ b/features/tagging.feature @@ -10,3 +10,13 @@ Feature: Tagging @journal : 1 @dan : 1 """ + + Scenario: Filtering journals should also filter tags + Given we use the config "tags.json" + When we run "jrnl -from 'may 2013' --tags" + Then we should get no error + and the output should be + """ + @idea : 1 + @dan : 1 + """ From cb55bccb176c4efbfa54cce1d21f9c5b765ae406 Mon Sep 17 00:00:00 2001 From: Manuel Ebert Date: Tue, 6 Aug 2013 17:57:36 -0700 Subject: [PATCH 3/4] Version bump --- CHANGELOG.md | 8 ++++++-- jrnl/__init__.py | 2 +- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6c3c430c..ca77eb20 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,11 @@ Changelog ========= -### 1.4.2 +### 1.5.0 + +* [Improved] Exporting, encrypting and displaying tags now takes your filter options into account. So you could export everything before May 2012: `jrnl -to 'may 2012' --export json`. Or encrypt all entries tagged with `@work` into a new journal: `jrnl @work --encrypt work_journal.txt`. Or display all tags of posts where Bob is also tagged: `jrnl @bob --tags` + +#### 1.4.2 * [Fixed] Tagging works again * Meta-info for PyPi updated @@ -10,7 +14,7 @@ Changelog * [Improved] Unifies encryption between Python 2 and 3. If you have problems reading encrypted journals afterwards, first decrypt your journal with the __old__ jrnl version (install with `pip install jrnl==1.3.1`, then `jrnl --decrypt`), upgrade jrnl (`pip install jrnl --upgrade`) and encrypt it again (`jrnl --encrypt`). -### 1.3.2 +#### 1.3.2 * [Improved] Everything that is not direct output of jrnl will be written stderr to improve integration diff --git a/jrnl/__init__.py b/jrnl/__init__.py index 64f3178f..6c783c61 100644 --- a/jrnl/__init__.py +++ b/jrnl/__init__.py @@ -7,7 +7,7 @@ jrnl is a simple journal application for your command line. """ __title__ = 'jrnl' -__version__ = '1.4.2' +__version__ = '1.5.0' __author__ = 'Manuel Ebert' __license__ = 'MIT License' __copyright__ = 'Copyright 2013 Manuel Ebert' From 5255e39448640a8e8ec3eaffd3c81fe6e29f7382 Mon Sep 17 00:00:00 2001 From: Manuel Ebert Date: Tue, 6 Aug 2013 18:10:42 -0700 Subject: [PATCH 4/4] Better tests for exporting to json --- features/exporting.feature | 54 +++++++++----------------------------- features/steps/core.py | 27 +++++++++++++++++++ 2 files changed, 39 insertions(+), 42 deletions(-) diff --git a/features/exporting.feature b/features/exporting.feature index 26a0f7b4..7f58876f 100644 --- a/features/exporting.feature +++ b/features/exporting.feature @@ -4,49 +4,19 @@ Feature: Expoting a Journal Given we use the config "tags.json" When we run "jrnl --export json" Then we should get no error - and the output should be - """ - { - "entries": [ - { - "body": "(1) write a command line @journal software\n(2) ???\n(3) PROFIT!", - "date": "2013-04-09", - "time": "15:39", - "title": "I have an @idea:" - }, - { - "body": "As alway's he shared his latest @idea on how to rule the world with me.", - "date": "2013-06-10", - "time": "15:40", - "title": "I met with @dan." - } - ], - "tags": { - "@idea": 2, - "@journal": 1, - "@dan": 1 - } - } - """ + and the output should be parsable as json + and "entries" in the json output should have 2 elements + and "tags" in the json output should contain "@idea" + and "tags" in the json output should contain "@journal" + and "tags" in the json output should contain "@dan" Scenario: Exporting using filters should only export parts of the journal Given we use the config "tags.json" When we run "jrnl -to 'may 2013' --export json" - Then we should get no error - and the output should be - """ - { - "entries": [ - { - "body": "(1) write a command line @journal software\n(2) ???\n(3) PROFIT!", - "date": "2013-04-09", - "time": "15:39", - "title": "I have an @idea:" - } - ], - "tags": { - "@idea": 1, - "@journal": 1 - } - } - """ + # Then we should get no error + Then the output should be parsable as json + and "entries" in the json output should have 1 element + and "tags" in the json output should contain "@idea" + and "tags" in the json output should contain "@journal" + and "tags" in the json output should not contain "@dan" + diff --git a/features/steps/core.py b/features/steps/core.py index fc9e15ff..bceab051 100644 --- a/features/steps/core.py +++ b/features/steps/core.py @@ -63,6 +63,33 @@ def run(context, command): def no_error(context): assert context.failed is False +@then('the output should be parsable as json') +def check_output_json(context): + out = context.stdout_capture.getvalue() + assert json.loads(out) + +@then('"{field}" in the json output should have {number:d} elements') +@then('"{field}" in the json output should have 1 element') +def check_output_field(context, field, number=1): + out = context.stdout_capture.getvalue() + out_json = json.loads(out) + assert field in out_json + assert len(out_json[field]) == number + +@then('"{field}" in the json output should not contain "{key}"') +def check_output_field_not_key(context, field, key): + out = context.stdout_capture.getvalue() + out_json = json.loads(out) + assert field in out_json + assert key not in out_json[field] + +@then('"{field}" in the json output should contain "{key}"') +def check_output_field_key(context, field, key): + out = context.stdout_capture.getvalue() + out_json = json.loads(out) + assert field in out_json + assert key in out_json[field] + @then('the output should be') def check_output(context): text = context.text.strip().splitlines()