mirror of
https://github.com/jrnl-org/jrnl.git
synced 2025-05-10 16:48:31 +02:00
Squashed commit of the following:
commit 75113187432939a51486422c3f70b3a9e2bcf0aa Merge: 74d185447e10fb
Author: Jonathan Wren <9453067+wren@users.noreply.github.com> Date: Thu Oct 24 17:02:10 2019 -0700 Merge pull request #665 from notbalanced/issue_662 Fixes Issue #662 - Day names not treated consistently for new entry commit 74d1854a4bba468221b4eee254bdee2bb40f5d5a Merge: 97e4d6a6a5726a
Author: Jonathan Wren <9453067+wren@users.noreply.github.com> Date: Sat Oct 5 15:30:57 2019 -0700 Merge pull request #418 from philipsd6/2.0-fancy_exporter Add exporter to output entries inside unicode box character boxes commit47e10fbee7
Author: Craig Moyer <craig.moyer@gmail.com> Date: Sun Sep 29 19:06:53 2019 -0400 Fix issue #662 to properly handle day names as new entry dates and command line (-on, -from, -to). commit9588913100
Author: Craig Moyer <craig.moyer@gmail.com> Date: Sun Sep 29 08:27:27 2019 -0400 Syncing with jrnl-org/master commit4c68eb193d
Merge:81dfebb
97e4d6a Author: Craig Moyer <craig.moyer@gmail.com> Date: Sun Sep 29 07:52:02 2019 -0400 Merge remote-tracking branch 'upstream/master' into 2.0-rc1-maebert commit81dfebb2c0
Author: Manuel Ebert <manuel@1450.me> Date: Mon Apr 29 20:34:18 2019 +0200 export changes commit6a5726acd2
Author: Philip Douglass <philip@philipdouglass.com> Date: Fri Dec 22 20:56:36 2017 -0500 Enable FancyExporter plugin commit3d1b226871
Author: Philip Douglass <philip@philipdouglass.com> Date: Fri Jan 29 11:17:41 2016 -0500 Add exporter to output entries inside unicode box character boxes
This commit is contained in:
parent
b95193d05a
commit
10d8a32b64
6 changed files with 126 additions and 10 deletions
|
@ -62,3 +62,50 @@ Feature: Zapped bugs should stay dead.
|
||||||
Then the output should contain "I'm going to activate the machine."
|
Then the output should contain "I'm going to activate the machine."
|
||||||
Then the output should contain "I've crossed so many timelines. Is there any going back?"
|
Then the output should contain "I've crossed so many timelines. Is there any going back?"
|
||||||
|
|
||||||
|
Scenario: Create entry using day of the week as entry date.
|
||||||
|
Given we use the config "basic.yaml"
|
||||||
|
When we run "jrnl monday: This is an entry on a Monday."
|
||||||
|
Then we should see the message "Entry added"
|
||||||
|
When we run "jrnl -1"
|
||||||
|
Then the output should contain "monday at 9am" in the local time
|
||||||
|
Then the output should contain "This is an entry on a Monday."
|
||||||
|
|
||||||
|
Scenario: Create entry using day of the week abbreviations as entry date.
|
||||||
|
Given we use the config "basic.yaml"
|
||||||
|
When we run "jrnl fri: This is an entry on a Friday."
|
||||||
|
Then we should see the message "Entry added"
|
||||||
|
When we run "jrnl -1"
|
||||||
|
Then the output should contain "friday at 9am" in the local time
|
||||||
|
|
||||||
|
Scenario: Displaying entries using -on today should display entries created today.
|
||||||
|
Given we use the config "basic.yaml"
|
||||||
|
When we run "jrnl today: Adding an entry right now."
|
||||||
|
Then we should see the message "Entry added"
|
||||||
|
When we run "jrnl -on today"
|
||||||
|
Then the output should contain "Adding an entry right now."
|
||||||
|
|
||||||
|
Scenario: Displaying entries using -from day should display correct entries
|
||||||
|
Given we use the config "basic.yaml"
|
||||||
|
When we run "jrnl yesterday: This thing happened yesterday"
|
||||||
|
Then we should see the message "Entry added"
|
||||||
|
When we run "jrnl today at 11:59pm: Adding an entry right now."
|
||||||
|
Then we should see the message "Entry added"
|
||||||
|
When we run "jrnl tomorrow: A future entry."
|
||||||
|
Then we should see the message "Entry added"
|
||||||
|
When we run "jrnl -from today"
|
||||||
|
Then the output should contain "Adding an entry right now."
|
||||||
|
Then the output should contain "A future entry."
|
||||||
|
Then the output should not contain "This thing happened yesterday"
|
||||||
|
|
||||||
|
Scenario: Displaying entries using -from and -to day should display correct entries
|
||||||
|
Given we use the config "basic.yaml"
|
||||||
|
When we run "jrnl yesterday: This thing happened yesterday"
|
||||||
|
Then we should see the message "Entry added"
|
||||||
|
When we run "jrnl today at 11:59pm: Adding an entry right now."
|
||||||
|
Then we should see the message "Entry added"
|
||||||
|
When we run "jrnl tomorrow: A future entry."
|
||||||
|
Then we should see the message "Entry added"
|
||||||
|
When we run "jrnl -from yesterday -to today"
|
||||||
|
Then the output should contain "This thing happened yesterday"
|
||||||
|
Then the output should contain "Adding an entry right now."
|
||||||
|
Then the output should not contain "A future entry."
|
||||||
|
|
|
@ -5,6 +5,9 @@ from jrnl import cli, install, Journal, util, plugins
|
||||||
from jrnl import __version__
|
from jrnl import __version__
|
||||||
from dateutil import parser as date_parser
|
from dateutil import parser as date_parser
|
||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
|
try: import parsedatetime.parsedatetime_consts as pdt
|
||||||
|
except ImportError: import parsedatetime as pdt
|
||||||
|
import time
|
||||||
import os
|
import os
|
||||||
import json
|
import json
|
||||||
import yaml
|
import yaml
|
||||||
|
@ -13,6 +16,10 @@ import tzlocal
|
||||||
import shlex
|
import shlex
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
|
consts = pdt.Constants(usePyICU=False)
|
||||||
|
consts.DOWParseStyle = -1 # Prefers past weekdays
|
||||||
|
CALENDAR = pdt.Calendar(consts)
|
||||||
|
|
||||||
|
|
||||||
class TestKeyring(keyring.backend.KeyringBackend):
|
class TestKeyring(keyring.backend.KeyringBackend):
|
||||||
"""A test keyring that just stores its values in a hash"""
|
"""A test keyring that just stores its values in a hash"""
|
||||||
|
@ -221,9 +228,9 @@ def check_output(context, text=None):
|
||||||
def check_output_time_inline(context, text):
|
def check_output_time_inline(context, text):
|
||||||
out = context.stdout_capture.getvalue()
|
out = context.stdout_capture.getvalue()
|
||||||
local_tz = tzlocal.get_localzone()
|
local_tz = tzlocal.get_localzone()
|
||||||
utc_time = date_parser.parse(text)
|
date, flag = CALENDAR.parse(text)
|
||||||
local_date = utc_time.astimezone(local_tz).strftime("%Y-%m-%d %H:%M")
|
output_date = time.strftime("%Y-%m-%d %H:%M",date)
|
||||||
assert local_date in out, local_date
|
assert output_date in out, output_date
|
||||||
|
|
||||||
|
|
||||||
@then('the output should contain')
|
@then('the output should contain')
|
||||||
|
|
|
@ -122,7 +122,8 @@ class Journal:
|
||||||
try:
|
try:
|
||||||
new_date = datetime.strptime(date_blob, self.config["timeformat"])
|
new_date = datetime.strptime(date_blob, self.config["timeformat"])
|
||||||
except ValueError:
|
except ValueError:
|
||||||
new_date = time.parse(date_blob)
|
# Passing in a date that had brackets around it
|
||||||
|
new_date = time.parse(date_blob, bracketed=True)
|
||||||
|
|
||||||
if new_date:
|
if new_date:
|
||||||
if entries:
|
if entries:
|
||||||
|
|
|
@ -9,8 +9,9 @@ from .tag_exporter import TagExporter
|
||||||
from .xml_exporter import XMLExporter
|
from .xml_exporter import XMLExporter
|
||||||
from .yaml_exporter import YAMLExporter
|
from .yaml_exporter import YAMLExporter
|
||||||
from .template_exporter import __all__ as template_exporters
|
from .template_exporter import __all__ as template_exporters
|
||||||
|
from .fancy_exporter import FancyExporter
|
||||||
|
|
||||||
__exporters =[JSONExporter, MarkdownExporter, TagExporter, TextExporter, XMLExporter, YAMLExporter] + template_exporters
|
__exporters =[JSONExporter, MarkdownExporter, TagExporter, TextExporter, XMLExporter, YAMLExporter, FancyExporter] + template_exporters
|
||||||
__importers =[JRNLImporter]
|
__importers =[JRNLImporter]
|
||||||
|
|
||||||
__exporter_types = {name: plugin for plugin in __exporters for name in plugin.names}
|
__exporter_types = {name: plugin for plugin in __exporters for name in plugin.names}
|
||||||
|
|
56
jrnl/plugins/fancy_exporter.py
Normal file
56
jrnl/plugins/fancy_exporter.py
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
# encoding: utf-8
|
||||||
|
|
||||||
|
from __future__ import absolute_import, unicode_literals, print_function
|
||||||
|
from .text_exporter import TextExporter
|
||||||
|
from textwrap import TextWrapper
|
||||||
|
|
||||||
|
|
||||||
|
class FancyExporter(TextExporter):
|
||||||
|
"""This Exporter can convert entries and journals into text with unicode box drawing characters."""
|
||||||
|
names = ["fancy", "boxed"]
|
||||||
|
extension = "txt"
|
||||||
|
|
||||||
|
border_a="┎"
|
||||||
|
border_b="─"
|
||||||
|
border_c="╮"
|
||||||
|
border_d="╘"
|
||||||
|
border_e="═"
|
||||||
|
border_f="╕"
|
||||||
|
border_g="┃"
|
||||||
|
border_h="│"
|
||||||
|
border_i="┠"
|
||||||
|
border_j="╌"
|
||||||
|
border_k="┤"
|
||||||
|
border_l="┖"
|
||||||
|
border_m="┘"
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def export_entry(cls, entry):
|
||||||
|
"""Returns a fancy unicode representation of a single entry."""
|
||||||
|
date_str = entry.date.strftime(entry.journal.config['timeformat'])
|
||||||
|
linewrap = entry.journal.config['linewrap'] or 78
|
||||||
|
initial_linewrap = linewrap - len(date_str) - 2
|
||||||
|
body_linewrap = linewrap - 2
|
||||||
|
card = [cls.border_a + cls.border_b*(initial_linewrap) + cls.border_c + date_str]
|
||||||
|
w = TextWrapper(width=initial_linewrap, initial_indent=cls.border_g+' ', subsequent_indent=cls.border_g+' ')
|
||||||
|
title_lines = w.wrap(entry.title)
|
||||||
|
card.append(title_lines[0].ljust(initial_linewrap+1) + cls.border_d + cls.border_e*(len(date_str)-1) + cls.border_f)
|
||||||
|
w.width = body_linewrap
|
||||||
|
if len(title_lines) > 1:
|
||||||
|
for line in w.wrap(' '.join([title_line[len(w.subsequent_indent):]
|
||||||
|
for title_line in title_lines[1:]])):
|
||||||
|
card.append(line.ljust(body_linewrap+1) + cls.border_h)
|
||||||
|
if entry.body:
|
||||||
|
card.append(cls.border_i + cls.border_j*body_linewrap + cls.border_k)
|
||||||
|
for line in entry.body.splitlines():
|
||||||
|
body_lines = w.wrap(line) or [cls.border_g]
|
||||||
|
for body_line in body_lines:
|
||||||
|
card.append(body_line.ljust(body_linewrap+1) + cls.border_h)
|
||||||
|
card.append(cls.border_l + cls.border_b*body_linewrap + cls.border_m)
|
||||||
|
return "\n".join(card)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def export_journal(cls, journal):
|
||||||
|
"""Returns a unicode representation of an entire journal."""
|
||||||
|
return "\n".join(cls.export_entry(entry) for entry in journal)
|
14
jrnl/time.py
14
jrnl/time.py
|
@ -12,15 +12,16 @@ consts.DOWParseStyle = -1 # "Monday" will be either today or the last Monday
|
||||||
CALENDAR = pdt.Calendar(consts)
|
CALENDAR = pdt.Calendar(consts)
|
||||||
|
|
||||||
|
|
||||||
def parse(date_str, inclusive=False, default_hour=None, default_minute=None):
|
def parse(date_str, inclusive=False, default_hour=None, default_minute=None, bracketed=False):
|
||||||
"""Parses a string containing a fuzzy date and returns a datetime.datetime object"""
|
"""Parses a string containing a fuzzy date and returns a datetime.datetime object"""
|
||||||
if not date_str:
|
if not date_str:
|
||||||
return None
|
return None
|
||||||
elif isinstance(date_str, datetime):
|
elif isinstance(date_str, datetime):
|
||||||
return date_str
|
return date_str
|
||||||
|
|
||||||
# Don't try to parse anything with 6 or less characters. It's probably a markdown footnote
|
# Don't try to parse anything with 6 or less characters and was parsed from the existing journal.
|
||||||
if len(date_str) <= 6:
|
# It's probably a markdown footnote
|
||||||
|
if len(date_str) <= 6 and bracketed:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
default_date = DEFAULT_FUTURE if inclusive else DEFAULT_PAST
|
default_date = DEFAULT_FUTURE if inclusive else DEFAULT_PAST
|
||||||
|
@ -51,8 +52,11 @@ def parse(date_str, inclusive=False, default_hour=None, default_minute=None):
|
||||||
except TypeError:
|
except TypeError:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
if flag == 1: # Date found, but no time. Use the default time.
|
if flag is 1: # Date found, but no time. Use the default time.
|
||||||
date = datetime(*date[:3], hour=default_hour or 0, minute=default_minute or 0)
|
date = datetime(*date[:3],
|
||||||
|
hour=23 if inclusive else default_hour or 0,
|
||||||
|
minute=59 if inclusive else default_minute or 0,
|
||||||
|
second=59 if inclusive else 0)
|
||||||
else:
|
else:
|
||||||
date = datetime(*date[:6])
|
date = datetime(*date[:6])
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue