mirror of
https://github.com/jrnl-org/jrnl.git
synced 2025-05-20 04:58:32 +02:00
Merge branch 'master' into micah-docs-666
This commit is contained in:
commit
256a0b1e27
21 changed files with 194 additions and 140 deletions
|
@ -7,7 +7,7 @@ If you use jrnl, you can totally make our day by just saying "thanks for the cod
|
||||||
Docs & Typos
|
Docs & Typos
|
||||||
------------
|
------------
|
||||||
|
|
||||||
If you find a typo or a mistake in the docs, please fix it right away and send a pull request. The Right Way™ to fix the docs is to edit the `docs/*.rst` files on the **master** branch. You can see the result if you run `make html` inside the project's root directory, and then open `docs/_build/html/index.html` in your browser. Note that this requires [lessc](http://lesscss.org/) and [Sphinx](https://pypi.python.org/pypi/Sphinx) to be installed. Changes to the CSS or Javascript should be made on `docs/_themes/jrnl/`. The `gh-pages` branch is automatically maintained and updates from `master`; you should never have to edit that.
|
If you find a typo or a mistake in the docs, please fix it right away and send a pull request. The Right Way™ to fix the docs is to edit the `docs/*.md` files on the **master** branch. You can see the result if you run `make html` inside the project's root directory, which will open a browser that hot-reloads as you change the docs. This requires [mkdocs](https://www.mkdocs.org) to be installed. The `gh-pages` branch is automatically maintained and updates from `master`; you should never have to edit that.
|
||||||
|
|
||||||
Bugs
|
Bugs
|
||||||
----
|
----
|
||||||
|
|
6
Makefile
6
Makefile
|
@ -11,11 +11,11 @@ clean:
|
||||||
rm -f *.html
|
rm -f *.html
|
||||||
|
|
||||||
html:
|
html:
|
||||||
mkdocs serve
|
poetry run mkdocs serve
|
||||||
|
|
||||||
# Build GitHub Page from docs
|
# Build GitHub Page from docs
|
||||||
docs:
|
docs:
|
||||||
mkdocs gh-deploy
|
poetry run mkdocs gh-deploy
|
||||||
|
|
||||||
format: ## check style with flake8
|
format: ## check style with flake8
|
||||||
poetry run black features jrnl
|
poetry run black features jrnl
|
||||||
|
@ -31,7 +31,7 @@ dist: clean ## builds source and wheel package
|
||||||
|
|
||||||
release: dist ## package and upload a release
|
release: dist ## package and upload a release
|
||||||
poetry publish
|
poetry publish
|
||||||
mkdocs gh-deploy
|
poetry run mkdocs gh-deploy
|
||||||
|
|
||||||
install: clean ## install the package to the active Python's site-packages
|
install: clean ## install the package to the active Python's site-packages
|
||||||
poetry install
|
poetry install
|
||||||
|
|
|
@ -9,7 +9,7 @@ Optionally, your journal can be encrypted using the [256-bit AES](http://en.wiki
|
||||||
|
|
||||||
### Why keep a journal?
|
### Why keep a journal?
|
||||||
|
|
||||||
Journals aren't just for angsty teenagers and people who have too much time on their summer vacation. A journal helps you to keep track of the things you get done and how you did them. Your imagination may be limitless, but your memory isn't. For personal use, make it a good habit to write at least 20 words a day. Just to reflect what made this day special, why you haven't wasted it. For professional use, consider a text-based journal to be the perfect complement to your GTD todo list - a documentation of what and how you've done it.
|
Journals aren't just for people who have too much time on their summer vacation. A journal helps you to keep track of the things you get done and how you did them. Your imagination may be limitless, but your memory isn't. For personal use, make it a good habit to write at least 20 words a day. Just to reflect what made this day special, why you haven't wasted it. For professional use, consider a text-based journal to be the perfect complement to your GTD todo list - a documentation of what and how you've done it.
|
||||||
|
|
||||||
In a Nutshell
|
In a Nutshell
|
||||||
-------------
|
-------------
|
||||||
|
|
|
@ -105,13 +105,11 @@ that journal.
|
||||||
this option will most likely result in your journal file being
|
this option will most likely result in your journal file being
|
||||||
impossible to load.
|
impossible to load.
|
||||||
|
|
||||||
### Known Issues
|
## Known Issues
|
||||||
|
|
||||||
- The Windows shell prior to Windows 7 has issues with unicode
|
### Unicode on Windows
|
||||||
encoding. If you want to use non-ascii characters, change the
|
|
||||||
codepage with `chcp 1252` before using
|
The Windows shell prior to Windows 7 has issues with unicode encoding.
|
||||||
`jrnl` (Thanks to Yves Pouplard for
|
To use non-ascii characters, first tweak Python to recognize the encoding by adding `'cp65001': 'utf_8'`, to `Lib/encoding/aliases.py`. Then, change the codepage with `chcp 1252` before using `jrnl`.
|
||||||
solving this!)
|
|
||||||
- `jrnl`relies on the PyCrypto
|
(Related issue: [#486](https://github.com/jrnl-org/jrnl/issues/486))
|
||||||
package to encrypt journals, which has some known problems with
|
|
||||||
installing on Windows and within virtual environments.
|
|
||||||
|
|
|
@ -13,7 +13,7 @@ AES](http://en.wikipedia.org/wiki/Advanced_Encryption_Standard).
|
||||||
|
|
||||||
## Why keep a journal?
|
## Why keep a journal?
|
||||||
|
|
||||||
Journals aren't just for angsty teenagers and people who have too much
|
Journals aren't just for people who have too much
|
||||||
time on their summer vacation. A journal helps you to keep track of the
|
time on their summer vacation. A journal helps you to keep track of the
|
||||||
things you get done and how you did them. Your imagination may be
|
things you get done and how you did them. Your imagination may be
|
||||||
limitless, but your memory isn't.
|
limitless, but your memory isn't.
|
||||||
|
|
|
@ -15,9 +15,8 @@ And will get something like `@melo: 9`, meaning there are 9 entries
|
||||||
where both `@alberto` and `@melo` are tagged. How does this work? First,
|
where both `@alberto` and `@melo` are tagged. How does this work? First,
|
||||||
`jrnl @alberto` will filter the journal to only entries containing the
|
`jrnl @alberto` will filter the journal to only entries containing the
|
||||||
tag `@alberto`, and then the `--tags` option will print out how often
|
tag `@alberto`, and then the `--tags` option will print out how often
|
||||||
each tag occurred in this <span class="title-ref">filtered</span>
|
each tag occurred in this filtered journal. Finally, we pipe this to
|
||||||
journal. Finally, we pipe this to `grep` which will only display the
|
`grep` which will only display the line containing `@melo`.
|
||||||
line containing `@melo`.
|
|
||||||
|
|
||||||
### Combining filters
|
### Combining filters
|
||||||
|
|
||||||
|
@ -66,17 +65,19 @@ If you do that often, consider creating a function in your `.bashrc` or
|
||||||
|
|
||||||
``` sh
|
``` sh
|
||||||
jrnlimport () {
|
jrnlimport () {
|
||||||
echo `stat -f %Sm -t '%d %b %Y at %H:%M: ' $1` `cat $1` | jrnl
|
echo `stat -f %Sm -t '%d %b %Y at %H:%M: ' $1` `cat $1` | jrnl
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### Using templates
|
### Using templates
|
||||||
|
|
||||||
Say you always want to use the same template for creating new entries.
|
Say you always want to use the same template for creating new entries.
|
||||||
If you have an `external editor <advanced>` set up, you can use this :
|
If you have an [external editor](../advanced) set up, you can use this:
|
||||||
|
|
||||||
jrnl < my_template.txt
|
```sh
|
||||||
$ jrnl -1 --edit
|
jrnl < my_template.txt
|
||||||
|
jrnl -1 --edit
|
||||||
|
```
|
||||||
|
|
||||||
Another nice solution that allows you to define individual prompts comes
|
Another nice solution that allows you to define individual prompts comes
|
||||||
from [Jacobo de
|
from [Jacobo de
|
||||||
|
@ -142,9 +143,7 @@ you can find the right string to use by inspecting iA Writer's
|
||||||
`Info.plist` file in your shell:
|
`Info.plist` file in your shell:
|
||||||
|
|
||||||
``` sh
|
``` sh
|
||||||
$ grep -A 1 CFBundleIdentifier /Applications/iA\ Writer.app/Contents/Info.plist
|
grep -A 1 CFBundleIdentifier /Applications/iA\ Writer.app/Contents/Info.plist
|
||||||
<key>CFBundleIdentifier</key>
|
|
||||||
<string>pro.writer.mac</string>
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### Notepad++ on Windows
|
### Notepad++ on Windows
|
||||||
|
|
|
@ -37,7 +37,8 @@ jrnl today at 3am: I just met Steve Buscemi in a bar! He looked funny.
|
||||||
!!! note
|
!!! note
|
||||||
Most shell contains a certain number of reserved characters, such as `#`
|
Most shell contains a certain number of reserved characters, such as `#`
|
||||||
and `*`. Unbalanced quotes, parenthesis, and so on will also get into
|
and `*`. Unbalanced quotes, parenthesis, and so on will also get into
|
||||||
the way of your editing. For writing longer entries, just enter `jrnl`
|
the way of your editing.
|
||||||
|
For writing longer entries, just enter `jrnl`
|
||||||
and hit `return`. Only then enter the text of your journal entry.
|
and hit `return`. Only then enter the text of your journal entry.
|
||||||
Alternatively, `use an external editor <advanced>`).
|
Alternatively, `use an external editor <advanced>`).
|
||||||
|
|
||||||
|
@ -75,9 +76,9 @@ The following options are equivalent:
|
||||||
- `jrnl Best day of my life.*`
|
- `jrnl Best day of my life.*`
|
||||||
|
|
||||||
!!! note
|
!!! note
|
||||||
Just make sure that the asterisk sign is **not** surrounded by
|
Just make sure that the asterisk sign is **not** surrounded by
|
||||||
whitespaces, e.g. `jrnl Best day of my life! *` will **not** work (the
|
whitespaces, e.g. `jrnl Best day of my life! *` will **not** work (the
|
||||||
reason being that the `*` sign has a special meaning on most shells).
|
reason being that the `*` sign has a special meaning on most shells).
|
||||||
|
|
||||||
## Viewing
|
## Viewing
|
||||||
|
|
||||||
|
@ -126,9 +127,9 @@ You can change which symbols you'd like to use for tagging in the
|
||||||
configuration.
|
configuration.
|
||||||
|
|
||||||
!!! note
|
!!! note
|
||||||
`jrnl @pinkie @WorldDomination` will switch to viewing mode because
|
`jrnl @pinkie @WorldDomination` will switch to viewing mode because
|
||||||
although **no** command line arguments are given, all the input strings
|
although **no** command line arguments are given, all the input strings
|
||||||
look like tags - *jrnl* will assume you want to filter by tag.
|
look like tags - *jrnl* will assume you want to filter by tag.
|
||||||
|
|
||||||
## Editing older entries
|
## Editing older entries
|
||||||
|
|
||||||
|
@ -157,3 +158,4 @@ jrnl @girlfriend -until 'june 2012' --edit
|
||||||
```
|
```
|
||||||
|
|
||||||
Just select all text, press delete, and everything is gone...
|
Just select all text, press delete, and everything is gone...
|
||||||
|
|
||||||
|
|
|
@ -29,14 +29,3 @@
|
||||||
When we run "jrnl simple -n 1"
|
When we run "jrnl simple -n 1"
|
||||||
Then we should not see the message "Password"
|
Then we should not see the message "Password"
|
||||||
and the output should contain "2013-06-10 15:40 Life is good"
|
and the output should contain "2013-06-10 15:40 Life is good"
|
||||||
|
|
||||||
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
|
|
||||||
"""
|
|
||||||
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"
|
|
||||||
|
|
|
@ -42,11 +42,9 @@ Feature: Exporting a Journal
|
||||||
When we run "jrnl --export markdown"
|
When we run "jrnl --export markdown"
|
||||||
Then the output should be
|
Then the output should be
|
||||||
"""
|
"""
|
||||||
2015
|
# 2015
|
||||||
====
|
|
||||||
|
|
||||||
April
|
## April
|
||||||
-----
|
|
||||||
|
|
||||||
### 2015-04-14 13:23 Heading Test
|
### 2015-04-14 13:23 Heading Test
|
||||||
|
|
||||||
|
|
|
@ -43,17 +43,6 @@ Feature: Zapped bugs should stay dead.
|
||||||
| Hope to get a lot of traffic.
|
| Hope to get a lot of traffic.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
Scenario: Upgrade and parse journals with square brackets
|
|
||||||
Given we use the config "upgrade_from_195.json"
|
|
||||||
When we run "jrnl -9" and enter "Y"
|
|
||||||
Then the output should contain
|
|
||||||
"""
|
|
||||||
2010-06-10 15:00 A life without chocolate is like a bad analogy.
|
|
||||||
|
|
||||||
2013-06-10 15:40 He said "[this] is the best time to be alive".
|
|
||||||
"""
|
|
||||||
Then the journal should have 2 entries
|
|
||||||
|
|
||||||
Scenario: Integers in square brackets should not be read as dates
|
Scenario: Integers in square brackets should not be read as dates
|
||||||
Given we use the config "brackets.yaml"
|
Given we use the config "brackets.yaml"
|
||||||
When we run "jrnl -1"
|
When we run "jrnl -1"
|
||||||
|
|
|
@ -50,3 +50,35 @@ Feature: Tagging
|
||||||
@foo : 1
|
@foo : 1
|
||||||
@bar : 1
|
@bar : 1
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
Scenario: Excluding a tag should filter it
|
||||||
|
Given we use the config "basic.yaml"
|
||||||
|
When we run "jrnl today: @foo came over, we went to a bar"
|
||||||
|
When we run "jrnl I have decided I did not enjoy that @bar"
|
||||||
|
When we run "jrnl --tags -not @bar"
|
||||||
|
Then the output should be
|
||||||
|
"""
|
||||||
|
@foo : 1
|
||||||
|
"""
|
||||||
|
|
||||||
|
Scenario: Excluding a tag should filter an entry, even if an unfiltered tag is in that entry
|
||||||
|
Given we use the config "basic.yaml"
|
||||||
|
When we run "jrnl today: I do @not think this will show up @thought"
|
||||||
|
When we run "jrnl today: I think this will show up @thought"
|
||||||
|
When we run "jrnl --tags -not @not"
|
||||||
|
Then the output should be
|
||||||
|
"""
|
||||||
|
@thought : 1
|
||||||
|
"""
|
||||||
|
|
||||||
|
Scenario: Excluding multiple tags should filter them
|
||||||
|
Given we use the config "basic.yaml"
|
||||||
|
When we run "jrnl today: I do @not think this will show up @thought"
|
||||||
|
When we run "jrnl today: I think this will show up @thought"
|
||||||
|
When we run "jrnl today: This should @never show up @thought"
|
||||||
|
When we run "jrnl today: What a nice day for filtering @thought"
|
||||||
|
When we run "jrnl --tags -not @not @never"
|
||||||
|
Then the output should be
|
||||||
|
"""
|
||||||
|
@thought : 2
|
||||||
|
"""
|
||||||
|
|
23
features/upgrade.feature
Normal file
23
features/upgrade.feature
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
Feature: Upgrading Journals from 1.x.x to 2.x.x
|
||||||
|
|
||||||
|
Scenario: Upgrade and parse journals with square brackets
|
||||||
|
Given we use the config "upgrade_from_195.json"
|
||||||
|
When we run "jrnl -9" and enter "Y"
|
||||||
|
Then the output should contain
|
||||||
|
"""
|
||||||
|
2010-06-10 15:00 A life without chocolate is like a bad analogy.
|
||||||
|
|
||||||
|
2013-06-10 15:40 He said "[this] is the best time to be alive".
|
||||||
|
"""
|
||||||
|
Then the journal should have 2 entries
|
||||||
|
|
||||||
|
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
|
||||||
|
"""
|
||||||
|
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"
|
|
@ -84,9 +84,20 @@ class Journal(object):
|
||||||
def write(self, filename=None):
|
def write(self, filename=None):
|
||||||
"""Dumps the journal into the config file, overwriting it"""
|
"""Dumps the journal into the config file, overwriting it"""
|
||||||
filename = filename or self.config['journal']
|
filename = filename or self.config['journal']
|
||||||
text = "\n".join([e.__unicode__() for e in self.entries])
|
text = self._to_text()
|
||||||
self._store(filename, text)
|
self._store(filename, text)
|
||||||
|
|
||||||
|
def validate_parsing(self):
|
||||||
|
"""Confirms that the jrnl is still parsed correctly after being dumped to text."""
|
||||||
|
new_entries = self._parse(self._to_text())
|
||||||
|
for i, entry in enumerate(self.entries):
|
||||||
|
if entry != new_entries[i]:
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
|
def _to_text(self):
|
||||||
|
return "\n".join([e.__unicode__() for e in self.entries])
|
||||||
|
|
||||||
def _load(self, filename):
|
def _load(self, filename):
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
|
@ -175,7 +186,7 @@ class Journal(object):
|
||||||
tag_counts = set([(tags.count(tag), tag) for tag in tags])
|
tag_counts = set([(tags.count(tag), tag) for tag in tags])
|
||||||
return [Tag(tag, count=count) for count, tag in sorted(tag_counts)]
|
return [Tag(tag, count=count) for count, tag in sorted(tag_counts)]
|
||||||
|
|
||||||
def filter(self, tags=[], start_date=None, end_date=None, starred=False, strict=False, short=False):
|
def filter(self, tags=[], start_date=None, end_date=None, starred=False, strict=False, short=False, exclude=[]):
|
||||||
"""Removes all entries from the journal that don't match the filter.
|
"""Removes all entries from the journal that don't match the filter.
|
||||||
|
|
||||||
tags is a list of tags, each being a string that starts with one of the
|
tags is a list of tags, each being a string that starts with one of the
|
||||||
|
@ -186,19 +197,24 @@ class Journal(object):
|
||||||
starred limits journal to starred entries
|
starred limits journal to starred entries
|
||||||
|
|
||||||
If strict is True, all tags must be present in an entry. If false, the
|
If strict is True, all tags must be present in an entry. If false, the
|
||||||
entry is kept if any tag is present."""
|
|
||||||
|
exclude is a list of the tags which should not appear in the results.
|
||||||
|
entry is kept if any tag is present, unless they appear in exclude."""
|
||||||
self.search_tags = set([tag.lower() for tag in tags])
|
self.search_tags = set([tag.lower() for tag in tags])
|
||||||
|
excluded_tags = set([tag.lower() for tag in exclude])
|
||||||
end_date = time.parse(end_date, inclusive=True)
|
end_date = time.parse(end_date, inclusive=True)
|
||||||
start_date = time.parse(start_date)
|
start_date = time.parse(start_date)
|
||||||
|
|
||||||
# If strict mode is on, all tags have to be present in entry
|
# If strict mode is on, all tags have to be present in entry
|
||||||
tagged = self.search_tags.issubset if strict else self.search_tags.intersection
|
tagged = self.search_tags.issubset if strict else self.search_tags.intersection
|
||||||
|
excluded = lambda tags: len([tag for tag in tags if tag in excluded_tags]) > 0
|
||||||
result = [
|
result = [
|
||||||
entry for entry in self.entries
|
entry 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 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))
|
||||||
]
|
]
|
||||||
|
|
||||||
self.entries = result
|
self.entries = result
|
||||||
|
|
13
jrnl/cli.py
13
jrnl/cli.py
|
@ -13,7 +13,7 @@ from . import Journal
|
||||||
from . import util
|
from . import util
|
||||||
from . import install
|
from . import install
|
||||||
from . import plugins
|
from . import plugins
|
||||||
from .util import ERROR_COLOR, RESET_COLOR
|
from .util import ERROR_COLOR, RESET_COLOR, UserAbort
|
||||||
import jrnl
|
import jrnl
|
||||||
import argparse
|
import argparse
|
||||||
import sys
|
import sys
|
||||||
|
@ -39,6 +39,7 @@ def parse_args(args=None):
|
||||||
reading.add_argument('-and', dest='strict', action="store_true", help='Filter by tags using AND (default: OR)')
|
reading.add_argument('-and', dest='strict', action="store_true", help='Filter by tags using AND (default: OR)')
|
||||||
reading.add_argument('-starred', dest='starred', action="store_true", help='Show only starred entries')
|
reading.add_argument('-starred', dest='starred', action="store_true", help='Show only starred entries')
|
||||||
reading.add_argument('-n', dest='limit', default=None, metavar="N", help="Shows the last n entries matching the filter. '-n 3' and '-3' have the same effect.", nargs="?", type=int)
|
reading.add_argument('-n', dest='limit', default=None, metavar="N", help="Shows the last n entries matching the filter. '-n 3' and '-3' have the same effect.", nargs="?", type=int)
|
||||||
|
reading.add_argument('-not', dest='excluded', nargs='+', default=[], metavar="E", help="Exclude entries with these tags")
|
||||||
|
|
||||||
exporting = parser.add_argument_group('Export / Import', 'Options for transmogrifying your journal')
|
exporting = parser.add_argument_group('Export / Import', 'Options for transmogrifying your journal')
|
||||||
exporting.add_argument('-s', '--short', dest='short', action="store_true", help='Show only titles or line containing the search tags')
|
exporting.add_argument('-s', '--short', dest='short', action="store_true", help='Show only titles or line containing the search tags')
|
||||||
|
@ -143,7 +144,12 @@ def run(manual_args=None):
|
||||||
print(util.py2encode(version_str))
|
print(util.py2encode(version_str))
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
|
|
||||||
config = install.load_or_install_jrnl()
|
try:
|
||||||
|
config = install.load_or_install_jrnl()
|
||||||
|
except UserAbort as err:
|
||||||
|
util.prompt("\n{}".format(err))
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
if args.ls:
|
if args.ls:
|
||||||
util.prnt(list_journals(config))
|
util.prnt(list_journals(config))
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
|
@ -234,7 +240,8 @@ def run(manual_args=None):
|
||||||
start_date=args.start_date, end_date=args.end_date,
|
start_date=args.start_date, end_date=args.end_date,
|
||||||
strict=args.strict,
|
strict=args.strict,
|
||||||
short=args.short,
|
short=args.short,
|
||||||
starred=args.starred)
|
starred=args.starred,
|
||||||
|
exclude=args.excluded)
|
||||||
journal.limit(args.limit)
|
journal.limit(args.limit)
|
||||||
|
|
||||||
# Reading mode
|
# Reading mode
|
||||||
|
|
|
@ -12,8 +12,10 @@ from . import upgrade
|
||||||
from . import __version__
|
from . import __version__
|
||||||
from .Journal import PlainJournal
|
from .Journal import PlainJournal
|
||||||
from .EncryptedJournal import EncryptedJournal
|
from .EncryptedJournal import EncryptedJournal
|
||||||
|
from .util import UserAbort
|
||||||
import yaml
|
import yaml
|
||||||
import logging
|
import logging
|
||||||
|
import sys
|
||||||
|
|
||||||
DEFAULT_CONFIG_NAME = 'jrnl.yaml'
|
DEFAULT_CONFIG_NAME = 'jrnl.yaml'
|
||||||
DEFAULT_JOURNAL_NAME = 'journal.txt'
|
DEFAULT_JOURNAL_NAME = 'journal.txt'
|
||||||
|
@ -63,7 +65,7 @@ def upgrade_config(config):
|
||||||
This essentially automatically ports jrnl installations if new config parameters are introduced in later
|
This essentially automatically ports jrnl installations if new config parameters are introduced in later
|
||||||
versions."""
|
versions."""
|
||||||
missing_keys = set(default_config).difference(config)
|
missing_keys = set(default_config).difference(config)
|
||||||
if missing_keys or config['version'] != __version__:
|
if missing_keys:
|
||||||
for key in missing_keys:
|
for key in missing_keys:
|
||||||
config[key] = default_config[key]
|
config[key] = default_config[key]
|
||||||
save_config(config)
|
save_config(config)
|
||||||
|
@ -85,12 +87,26 @@ def load_or_install_jrnl():
|
||||||
if os.path.exists(config_path):
|
if os.path.exists(config_path):
|
||||||
log.debug('Reading configuration from file %s', config_path)
|
log.debug('Reading configuration from file %s', config_path)
|
||||||
config = util.load_config(config_path)
|
config = util.load_config(config_path)
|
||||||
upgrade.upgrade_jrnl_if_necessary(config_path)
|
|
||||||
|
try:
|
||||||
|
upgrade.upgrade_jrnl_if_necessary(config_path)
|
||||||
|
except upgrade.UpgradeValidationException:
|
||||||
|
util.prompt("Aborting upgrade.")
|
||||||
|
util.prompt("Please tell us about this problem at the following URL:")
|
||||||
|
util.prompt("https://github.com/jrnl-org/jrnl/issues/new?title=UpgradeValidationException")
|
||||||
|
util.prompt("Exiting.")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
upgrade_config(config)
|
upgrade_config(config)
|
||||||
|
|
||||||
return config
|
return config
|
||||||
else:
|
else:
|
||||||
log.debug('Configuration file not found, installing jrnl...')
|
log.debug('Configuration file not found, installing jrnl...')
|
||||||
return install()
|
try:
|
||||||
|
config = install()
|
||||||
|
except KeyboardInterrupt:
|
||||||
|
raise UserAbort("Installation aborted")
|
||||||
|
return config
|
||||||
|
|
||||||
|
|
||||||
def install():
|
def install():
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
from __future__ import absolute_import, unicode_literals, print_function
|
from __future__ import absolute_import, unicode_literals, print_function
|
||||||
from .text_exporter import TextExporter
|
from .text_exporter import TextExporter
|
||||||
|
import os
|
||||||
import re
|
import re
|
||||||
import sys
|
import sys
|
||||||
from ..util import WARNING_COLOR, RESET_COLOR
|
from ..util import WARNING_COLOR, RESET_COLOR
|
||||||
|
@ -30,17 +31,17 @@ class MarkdownExporter(TextExporter):
|
||||||
previous_line = ''
|
previous_line = ''
|
||||||
warn_on_heading_level = False
|
warn_on_heading_level = False
|
||||||
for line in body.splitlines(True):
|
for line in body.splitlines(True):
|
||||||
if re.match(r"#+ ", line):
|
if re.match(r"^#+ ", line):
|
||||||
"""ATX style headings"""
|
"""ATX style headings"""
|
||||||
newbody = newbody + previous_line + heading + line
|
newbody = newbody + previous_line + heading + line
|
||||||
if re.match(r"#######+ ", heading + line):
|
if re.match(r"^#######+ ", heading + line):
|
||||||
warn_on_heading_level = True
|
warn_on_heading_level = True
|
||||||
line = ''
|
line = ''
|
||||||
elif re.match(r"=+$", line) and not re.match(r"^$", previous_line):
|
elif re.match(r"^=+$", line.rstrip()) and not re.match(r"^$", previous_line.strip()):
|
||||||
"""Setext style H1"""
|
"""Setext style H1"""
|
||||||
newbody = newbody + heading + "# " + previous_line
|
newbody = newbody + heading + "# " + previous_line
|
||||||
line = ''
|
line = ''
|
||||||
elif re.match(r"-+$", line) and not re.match(r"^$", previous_line):
|
elif re.match(r"^-+$", line.rstrip()) and not re.match(r"^$", previous_line.strip()):
|
||||||
"""Setext style H2"""
|
"""Setext style H2"""
|
||||||
newbody = newbody + heading + "## " + previous_line
|
newbody = newbody + heading + "## " + previous_line
|
||||||
line = ''
|
line = ''
|
||||||
|
@ -68,12 +69,12 @@ class MarkdownExporter(TextExporter):
|
||||||
for e in journal.entries:
|
for e in journal.entries:
|
||||||
if not e.date.year == year:
|
if not e.date.year == year:
|
||||||
year = e.date.year
|
year = e.date.year
|
||||||
out.append(str(year))
|
out.append("# " + str(year))
|
||||||
out.append("=" * len(str(year)) + "\n")
|
out.append("")
|
||||||
if not e.date.month == month:
|
if not e.date.month == month:
|
||||||
month = e.date.month
|
month = e.date.month
|
||||||
out.append(e.date.strftime("%B"))
|
out.append("## " + e.date.strftime("%B"))
|
||||||
out.append('-' * len(e.date.strftime("%B")) + "\n")
|
out.append("")
|
||||||
out.append(cls.export_entry(e, False))
|
out.append(cls.export_entry(e, False))
|
||||||
result = "\n".join(out)
|
result = "\n".join(out)
|
||||||
return result
|
return result
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
from __future__ import absolute_import, unicode_literals, print_function
|
from __future__ import absolute_import, unicode_literals, print_function
|
||||||
from .text_exporter import TextExporter
|
from .text_exporter import TextExporter
|
||||||
|
import os
|
||||||
import re
|
import re
|
||||||
import sys
|
import sys
|
||||||
from ..util import WARNING_COLOR, ERROR_COLOR, RESET_COLOR
|
from ..util import WARNING_COLOR, ERROR_COLOR, RESET_COLOR
|
||||||
|
@ -34,17 +35,17 @@ class YAMLExporter(TextExporter):
|
||||||
previous_line = ''
|
previous_line = ''
|
||||||
warn_on_heading_level = False
|
warn_on_heading_level = False
|
||||||
for line in entry.body.splitlines(True):
|
for line in entry.body.splitlines(True):
|
||||||
if re.match(r"#+ ", line):
|
if re.match(r"^#+ ", line):
|
||||||
"""ATX style headings"""
|
"""ATX style headings"""
|
||||||
newbody = newbody + previous_line + heading + line
|
newbody = newbody + previous_line + heading + line
|
||||||
if re.match(r"#######+ ", heading + line):
|
if re.match(r"^#######+ ", heading + line):
|
||||||
warn_on_heading_level = True
|
warn_on_heading_level = True
|
||||||
line = ''
|
line = ''
|
||||||
elif re.match(r"=+$", line) and not re.match(r"^$", previous_line):
|
elif re.match(r"^=+$", line.rstrip()) and not re.match(r"^$", previous_line.strip()):
|
||||||
"""Setext style H1"""
|
"""Setext style H1"""
|
||||||
newbody = newbody + heading + "# " + previous_line
|
newbody = newbody + heading + "# " + previous_line
|
||||||
line = ''
|
line = ''
|
||||||
elif re.match(r"-+$", line) and not re.match(r"^$", previous_line):
|
elif re.match(r"^-+$", line.rstrip()) and not re.match(r"^$", previous_line.strip()):
|
||||||
"""Setext style H2"""
|
"""Setext style H2"""
|
||||||
newbody = newbody + heading + "## " + previous_line
|
newbody = newbody + heading + "## " + previous_line
|
||||||
line = ''
|
line = ''
|
||||||
|
|
|
@ -4,7 +4,7 @@ from . import __version__
|
||||||
from . import Journal
|
from . import Journal
|
||||||
from . import util
|
from . import util
|
||||||
from .EncryptedJournal import EncryptedJournal
|
from .EncryptedJournal import EncryptedJournal
|
||||||
import sys
|
from .util import UserAbort
|
||||||
import os
|
import os
|
||||||
import codecs
|
import codecs
|
||||||
|
|
||||||
|
@ -44,6 +44,7 @@ older versions of jrnl anymore.
|
||||||
encrypted_journals = {}
|
encrypted_journals = {}
|
||||||
plain_journals = {}
|
plain_journals = {}
|
||||||
other_journals = {}
|
other_journals = {}
|
||||||
|
all_journals = []
|
||||||
|
|
||||||
for journal_name, journal_conf in config['journals'].items():
|
for journal_name, journal_conf in config['journals'].items():
|
||||||
if isinstance(journal_conf, dict):
|
if isinstance(journal_conf, dict):
|
||||||
|
@ -76,28 +77,44 @@ older versions of jrnl anymore.
|
||||||
for journal, path in other_journals.items():
|
for journal, path in other_journals.items():
|
||||||
util.prompt(" {:{pad}} -> {}".format(journal, path, pad=longest_journal_name))
|
util.prompt(" {:{pad}} -> {}".format(journal, path, pad=longest_journal_name))
|
||||||
|
|
||||||
cont = util.yesno("\nContinue upgrading jrnl?", default=False)
|
try:
|
||||||
if not cont:
|
cont = util.yesno("\nContinue upgrading jrnl?", default=False)
|
||||||
util.prompt("jrnl NOT upgraded, exiting.")
|
if not cont:
|
||||||
sys.exit(1)
|
raise KeyboardInterrupt
|
||||||
|
except KeyboardInterrupt:
|
||||||
|
raise UserAbort("jrnl NOT upgraded, exiting.")
|
||||||
|
|
||||||
for journal_name, path in encrypted_journals.items():
|
for journal_name, path in encrypted_journals.items():
|
||||||
util.prompt("\nUpgrading encrypted '{}' journal stored in {}...".format(journal_name, path))
|
util.prompt("\nUpgrading encrypted '{}' journal stored in {}...".format(journal_name, path))
|
||||||
backup(path, binary=True)
|
backup(path, binary=True)
|
||||||
old_journal = Journal.open_journal(journal_name, util.scope_config(config, journal_name), legacy=True)
|
old_journal = Journal.open_journal(journal_name, util.scope_config(config, journal_name), legacy=True)
|
||||||
new_journal = EncryptedJournal.from_journal(old_journal)
|
all_journals.append(EncryptedJournal.from_journal(old_journal))
|
||||||
new_journal.write()
|
|
||||||
util.prompt(" Done.")
|
|
||||||
|
|
||||||
for journal_name, path in plain_journals.items():
|
for journal_name, path in plain_journals.items():
|
||||||
util.prompt("\nUpgrading plain text '{}' journal stored in {}...".format(journal_name, path))
|
util.prompt("\nUpgrading plain text '{}' journal stored in {}...".format(journal_name, path))
|
||||||
backup(path)
|
backup(path)
|
||||||
old_journal = Journal.open_journal(journal_name, util.scope_config(config, journal_name), legacy=True)
|
old_journal = Journal.open_journal(journal_name, util.scope_config(config, journal_name), legacy=True)
|
||||||
new_journal = Journal.PlainJournal.from_journal(old_journal)
|
all_journals.append(Journal.PlainJournal.from_journal(old_journal))
|
||||||
new_journal.write()
|
|
||||||
util.prompt(" Done.")
|
# loop through lists to validate
|
||||||
|
failed_journals = [j for j in all_journals if not j.validate_parsing()]
|
||||||
|
|
||||||
|
if len(failed_journals) > 0:
|
||||||
|
util.prompt("\nThe following journal{} failed to upgrade:\n{}".format(
|
||||||
|
's' if len(failed_journals) > 1 else '', "\n".join(j.name for j in failed_journals))
|
||||||
|
)
|
||||||
|
|
||||||
|
raise UpgradeValidationException
|
||||||
|
|
||||||
|
# write all journals - or - don't
|
||||||
|
for j in all_journals:
|
||||||
|
j.write()
|
||||||
|
|
||||||
util.prompt("\nUpgrading config...")
|
util.prompt("\nUpgrading config...")
|
||||||
backup(config_path)
|
backup(config_path)
|
||||||
|
|
||||||
util.prompt("\nWe're all done here and you can start enjoying jrnl 2.".format(config_path))
|
util.prompt("\nWe're all done here and you can start enjoying jrnl 2.".format(config_path))
|
||||||
|
|
||||||
|
class UpgradeValidationException(Exception):
|
||||||
|
"""Raised when the contents of an upgraded journal do not match the old journal"""
|
||||||
|
pass
|
||||||
|
|
|
@ -47,6 +47,10 @@ SENTENCE_SPLITTER = re.compile(r"""
|
||||||
)""", re.UNICODE | re.VERBOSE)
|
)""", re.UNICODE | re.VERBOSE)
|
||||||
|
|
||||||
|
|
||||||
|
class UserAbort(Exception):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
def getpass(prompt="Password: "):
|
def getpass(prompt="Password: "):
|
||||||
if not TEST:
|
if not TEST:
|
||||||
return gp.getpass(bytes(prompt))
|
return gp.getpass(bytes(prompt))
|
||||||
|
|
55
poetry.lock
generated
55
poetry.lock
generated
|
@ -34,11 +34,6 @@ optional = false
|
||||||
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
|
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
|
||||||
version = "19.1.0"
|
version = "19.1.0"
|
||||||
|
|
||||||
[package.extras]
|
|
||||||
dev = ["coverage", "hypothesis", "pympler", "pytest", "six", "zope.interface", "sphinx", "pre-commit"]
|
|
||||||
docs = ["sphinx", "zope.interface"]
|
|
||||||
tests = ["coverage", "hypothesis", "pympler", "pytest", "six", "zope.interface"]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
category = "dev"
|
category = "dev"
|
||||||
description = "behave is behaviour-driven development, Python style"
|
description = "behave is behaviour-driven development, Python style"
|
||||||
|
@ -52,10 +47,6 @@ parse = ">=1.8.2"
|
||||||
parse-type = ">=0.4.2"
|
parse-type = ">=0.4.2"
|
||||||
six = ">=1.11"
|
six = ">=1.11"
|
||||||
|
|
||||||
[package.extras]
|
|
||||||
develop = ["coverage", "pytest (>=3.0)", "pytest-cov", "tox", "invoke (>=0.21.0)", "path.py (>=8.1.2)", "pycmd", "pathlib", "modernize (>=0.5)", "pylint"]
|
|
||||||
docs = ["sphinx (>=1.6)", "sphinx-bootstrap-theme (>=0.6)"]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
category = "dev"
|
category = "dev"
|
||||||
description = "The uncompromising code formatter."
|
description = "The uncompromising code formatter."
|
||||||
|
@ -70,9 +61,6 @@ attrs = ">=17.4.0"
|
||||||
click = ">=6.5"
|
click = ">=6.5"
|
||||||
toml = ">=0.9.4"
|
toml = ">=0.9.4"
|
||||||
|
|
||||||
[package.extras]
|
|
||||||
d = ["aiohttp (>=3.3.2)"]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
category = "main"
|
category = "main"
|
||||||
description = "Foreign Function Interface for Python calling C code."
|
description = "Foreign Function Interface for Python calling C code."
|
||||||
|
@ -114,13 +102,6 @@ asn1crypto = ">=0.21.0"
|
||||||
cffi = ">=1.8,<1.11.3 || >1.11.3"
|
cffi = ">=1.8,<1.11.3 || >1.11.3"
|
||||||
six = ">=1.4.1"
|
six = ">=1.4.1"
|
||||||
|
|
||||||
[package.extras]
|
|
||||||
docs = ["sphinx (>=1.6.5,<1.8.0 || >1.8.0)", "sphinx-rtd-theme"]
|
|
||||||
docstest = ["doc8", "pyenchant (>=1.6.11)", "twine (>=1.12.0)", "sphinxcontrib-spelling (>=4.0.1)"]
|
|
||||||
idna = ["idna (>=2.1)"]
|
|
||||||
pep8test = ["flake8", "flake8-import-order", "pep8-naming"]
|
|
||||||
test = ["pytest (>=3.6.0,<3.9.0 || >3.9.0,<3.9.1 || >3.9.1,<3.9.2 || >3.9.2)", "pretend", "iso8601", "pytz", "hypothesis (>=1.11.4,<3.79.2 || >3.79.2)"]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
category = "main"
|
category = "main"
|
||||||
description = "Discover and load entry points from installed packages."
|
description = "Discover and load entry points from installed packages."
|
||||||
|
@ -154,7 +135,7 @@ version = "0.17.1"
|
||||||
[[package]]
|
[[package]]
|
||||||
category = "main"
|
category = "main"
|
||||||
description = "Low-level, pure Python DBus protocol wrapper."
|
description = "Low-level, pure Python DBus protocol wrapper."
|
||||||
marker = "python_version >= \"3.3\" and python_version < \"4.0\" and sys_platform == \"linux\""
|
marker = "sys_platform == \"linux\""
|
||||||
name = "jeepney"
|
name = "jeepney"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.5"
|
python-versions = ">=3.5"
|
||||||
|
@ -171,13 +152,9 @@ version = "2.10.1"
|
||||||
[package.dependencies]
|
[package.dependencies]
|
||||||
MarkupSafe = ">=0.23"
|
MarkupSafe = ">=0.23"
|
||||||
|
|
||||||
[package.extras]
|
|
||||||
i18n = ["Babel (>=0.8)"]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
category = "main"
|
category = "main"
|
||||||
description = "Store and access your passwords safely."
|
description = "Store and access your passwords safely."
|
||||||
marker = "python_version >= \"3.3\" and python_version < \"4.0\""
|
|
||||||
name = "keyring"
|
name = "keyring"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.5"
|
python-versions = ">=3.5"
|
||||||
|
@ -188,10 +165,6 @@ entrypoints = "*"
|
||||||
pywin32-ctypes = "<0.1.0 || >0.1.0,<0.1.1 || >0.1.1"
|
pywin32-ctypes = "<0.1.0 || >0.1.0,<0.1.1 || >0.1.1"
|
||||||
secretstorage = "*"
|
secretstorage = "*"
|
||||||
|
|
||||||
[package.extras]
|
|
||||||
docs = ["sphinx", "jaraco.packaging (>=3.2)", "rst.linker (>=1.9)"]
|
|
||||||
testing = ["pytest (>=3.5,<3.7.3 || >3.7.3)", "pytest-checkdocs", "pytest-flake8", "pytest-black-multipy"]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
category = "dev"
|
category = "dev"
|
||||||
description = "Python LiveReload is an awesome tool for web developers"
|
description = "Python LiveReload is an awesome tool for web developers"
|
||||||
|
@ -215,9 +188,6 @@ version = "3.1.1"
|
||||||
[package.dependencies]
|
[package.dependencies]
|
||||||
setuptools = ">=36"
|
setuptools = ">=36"
|
||||||
|
|
||||||
[package.extras]
|
|
||||||
testing = ["coverage", "pyyaml"]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
category = "dev"
|
category = "dev"
|
||||||
description = "Safely add untrusted strings to HTML/XML markup."
|
description = "Safely add untrusted strings to HTML/XML markup."
|
||||||
|
@ -278,10 +248,6 @@ version = "0.4.2"
|
||||||
parse = ">=1.8"
|
parse = ">=1.8"
|
||||||
six = ">=1.11"
|
six = ">=1.11"
|
||||||
|
|
||||||
[package.extras]
|
|
||||||
develop = ["coverage", "pytest (>=3.0)", "pytest-cov", "tox"]
|
|
||||||
docs = ["sphinx (>=1.2)"]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
category = "main"
|
category = "main"
|
||||||
description = "Parse human-readable date/time text."
|
description = "Parse human-readable date/time text."
|
||||||
|
@ -301,11 +267,6 @@ optional = false
|
||||||
python-versions = "*"
|
python-versions = "*"
|
||||||
version = "1.7.1"
|
version = "1.7.1"
|
||||||
|
|
||||||
[package.extras]
|
|
||||||
argon2 = ["argon2-cffi (>=16.2)"]
|
|
||||||
bcrypt = ["bcrypt (>=3.1.0)"]
|
|
||||||
totp = ["cryptography"]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
category = "dev"
|
category = "dev"
|
||||||
description = "Python style guide checker"
|
description = "Python style guide checker"
|
||||||
|
@ -352,7 +313,7 @@ version = "2019.1"
|
||||||
[[package]]
|
[[package]]
|
||||||
category = "main"
|
category = "main"
|
||||||
description = ""
|
description = ""
|
||||||
marker = "python_version >= \"3.3\" and python_version < \"4.0\" and sys_platform == \"win32\""
|
marker = "sys_platform == \"win32\""
|
||||||
name = "pywin32-ctypes"
|
name = "pywin32-ctypes"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = "*"
|
python-versions = "*"
|
||||||
|
@ -367,17 +328,17 @@ python-versions = "*"
|
||||||
version = "0.26"
|
version = "0.26"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
category = "dev"
|
category = "main"
|
||||||
description = "YAML parser and emitter for Python"
|
description = "YAML parser and emitter for Python"
|
||||||
name = "pyyaml"
|
name = "pyyaml"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = "*"
|
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
|
||||||
version = "5.1.1"
|
version = "5.1.2"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
category = "main"
|
category = "main"
|
||||||
description = "Python bindings to FreeDesktop.org Secret Service API"
|
description = "Python bindings to FreeDesktop.org Secret Service API"
|
||||||
marker = "python_version >= \"3.3\" and python_version < \"4.0\" and sys_platform == \"linux\""
|
marker = "sys_platform == \"linux\""
|
||||||
name = "secretstorage"
|
name = "secretstorage"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.5"
|
python-versions = ">=3.5"
|
||||||
|
@ -423,7 +384,7 @@ version = "1.5.1"
|
||||||
pytz = "*"
|
pytz = "*"
|
||||||
|
|
||||||
[metadata]
|
[metadata]
|
||||||
content-hash = "dfea1af4681213904e1a1a226754c6ca97ffe666c75b9772b0dd30c27525e0f6"
|
content-hash = "9896cf59c7552b6ad95219ee5555c7445a3fab39c2e4f4c6f3d991a36635e44b"
|
||||||
python-versions = "^3.7"
|
python-versions = "^3.7"
|
||||||
|
|
||||||
[metadata.hashes]
|
[metadata.hashes]
|
||||||
|
@ -460,7 +421,7 @@ python-dateutil = ["7e6584c74aeed623791615e26efd690f29817a27c73085b78e4bad02493d
|
||||||
pytz = ["303879e36b721603cc54604edcac9d20401bdbe31e1e4fdee5b9f98d5d31dfda", "d747dd3d23d77ef44c6a3526e274af6efeb0a6f1afd5a69ba4d5be4098c8e141"]
|
pytz = ["303879e36b721603cc54604edcac9d20401bdbe31e1e4fdee5b9f98d5d31dfda", "d747dd3d23d77ef44c6a3526e274af6efeb0a6f1afd5a69ba4d5be4098c8e141"]
|
||||||
pywin32-ctypes = ["24ffc3b341d457d48e8922352130cf2644024a4ff09762a2261fd34c36ee5942", "9dc2d991b3479cc2df15930958b674a48a227d5361d413827a4cfd0b5876fc98"]
|
pywin32-ctypes = ["24ffc3b341d457d48e8922352130cf2644024a4ff09762a2261fd34c36ee5942", "9dc2d991b3479cc2df15930958b674a48a227d5361d413827a4cfd0b5876fc98"]
|
||||||
pyxdg = ["1948ff8e2db02156c0cccd2529b43c0cff56ebaa71f5f021bbd755bc1419190e", "fe2928d3f532ed32b39c32a482b54136fe766d19936afc96c8f00645f9da1a06"]
|
pyxdg = ["1948ff8e2db02156c0cccd2529b43c0cff56ebaa71f5f021bbd755bc1419190e", "fe2928d3f532ed32b39c32a482b54136fe766d19936afc96c8f00645f9da1a06"]
|
||||||
pyyaml = ["57acc1d8533cbe51f6662a55434f0dbecfa2b9eaf115bede8f6fd00115a0c0d3", "588c94b3d16b76cfed8e0be54932e5729cc185caffaa5a451e7ad2f7ed8b4043", "68c8dd247f29f9a0d09375c9c6b8fdc64b60810ebf07ba4cdd64ceee3a58c7b7", "70d9818f1c9cd5c48bb87804f2efc8692f1023dac7f1a1a5c61d454043c1d265", "86a93cccd50f8c125286e637328ff4eef108400dd7089b46a7be3445eecfa391", "a0f329125a926876f647c9fa0ef32801587a12328b4a3c741270464e3e4fa778", "a3c252ab0fa1bb0d5a3f6449a4826732f3eb6c0270925548cac342bc9b22c225", "b4bb4d3f5e232425e25dda21c070ce05168a786ac9eda43768ab7f3ac2770955", "cd0618c5ba5bda5f4039b9398bb7fb6a317bb8298218c3de25c47c4740e4b95e", "ceacb9e5f8474dcf45b940578591c7f3d960e82f926c707788a570b51ba59190", "fe6a88094b64132c4bb3b631412e90032e8cfe9745a58370462240b8cb7553cd"]
|
pyyaml = ["0113bc0ec2ad727182326b61326afa3d1d8280ae1122493553fd6f4397f33df9", "01adf0b6c6f61bd11af6e10ca52b7d4057dd0be0343eb9283c878cf3af56aee4", "5124373960b0b3f4aa7df1707e63e9f109b5263eca5976c66e08b1c552d4eaf8", "5ca4f10adbddae56d824b2c09668e91219bb178a1eee1faa56af6f99f11bf696", "7907be34ffa3c5a32b60b95f4d95ea25361c951383a894fec31be7252b2b6f34", "7ec9b2a4ed5cad025c2278a1e6a19c011c80a3caaac804fd2d329e9cc2c287c9", "87ae4c829bb25b9fe99cf71fbb2140c448f534e24c998cc60f39ae4f94396a73", "9de9919becc9cc2ff03637872a440195ac4241c80536632fffeb6a1e25a74299", "a5a85b10e450c66b49f98846937e8cfca1db3127a9d5d1e31ca45c3d0bef4c5b", "b0997827b4f6a7c286c01c5f60384d218dca4ed7d9efa945c3e1aa623d5709ae", "b631ef96d3222e62861443cc89d6563ba3eeb816eeb96b2629345ab795e53681", "bf47c0607522fdbca6c9e817a6e81b08491de50f3766a7a0e6a5be7905961b41", "f81025eddd0327c7d4cfe9b62cf33190e1e736cc6e97502b3ec425f574b3e7a8"]
|
||||||
secretstorage = ["20c797ae48a4419f66f8d28fc221623f11fc45b6828f96bdb1ad9990acb59f92", "7a119fb52a88e398dbb22a4b3eb39b779bfbace7e4153b7bc6e5954d86282a8a"]
|
secretstorage = ["20c797ae48a4419f66f8d28fc221623f11fc45b6828f96bdb1ad9990acb59f92", "7a119fb52a88e398dbb22a4b3eb39b779bfbace7e4153b7bc6e5954d86282a8a"]
|
||||||
six = ["3350809f0555b11f552448330d0b52d5f24c91a322ea4a15ef22629740f3761c", "d16a0141ec1a18405cd4ce8b4613101da75da0e9a7aec5bdd4fa804d0e0eba73"]
|
six = ["3350809f0555b11f552448330d0b52d5f24c91a322ea4a15ef22629740f3761c", "d16a0141ec1a18405cd4ce8b4613101da75da0e9a7aec5bdd4fa804d0e0eba73"]
|
||||||
toml = ["229f81c57791a41d65e399fc06bf0848bab550a9dfd5ed66df18ce5f05e73d5c", "235682dd292d5899d361a811df37e04a8828a5b1da3115886b73cf81ebc9100e", "f1db651f9657708513243e61e6cc67d101a39bad662eaa9b5546f789338e07a3"]
|
toml = ["229f81c57791a41d65e399fc06bf0848bab550a9dfd5ed66df18ce5f05e73d5c", "235682dd292d5899d361a811df37e04a8828a5b1da3115886b73cf81ebc9100e", "f1db651f9657708513243e61e6cc67d101a39bad662eaa9b5546f789338e07a3"]
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
[tool.poetry]
|
[tool.poetry]
|
||||||
name = "jrnl"
|
name = "jrnl"
|
||||||
version = "2.0.0"
|
version = "2.1"
|
||||||
description = "Collect your thoughts and notes without leaving the command line."
|
description = "Collect your thoughts and notes without leaving the command line."
|
||||||
authors = [
|
authors = [
|
||||||
"Manuel Ebert <manuel@1450.me>",
|
"Manuel Ebert <manuel@1450.me>",
|
||||||
"Jonathan Wren",
|
"Jonathan Wren <jonathan@nowandwren.com>",
|
||||||
"Micah Ellison"
|
"Micah Ellison <micahellison@gmail.com>"
|
||||||
]
|
]
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
|
@ -24,6 +24,7 @@ tzlocal = "^1.5"
|
||||||
asteval = "^0.9.14"
|
asteval = "^0.9.14"
|
||||||
colorama = {version = "^0.4.1",platform = "win32"}
|
colorama = {version = "^0.4.1",platform = "win32"}
|
||||||
python-dateutil = "^2.8"
|
python-dateutil = "^2.8"
|
||||||
|
pyyaml = "^5.1"
|
||||||
|
|
||||||
[tool.poetry.dev-dependencies]
|
[tool.poetry.dev-dependencies]
|
||||||
behave = "^1.2"
|
behave = "^1.2"
|
||||||
|
|
Loading…
Add table
Reference in a new issue