mirror of
https://github.com/jrnl-org/jrnl.git
synced 2025-05-10 08:38:32 +02:00
commit
d50e55480a
13 changed files with 245 additions and 16 deletions
|
@ -5,7 +5,7 @@ python:
|
|||
- "3.3"
|
||||
install:
|
||||
- "pip install -q -r requirements.txt --use-mirrors"
|
||||
- "pip install -q behave"
|
||||
- "pip install -q behave python-dateutil"
|
||||
# command to run tests
|
||||
script:
|
||||
- python --version
|
||||
|
|
12
CHANGELOG.md
12
CHANGELOG.md
|
@ -1,11 +1,19 @@
|
|||
Changelog
|
||||
=========
|
||||
|
||||
### 1.5.2
|
||||
#### 1.5.4
|
||||
|
||||
* [New] DayOne journals can now handle tags
|
||||
|
||||
#### 1.5.3
|
||||
|
||||
* [Fixed] DayOne integration with older DayOne Journals
|
||||
|
||||
#### 1.5.2
|
||||
|
||||
* [Improved] Soft-deprecated `-to` for filtering by time and introduces `-until` instead.
|
||||
|
||||
### 1.5.1
|
||||
#### 1.5.1
|
||||
|
||||
* [Fixed] Fixed a bug introduced in 1.5.0 that caused the entire journal to be printed after composing an entry
|
||||
|
||||
|
|
|
@ -204,11 +204,11 @@ The configuration file is a simple JSON file with the following options.
|
|||
|
||||
### DayOne Integration
|
||||
|
||||
Using your DayOne journal instead of a flat text file is dead simple - instead of pointing to a text file, set the `"journal"` key in your `.jrnl_conf` to point to your DayOne journal. This is a folder ending with `.dayone`, and it's located at
|
||||
Using your DayOne journal instead of a flat text file is dead simple - instead of pointing to a text file, change your `.jrnl_conf` to point to your DayOne journal. This is a folder ending with `.dayone`, and it's located at
|
||||
|
||||
* `~/Library/Application Support/Day One/` by default
|
||||
* `~/Dropbox/Apps/Day One/` if you're syncing with Dropbox and
|
||||
* `~/Library/Mobile Documents/5U8NS4GX82~com~dayoneapp~dayone/Documents/` if you're syncing with iCloud.
|
||||
* `~/Library/Application Support/Day One/` by default
|
||||
* `~/Dropbox/Apps/Day One/` if you're syncing with Dropbox and
|
||||
* `~/Library/Mobile Documents/5U8NS4GX82~com~dayoneapp~dayone/Documents/` if you're syncing with iCloud.
|
||||
|
||||
Instead of all entries being in a single file, each entry will live in a separate `plist` file. You can also star entries when you write them:
|
||||
|
||||
|
|
14
features/data/configs/dayone.json
Normal file
14
features/data/configs/dayone.json
Normal file
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
"default_hour": 9,
|
||||
"timeformat": "%Y-%m-%d %H:%M",
|
||||
"linewrap": 80,
|
||||
"encrypt": false,
|
||||
"editor": "",
|
||||
"default_minute": 0,
|
||||
"highlight": true,
|
||||
"password": "",
|
||||
"journals": {
|
||||
"default": "features/journals/dayone.dayone"
|
||||
},
|
||||
"tagsymbols": "@"
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>Creation Date</key>
|
||||
<date>2013-05-17T18:39:20Z</date>
|
||||
<key>Creator</key>
|
||||
<dict>
|
||||
<key>Device Agent</key>
|
||||
<string>Macintosh/MacBookAir5,2</string>
|
||||
<key>Generation Date</key>
|
||||
<date>2013-08-17T18:39:20Z</date>
|
||||
<key>Host Name</key>
|
||||
<string>Egeria</string>
|
||||
<key>OS Agent</key>
|
||||
<string>Mac OS X/10.8.4</string>
|
||||
<key>Software Agent</key>
|
||||
<string>Day One (Mac)/1.8</string>
|
||||
</dict>
|
||||
<key>Entry Text</key>
|
||||
<string>This entry has tags!</string>
|
||||
<key>Starred</key>
|
||||
<false/>
|
||||
<key>Tags</key>
|
||||
<array>
|
||||
<string>work</string>
|
||||
<string>play</string>
|
||||
</array>
|
||||
<key>Time Zone</key>
|
||||
<string>America/Los_Angeles</string>
|
||||
<key>UUID</key>
|
||||
<string>044F3747A38546168B572C2E3F217FA2</string>
|
||||
</dict>
|
||||
</plist>
|
|
@ -0,0 +1,46 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>Creation Date</key>
|
||||
<date>2013-06-17T18:38:29Z</date>
|
||||
<key>Creator</key>
|
||||
<dict>
|
||||
<key>Device Agent</key>
|
||||
<string>Macintosh/MacBookAir5,2</string>
|
||||
<key>Generation Date</key>
|
||||
<date>2013-08-17T18:38:29Z</date>
|
||||
<key>Host Name</key>
|
||||
<string>Egeria</string>
|
||||
<key>OS Agent</key>
|
||||
<string>Mac OS X/10.8.4</string>
|
||||
<key>Software Agent</key>
|
||||
<string>Day One (Mac)/1.8</string>
|
||||
</dict>
|
||||
<key>Entry Text</key>
|
||||
<string>This entry has a location.</string>
|
||||
<key>Location</key>
|
||||
<dict>
|
||||
<key>Administrative Area</key>
|
||||
<string>California</string>
|
||||
<key>Country</key>
|
||||
<string>Germany</string>
|
||||
<key>Latitude</key>
|
||||
<real>52.4979764</real>
|
||||
<key>Locality</key>
|
||||
<string>Berlin</string>
|
||||
<key>Longitude</key>
|
||||
<real>13.2404758</real>
|
||||
<key>Place Name</key>
|
||||
<string>Abandoned Spy Tower</string>
|
||||
</dict>
|
||||
<key>Starred</key>
|
||||
<false/>
|
||||
<key>Tags</key>
|
||||
<array/>
|
||||
<key>Time Zone</key>
|
||||
<string>Europe/Berlin</string>
|
||||
<key>UUID</key>
|
||||
<string>0BDDD6CDA43C4A9AA2681517CC35AD9D</string>
|
||||
</dict>
|
||||
</plist>
|
|
@ -0,0 +1,31 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>Creation Date</key>
|
||||
<date>2013-07-17T18:38:08Z</date>
|
||||
<key>Creator</key>
|
||||
<dict>
|
||||
<key>Device Agent</key>
|
||||
<string>Macintosh/MacBookAir5,2</string>
|
||||
<key>Generation Date</key>
|
||||
<date>2013-08-17T18:38:08Z</date>
|
||||
<key>Host Name</key>
|
||||
<string>Egeria</string>
|
||||
<key>OS Agent</key>
|
||||
<string>Mac OS X/10.8.4</string>
|
||||
<key>Software Agent</key>
|
||||
<string>Day One (Mac)/1.8</string>
|
||||
</dict>
|
||||
<key>Entry Text</key>
|
||||
<string>This entry is starred!</string>
|
||||
<key>Starred</key>
|
||||
<true/>
|
||||
<key>Tags</key>
|
||||
<array/>
|
||||
<key>Time Zone</key>
|
||||
<string>America/Los_Angeles</string>
|
||||
<key>UUID</key>
|
||||
<string>422BC895507944A291E6FC44FC6B8BFC</string>
|
||||
</dict>
|
||||
</plist>
|
|
@ -0,0 +1,29 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>Creation Date</key>
|
||||
<date>2013-01-17T18:37:50Z</date>
|
||||
<key>Creator</key>
|
||||
<dict>
|
||||
<key>Device Agent</key>
|
||||
<string>Macintosh/MacBookAir5,2</string>
|
||||
<key>Generation Date</key>
|
||||
<date>2013-08-17T18:37:50Z</date>
|
||||
<key>Host Name</key>
|
||||
<string>Egeria</string>
|
||||
<key>OS Agent</key>
|
||||
<string>Mac OS X/10.8.4</string>
|
||||
<key>Software Agent</key>
|
||||
<string>Day One (Mac)/1.8</string>
|
||||
</dict>
|
||||
<key>Entry Text</key>
|
||||
<string>This is a DayOne entry without Timezone.</string>
|
||||
<key>Starred</key>
|
||||
<false/>
|
||||
<key>Tags</key>
|
||||
<array/>
|
||||
<key>UUID</key>
|
||||
<string>4BB1F46946AD439996C9B59DE7C4DDC1</string>
|
||||
</dict>
|
||||
</plist>
|
48
features/dayone.feature
Normal file
48
features/dayone.feature
Normal file
|
@ -0,0 +1,48 @@
|
|||
Feature: DayOne Ingetration
|
||||
|
||||
Scenario: Loading a DayOne Journal
|
||||
Given we use the config "dayone.json"
|
||||
When we run "jrnl -from 'feb 2013'"
|
||||
Then we should get no error
|
||||
and the output should be
|
||||
"""
|
||||
2013-05-17 11:39 This entry has tags!
|
||||
|
||||
2013-06-17 20:38 This entry has a location.
|
||||
|
||||
2013-07-17 11:38 This entry is starred!
|
||||
"""
|
||||
|
||||
Scenario: Entries without timezone information will be intepreted in the current timezone
|
||||
Given we use the config "dayone.json"
|
||||
When we run "jrnl -until 'feb 2013'"
|
||||
Then we should get no error
|
||||
and the output should contain "2013-01-17T18:37Z" in the local time
|
||||
|
||||
Scenario: Writing into Dayone
|
||||
Given we use the config "dayone.json"
|
||||
When we run "jrnl 01 may 1979: Being born hurts."
|
||||
and we run "jrnl -until 1980"
|
||||
Then the output should be
|
||||
"""
|
||||
1979-05-01 09:00 Being born hurts.
|
||||
"""
|
||||
|
||||
Scenario: Loading tags from a DayOne Journal
|
||||
Given we use the config "dayone.json"
|
||||
When we run "jrnl --tags"
|
||||
Then the output should be
|
||||
"""
|
||||
work : 1
|
||||
play : 1
|
||||
"""
|
||||
|
||||
Scenario: Saving tags from a DayOne Journal
|
||||
Given we use the config "dayone.json"
|
||||
When we run "jrnl A hard day at @work"
|
||||
and we run "jrnl --tags"
|
||||
Then the output should be
|
||||
"""
|
||||
work : 2
|
||||
play : 1
|
||||
"""
|
|
@ -18,7 +18,11 @@ def before_scenario(context, scenario):
|
|||
if not os.path.exists(working_dir):
|
||||
os.mkdir(working_dir)
|
||||
for filename in os.listdir(original):
|
||||
shutil.copy2(os.path.join(original, filename), working_dir)
|
||||
source = os.path.join(original, filename)
|
||||
if os.path.isdir(source):
|
||||
shutil.copytree(source, os.path.join(working_dir, filename))
|
||||
else:
|
||||
shutil.copy2(source, working_dir)
|
||||
|
||||
def after_scenario(context, scenario):
|
||||
"""After each scenario, restore all test data and remove working_dirs."""
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
from behave import *
|
||||
from jrnl import jrnl, Journal
|
||||
from jrnl import jrnl, Journal, util
|
||||
from dateutil import parser as date_parser
|
||||
import os
|
||||
import sys
|
||||
import json
|
||||
import pytz
|
||||
try:
|
||||
from io import StringIO
|
||||
except ImportError:
|
||||
|
@ -66,15 +68,15 @@ def no_error(context):
|
|||
@then('the output should be parsable as json')
|
||||
def check_output_json(context):
|
||||
out = context.stdout_capture.getvalue()
|
||||
assert json.loads(out)
|
||||
assert json.loads(out), 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
|
||||
assert field in out_json, [field, out_json]
|
||||
assert len(out_json[field]) == number, len(out_json[field])
|
||||
|
||||
@then('"{field}" in the json output should not contain "{key}"')
|
||||
def check_output_field_not_key(context, field, key):
|
||||
|
@ -95,7 +97,16 @@ def check_output(context):
|
|||
text = context.text.strip().splitlines()
|
||||
out = context.stdout_capture.getvalue().strip().splitlines()
|
||||
for line_text, line_out in zip(text, out):
|
||||
assert line_text.strip() == line_out.strip()
|
||||
assert line_text.strip() == line_out.strip(), [line_text.strip(), line_out.strip()]
|
||||
|
||||
@then('the output should contain "{text}" in the local time')
|
||||
def check_output_time_inline(context, text):
|
||||
out = context.stdout_capture.getvalue()
|
||||
local_tz = pytz.timezone(util.get_local_timezone())
|
||||
utc_time = date_parser.parse(text)
|
||||
date = utc_time + local_tz._utcoffset
|
||||
local_date = date.strftime("%Y-%m-%d %H:%M")
|
||||
assert local_date in out, local_date
|
||||
|
||||
@then('the output should contain "{text}"')
|
||||
def check_output_inline(context, text):
|
||||
|
|
|
@ -315,13 +315,14 @@ class DayOne(Journal):
|
|||
dict_entry = plistlib.readPlist(plist_entry)
|
||||
try:
|
||||
timezone = pytz.timezone(dict_entry['Time Zone'])
|
||||
except pytz.exceptions.UnknownTimeZoneError:
|
||||
except (KeyError, pytz.exceptions.UnknownTimeZoneError):
|
||||
timezone = pytz.timezone(util.get_local_timezone())
|
||||
date = dict_entry['Creation Date']
|
||||
date = date + timezone.utcoffset(date)
|
||||
entry = self.new_entry(raw=dict_entry['Entry Text'], date=date, sort=False)
|
||||
entry.starred = dict_entry["Starred"]
|
||||
entry.uuid = dict_entry["UUID"]
|
||||
entry.tags = dict_entry.get("Tags", [])
|
||||
# We're using new_entry to create the Entry object, which adds the entry
|
||||
# to self.entries already. However, in the original Journal.__init__, this
|
||||
# method is expected to return a list of newly created entries, which is why
|
||||
|
@ -343,6 +344,9 @@ class DayOne(Journal):
|
|||
'Starred': entry.starred if hasattr(entry, 'starred') else False,
|
||||
'Entry Text': entry.title+"\n"+entry.body,
|
||||
'Time Zone': util.get_local_timezone(),
|
||||
'UUID': new_uuid
|
||||
'UUID': new_uuid,
|
||||
'Tags': [tag.strip(self.config['tagsymbols']) for tag in entry.tags]
|
||||
}
|
||||
# print entry_plist
|
||||
|
||||
plistlib.writePlist(entry_plist, filename)
|
||||
|
|
|
@ -7,7 +7,7 @@ jrnl is a simple journal application for your command line.
|
|||
"""
|
||||
|
||||
__title__ = 'jrnl'
|
||||
__version__ = '1.5.2'
|
||||
__version__ = '1.5.4'
|
||||
__author__ = 'Manuel Ebert'
|
||||
__license__ = 'MIT License'
|
||||
__copyright__ = 'Copyright 2013 Manuel Ebert'
|
||||
|
|
Loading…
Add table
Reference in a new issue