mirror of
https://github.com/jrnl-org/jrnl.git
synced 2025-05-10 16:48:31 +02:00
Add new -today-in-history
, -month
, -day
, and -year
search filters (#1145)
* Introduce -reminisce, -month, -day, and -year * Update expected_args in parse_args tests * Add check before creating compare_d * Misc changes * Implement testing for -month, -day, -year, and -reminisce * Compress tests into one Scenario Outline * Fix failing tests by updating dates_similar journal * Create 'we set current date and time to' step * Use time.parse in reminisce * Update dates_similar journal * Make 'Searching in a journal' test shorter * Lint * Implement reminiscing test * Add combination tests * Finalize tests * Finalize pytests * Simplify reminisce tests * Change reminsice help (since it also shows today's entries) * Re-do tests; use various tests * Remove old test data * Better scenario description * Standardize format for compare_d * Rename -reminisce to -today-in-history
This commit is contained in:
parent
18058c74e5
commit
f0e8fa2060
6 changed files with 184 additions and 0 deletions
|
@ -214,6 +214,96 @@ Feature: Searching in a journal
|
||||||
| But I'm better.
|
| But I'm better.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
Scenario Outline: Searching by month
|
||||||
|
Given we use the config "<config>.yaml"
|
||||||
|
And we use the password "test" if prompted
|
||||||
|
When we run "jrnl -month 9 --short"
|
||||||
|
Then the output should be "2020-09-24 09:14 The third entry finally after weeks without writing."
|
||||||
|
And we flush the output
|
||||||
|
When we run "jrnl -month Sept --short"
|
||||||
|
Then the output should be "2020-09-24 09:14 The third entry finally after weeks without writing."
|
||||||
|
And we flush the output
|
||||||
|
When we run "jrnl -month September --short"
|
||||||
|
Then the output should be "2020-09-24 09:14 The third entry finally after weeks without writing."
|
||||||
|
|
||||||
|
Examples: configs
|
||||||
|
| config |
|
||||||
|
| basic_onefile |
|
||||||
|
| basic_encrypted |
|
||||||
|
| basic_folder |
|
||||||
|
| basic_dayone |
|
||||||
|
|
||||||
|
Scenario Outline: Searching by day
|
||||||
|
Given we use the config "<config>.yaml"
|
||||||
|
And we use the password "test" if prompted
|
||||||
|
When we run "jrnl -day 31 --short"
|
||||||
|
Then the output should be "2020-08-31 14:32 A second entry in what I hope to be a long series."
|
||||||
|
|
||||||
|
Examples: configs
|
||||||
|
| config |
|
||||||
|
| basic_onefile |
|
||||||
|
| basic_encrypted |
|
||||||
|
| basic_folder |
|
||||||
|
| basic_dayone |
|
||||||
|
|
||||||
|
Scenario Outline: Searching by year
|
||||||
|
Given we use the config "<config>.yaml"
|
||||||
|
And we use the password "test" if prompted
|
||||||
|
When we run "jrnl 2019-01-01 01:01: I like this year."
|
||||||
|
And we run "jrnl -year 2019 --short"
|
||||||
|
Then the output should be "2019-01-01 01:01 I like this year."
|
||||||
|
And we flush the output
|
||||||
|
When we run "jrnl -year 19 --short"
|
||||||
|
Then the output should be "2019-01-01 01:01 I like this year."
|
||||||
|
|
||||||
|
Examples: configs
|
||||||
|
| config |
|
||||||
|
| basic_onefile |
|
||||||
|
| basic_encrypted |
|
||||||
|
| basic_folder |
|
||||||
|
| basic_dayone |
|
||||||
|
|
||||||
|
Scenario Outline: Combining month, day, and year search terms
|
||||||
|
Given we use the config "<config>.yaml"
|
||||||
|
And we use the password "test" if prompted
|
||||||
|
When we run "jrnl -month 08 -day 29 --short"
|
||||||
|
Then the output should be "2020-08-29 11:11 Entry the first."
|
||||||
|
And we flush the output
|
||||||
|
When we run "jrnl -day 29 -year 2020 --short"
|
||||||
|
Then the output should be "2020-08-29 11:11 Entry the first."
|
||||||
|
And we flush the output
|
||||||
|
When we run "jrnl -month 09 -year 2020 --short"
|
||||||
|
Then the output should be "2020-09-24 09:14 The third entry finally after weeks without writing."
|
||||||
|
And we flush the output
|
||||||
|
When we run "jrnl -month 08 -day 29 -year 2020 --short"
|
||||||
|
Then the output should be "2020-08-29 11:11 Entry the first."
|
||||||
|
|
||||||
|
Examples: configs
|
||||||
|
| config |
|
||||||
|
| basic_onefile |
|
||||||
|
| basic_encrypted |
|
||||||
|
| basic_folder |
|
||||||
|
| basic_dayone |
|
||||||
|
|
||||||
|
Scenario Outline: Searching today in history
|
||||||
|
Given we use the config "<config>.yaml"
|
||||||
|
And we use the password "test" if prompted
|
||||||
|
And we set current date and time to "2020-08-31 14:32"
|
||||||
|
When we run "jrnl 2019-08-31 01:01: Hi, from last year."
|
||||||
|
And we run "jrnl -today-in-history --short"
|
||||||
|
Then the output should be
|
||||||
|
"""
|
||||||
|
2019-08-31 01:01 Hi, from last year.
|
||||||
|
2020-08-31 14:32 A second entry in what I hope to be a long series.
|
||||||
|
"""
|
||||||
|
|
||||||
|
Examples: configs
|
||||||
|
| config |
|
||||||
|
| basic_onefile |
|
||||||
|
| basic_encrypted |
|
||||||
|
| basic_folder |
|
||||||
|
| basic_dayone |
|
||||||
|
|
||||||
Scenario: Loading a DayOne Journal
|
Scenario: Loading a DayOne Journal
|
||||||
Given we use the config "dayone.yaml"
|
Given we use the config "dayone.yaml"
|
||||||
When we run "jrnl -from 'feb 2013'"
|
When we run "jrnl -from 'feb 2013'"
|
||||||
|
|
|
@ -17,6 +17,7 @@ import keyring
|
||||||
import toml
|
import toml
|
||||||
import yaml
|
import yaml
|
||||||
|
|
||||||
|
import jrnl.time
|
||||||
from jrnl import Journal
|
from jrnl import Journal
|
||||||
from jrnl import __version__
|
from jrnl import __version__
|
||||||
from jrnl import plugins
|
from jrnl import plugins
|
||||||
|
@ -159,6 +160,11 @@ def disable_keyring(context):
|
||||||
keyring.core.set_keyring(NoKeyring())
|
keyring.core.set_keyring(NoKeyring())
|
||||||
|
|
||||||
|
|
||||||
|
@given('we set current date and time to "{dt}"')
|
||||||
|
def set_datetime(context, dt):
|
||||||
|
context.now = dt
|
||||||
|
|
||||||
|
|
||||||
@when('we change directory to "{path}"')
|
@when('we change directory to "{path}"')
|
||||||
def move_up_dir(context, path):
|
def move_up_dir(context, path):
|
||||||
os.chdir(path)
|
os.chdir(path)
|
||||||
|
@ -197,6 +203,7 @@ def open_editor_and_enter(context, method, text=""):
|
||||||
patch("subprocess.call", side_effect=_mock_editor) as mock_editor, \
|
patch("subprocess.call", side_effect=_mock_editor) as mock_editor, \
|
||||||
patch("getpass.getpass", side_effect=_mock_getpass(password)) as mock_getpass, \
|
patch("getpass.getpass", side_effect=_mock_getpass(password)) as mock_getpass, \
|
||||||
patch("sys.stdin.isatty", return_value=True), \
|
patch("sys.stdin.isatty", return_value=True), \
|
||||||
|
patch("jrnl.time.parse", side_effect=_mock_time_parse(context)), \
|
||||||
patch("jrnl.config.get_config_path", side_effect=lambda: context.config_path), \
|
patch("jrnl.config.get_config_path", side_effect=lambda: context.config_path), \
|
||||||
patch("jrnl.install.get_config_path", side_effect=lambda: context.config_path) \
|
patch("jrnl.install.get_config_path", side_effect=lambda: context.config_path) \
|
||||||
:
|
:
|
||||||
|
@ -289,6 +296,18 @@ def _mock_input(inputs):
|
||||||
return prompt_return
|
return prompt_return
|
||||||
|
|
||||||
|
|
||||||
|
def _mock_time_parse(context):
|
||||||
|
original_parse = jrnl.time.parse
|
||||||
|
if "now" not in context:
|
||||||
|
return original_parse
|
||||||
|
|
||||||
|
def wrapper(input, *args, **kwargs):
|
||||||
|
input = context.now if input == "now" else input
|
||||||
|
return original_parse(input, *args, **kwargs)
|
||||||
|
|
||||||
|
return wrapper
|
||||||
|
|
||||||
|
|
||||||
@when('we run "{command}" and enter')
|
@when('we run "{command}" and enter')
|
||||||
@when('we run "{command}" and enter nothing')
|
@when('we run "{command}" and enter nothing')
|
||||||
@when('we run "{command}" and enter "{inputs}"')
|
@when('we run "{command}" and enter "{inputs}"')
|
||||||
|
@ -322,6 +341,7 @@ def run_with_input(context, command, inputs=""):
|
||||||
patch("getpass.getpass", side_effect=_mock_getpass(password)) as mock_getpass, \
|
patch("getpass.getpass", side_effect=_mock_getpass(password)) as mock_getpass, \
|
||||||
patch("sys.stdin.read", side_effect=text) as mock_read, \
|
patch("sys.stdin.read", side_effect=text) as mock_read, \
|
||||||
patch("subprocess.call", side_effect=_mock_editor) as mock_editor, \
|
patch("subprocess.call", side_effect=_mock_editor) as mock_editor, \
|
||||||
|
patch("jrnl.time.parse", side_effect=_mock_time_parse(context)), \
|
||||||
patch("jrnl.config.get_config_path", side_effect=lambda: context.config_path), \
|
patch("jrnl.config.get_config_path", side_effect=lambda: context.config_path), \
|
||||||
patch("jrnl.install.get_config_path", side_effect=lambda: context.config_path) \
|
patch("jrnl.install.get_config_path", side_effect=lambda: context.config_path) \
|
||||||
:
|
:
|
||||||
|
@ -406,6 +426,7 @@ def run(context, command, text=""):
|
||||||
patch("getpass.getpass", side_effect=_mock_getpass(password)) as mock_getpass, \
|
patch("getpass.getpass", side_effect=_mock_getpass(password)) as mock_getpass, \
|
||||||
patch("subprocess.call", side_effect=_mock_editor) as mock_editor, \
|
patch("subprocess.call", side_effect=_mock_editor) as mock_editor, \
|
||||||
patch("sys.stdin.read", side_effect=lambda: text), \
|
patch("sys.stdin.read", side_effect=lambda: text), \
|
||||||
|
patch("jrnl.time.parse", side_effect=_mock_time_parse(context)), \
|
||||||
patch("jrnl.config.get_config_path", side_effect=lambda: context.config_path), \
|
patch("jrnl.config.get_config_path", side_effect=lambda: context.config_path), \
|
||||||
patch("jrnl.install.get_config_path", side_effect=lambda: context.config_path) \
|
patch("jrnl.install.get_config_path", side_effect=lambda: context.config_path) \
|
||||||
:
|
:
|
||||||
|
|
|
@ -189,6 +189,9 @@ class Journal:
|
||||||
def filter(
|
def filter(
|
||||||
self,
|
self,
|
||||||
tags=[],
|
tags=[],
|
||||||
|
month=None,
|
||||||
|
day=None,
|
||||||
|
year=None,
|
||||||
start_date=None,
|
start_date=None,
|
||||||
end_date=None,
|
end_date=None,
|
||||||
starred=False,
|
starred=False,
|
||||||
|
@ -220,11 +223,19 @@ class Journal:
|
||||||
if contains:
|
if contains:
|
||||||
contains_lower = contains.casefold()
|
contains_lower = contains.casefold()
|
||||||
|
|
||||||
|
# Create datetime object for comparison below
|
||||||
|
# this approach allows various formats
|
||||||
|
if month or day or year:
|
||||||
|
compare_d = time.parse(f"{month or 1}.{day or 1}.{year or 1}")
|
||||||
|
|
||||||
result = [
|
result = [
|
||||||
entry
|
entry
|
||||||
for entry in self.entries
|
for entry in self.entries
|
||||||
if (not tags or tagged(entry.tags))
|
if (not tags or tagged(entry.tags))
|
||||||
and (not starred or entry.starred)
|
and (not starred or entry.starred)
|
||||||
|
and (not month or entry.date.month == compare_d.month)
|
||||||
|
and (not day or entry.date.day == compare_d.day)
|
||||||
|
and (not year or entry.date.year == compare_d.year)
|
||||||
and (not start_date or entry.date >= start_date)
|
and (not start_date or entry.date >= start_date)
|
||||||
and (not end_date or entry.date <= end_date)
|
and (not end_date or entry.date <= end_date)
|
||||||
and (not exclude or not excluded(entry.tags))
|
and (not exclude or not excluded(entry.tags))
|
||||||
|
|
24
jrnl/args.py
24
jrnl/args.py
|
@ -176,6 +176,30 @@ def parse_args(args=[]):
|
||||||
reading.add_argument(
|
reading.add_argument(
|
||||||
"-on", dest="on_date", metavar="DATE", help="Show entries on this date"
|
"-on", dest="on_date", metavar="DATE", help="Show entries on this date"
|
||||||
)
|
)
|
||||||
|
reading.add_argument(
|
||||||
|
"-today-in-history",
|
||||||
|
dest="today_in_history",
|
||||||
|
action="store_true",
|
||||||
|
help="Show entries of today over the years",
|
||||||
|
)
|
||||||
|
reading.add_argument(
|
||||||
|
"-month",
|
||||||
|
dest="month",
|
||||||
|
metavar="DATE",
|
||||||
|
help="Show entries on this month of any year",
|
||||||
|
)
|
||||||
|
reading.add_argument(
|
||||||
|
"-day",
|
||||||
|
dest="day",
|
||||||
|
metavar="DATE",
|
||||||
|
help="Show entries on this day of any month",
|
||||||
|
)
|
||||||
|
reading.add_argument(
|
||||||
|
"-year",
|
||||||
|
dest="year",
|
||||||
|
metavar="DATE",
|
||||||
|
help="Show entries of a specific year",
|
||||||
|
)
|
||||||
reading.add_argument(
|
reading.add_argument(
|
||||||
"-from",
|
"-from",
|
||||||
dest="start_date",
|
dest="start_date",
|
||||||
|
|
13
jrnl/jrnl.py
13
jrnl/jrnl.py
|
@ -15,6 +15,7 @@ from .config import get_config_path
|
||||||
from .editor import get_text_from_editor
|
from .editor import get_text_from_editor
|
||||||
from .editor import get_text_from_stdin
|
from .editor import get_text_from_stdin
|
||||||
from .exception import UserAbort
|
from .exception import UserAbort
|
||||||
|
from . import time
|
||||||
|
|
||||||
|
|
||||||
def run(args):
|
def run(args):
|
||||||
|
@ -77,6 +78,10 @@ def _is_write_mode(args, config, **kwargs):
|
||||||
args.edit,
|
args.edit,
|
||||||
args.export,
|
args.export,
|
||||||
args.end_date,
|
args.end_date,
|
||||||
|
args.today_in_history,
|
||||||
|
args.month,
|
||||||
|
args.day,
|
||||||
|
args.year,
|
||||||
args.limit,
|
args.limit,
|
||||||
args.on_date,
|
args.on_date,
|
||||||
args.short,
|
args.short,
|
||||||
|
@ -206,8 +211,16 @@ def _search_journal(args, journal, **kwargs):
|
||||||
if args.on_date:
|
if args.on_date:
|
||||||
args.start_date = args.end_date = args.on_date
|
args.start_date = args.end_date = args.on_date
|
||||||
|
|
||||||
|
if args.today_in_history:
|
||||||
|
now = time.parse("now")
|
||||||
|
args.day = now.day
|
||||||
|
args.month = now.month
|
||||||
|
|
||||||
journal.filter(
|
journal.filter(
|
||||||
tags=args.text,
|
tags=args.text,
|
||||||
|
month=args.month,
|
||||||
|
day=args.day,
|
||||||
|
year=args.year,
|
||||||
start_date=args.start_date,
|
start_date=args.start_date,
|
||||||
end_date=args.end_date,
|
end_date=args.end_date,
|
||||||
strict=args.strict,
|
strict=args.strict,
|
||||||
|
|
|
@ -18,6 +18,10 @@ def expected_args(**kwargs):
|
||||||
"delete": False,
|
"delete": False,
|
||||||
"edit": False,
|
"edit": False,
|
||||||
"end_date": None,
|
"end_date": None,
|
||||||
|
"today_in_history": False,
|
||||||
|
"month": None,
|
||||||
|
"day": None,
|
||||||
|
"year": None,
|
||||||
"excluded": [],
|
"excluded": [],
|
||||||
"export": False,
|
"export": False,
|
||||||
"filename": None,
|
"filename": None,
|
||||||
|
@ -147,6 +151,27 @@ def test_on_date_alone():
|
||||||
assert cli_as_dict("-on 'saturday'") == expected_args(on_date="saturday")
|
assert cli_as_dict("-on 'saturday'") == expected_args(on_date="saturday")
|
||||||
|
|
||||||
|
|
||||||
|
def test_month_alone():
|
||||||
|
assert cli_as_dict("-month 1") == expected_args(month="1")
|
||||||
|
assert cli_as_dict("-month 01") == expected_args(month="01")
|
||||||
|
assert cli_as_dict("-month January") == expected_args(month="January")
|
||||||
|
assert cli_as_dict("-month Jan") == expected_args(month="Jan")
|
||||||
|
|
||||||
|
|
||||||
|
def test_day_alone():
|
||||||
|
assert cli_as_dict("-day 1") == expected_args(day="1")
|
||||||
|
assert cli_as_dict("-day 01") == expected_args(day="01")
|
||||||
|
|
||||||
|
|
||||||
|
def test_year_alone():
|
||||||
|
assert cli_as_dict("-year 2021") == expected_args(year="2021")
|
||||||
|
assert cli_as_dict("-year 21") == expected_args(year="21")
|
||||||
|
|
||||||
|
|
||||||
|
def test_today_in_history_alone():
|
||||||
|
assert cli_as_dict("-today-in-history") == expected_args(today_in_history=True)
|
||||||
|
|
||||||
|
|
||||||
def test_short_alone():
|
def test_short_alone():
|
||||||
assert cli_as_dict("--short") == expected_args(short=True)
|
assert cli_as_dict("--short") == expected_args(short=True)
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue