Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pretty print journal entries #692

Merged
merged 43 commits into from
Nov 19, 2019
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
e7da8c1
Pretty print journal entry titles and dates.
alichtman Oct 25, 2019
1d4bbea
Removed extra newline at end of title
alichtman Oct 25, 2019
b4bfc2c
Use ansiwrap to properly wrap strings with ANSI escapes
alichtman Oct 26, 2019
75a8249
Add ansiwrap to pyproject.toml
alichtman Oct 26, 2019
01db72b
Allow configuration of colors
alichtman Nov 6, 2019
b2d3fc8
Add color configuration documentation
alichtman Nov 6, 2019
8053d25
Fix broken tests due to config change
alichtman Nov 6, 2019
eb1ed3c
Add tests for colors in configs
alichtman Nov 6, 2019
1a0847b
Add colorama dependency for all platforms
alichtman Nov 6, 2019
a23a818
Allow users to disable colorization of output
alichtman Nov 6, 2019
c63c999
Update poetry.lock
alichtman Nov 6, 2019
4b934e3
Add tag and body color customization options
alichtman Nov 6, 2019
94a2b78
Fix colorization of tags in title and body
alichtman Nov 6, 2019
6f3866c
Updated tests to use no color by default
alichtman Nov 6, 2019
6145682
Change pass to continue in verify_config()
alichtman Nov 6, 2019
baa3ffb
Better style in Entry.py
alichtman Nov 6, 2019
c3b1818
Reduce code duplication for tag highlighting
alichtman Nov 6, 2019
6830535
Properly colorize tags and print body
alichtman Nov 7, 2019
82d3c65
Reformatting and clean up
alichtman Nov 7, 2019
6ce83c7
Replace list comprehension with generator
alichtman Nov 7, 2019
89c4366
Handle invalid colors by not using a color
alichtman Nov 7, 2019
41fb8d4
Process ANSI escapes properly with behave
alichtman Nov 7, 2019
e9bfe4d
Fixed the 'spaces after tags directly next to punctuation' bug
alichtman Nov 7, 2019
dd81c7d
Closer to working tag colorization but not perfect
alichtman Nov 8, 2019
acc754e
Add tests printing for multiline journals
alichtman Nov 8, 2019
99426ce
Correctly indent first line of multiline entry
alichtman Nov 8, 2019
b6f6b29
Add test for multiline entries with tags
alichtman Nov 8, 2019
95b23d4
Remove redundant UNICODE flag
alichtman Nov 8, 2019
7747226
Progress towards proper tag colorization and body formatting
alichtman Nov 8, 2019
8d0aa98
Fix newline colorization bug
alichtman Nov 9, 2019
09c0ccc
And now the space just ends up before the tag instead of after it
alichtman Nov 9, 2019
c65c78c
Fix assertion syntax warning
alichtman Nov 9, 2019
fcc64fa
Moved tag test to tagging.feature file
alichtman Nov 9, 2019
f218374
Strip out debug code and clean up
alichtman Nov 9, 2019
139835c
Bold datetimes in title
alichtman Nov 9, 2019
ea46922
Bold all titles
alichtman Nov 9, 2019
712b471
Merge branch 'master' into pretty-print-entries
alichtman Nov 12, 2019
6ad5188
Merge branch 'master' into pretty-print-entries
alichtman Nov 12, 2019
09802cc
Remove PY2 and PY3 constants
alichtman Nov 16, 2019
8c9b040
Fix regression in features/steps/core.py
alichtman Nov 16, 2019
f2bf1ff
Fix tag_regex
alichtman Nov 16, 2019
edb0d8e
Remove redundant re.UNICODE flag
alichtman Nov 17, 2019
566ab5c
Remove extraneous code
alichtman Nov 17, 2019
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions docs/advanced.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,9 @@ and can be edited with any plain text editor.
- `highlight`
if `true`, tags will be highlighted in cyan.
- `linewrap`
controls the width of the output. Set to `false` if you don't
want to wrap long lines.
controls the width of the output. Set to `false` if you don't want to wrap long lines.
- `colors`
dictionary that controls the colors used to display journal entries. It has two subkeys, which are: `date` and `title`. Current valid values are: `BLACK`, `RED`, `GREEN`, `YELLOW`, `BLUE`, `MAGENTA`, `CYAN`, and `WHITE`. `colorama.Fore` is used for colorization, and you can find the [docs here](https://github.com/tartley/colorama#colored-output).

!!! note
Although it seems intuitive to use the `#`
Expand Down
9 changes: 9 additions & 0 deletions features/core.feature
Original file line number Diff line number Diff line change
Expand Up @@ -58,3 +58,12 @@ Feature: Basic reading and writing to a journal
When we run "jrnl -on 2013-06-10 -s"
Then the output should be "2013-06-10 15:40 Life is good."

Scenario: Invalid color configuration
Given we use the config "invalid_color.yaml"
When we run "jrnl -on 2013-06-10 -s"
Then the output should be
"""
[ERROR: date set to invalid color: not-a-color]
[ERROR: title set to invalid color: also-not-a-color]
2013-06-10 15:40 Life is good.
"""
3 changes: 3 additions & 0 deletions features/data/configs/basic.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,6 @@ tagsymbols: "@"
template: false
timeformat: "%Y-%m-%d %H:%M"
indent_character: "|"
colors:
date: red
title: green
3 changes: 3 additions & 0 deletions features/data/configs/bug153.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,6 @@ tagsymbols: '@'
template: false
timeformat: '%Y-%m-%d %H:%M'
indent_character: "|"
colors:
date: red
title: green
15 changes: 15 additions & 0 deletions features/data/configs/invalid_color.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
default_hour: 9
default_minute: 0
editor: ""
encrypt: false
highlight: true
journals:
default: features/journals/simple.journal
linewrap: 80
tagsymbols: "@"
template: false
timeformat: "%Y-%m-%d %H:%M"
indent_character: "|"
colors:
date: not-a-color
title: also-not-a-color
3 changes: 3 additions & 0 deletions features/data/configs/markdown-headings-335.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,6 @@ password: ''
tagsymbols: '@'
timeformat: '%Y-%m-%d %H:%M'
indent_character: "|"
colors:
date: red
title: green
12 changes: 12 additions & 0 deletions features/data/configs/no_colors.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
default_hour: 9
default_minute: 0
editor: ""
encrypt: false
highlight: true
journals:
default: features/journals/simple.journal
linewrap: 80
tagsymbols: "@"
template: false
timeformat: "%Y-%m-%d %H:%M"
indent_character: "|"
3 changes: 3 additions & 0 deletions features/data/configs/tags-216.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,6 @@ password: ''
tagsymbols: '@'
timeformat: '%Y-%m-%d %H:%M'
indent_character: "|"
colors:
date: red
title: green
3 changes: 3 additions & 0 deletions features/data/configs/tags-237.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,6 @@ password: ''
tagsymbols: '@'
timeformat: '%Y-%m-%d %H:%M'
indent_character: "|"
colors:
date: red
title: green
3 changes: 3 additions & 0 deletions features/data/configs/tags.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,6 @@ password: ''
tagsymbols: '@'
timeformat: '%Y-%m-%d %H:%M'
indent_character: "|"
colors:
date: red
title: green
25 changes: 16 additions & 9 deletions features/steps/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@
from jrnl import cli, install, Journal, util, plugins
from jrnl import __version__
from dateutil import parser as date_parser
from ansiwrap import strip_color
from collections import defaultdict
import os
import ast
import json
import yaml
import keyring
Expand Down Expand Up @@ -170,15 +172,15 @@ def check_json_output_path(context, path, value):
@then('the output should be "{text}"')
def check_output(context, text=None):
text = (text or context.text).strip().splitlines()
out = context.stdout_capture.getvalue().strip().splitlines()
out = strip_color(context.stdout_capture.getvalue().strip()).splitlines()
assert len(text) == len(out), "Output has {} lines (expected: {})".format(len(out), len(text))
for line_text, line_out in zip(text, out):
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()
out = strip_color(context.stdout_capture.getvalue())
local_tz = tzlocal.get_localzone()
utc_time = date_parser.parse(text)
local_date = utc_time.astimezone(local_tz).strftime("%Y-%m-%d %H:%M")
Expand All @@ -189,7 +191,7 @@ def check_output_time_inline(context, text):
@then('the output should contain "{text}"')
def check_output_inline(context, text=None):
text = text or context.text
out = context.stdout_capture.getvalue()
out = strip_color(context.stdout_capture.getvalue())
if isinstance(out, bytes):
out = out.decode('utf-8')
alichtman marked this conversation as resolved.
Show resolved Hide resolved
assert text in out, text
Expand Down Expand Up @@ -233,12 +235,17 @@ def journal_doesnt_exist(context, journal_name="default"):
@then('the config should have "{key}" set to "{value}"')
@then('the config for journal "{journal}" should have "{key}" set to "{value}"')
def config_var(context, key, value, journal=None):
t, value = value.split(":")
value = {
"bool": lambda v: v.lower() == "true",
"int": int,
"str": str
}[t](value)
if not value[0] == "{":
t, value = value.split(":")
value = {
"bool": lambda v: v.lower() == "true",
"int": int,
"str": str
}[t](value)
else:
# Handle value being a dictionary
value = ast.literal_eval(value)

config = util.load_config(install.CONFIG_FILE_PATH)
if journal:
config = config["journals"][journal]
Expand Down
7 changes: 6 additions & 1 deletion features/upgrade.feature
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,16 @@ Feature: Upgrading Journals from 1.x.x to 2.x.x

Scenario: Upgrading a journal encrypted with jrnl 1.x
Given we use the config "encrypted_old.json"
When we run "jrnl -n 1" and enter
When we run "jrnl -n 1" and enter
"""
Y
bad doggie no biscuit
bad doggie no biscuit
"""
Then we should see the message "Password"
and the output should contain "2013-06-10 15:40 Life is good"

Scenario: Upgrading a config without colors to colors
Given we use the config "no_colors.yaml"
When we run "jrnl -n 1"
Then the config should have "colors" set to "{'date':'red', 'title':'blue'}"
14 changes: 9 additions & 5 deletions jrnl/Entry.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@

from __future__ import unicode_literals
import re
import textwrap
import ansiwrap
from datetime import datetime
from .util import split_title
from .util import split_title, colorize


class Entry:
Expand Down Expand Up @@ -79,9 +79,12 @@ def pprint(self, short=False):
else:
indent = ""
if not short and self.journal.config['linewrap']:
title = textwrap.fill(date_str + " " + self.title, self.journal.config['linewrap'])
# Color date and color / bold title and make sure first line of title is bolded
title = ansiwrap.fill(colorize(date_str, self.journal.config['colors']['date']) + " " +
colorize(self.title, self.journal.config['colors']['title'], bold=True),
self.journal.config['linewrap'])
body = "\n".join([
textwrap.fill(
ansiwrap.fill(
line,
self.journal.config['linewrap'],
initial_indent=indent,
Expand All @@ -90,7 +93,8 @@ def pprint(self, short=False):
for line in self.body.rstrip(" \n").splitlines()
])
else:
title = date_str + " " + self.title.rstrip("\n ")
title = colorize(date_str, self.journal.config['colors']['date']) + " " +\
colorize(self.title.rstrip("\n"), self.journal.config['colors']['title'], bold=True)
body = self.body.rstrip("\n ")

# Suppress bodies that are just blanks and new lines.
Expand Down
4 changes: 2 additions & 2 deletions jrnl/Journal.py
Original file line number Diff line number Diff line change
Expand Up @@ -152,12 +152,12 @@ def pprint(self, short=False):
for tag in self.search_tags:
tagre = re.compile(re.escape(tag), re.IGNORECASE)
pp = re.sub(tagre,
lambda match: util.colorize(match.group(0)),
lambda match: util.colorize(match.group(0), "CYAN"),
pp, re.UNICODE)
else:
pp = re.sub(
Entry.Entry.tag_regex(self.config['tagsymbols']),
lambda match: util.colorize(match.group(0)),
lambda match: util.colorize(match.group(0), "CYAN"),
pp
)
return pp
Expand Down
8 changes: 7 additions & 1 deletion jrnl/install.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
from . import __version__
from .Journal import PlainJournal
from .EncryptedJournal import EncryptedJournal
from .util import UserAbort
from .util import UserAbort, verify_config
import yaml
import logging
import sys
Expand Down Expand Up @@ -42,6 +42,7 @@ def module_exists(module_name):
else:
return True


default_config = {
'version': __version__,
'journals': {
Expand All @@ -57,6 +58,10 @@ def module_exists(module_name):
'highlight': True,
'linewrap': 79,
'indent_character': '|',
'colors': {
'date': 'red',
'title': 'blue',
alichtman marked this conversation as resolved.
Show resolved Hide resolved
},
}


Expand Down Expand Up @@ -98,6 +103,7 @@ def load_or_install_jrnl():
sys.exit(1)

upgrade_config(config)
verify_config(config)

return config
else:
Expand Down
35 changes: 28 additions & 7 deletions jrnl/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@
import os
import getpass as gp
import yaml
import colorama
if "win32" in sys.platform:
import colorama
colorama.init()
import re
import tempfile
Expand All @@ -30,9 +30,9 @@
TEST = False
__cached_tz = None

WARNING_COLOR = "\033[33m"
ERROR_COLOR = "\033[31m"
RESET_COLOR = "\033[0m"
WARNING_COLOR = colorama.Fore.YELLOW
ERROR_COLOR = colorama.Fore.RED
RESET_COLOR = colorama.Fore.RESET

# Based on Segtok by Florian Leitner
# https://github.com/fnl/segtok
Expand Down Expand Up @@ -162,6 +162,21 @@ def scope_config(config, journal_name):
return config


def verify_config(config):
"""
Ensures the keys set for colors are valid colorama.Fore attributes.
:return: True if all keys are set correctly, False otherwise
"""
all_valid_colors = True
for key, color in config["colors"].items():
if not getattr(colorama.Fore, color.upper(), None):
# TODO: Not sure whether both of these should stay or not.
alichtman marked this conversation as resolved.
Show resolved Hide resolved
print("[{2}ERROR{3}: {0} set to invalid color: {1}]".format(key, color, ERROR_COLOR, RESET_COLOR))
log.error("Invalid color configuration value for '{0}'.".format(key))
all_valid_colors = False
return all_valid_colors


def get_text_from_editor(config, template=""):
filehandle, tmpfile = tempfile.mkstemp(prefix="jrnl", text=True, suffix=".txt")
with codecs.open(tmpfile, 'w', "utf-8") as f:
Expand All @@ -180,9 +195,15 @@ def get_text_from_editor(config, template=""):
return raw


def colorize(string):
"""Returns the string wrapped in cyan ANSI escape"""
return u"\033[36m{}\033[39m".format(string)
def colorize(string, color, bold=False):
"""Returns the string colored with colorama.Fore.color. If the color set
by the user doesn't exist in the colorama.Fore attributes, the colorization
is done with WHITE."""
color_escape = getattr(colorama.Fore, color.upper(), colorama.Fore.WHITE)
if not bold:
return color_escape + string + colorama.Fore.RESET
else:
return colorama.Style.BRIGHT + color_escape + string + colorama.Style.RESET_ALL


def slugify(string):
Expand Down
23 changes: 22 additions & 1 deletion poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,10 @@ keyring = "^19.0"
pytz = "^2019.1"
tzlocal = "^1.5"
asteval = "^0.9.14"
colorama = {version = "^0.4.1",platform = "win32"}
colorama = "^0.4.1"
python-dateutil = "^2.8"
pyyaml = "^5.1"
ansiwrap = "^0.8.4"

[tool.poetry.dev-dependencies]
behave = "^1.2"
Expand Down