mirror of
https://github.com/jrnl-org/jrnl.git
synced 2025-05-20 21:18:32 +02:00
Merge branch 'develop' into 2.4-dayone-fixes
This commit is contained in:
commit
70e7d59396
52 changed files with 1133 additions and 442 deletions
|
@ -59,6 +59,6 @@ git config --global user.email "jrnl.bot@gmail.com"
|
|||
git config --global user.name "Jrnl Bot"
|
||||
git checkout $BRANCH
|
||||
git add "$FILENAME"
|
||||
git commit -m "Updating changelog [ci skip]"
|
||||
git commit -m "Update changelog [ci skip]"
|
||||
git push https://${GITHUB_TOKEN}@github.com/jrnl-org/jrnl.git $BRANCH
|
||||
|
||||
|
|
36
.build/gitlab-ci.yml
Normal file
36
.build/gitlab-ci.yml
Normal file
|
@ -0,0 +1,36 @@
|
|||
# This file is a template, and might need editing before it works on your project.
|
||||
# Official language image. Look for the different tagged releases at:
|
||||
# https://hub.docker.com/r/library/python/tags/
|
||||
image: python:latest
|
||||
|
||||
# Change pip's cache directory to be inside the project directory since we can
|
||||
# only cache local items.
|
||||
variables:
|
||||
PIP_CACHE_DIR: "$CI_PROJECT_DIR/.cache/pip"
|
||||
|
||||
# Pip's cache doesn't store the python packages
|
||||
# https://pip.pypa.io/en/stable/reference/pip_install/#caching
|
||||
#
|
||||
# If you want to also cache the installed packages, you have to install
|
||||
# them in a virtualenv and cache it as well.
|
||||
cache:
|
||||
paths:
|
||||
- .cache/pip
|
||||
|
||||
before_script:
|
||||
- python -V # Print out python version for debugging
|
||||
- pip install poetry
|
||||
|
||||
release:
|
||||
rules:
|
||||
- if: $RELEASE != null
|
||||
script:
|
||||
- git config --global user.email "jrnl.bot@gmail.com"
|
||||
- git config --global user.name "Jrnl Bot"
|
||||
- git checkout "$CI_COMMIT_BRANCH"
|
||||
- poetry version "$RELEASE"
|
||||
- echo __version__ = \"$RELEASE\" > jrnl/__version__.py
|
||||
- git add pyproject.toml jrnl/__version__.py
|
||||
- git commit -m "Increment version to ${RELEASE}"
|
||||
- git tag -a -m "$RELEASE" "$RELEASE"
|
||||
- git push --follow-tags "https://${GITHUB_TOKEN}@github.com/jrnl-org/jrnl.git" "$CI_COMMIT_BRANCH"
|
2
.gitattributes
vendored
Normal file
2
.gitattributes
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
*.journal text eol=lf
|
||||
*.feature text eol=lf
|
40
.github/ISSUE_TEMPLATE/bug_report.md
vendored
40
.github/ISSUE_TEMPLATE/bug_report.md
vendored
|
@ -7,20 +7,36 @@ assignees: ''
|
|||
|
||||
---
|
||||
|
||||
## Bug report
|
||||
## Bug Report
|
||||
<!--
|
||||
Hello, and thank you for reporting an issue!
|
||||
Please fill out the points below, as it will make our process much easier.
|
||||
-->
|
||||
|
||||
Hello! Thank you for reporting an issue!
|
||||
If you would fill out the below points, that would make our process a whole lot easier!
|
||||
<!-- Please tell us about your environment -->
|
||||
### Environment
|
||||
- Jrnl version: <!-- Run `jrnl -v` -->
|
||||
- Install method: <!-- How did you install jrnl? (pipx, brew, etc) -->
|
||||
- OS <!-- What is your operating system? (MacOS, Linux, Windows) -->
|
||||
|
||||
* **Please tell us about your environment:**
|
||||
- Jrnl version: (run `jrnl -v`)
|
||||
- How you installed Jrnl
|
||||
- Operating system [MacOS, Linux, Windows?]
|
||||
### Current Behavior
|
||||
<!--
|
||||
Please put a short description of what is currently happening.
|
||||
-->
|
||||
|
||||
* **What is the current behavior?**
|
||||
### Expected Behavior
|
||||
<!--
|
||||
Please write a short description of what you would expect to happen
|
||||
(instead of what is currently happening).
|
||||
-->
|
||||
|
||||
* **Please provide the steps to reproduce and if possible a minimal demo of the problem**
|
||||
### Repro Steps
|
||||
<!--
|
||||
Please provide the steps to reproduce the problem. It is important for you to
|
||||
be as precise as possible here, since more info will let us help you faster.
|
||||
-->
|
||||
|
||||
* **What is the expected behavior?**
|
||||
|
||||
* **Other information** (e.g. detailed explanation, stacktraces, related issues, suggestions how to fix, links for us to have context, eg. stackoverflow, gitter, etc)
|
||||
### Other Information
|
||||
<!-- (e.g. more detailed explanation, stacktraces, related
|
||||
issues, suggestions how to fix, links for us to have context, eg.
|
||||
stackoverflow, gitter, etc) -->
|
||||
|
|
24
.github/ISSUE_TEMPLATE/feature_request.md
vendored
24
.github/ISSUE_TEMPLATE/feature_request.md
vendored
|
@ -8,12 +8,24 @@ assignees: ''
|
|||
---
|
||||
|
||||
## Feature Request
|
||||
<!--
|
||||
Hello, and thank you for reporting an issue!
|
||||
Please fill out the points below, as it will make our process much easier.
|
||||
-->
|
||||
|
||||
Hello! Thank you for reporting an issue!
|
||||
If you would fill out the below points, that would make our process a whole lot easier!
|
||||
### Use Case/Motivation
|
||||
<!--
|
||||
What is the motivation / use case for changing the behavior?
|
||||
-->
|
||||
|
||||
* **What is the motivation / use case for changing the behavior?**
|
||||
### Example Usage
|
||||
<!--
|
||||
Please provide examples of the usage you would like to see.
|
||||
e.g `jrnl --new-flag="super cool new feature"`
|
||||
-->
|
||||
|
||||
* **Please provide examples of the usage**
|
||||
|
||||
* **Other information** (e.g. detailed explanation, stacktraces, related issues, suggestions how to fix, links for us to have context, eg. stackoverflow, gitter, etc)
|
||||
### Other information
|
||||
<!--
|
||||
Please provide any other relevant info about this request (e.g. stacktraces,
|
||||
related issues, suggestions how to fix, etc)
|
||||
-->
|
||||
|
|
39
.github/ISSUE_TEMPLATE/support_request.md
vendored
39
.github/ISSUE_TEMPLATE/support_request.md
vendored
|
@ -7,20 +7,33 @@ assignees: ''
|
|||
|
||||
---
|
||||
|
||||
## Support request
|
||||
## Support Request
|
||||
<!--
|
||||
Hello, and thank you for reporting an issue!
|
||||
Please fill out the points below, as it will make our process much easier.
|
||||
-->
|
||||
|
||||
Hello! Thank you for reporting an issue!
|
||||
If you would fill out the below points, that would make our process a whole lot easier!
|
||||
### Environment
|
||||
<!--
|
||||
Please tell us about your environment
|
||||
-->
|
||||
- Jrnl version: <!-- Run `jrnl -v` -->
|
||||
- Install method: <!-- How did you install jrnl? (pipx, brew, etc) -->
|
||||
- OS <!-- What is your operating system? (MacOS, Linux, Windows) -->
|
||||
|
||||
* **Please tell us about your environment:**
|
||||
### What are you trying to do?
|
||||
<!--
|
||||
Please write a short description of what is happening.
|
||||
-->
|
||||
|
||||
- Jrnl version: (run `jrnl -v`)
|
||||
- How you installed Jrnl
|
||||
### What have you tried?
|
||||
<!--
|
||||
Have you tried anything to fix the problem? This can help give us more
|
||||
information to help you with.
|
||||
-->
|
||||
|
||||
- Operating system [MacOS, Linux, Windows?]
|
||||
|
||||
* **What are you trying to do?**
|
||||
|
||||
* **What have you tried?**
|
||||
|
||||
* **Other information** (e.g. detailed explanation, stacktraces, related issues, suggestions how to fix, links for us to have context, eg. stackoverflow, gitter, etc)
|
||||
### Other Information
|
||||
<!--
|
||||
Is there anything else we should know that might be helpful?
|
||||
e.g. detailed explanation, stacktraces, related issues, suggestions how to fix
|
||||
-->
|
||||
|
|
39
.github/PULL_REQUEST_TEMPLATE.md
vendored
39
.github/PULL_REQUEST_TEMPLATE.md
vendored
|
@ -1,19 +1,26 @@
|
|||
<!--
|
||||
Thank you for wanting to contribute!
|
||||
|
||||
# **TEMPLATE PLEASE EDIT**
|
||||
*Thank you for wanting to contribute! Please fill out this description as well as look at the checklist!*
|
||||
Please fill out this description, and the checklist below.
|
||||
|
||||
Here are some key points to include in your description:
|
||||
- What is this new code intended to do?
|
||||
- Are there any related issues?
|
||||
- What is the motivation for this change?
|
||||
- What is an example of usage, or changes to config files? (if applicable)
|
||||
-->
|
||||
|
||||
*Short block of text containing:
|
||||
- Relevant changes in text form
|
||||
- related issues
|
||||
- Motivation (if applicable)
|
||||
- Example of usage (if applicable)
|
||||
- Example of changes to config files (if applicable)
|
||||
*
|
||||
### Checklist
|
||||
- [ ] The code change is tested and works locally.
|
||||
- [ ] Tests pass. Your PR cannot be merged unless tests pass
|
||||
- [ ] There is no commented out code in this PR.
|
||||
- [ ] Have you followed the guidelines in our Contributing document?
|
||||
- [ ] Have you checked to ensure there aren't other open [Pull Requests](../pulls) for the same update/change?
|
||||
- [ ] Have you added an explanation of what your changes do and why you'd like us to include them?
|
||||
- [ ] Have you written new tests for your core changes, as applicable?
|
||||
|
||||
- [ ] I have read the [contributing doc](https://github.com/jrnl-org/jrnl/blob/develop/CONTRIBUTING.md).
|
||||
- [ ] I have included a link to the relevant issue number.
|
||||
- [ ] I have tested this code locally.
|
||||
- [ ] I have checked to ensure there aren't other open [pull requests](../pulls)
|
||||
for the same issue.
|
||||
- [ ] I have you written new tests for these changes, as needed.
|
||||
- [ ] All tests pass.
|
||||
<!--
|
||||
NOTE: Your PR may not be reviewed if there are any failing tests. You can run
|
||||
tests locally with `make test` (see the contributing doc if you need help with
|
||||
`make`), or use our automated tests after you submit your PR.
|
||||
-->
|
||||
|
|
39
.github/lock.yml
vendored
Normal file
39
.github/lock.yml
vendored
Normal file
|
@ -0,0 +1,39 @@
|
|||
# Configuration for Lock Threads - https://github.com/dessant/lock-threads-app
|
||||
|
||||
# Number of days of inactivity before a closed issue or pull request is locked
|
||||
daysUntilLock: 90
|
||||
|
||||
# Skip issues and pull requests created before a given timestamp. Timestamp must
|
||||
# follow ISO 8601 (`YYYY-MM-DD`). Set to `false` to disable
|
||||
skipCreatedBefore: false
|
||||
|
||||
# Issues and pull requests with these labels will be ignored. Set to `[]` to disable
|
||||
exemptLabels: []
|
||||
|
||||
# Label to add before locking, such as `outdated`. Set to `false` to disable
|
||||
lockLabel: ':lock:'
|
||||
|
||||
# Comment to post before locking. Set to `false` to disable
|
||||
lockComment: >
|
||||
This thread has been automatically locked since there has not been
|
||||
any recent activity after it was closed. Please open a new issue for
|
||||
related bugs. You can link back here from your new issue to continue
|
||||
the conversation.
|
||||
|
||||
# Assign `resolved` as the reason for locking. Set to `false` to disable
|
||||
setLockReason: true
|
||||
|
||||
# Limit to only `issues` or `pulls`
|
||||
# only: issues
|
||||
|
||||
# Optionally, specify configuration settings just for `issues` or `pulls`
|
||||
# issues:
|
||||
# exemptLabels:
|
||||
# - help-wanted
|
||||
# lockLabel: outdated
|
||||
|
||||
# pulls:
|
||||
# daysUntilLock: 30
|
||||
|
||||
# Repository to extend settings from
|
||||
# _extends: repo
|
29
.travis.yml
29
.travis.yml
|
@ -129,19 +129,9 @@ jobs:
|
|||
env:
|
||||
TZ: America/Edmonton
|
||||
|
||||
# Changelog for Unreleased changes
|
||||
- stage: Update Changelog
|
||||
if: (tag IS present) OR (branch = develop AND type NOT IN (pull_request))
|
||||
install:
|
||||
- echo 'Skipping install'
|
||||
script:
|
||||
- ./.build/generate_changelog.sh
|
||||
|
||||
- stage: Deploy
|
||||
if: tag IS present
|
||||
before_deploy:
|
||||
- poetry version "$TRAVIS_TAG"
|
||||
- echo __version__ = \"$TRAVIS_TAG\" > jrnl/__version__.py
|
||||
- poetry build
|
||||
script:
|
||||
- echo "Deployment starting..."
|
||||
|
@ -150,12 +140,13 @@ jobs:
|
|||
script: poetry publish
|
||||
skip_cleanup: true
|
||||
on:
|
||||
branch: master
|
||||
tags: true
|
||||
after_deploy:
|
||||
- git config --global user.email "jrnl.bot@gmail.com"
|
||||
- git config --global user.name "Jrnl Bot"
|
||||
- git checkout master
|
||||
- git add pyproject.toml jrnl/__version__.py
|
||||
- git commit -m "Incrementing version to ${TRAVIS_TAG} [ci skip]"
|
||||
- git push https://${GITHUB_TOKEN}@github.com/jrnl-org/jrnl.git master
|
||||
all_branches: true
|
||||
|
||||
# Changelog for Unreleased changes
|
||||
- stage: Update Changelog
|
||||
if: (tag IS present) OR (branch = develop AND type NOT IN (pull_request))
|
||||
install:
|
||||
- echo 'Skipping installation step'
|
||||
script:
|
||||
- ./.build/generate_changelog.sh
|
||||
|
||||
|
|
50
CHANGELOG.md
50
CHANGELOG.md
|
@ -21,25 +21,59 @@
|
|||
|
||||
## [Unreleased](https://github.com/jrnl-org/jrnl/)
|
||||
|
||||
[Full Changelog](https://github.com/jrnl-org/jrnl/compare/v2.3.1...HEAD)
|
||||
[Full Changelog](https://github.com/jrnl-org/jrnl/compare/v2.4.2...HEAD)
|
||||
|
||||
**Implemented enhancements:**
|
||||
|
||||
- Upgrade license to GPLv3 [\#918](https://github.com/jrnl-org/jrnl/pull/918) ([wren](https://github.com/wren))
|
||||
- Speed up jrnl by 10%, improve slow imports [\#959](https://github.com/jrnl-org/jrnl/pull/959) ([wotgl](https://github.com/wotgl))
|
||||
|
||||
**Fixed bugs:**
|
||||
|
||||
- Fix title splitting logic to account for both newlines and periods [\#958](https://github.com/jrnl-org/jrnl/pull/958) ([eshrh](https://github.com/eshrh))
|
||||
- Fix editor config when an argument with a space is used [\#953](https://github.com/jrnl-org/jrnl/pull/953) ([wren](https://github.com/wren))
|
||||
- Ask for password before adding entry instead of after [\#951](https://github.com/jrnl-org/jrnl/pull/951) ([ollybritton](https://github.com/ollybritton))
|
||||
- Fix duplicate text in multiple tag search [\#948](https://github.com/jrnl-org/jrnl/pull/948) ([micahellison](https://github.com/micahellison))
|
||||
|
||||
**Build:**
|
||||
|
||||
- Update makefile to match pipeline better [\#919](https://github.com/jrnl-org/jrnl/pull/919) ([wren](https://github.com/wren))
|
||||
- Fix for hanging Windows tests on Travis [\#969](https://github.com/jrnl-org/jrnl/pull/969) ([wren](https://github.com/wren))
|
||||
- Ensure test data is always checked out with LF line endings [\#965](https://github.com/jrnl-org/jrnl/pull/965) ([micahellison](https://github.com/micahellison))
|
||||
- Update lockbot comment to encourage linking to issue [\#941](https://github.com/jrnl-org/jrnl/pull/941) ([MinchinWeb](https://github.com/MinchinWeb))
|
||||
|
||||
**Updated documentation:**
|
||||
|
||||
- Docs: editing config isn't always destructive [\#923](https://github.com/jrnl-org/jrnl/pull/923) ([Epskampie](https://github.com/Epskampie))
|
||||
- Cleaned up usage.md for clarity, formatting, and grammar. [\#956](https://github.com/jrnl-org/jrnl/pull/956) ([guydebros](https://github.com/guydebros))
|
||||
|
||||
# Changelog
|
||||
## [v2.4.2](https://pypi.org/project/jrnl/v2.4.2/) (2020-05-09)
|
||||
|
||||
## [Unreleased](https://github.com/jrnl-org/jrnl/)
|
||||
[Full Changelog](https://github.com/jrnl-org/jrnl/compare/v2.4.1...v2.4.2)
|
||||
|
||||
[Full Changelog](https://github.com/jrnl-org/jrnl/compare/v2.3.1...HEAD)
|
||||
**Fixed bugs:**
|
||||
|
||||
- Prevent filtered delete from deleting journal [\#935](https://github.com/jrnl-org/jrnl/pull/935) ([micahellison](https://github.com/micahellison))
|
||||
|
||||
**Build:**
|
||||
|
||||
- Make sure testing cleans up after itself [\#940](https://github.com/jrnl-org/jrnl/pull/940) ([wren](https://github.com/wren))
|
||||
- Allow most recent pytz version and update dependencies [\#937](https://github.com/jrnl-org/jrnl/pull/937) ([micahellison](https://github.com/micahellison))
|
||||
- Use gitlab to trigger releases in pipeline [\#947](https://github.com/jrnl-org/jrnl/pull/947) ([wren](https://github.com/wren))
|
||||
|
||||
**Updated documentation:**
|
||||
|
||||
- Change jrnl.sh GitHub new issue link to issue template chooser [\#936](https://github.com/jrnl-org/jrnl/pull/936) ([micahellison](https://github.com/micahellison))
|
||||
- Improve privacy, security, and encryption documentation \#896 [\#925](https://github.com/jrnl-org/jrnl/pull/925) ([micahellison](https://github.com/micahellison))
|
||||
|
||||
## [v2.4.1](https://pypi.org/project/jrnl/v2.4.1/) (2020-05-02)
|
||||
|
||||
[Full Changelog](https://github.com/jrnl-org/jrnl/compare/v2.4...v2.4.1)
|
||||
|
||||
**Fixed bugs:**
|
||||
|
||||
- Disable --delete due to critical bug [\#934](https://github.com/jrnl-org/jrnl/pull/934) ([wren](https://github.com/wren))
|
||||
|
||||
## [v2.4](https://pypi.org/project/jrnl/v2.4/) (2020-04-25)
|
||||
|
||||
[Full Changelog](https://github.com/jrnl-org/jrnl/compare/v2.3.1...v2.4)
|
||||
|
||||
**Implemented enhancements:**
|
||||
|
||||
|
@ -67,6 +101,8 @@
|
|||
- Update twitter buttons, contribution in footer [\#905](https://github.com/jrnl-org/jrnl/pull/905) ([wren](https://github.com/wren))
|
||||
- Change install doc guideline from pip to pipx [\#904](https://github.com/jrnl-org/jrnl/pull/904) ([micahellison](https://github.com/micahellison))
|
||||
- Update twitter buttons, contribution in footer [\#905](https://github.com/jrnl-org/jrnl/pull/905) ([wren](https://github.com/wren))
|
||||
- Clean up readme file [\#924](https://github.com/jrnl-org/jrnl/pull/924) ([wren](https://github.com/wren))
|
||||
- Clarify that editing config isn't always destructive [\#923](https://github.com/jrnl-org/jrnl/pull/923) ([Epskampie](https://github.com/Epskampie))
|
||||
|
||||
## [v2.3](https://pypi.org/project/jrnl/v2.3/) (2020-03-21)
|
||||
|
||||
|
|
|
@ -31,40 +31,20 @@ your journal.
|
|||
|
||||
If you don’t initially store the password in the keychain but decide to
|
||||
do so at a later point – or maybe want to store it on one computer but
|
||||
not on another – you can simply run `jrnl --encrypt` on an encrypted
|
||||
not on another – you can run `jrnl --encrypt` on an encrypted
|
||||
journal and use the same password again.
|
||||
|
||||
## A note on security
|
||||
|
||||
While jrnl follows best practises, true security is an illusion.
|
||||
Specifically, jrnl will leave traces in your memory and your shell
|
||||
history – it’s meant to keep journals secure in transit, for example
|
||||
when storing it on an
|
||||
[untrusted](http://techcrunch.com/2014/04/09/condoleezza-rice-joins-dropboxs-board/)
|
||||
services such as Dropbox. If you’re concerned about security, disable
|
||||
history logging for journal in your `.bashrc`:
|
||||
While `jrnl` follows best practices, total security is an illusion.
|
||||
There are a number of ways that people can at least partially
|
||||
compromise your `jrnl` data. See the [Privacy and Security](./security.md)
|
||||
documentation for more information.
|
||||
|
||||
``` sh
|
||||
HISTIGNORE="$HISTIGNORE:jrnl *"
|
||||
```
|
||||
## No password recovery
|
||||
|
||||
If you are using zsh instead of bash, you can get the same behaviour by
|
||||
adding this to your `zshrc`:
|
||||
|
||||
``` sh
|
||||
setopt HIST_IGNORE_SPACE
|
||||
alias jrnl=" jrnl"
|
||||
```
|
||||
|
||||
If you are using `fish` instead of `bash` or `zsh`, you can get the same behaviour by
|
||||
adding this to your `fish` configuration:
|
||||
|
||||
``` sh
|
||||
abbr --add jrnl " jrnl"
|
||||
```
|
||||
|
||||
To delete existing `jrnl` commands from `fish`’s history, run
|
||||
`history delete --prefix 'jrnl '`.
|
||||
There is no method to recover or reset your `jrnl` password. If you lose it,
|
||||
your data is inaccessible.
|
||||
|
||||
## Manual decryption
|
||||
|
||||
|
|
|
@ -73,7 +73,7 @@ jrnlimport () {
|
|||
!!! note
|
||||
Templates require an [external editor](./advanced.md) be configured.
|
||||
|
||||
A template is a code snippet that makes it easier to enter use repeated text
|
||||
A template is a code snippet that makes it easier to use repeated text
|
||||
each time a new journal entry is started. There are two ways you can utilize
|
||||
templates in your entries.
|
||||
|
||||
|
|
74
docs/security.md
Normal file
74
docs/security.md
Normal file
|
@ -0,0 +1,74 @@
|
|||
# Privacy and Security
|
||||
|
||||
`jrnl` is designed with privacy and security in mind, but there are some
|
||||
limitations to be aware of.
|
||||
|
||||
## Password strength
|
||||
|
||||
`jrnl` doesn't enforce password strength requirements. Short or commonly-used
|
||||
passwords can easily be circumvented by someone with basic security skills
|
||||
and access to your encrypted `jrnl` file.
|
||||
|
||||
## Shell history
|
||||
|
||||
Since you can enter entries from the command line, any tool
|
||||
that logs command line actions is a potential security risk. See
|
||||
below for how to deal with this problem in various shells.
|
||||
|
||||
### bash
|
||||
|
||||
You can disable history logging for jrnl in your `.bashrc`:
|
||||
|
||||
``` sh
|
||||
HISTIGNORE="$HISTIGNORE:jrnl *"
|
||||
```
|
||||
|
||||
### zsh
|
||||
|
||||
Disable history logging by adding this to your `zshrc`:
|
||||
|
||||
``` sh
|
||||
setopt HIST_IGNORE_SPACE
|
||||
alias jrnl=" jrnl"
|
||||
```
|
||||
|
||||
### fish
|
||||
|
||||
Add this abbreviation to your `fish` configuration to run jrnl with
|
||||
a space before it, which prevents `fish` from logging it:
|
||||
|
||||
``` sh
|
||||
abbr --add jrnl " jrnl"
|
||||
```
|
||||
|
||||
To delete existing `jrnl` commands from `fish`’s history, run
|
||||
`history delete --prefix 'jrnl '`.
|
||||
|
||||
### Windows Command Prompt
|
||||
|
||||
Windows doesn't log history to disk, but it does keep it in your command
|
||||
prompt session. Close the command prompt or press Alt+F7 to clear its
|
||||
history after journaling.
|
||||
|
||||
## Files in transit from editor to jrnl
|
||||
|
||||
When creating or editing an entry, `jrnl` uses a plain text temporary file on disk
|
||||
to give your editor access to it. `jrnl` deletes the temporary file when it
|
||||
saves the entry back to your journal.
|
||||
|
||||
If you save an entry but haven't closed your editor yet, and your computer shuts
|
||||
off or the `jrnl` process is killed, the entry remains on your disk as a
|
||||
temporary file. You can mitigate this issue by only saving with your editor
|
||||
right before closing it.
|
||||
|
||||
## Plausible deniability
|
||||
|
||||
You may be able to hide the contents of your journal behind a layer of encryption,
|
||||
but if someone has access to your configuration file, then they can figure out that
|
||||
you have a journal, where that journal file is, and when you last edited it.
|
||||
With a sufficient power imbalance, someone may be able to force you to unencrypt
|
||||
it through non-technical means.
|
||||
|
||||
## Notice any other risks?
|
||||
|
||||
Please let the maintainers know by [filing an issue on GitHub](https://github.com/jrnl-org/jrnl/issues).
|
2
docs/theme/index.html
vendored
2
docs/theme/index.html
vendored
|
@ -95,7 +95,7 @@
|
|||
</div>
|
||||
</main>
|
||||
<footer>
|
||||
jrnl is made with love by <a href="https://github.com/jrnl-org/jrnl/graphs/contributors" title="Contributors">many fabulous people</a>. If you need help, <a href="https://github.com/jrnl-org/jrnl/issues/new" title="Open a new issue on Github">submit an issue</a> on Github.
|
||||
jrnl is made with love by <a href="https://github.com/jrnl-org/jrnl/graphs/contributors" title="Contributors">many fabulous people</a>. If you need help, <a href="https://github.com/jrnl-org/jrnl/issues/new/choose" title="Open a new issue on Github">submit an issue</a> on Github.
|
||||
</footer>
|
||||
<script src="//cdnjs.cloudflare.com/ajax/libs/typed.js/2.0.10/typed.min.js"></script>
|
||||
<script>
|
||||
|
|
242
docs/usage.md
242
docs/usage.md
|
@ -1,56 +1,44 @@
|
|||
# Basic Usage
|
||||
# Basic Usage #
|
||||
|
||||
`jrnl` has two modes: **composing** and **viewing**. Basically, whenever
|
||||
you _don't_ supply any arguments that start
|
||||
with a dash or double-dash, you're in composing mode, meaning you can
|
||||
write your entry on the command line or an editor of your choice.
|
||||
`jrnl` has two modes: **composing** and **viewing**. Whenever you don't enter
|
||||
any arguments that start with a dash (`-`) or double-dash (`--`), you're in
|
||||
composing mode, meaning that you can write your entry on the command line.
|
||||
|
||||
We intentionally break a convention on command line arguments: all
|
||||
arguments starting with a _single dash_
|
||||
will _filter_ your journal before viewing
|
||||
it, and can be combined arbitrarily. Arguments with a
|
||||
_double dash_ will control how your journal
|
||||
is displayed or exported and are mutually exclusive (ie. you can only
|
||||
specify one way to display or export your journal at a time).
|
||||
We intentionally break a convention on command line arguments: all arguments
|
||||
starting with a _single dash_ (`-`) will _filter_ your journal before viewing
|
||||
it. Filter arguments can be combined arbitrarily. Arguments with a _double dash_
|
||||
(`--`) will _control_ how your journal is displayed or exported. Control
|
||||
arguments are mutually exclusive (i.e., you can only specify one way to display
|
||||
or export your journal at a time).
|
||||
|
||||
## Listing Journals
|
||||
## Composing Entries ##
|
||||
|
||||
You can list the journals accessible by jrnl
|
||||
Composing mode is entered by either starting `jrnl` without any arguments --
|
||||
which will launch an external editor -- or by just writing an entry on the
|
||||
command line:
|
||||
|
||||
```sh
|
||||
jrnl -ls
|
||||
```
|
||||
|
||||
The journals displayed correspond to those specified in the jrnl
|
||||
configuration file.
|
||||
|
||||
## Composing Entries
|
||||
|
||||
Composing mode is entered by either starting `jrnl` without any
|
||||
arguments -- which will prompt you to write an entry or launch your
|
||||
editor -- or by just writing an entry on the prompt, such as
|
||||
|
||||
```sh
|
||||
jrnl today at 3am: I just met Steve Buscemi in a bar! He looked funny.
|
||||
jrnl today at 3am: I just met Steve Buscemi in a bar! What a nice guy.
|
||||
```
|
||||
|
||||
!!! note
|
||||
Most shell contains a certain number of reserved characters, such as `#`
|
||||
and `*`. Unbalanced quotes, parenthesis, and so on will also get into
|
||||
the way of your editing.
|
||||
For writing longer entries, just enter `jrnl`
|
||||
and hit `return`. Only then enter the text of your journal entry.
|
||||
Alternatively, `use an external editor <advanced>`).
|
||||
Most shells contain a certain number of reserved characters, such as `#` and
|
||||
`*`. These characters, as well as unbalanced single or double quotation
|
||||
marks, parentheses, and others, likely will cause problems. Although
|
||||
reserved characters can be escaped using `\`, this is not ideal for
|
||||
long-form writing. The solution: first enter `jrnl` and hit `return`. You
|
||||
can then enter the text of your journal entry. Alternatively, you can [use
|
||||
an external editor](./advanced.md)).
|
||||
|
||||
You can also import an entry directly from a file
|
||||
You can also import an entry directly from a file:
|
||||
|
||||
```sh
|
||||
jrnl < my_entry.txt
|
||||
```
|
||||
|
||||
### Smart timestamps
|
||||
### Specifying Date and Time ###
|
||||
|
||||
Timestamps that work:
|
||||
If you don't specify a date and time (e.g., `jrnl finished writing letter to brother`), `jrnl` will create an entry using the current date and time. For retrospective entries, you can use a timestamp to tell `jrnl` where to put the entry. Timestamps can be entered using a variety of formats. Here are some that work:
|
||||
|
||||
- at 6am
|
||||
- yesterday
|
||||
|
@ -59,102 +47,188 @@ Timestamps that work:
|
|||
- 2 march 2012
|
||||
- 7 apr
|
||||
- 5/20/1998 at 23:42
|
||||
- 2020-05-22T15:55-04:00
|
||||
|
||||
### Starring entries
|
||||
If you don't use a timestamp, `jrnl` will create an entry using the current
|
||||
time. If you use a date only (no time), `jrnl` will use the default time
|
||||
specified in your configuration file (see [advanced usage](./advanced.md)).
|
||||
Behind the scenes, `jrnl` reorganizes entries in chronological order.
|
||||
|
||||
To mark an entry as a favourite, simply "star" it
|
||||
### Using Tags ###
|
||||
|
||||
`jrnl` supports tags. Note that because `#` is a reserved character, the default
|
||||
tag symbol is `@`. You can specify your own tag symbol in the configuration
|
||||
file. There is no limit to how many tags you can use in an entry. To use tags,
|
||||
simply preface the desired tag with the symbol:
|
||||
|
||||
```sh
|
||||
jrnl Had a wonderful day at the @beach with @Tom and @Anna.
|
||||
```
|
||||
|
||||
Although you can use capitals while tagging an entry, searches by tag are
|
||||
case-insensitive.
|
||||
|
||||
### Starring Entries ###
|
||||
|
||||
To mark an entry as a favorite, simply "star" it using an asterisk (`*`):
|
||||
|
||||
```sh
|
||||
jrnl last sunday *: Best day of my life.
|
||||
```
|
||||
|
||||
If you don't want to add a date (ie. your entry will be dated as now),
|
||||
The following options are equivalent:
|
||||
If you don't want to add a date (i.e., you want the date to be entered as
|
||||
_now_), the following options are equivalent:
|
||||
|
||||
- `jrnl *: Best day of my life.`
|
||||
- `jrnl *Best day of my life.`
|
||||
- `jrnl Best day of my life.*`
|
||||
|
||||
!!! note
|
||||
Just make sure that the asterisk sign is **not** surrounded by
|
||||
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).
|
||||
!!! note Make sure that the asterisk (`*`) is **not** surrounded by whitespaces.
|
||||
`jrnl Best day of my life! *` will not work because the `*` character has a
|
||||
special meaning in most shells.
|
||||
|
||||
## Viewing
|
||||
## Viewing Entries ##
|
||||
|
||||
`jrnl` can display entries in a variety of ways. Entries are filtered using commands preceded by a single dash (`-`). Type `jrnl -h` for a list of
|
||||
commands.
|
||||
|
||||
It is possible to see all entries by entering `jrnl -until today`. However, in
|
||||
most cases you will likely want to use a filter to see specific entries that
|
||||
meet certain criteria. `jrnl` provides several filtering commands, prefaced by a
|
||||
single dash (`-`), that allow you to find exactly what you're looking for. For
|
||||
example,
|
||||
|
||||
```sh
|
||||
jrnl -n 10
|
||||
```
|
||||
|
||||
will list you the ten latest entries (if you're lazy, `jrnl -10` will do
|
||||
the same),
|
||||
lists the ten most recent entries. `jrnl -10` is even more concise and works the
|
||||
same way. If you want to see all of the entries you wrote from the beginning of
|
||||
last year until the end of this past March, you would enter
|
||||
|
||||
```sh
|
||||
jrnl -from "last year" -until march
|
||||
```
|
||||
|
||||
everything that happened from the start of last year to the start of
|
||||
last march. To only see your favourite entries, use
|
||||
Filter criteria that use more than one word require surrounding quotes (`""`).
|
||||
|
||||
### Text Search ###
|
||||
|
||||
The `-contains` command displays all entries containing a specific string. This
|
||||
may be helpful when you're searching for entries and you can't remember if you
|
||||
tagged any words when you wrote them.
|
||||
|
||||
You may realize that you use a word a lot and want to turn it into a tag in all
|
||||
of your previous entries.
|
||||
|
||||
```sh
|
||||
jrnl -starred
|
||||
jrnl -contains "dogs" --edit
|
||||
```
|
||||
|
||||
## Using Tags
|
||||
opens your external editor so that you can add a tag symbol (`@` by default) to
|
||||
all instances of the word "dogs."
|
||||
|
||||
Keep track of people, projects or locations, by tagging them with an `@`
|
||||
in your entries
|
||||
### Filtering by Tag ###
|
||||
|
||||
```sh
|
||||
jrnl Had a wonderful day on the @beach with @Tom and @Anna.
|
||||
```
|
||||
|
||||
You can filter your journal entries just like this:
|
||||
You can filter your journal entries by tag. For example,
|
||||
|
||||
```sh
|
||||
jrnl @pinkie @WorldDomination
|
||||
```
|
||||
|
||||
Will print all entries in which either `@pinkie` or `@WorldDomination`
|
||||
occurred.
|
||||
displays all entries in which either `@pinkie` or `@WorldDomination`
|
||||
occurred. Tag filters can be combined with other filters:
|
||||
|
||||
```sh
|
||||
jrnl -n 5 -and @pinkie @WorldDomination
|
||||
jrnl -n 5 @pinkie -and @WorldDomination
|
||||
```
|
||||
|
||||
the last five entries containing both `@pinkie` **and** `@worldDomination`.
|
||||
You can change which symbols you'd like to use for tagging in the
|
||||
configuration.
|
||||
displays the last five entries containing _both_ `@pinkie` _and_
|
||||
`@worldDomination`. You can change which symbols you'd like to use for tagging
|
||||
in the configuration.
|
||||
|
||||
!!! note
|
||||
`jrnl @pinkie @WorldDomination` will switch to viewing mode because
|
||||
although **no** command line arguments are given, all the input strings
|
||||
look like tags - _jrnl_ will assume you want to filter by tag.
|
||||
Entering `jrnl @pinkie @WorldDomination` will display entries in which both
|
||||
tags are present because, although no command line arguments are given, all
|
||||
of the input strings look like tags. `jrnl` will assume you want to filter
|
||||
by tag, rather than create a new entry that consists only of tags.
|
||||
|
||||
## Editing older entries
|
||||
### Viewing Starred Entries ###
|
||||
|
||||
You can edit selected entries after you wrote them. This is particularly
|
||||
useful when your journal file is encrypted. To use this feature, you need
|
||||
to have an editor configured in your journal configuration file (see
|
||||
`advanced usage <advanced>`)
|
||||
To display only your favorite (starred) entries, enter
|
||||
|
||||
```sh
|
||||
jrnl -starred
|
||||
```
|
||||
|
||||
## Editing Entries ##
|
||||
|
||||
You can edit entries after writing them. This is particularly useful when your
|
||||
journal file is encrypted. To use this feature, you need to have an external
|
||||
editor configured in your configuration file. You can also edit only the entries
|
||||
that match specific search criteria. For example,
|
||||
|
||||
```sh
|
||||
jrnl -until 1950 @texas -and @history --edit
|
||||
```
|
||||
|
||||
Will open your editor with all entries tagged with `@texas` and
|
||||
`@history` before 1950. You can make any changes to them you want; after
|
||||
you save the file and close the editor, your journal will be updated.
|
||||
opens your external editor displaying all entries tagged with `@texas` and
|
||||
`@history` that were written before 1950. After making changes, save and close
|
||||
the file, and only those entries will be modified (and encrypted, if
|
||||
applicable).
|
||||
|
||||
Of course, if you are using multiple journals, you can also edit e.g.
|
||||
the latest entry of your work journal with `jrnl work -n 1 --edit`. In
|
||||
any case, this will bring up your editor and save (and, if applicable,
|
||||
encrypt) your edited journal after you save and exit the editor.
|
||||
|
||||
You can also use this feature for deleting entries from your journal
|
||||
If you are using multiple journals, it's easy to edit specific entries from
|
||||
specific journals. Simply prefix the filter string with the name of the journal.
|
||||
For example,
|
||||
|
||||
```sh
|
||||
jrnl @texas -until 'june 2012' --edit
|
||||
jrnl work -n 1 --edit
|
||||
```
|
||||
|
||||
Just select all text, press delete, and everything is gone...
|
||||
opens the most recent entry in the 'work' journal in your external editor.
|
||||
|
||||
## Deleting Entries ##
|
||||
|
||||
The `--delete` command opens an interactive interface for deleting entries. The
|
||||
date and title of each entry in the journal are presented one at a time, and you
|
||||
can choose whether to keep or delete each entry.
|
||||
|
||||
If no filters are specified, `jrnl` will ask you to keep or delete each entry in
|
||||
the entire journal, one by one. If there are a lot of entries in the journal, it
|
||||
may be more efficient to filter entries before passing the `--delete` command.
|
||||
|
||||
Here's an example. Say you have a journal into which you've imported the last 12
|
||||
years of blog posts. You use the `@book` tag a lot, and for some reason you want
|
||||
to delete some, but not all, of the entries in which you used that tag, but only
|
||||
the ones you wrote at some point in 2004 or earlier. You're not sure which
|
||||
entries you want to keep, and you want to look through them before deciding.
|
||||
This is what you might enter:
|
||||
|
||||
```sh
|
||||
jrnl -to 2004 @book --delete
|
||||
```
|
||||
|
||||
`jrnl` will show you only the relevant entries, and you can choose the ones you
|
||||
want to delete.
|
||||
|
||||
You may want to delete _all_ of the entries containing `@book` that you wrote in
|
||||
2004 or earlier. If there are dozens or hundreds, the easiest way would be to
|
||||
use an external editor. Open an editor with the entries you want to delete...
|
||||
|
||||
```sh
|
||||
jrnl -to 2004 @book --edit
|
||||
```
|
||||
|
||||
...select everything, delete it, save and close, and all of those entries are
|
||||
removed from the journal.
|
||||
|
||||
## Listing Journals ##
|
||||
|
||||
To list all of your journals:
|
||||
|
||||
```sh
|
||||
jrnl -ls
|
||||
```
|
||||
|
||||
The journals displayed correspond to those specified in the `jrnl` configuration
|
||||
file.
|
||||
|
|
|
@ -26,6 +26,18 @@ Feature: Basic reading and writing to a journal
|
|||
| There is a blank line above this.
|
||||
"""
|
||||
|
||||
Scenario: Multiline entry with punctuation
|
||||
Given we use the config "basic.yaml"
|
||||
When we run "jrnl This is. the title\\n This is the second line"
|
||||
and we run "jrnl -n 1"
|
||||
Then the output should contain "This is. the title"
|
||||
|
||||
Scenario: Single line entry with punctuation
|
||||
Given we use the config "basic.yaml"
|
||||
When we run "jrnl This is. the title"
|
||||
and we run "jrnl -n 1"
|
||||
Then the output should contain "| the title"
|
||||
|
||||
Scenario: Writing an entry from command line
|
||||
Given we use the config "basic.yaml"
|
||||
When we run "jrnl 23 july 2013: A cold and stormy day. I ate crisps on the sofa."
|
||||
|
@ -33,12 +45,20 @@ Feature: Basic reading and writing to a journal
|
|||
When we run "jrnl -n 1"
|
||||
Then the output should contain "2013-07-23 09:00 A cold and stormy day."
|
||||
|
||||
@skip_win
|
||||
Scenario: Writing an empty entry from the editor
|
||||
Given we use the config "editor.yaml"
|
||||
When we open the editor and enter nothing
|
||||
Then we should see the message "[Nothing saved to file]"
|
||||
|
||||
Scenario: Sending an argument with spaces to the editor should work
|
||||
Given we use the config "editor-args.yaml"
|
||||
When we open the editor and enter "lorem ipsum"
|
||||
Then the editor should have been called with 5 arguments
|
||||
And one editor argument should be "vim"
|
||||
And one editor argument should be "-f"
|
||||
And one editor argument should be "-c"
|
||||
And one editor argument should match "'?setf markdown'?"
|
||||
|
||||
Scenario: Writing an empty entry from the command line
|
||||
Given we use the config "basic.yaml"
|
||||
When we run "jrnl" and enter nothing
|
||||
|
|
12
features/data/configs/deletion_filters.yaml
Normal file
12
features/data/configs/deletion_filters.yaml
Normal file
|
@ -0,0 +1,12 @@
|
|||
default_hour: 9
|
||||
default_minute: 0
|
||||
editor: ""
|
||||
encrypt: false
|
||||
highlight: true
|
||||
journals:
|
||||
default: features/journals/deletion_filters.journal
|
||||
linewrap: 80
|
||||
tagsymbols: "@"
|
||||
template: false
|
||||
timeformat: "%Y-%m-%d %H:%M"
|
||||
indent_character: "|"
|
12
features/data/configs/editor-args.yaml
Normal file
12
features/data/configs/editor-args.yaml
Normal file
|
@ -0,0 +1,12 @@
|
|||
default_hour: 9
|
||||
default_minute: 0
|
||||
editor: vim -f -c 'setf markdown'
|
||||
encrypt: false
|
||||
highlight: true
|
||||
journals:
|
||||
default: features/journals/simple.journal
|
||||
linewrap: 80
|
||||
tagsymbols: "@"
|
||||
template: false
|
||||
timeformat: "%Y-%m-%d %H:%M"
|
||||
indent_character: "|"
|
14
features/data/journals/deletion_filters.journal
Normal file
14
features/data/journals/deletion_filters.journal
Normal file
|
@ -0,0 +1,14 @@
|
|||
[2019-10-01 08:00] It's just another day in October.
|
||||
Not much to write about.
|
||||
|
||||
[2020-01-01 08:00] Happy New Year!
|
||||
So this is the New Year. @holidays
|
||||
|
||||
[2020-03-01 08:00] It's just another day in March.
|
||||
A stick, a stone, it's the end of the road.
|
||||
|
||||
[2020-05-01 09:00] Happy May Day!
|
||||
@holidays @springtime Several holidays fall on this date.
|
||||
|
||||
[2020-05-02 12:10] Writing tests. *
|
||||
@springtime They will help prevent bugs.
|
|
@ -1,5 +1,4 @@
|
|||
Feature: Delete entries from journal
|
||||
|
||||
Scenario: --delete flag allows deletion of single entry
|
||||
Given we use the config "deletion.yaml"
|
||||
When we run "jrnl -n 1"
|
||||
|
@ -18,3 +17,133 @@ Feature: Delete entries from journal
|
|||
"""
|
||||
2019-10-29 11:11 Second entry.
|
||||
"""
|
||||
|
||||
Scenario: Backing out of interactive delete does not change journal
|
||||
Given we use the config "deletion.yaml"
|
||||
When we run "jrnl --delete -n 1" and enter
|
||||
"""
|
||||
N
|
||||
"""
|
||||
Then the journal should have 3 entries
|
||||
And the journal should contain "[2019-10-29 11:11] First entry."
|
||||
And the journal should contain "[2019-10-29 11:11] Second entry."
|
||||
And the journal should contain "[2019-10-29 11:13] Third entry."
|
||||
|
||||
Scenario: --delete flag with nonsense input deletes nothing (issue #932)
|
||||
Given we use the config "deletion.yaml"
|
||||
When we run "jrnl --delete asdfasdf"
|
||||
When we run "jrnl -n 1"
|
||||
Then the output should contain
|
||||
"""
|
||||
2019-10-29 11:13 Third entry.
|
||||
"""
|
||||
And the journal should have 3 entries
|
||||
|
||||
Scenario: --delete flag with tag only deletes tagged entries
|
||||
Given we use the config "deletion_filters.yaml"
|
||||
When we run "jrnl --delete @holidays" and enter
|
||||
"""
|
||||
Y
|
||||
Y
|
||||
"""
|
||||
Then the journal should have 3 entries
|
||||
Then the journal should contain "[2019-10-01 08:00] It's just another day in October."
|
||||
and the journal should contain "[2020-03-01 08:00] It's just another day in March."
|
||||
and the journal should contain "[2020-05-02 12:10] Writing tests."
|
||||
|
||||
Scenario: --delete flag with multiple tags deletes all entries matching any of the tags
|
||||
Given we use the config "deletion_filters.yaml"
|
||||
When we run "jrnl --delete @holidays @springtime" and enter
|
||||
"""
|
||||
Y
|
||||
Y
|
||||
Y
|
||||
"""
|
||||
Then the journal should contain "[2019-10-01 08:00] It's just another day in October."
|
||||
and the journal should not contain "[2020-01-01 08:00] Happy New Year!"
|
||||
and the journal should contain "[2020-03-01 08:00] It's just another day in March."
|
||||
and the journal should not contain "[2020-05-01 09:00] Happy May Day!"
|
||||
and the journal should not contain "[2020-05-02 12:10] Writing tests. *"
|
||||
and the journal should have 2 entries
|
||||
|
||||
Scenario: --delete flag with -and and tags only deletes boolean AND of tagged entries
|
||||
Given we use the config "deletion_filters.yaml"
|
||||
When we run "jrnl --delete -and @holidays @springtime" and enter
|
||||
"""
|
||||
Y
|
||||
"""
|
||||
Then the journal should contain "[2019-10-01 08:00] It's just another day in October."
|
||||
and the journal should contain "[2020-01-01 08:00] Happy New Year!"
|
||||
and the journal should contain "[2020-03-01 08:00] It's just another day in March."
|
||||
and the journal should not contain "[2020-05-01 09:00] Happy May Day!"
|
||||
and the journal should contain "[2020-05-02 12:10] Writing tests. *"
|
||||
and the journal should have 4 entries
|
||||
|
||||
Scenario: --delete flag with -not does not delete entries with -not tag
|
||||
Given we use the config "deletion_filters.yaml"
|
||||
When we run "jrnl --delete @holidays -not @springtime" and enter
|
||||
"""
|
||||
Y
|
||||
"""
|
||||
Then the journal should contain "[2019-10-01 08:00] It's just another day in October."
|
||||
and the journal should not contain "[2020-01-01 08:00] Happy New Year!"
|
||||
and the journal should contain "[2020-03-01 08:00] It's just another day in March."
|
||||
and the journal should contain "[2020-05-01 09:00] Happy May Day!"
|
||||
and the journal should contain "[2020-05-02 12:10] Writing tests. *"
|
||||
and the journal should have 4 entries
|
||||
|
||||
Scenario: --delete flag with -from only deletes entries since a specified date
|
||||
Given we use the config "deletion_filters.yaml"
|
||||
When we run "jrnl --delete -from 2020-01-02" and enter
|
||||
"""
|
||||
Y
|
||||
Y
|
||||
Y
|
||||
"""
|
||||
Then the journal should contain "[2019-10-01 08:00] It's just another day in October."
|
||||
and the journal should contain "[2020-01-01 08:00] Happy New Year!"
|
||||
and the journal should not contain "[2020-03-01 08:00] It's just another day in March."
|
||||
and the journal should not contain "[2020-05-01 09:00] Happy May Day!"
|
||||
and the journal should not contain "[2020-05-02 12:10] Writing tests."
|
||||
and the journal should have 2 entries
|
||||
|
||||
Scenario: --delete flag with -to only deletes entries up to specified date
|
||||
Given we use the config "deletion_filters.yaml"
|
||||
When we run "jrnl --delete -to 2020-01-02" and enter
|
||||
"""
|
||||
Y
|
||||
Y
|
||||
"""
|
||||
Then the journal should not contain "[2019-10-01 08:00] It's just another day in October."
|
||||
and the journal should not contain "[2020-01-01 08:00] Happy New Year!"
|
||||
and the journal should contain "[2020-03-01 08:00] It's just another day in March."
|
||||
and the journal should contain "[2020-05-01 09:00] Happy May Day!"
|
||||
and the journal should contain "[2020-05-02 12:10] Writing tests."
|
||||
and the journal should have 3 entries
|
||||
|
||||
Scenario: --delete flag with -starred only deletes starred entries
|
||||
Given we use the config "deletion_filters.yaml"
|
||||
When we run "jrnl --delete -starred" and enter
|
||||
"""
|
||||
Y
|
||||
"""
|
||||
Then the journal should contain "[2019-10-01 08:00] It's just another day in October."
|
||||
and the journal should contain "[2020-01-01 08:00] Happy New Year!"
|
||||
and the journal should contain "[2020-03-01 08:00] It's just another day in March."
|
||||
and the journal should contain "[2020-05-01 09:00] Happy May Day!"
|
||||
and the journal should not contain "[2020-05-02 12:10] Writing tests. *"
|
||||
and the journal should have 4 entries
|
||||
|
||||
Scenario: --delete flag with -contains only entries containing expression
|
||||
Given we use the config "deletion_filters.yaml"
|
||||
When we run "jrnl --delete -contains happy" and enter
|
||||
"""
|
||||
Y
|
||||
Y
|
||||
"""
|
||||
Then the journal should contain "[2019-10-01 08:00] It's just another day in October."
|
||||
and the journal should not contain "[2020-01-01 08:00] Happy New Year!"
|
||||
and the journal should contain "[2020-03-01 08:00] It's just another day in March."
|
||||
and the journal should not contain "[2020-05-01 09:00] Happy May Day!"
|
||||
and the journal should contain "[2020-05-02 12:10] Writing tests. *"
|
||||
and the journal should have 3 entries
|
||||
|
|
|
@ -55,3 +55,27 @@
|
|||
Then the config for journal "simple" should have "encrypt" set to "bool:True"
|
||||
When we run "jrnl simple -n 1"
|
||||
Then the output should contain "2013-06-10 15:40 Life is good"
|
||||
|
||||
Scenario: Encrypt journal with no keyring backend and do not store in keyring
|
||||
Given we use the config "basic.yaml"
|
||||
When we disable the keychain
|
||||
and we run "jrnl test entry"
|
||||
and we run "jrnl --encrypt" and enter
|
||||
"""
|
||||
password
|
||||
password
|
||||
n
|
||||
"""
|
||||
Then we should get no error
|
||||
|
||||
Scenario: Encrypt journal with no keyring backend and do store in keyring
|
||||
Given we use the config "basic.yaml"
|
||||
When we disable the keychain
|
||||
and we run "jrnl test entry"
|
||||
and we run "jrnl --encrypt" and enter
|
||||
"""
|
||||
password
|
||||
password
|
||||
y
|
||||
"""
|
||||
Then we should get no error
|
||||
|
|
|
@ -1,8 +1,15 @@
|
|||
import shutil
|
||||
import os
|
||||
import shutil
|
||||
import sys
|
||||
|
||||
|
||||
def clean_all_working_dirs():
|
||||
for folder in ("configs", "journals", "cache"):
|
||||
working_dir = os.path.join("features", folder)
|
||||
if os.path.exists(working_dir):
|
||||
shutil.rmtree(working_dir)
|
||||
|
||||
|
||||
def before_feature(context, feature):
|
||||
# add "skip" tag
|
||||
# https://stackoverflow.com/a/42721605/4276230
|
||||
|
@ -18,10 +25,7 @@ def before_feature(context, feature):
|
|||
def before_scenario(context, scenario):
|
||||
"""Before each scenario, backup all config and journal test data."""
|
||||
# Clean up in case something went wrong
|
||||
for folder in ("configs", "journals"):
|
||||
working_dir = os.path.join("features", folder)
|
||||
if os.path.exists(working_dir):
|
||||
shutil.rmtree(working_dir)
|
||||
clean_all_working_dirs()
|
||||
|
||||
for folder in ("configs", "journals"):
|
||||
original = os.path.join("features", "data", folder)
|
||||
|
@ -48,7 +52,4 @@ def before_scenario(context, scenario):
|
|||
|
||||
def after_scenario(context, scenario):
|
||||
"""After each scenario, restore all test data and remove working_dirs."""
|
||||
for folder in ("configs", "journals"):
|
||||
working_dir = os.path.join("features", folder)
|
||||
if os.path.exists(working_dir):
|
||||
shutil.rmtree(working_dir)
|
||||
clean_all_working_dirs()
|
||||
|
|
|
@ -122,10 +122,16 @@ Feature: Exporting a Journal
|
|||
|
||||
Scenario: Export to yaml
|
||||
Given we use the config "tags.yaml"
|
||||
And we created a directory named "exported_journal"
|
||||
When we run "jrnl --export yaml -o exported_journal"
|
||||
Then "exported_journal" should contain the files ["2013-04-09_i-have-an-idea.md", "2013-06-10_i-met-with-dan.md"]
|
||||
And the content of exported yaml "exported_journal/2013-04-09_i-have-an-idea.md" should be
|
||||
And we create cache directory "exported_journal"
|
||||
When we run "jrnl --export yaml -o {cache_dir}" with cache directory "exported_journal"
|
||||
Then cache directory "exported_journal" should contain the files
|
||||
"""
|
||||
[
|
||||
"2013-04-09_i-have-an-idea.md",
|
||||
"2013-06-10_i-met-with-dan.md"
|
||||
]
|
||||
"""
|
||||
And the content of file "2013-04-09_i-have-an-idea.md" in cache directory "exported_journal" should be
|
||||
"""
|
||||
title: I have an @idea:
|
||||
date: 2013-04-09 15:39
|
||||
|
|
|
@ -76,30 +76,30 @@ Feature: Zapped bugs should stay dead.
|
|||
Then the output should not contain "But I'm better."
|
||||
|
||||
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"
|
||||
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
|
||||
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."
|
||||
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"
|
||||
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"
|
||||
|
@ -112,7 +112,7 @@ Feature: Zapped bugs should stay dead.
|
|||
|
||||
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"
|
||||
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"
|
||||
|
@ -148,10 +148,17 @@ Feature: Zapped bugs should stay dead.
|
|||
# See issues #768 and #881
|
||||
Scenario: Add a blank line to YAML export is there isn't one already
|
||||
Given we use the config "deletion.yaml"
|
||||
And we created a directory named "bug768"
|
||||
When we run "jrnl --export yaml -o bug768"
|
||||
Then "bug768" should contain the files ["2019-10-29_first-entry.md", "2019-10-29_second-entry.md", "2019-10-29_third-entry.md"]
|
||||
And the content of exported yaml "bug768/2019-10-29_third-entry.md" should be
|
||||
And we create cache directory "bug768"
|
||||
When we run "jrnl --export yaml -o {cache_dir}" with cache directory "bug768"
|
||||
Then cache directory "bug768" should contain the files
|
||||
"""
|
||||
[
|
||||
"2019-10-29_first-entry.md",
|
||||
"2019-10-29_second-entry.md",
|
||||
"2019-10-29_third-entry.md"
|
||||
]
|
||||
"""
|
||||
And the content of file "2019-10-29_third-entry.md" in cache directory "bug768" should be
|
||||
"""
|
||||
title: Third entry.
|
||||
date: 2019-10-29 11:13
|
||||
|
|
|
@ -1,23 +1,24 @@
|
|||
import ast
|
||||
from collections import defaultdict
|
||||
import os
|
||||
from pathlib import Path
|
||||
import re
|
||||
import shlex
|
||||
import sys
|
||||
import time
|
||||
from unittest.mock import patch
|
||||
|
||||
from behave import given, when, then
|
||||
from jrnl import cli, install, Journal, util, plugins
|
||||
from jrnl import __version__
|
||||
from collections import defaultdict
|
||||
import keyring
|
||||
import toml
|
||||
import yaml
|
||||
|
||||
from behave import given, then, when
|
||||
from jrnl import Journal, __version__, cli, install, plugins, util
|
||||
|
||||
try:
|
||||
import parsedatetime.parsedatetime_consts as pdt
|
||||
except ImportError:
|
||||
import parsedatetime as pdt
|
||||
import time
|
||||
import os
|
||||
import ast
|
||||
import yaml
|
||||
import keyring
|
||||
import shlex
|
||||
import sys
|
||||
from pathlib import Path
|
||||
import toml
|
||||
|
||||
consts = pdt.Constants(usePyICU=False)
|
||||
consts.DOWParseStyle = -1 # Prefers past weekdays
|
||||
|
@ -40,14 +41,28 @@ class TestKeyring(keyring.backend.KeyringBackend):
|
|||
self.keys[servicename][username] = None
|
||||
|
||||
|
||||
class NoKeyring(keyring.backend.KeyringBackend):
|
||||
"""A keyring that simulated an environment with no keyring backend."""
|
||||
|
||||
priority = 2
|
||||
keys = defaultdict(dict)
|
||||
|
||||
def set_password(self, servicename, username, password):
|
||||
raise keyring.errors.NoKeyringError
|
||||
|
||||
def get_password(self, servicename, username):
|
||||
raise keyring.errors.NoKeyringError
|
||||
|
||||
def delete_password(self, servicename, username):
|
||||
raise keyring.errors.NoKeyringError
|
||||
|
||||
|
||||
# set the keyring for keyring lib
|
||||
keyring.set_keyring(TestKeyring())
|
||||
|
||||
|
||||
def ushlex(command):
|
||||
if sys.version_info[0] == 3:
|
||||
return shlex.split(command)
|
||||
return map(lambda s: s.decode("UTF8"), shlex.split(command.encode("utf8")))
|
||||
return shlex.split(command, posix="win32" not in sys.platform)
|
||||
|
||||
|
||||
def read_journal(journal_name="default"):
|
||||
|
@ -87,14 +102,43 @@ def open_editor_and_enter(context, text=""):
|
|||
text = text or context.text or ""
|
||||
|
||||
def _mock_editor_function(command):
|
||||
context.editor_command = command
|
||||
tmpfile = command[-1]
|
||||
with open(tmpfile, "w+") as f:
|
||||
f.write(text)
|
||||
|
||||
return tmpfile
|
||||
|
||||
with patch("subprocess.call", side_effect=_mock_editor_function):
|
||||
run(context, "jrnl")
|
||||
# fmt: off
|
||||
# see: https://github.com/psf/black/issues/664
|
||||
with \
|
||||
patch("subprocess.call", side_effect=_mock_editor_function), \
|
||||
patch("sys.stdin.isatty", return_value=True) \
|
||||
:
|
||||
context.execute_steps('when we run "jrnl"')
|
||||
# fmt: on
|
||||
|
||||
|
||||
@then("the editor should have been called with {num} arguments")
|
||||
def count_editor_args(context, num):
|
||||
assert len(context.editor_command) == int(num)
|
||||
|
||||
|
||||
@then('one editor argument should be "{arg}"')
|
||||
def contains_editor_arg(context, arg):
|
||||
args = context.editor_command
|
||||
assert (
|
||||
arg in args and args.count(arg) == 1
|
||||
), f"\narg not in args exactly 1 time:\n{arg}\n{str(args)}"
|
||||
|
||||
|
||||
@then('one editor argument should match "{regex}"')
|
||||
def matches_editor_arg(context, regex):
|
||||
args = context.editor_command
|
||||
matches = list(filter(lambda x: re.match(regex, x), args))
|
||||
assert (
|
||||
len(matches) == 1
|
||||
), f"\nRegex didn't match exactly 1 time:\n{regex}\n{str(args)}"
|
||||
|
||||
|
||||
def _mock_getpass(inputs):
|
||||
|
@ -128,11 +172,12 @@ def run_with_input(context, command, inputs=""):
|
|||
args = ushlex(command)[1:]
|
||||
|
||||
# fmt: off
|
||||
# see: https://github.com/psf/black/issues/557
|
||||
with patch("builtins.input", side_effect=_mock_input(text)) as mock_input, \
|
||||
patch("getpass.getpass", side_effect=_mock_getpass(text)) as mock_getpass, \
|
||||
patch("sys.stdin.read", side_effect=text) as mock_read:
|
||||
|
||||
# see: https://github.com/psf/black/issues/664
|
||||
with \
|
||||
patch("builtins.input", side_effect=_mock_input(text)) as mock_input, \
|
||||
patch("getpass.getpass", side_effect=_mock_getpass(text)) as mock_getpass, \
|
||||
patch("sys.stdin.read", side_effect=text) as mock_read \
|
||||
:
|
||||
try:
|
||||
cli.run(args or [])
|
||||
context.exit_status = 0
|
||||
|
@ -151,11 +196,18 @@ def run_with_input(context, command, inputs=""):
|
|||
|
||||
|
||||
@when('we run "{command}"')
|
||||
def run(context, command):
|
||||
args = ushlex(command)[1:]
|
||||
@when('we run "{command}" with cache directory "{cache_dir}"')
|
||||
def run(context, command, cache_dir=None):
|
||||
if cache_dir is not None:
|
||||
cache_dir = os.path.join("features", "cache", cache_dir)
|
||||
command = command.format(cache_dir=cache_dir)
|
||||
|
||||
args = ushlex(command)
|
||||
|
||||
try:
|
||||
cli.run(args or None)
|
||||
context.exit_status = 0
|
||||
with patch("sys.argv", args):
|
||||
cli.run(args[1:])
|
||||
context.exit_status = 0
|
||||
except SystemExit as e:
|
||||
context.exit_status = e.code
|
||||
|
||||
|
@ -172,6 +224,11 @@ def set_keychain(context, journal, password):
|
|||
keyring.set_password("jrnl", journal, password)
|
||||
|
||||
|
||||
@when("we disable the keychain")
|
||||
def disable_keychain(context):
|
||||
keyring.core.set_keyring(NoKeyring())
|
||||
|
||||
|
||||
@then("we should get an error")
|
||||
def has_error(context):
|
||||
assert context.exit_status != 0, context.exit_status
|
||||
|
@ -257,6 +314,13 @@ def check_journal_content(context, text, journal_name="default"):
|
|||
assert text in journal, journal
|
||||
|
||||
|
||||
@then('the journal should not contain "{text}"')
|
||||
@then('journal "{journal_name}" should not contain "{text}"')
|
||||
def check_not_journal_content(context, text, journal_name="default"):
|
||||
journal = read_journal(journal_name)
|
||||
assert text not in journal, journal
|
||||
|
||||
|
||||
@then('journal "{journal_name}" should not exist')
|
||||
def journal_doesnt_exist(context, journal_name="default"):
|
||||
with open(install.CONFIG_FILE_PATH) as config_file:
|
||||
|
|
|
@ -3,7 +3,7 @@ import os
|
|||
import shutil
|
||||
from xml.etree import ElementTree
|
||||
|
||||
from behave import then, given
|
||||
from behave import given, then
|
||||
|
||||
|
||||
@then("the output should be parsable as json")
|
||||
|
@ -97,17 +97,24 @@ def assert_xml_output_tags(context, expected_tags_json_list):
|
|||
assert actual_tags == set(expected_tags), [actual_tags, set(expected_tags)]
|
||||
|
||||
|
||||
@given('we created a directory named "{dir_name}"')
|
||||
@given('we create cache directory "{dir_name}"')
|
||||
def create_directory(context, dir_name):
|
||||
if os.path.exists(dir_name):
|
||||
shutil.rmtree(dir_name)
|
||||
os.mkdir(dir_name)
|
||||
working_dir = os.path.join("features", "cache", dir_name)
|
||||
if os.path.exists(working_dir):
|
||||
shutil.rmtree(working_dir)
|
||||
os.makedirs(working_dir)
|
||||
|
||||
|
||||
@then('"{dir_name}" should contain the files {expected_files_json_list}')
|
||||
def assert_dir_contains_files(context, dir_name, expected_files_json_list):
|
||||
actual_files = os.listdir(dir_name)
|
||||
expected_files = json.loads(expected_files_json_list)
|
||||
@then('cache directory "{dir_name}" should contain the files')
|
||||
@then(
|
||||
'cache directory "{dir_name}" should contain the files {expected_files_json_list}'
|
||||
)
|
||||
def assert_dir_contains_files(context, dir_name, expected_files_json_list="[]"):
|
||||
working_dir = os.path.join("features", "cache", dir_name)
|
||||
actual_files = os.listdir(working_dir)
|
||||
|
||||
expected_files = context.text or expected_files_json_list
|
||||
expected_files = json.loads(expected_files)
|
||||
|
||||
# sort to deal with inconsistent default file ordering on different OS's
|
||||
actual_files.sort()
|
||||
|
@ -116,11 +123,12 @@ def assert_dir_contains_files(context, dir_name, expected_files_json_list):
|
|||
assert actual_files == expected_files, [actual_files, expected_files]
|
||||
|
||||
|
||||
@then('the content of exported yaml "{file_path}" should be')
|
||||
def assert_exported_yaml_file_content(context, file_path):
|
||||
@then('the content of file "{file_path}" in cache directory "{cache_dir}" should be')
|
||||
def assert_exported_yaml_file_content(context, file_path, cache_dir):
|
||||
expected_content = context.text.strip().splitlines()
|
||||
full_file_path = os.path.join("features", "cache", cache_dir, file_path)
|
||||
|
||||
with open(file_path, "r") as f:
|
||||
with open(full_file_path, "r") as f:
|
||||
actual_content = f.read().strip().splitlines()
|
||||
|
||||
for actual_line, expected_line in zip(actual_content, expected_content):
|
||||
|
|
|
@ -107,4 +107,15 @@ Feature: Tagging
|
|||
2013-06-10 15:40 I met with @dan.
|
||||
| As alway's he shared his latest @idea on how to rule the world with me.
|
||||
| inst
|
||||
"""
|
||||
"""
|
||||
|
||||
Scenario: Searching a journal for multiple tags with -and should display entries with those tags.
|
||||
Given we use the config "tags.yaml"
|
||||
When we run "jrnl -and @idea @journal"
|
||||
Then the output should be
|
||||
"""
|
||||
2013-04-09 15:39 I have an @idea:
|
||||
| (1) write a command line @journal software
|
||||
| (2) ???
|
||||
| (3) PROFIT!
|
||||
"""
|
||||
|
|
8
issue_template.md
Normal file
8
issue_template.md
Normal file
|
@ -0,0 +1,8 @@
|
|||
# Stop
|
||||
|
||||
Please don't file a blank issue.
|
||||
|
||||
Fill out one of the templates from the link below and we'll be better able to
|
||||
help you.
|
||||
|
||||
https://github.com/jrnl-org/jrnl/issues/new/choose
|
|
@ -1,24 +1,23 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
from . import Entry
|
||||
from . import Journal
|
||||
from . import time as jrnl_time
|
||||
from . import __title__ # 'jrnl'
|
||||
from . import __version__
|
||||
import os
|
||||
import re
|
||||
from datetime import datetime
|
||||
import time
|
||||
import fnmatch
|
||||
import os
|
||||
from pathlib import Path
|
||||
import plistlib
|
||||
import pytz
|
||||
import re
|
||||
import time
|
||||
import uuid
|
||||
import tzlocal
|
||||
from xml.parsers.expat import ExpatError
|
||||
import socket
|
||||
import platform
|
||||
|
||||
import pytz
|
||||
import tzlocal
|
||||
|
||||
from . import __title__, __version__, Entry, Journal
|
||||
from . import time as jrnl_time
|
||||
|
||||
|
||||
class DayOne(Journal.Journal):
|
||||
"""A special Journal handling DayOne files"""
|
||||
|
|
|
@ -1,16 +1,17 @@
|
|||
from . import util
|
||||
from .Journal import Journal, LegacyJournal
|
||||
import base64
|
||||
import hashlib
|
||||
import logging
|
||||
import os
|
||||
import sys
|
||||
|
||||
from cryptography.fernet import Fernet, InvalidToken
|
||||
from cryptography.hazmat.backends import default_backend
|
||||
from cryptography.hazmat.primitives import hashes, padding
|
||||
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
|
||||
import hashlib
|
||||
from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
|
||||
from cryptography.hazmat.backends import default_backend
|
||||
import sys
|
||||
import os
|
||||
import base64
|
||||
import logging
|
||||
|
||||
from . import util
|
||||
from .Journal import Journal, LegacyJournal
|
||||
|
||||
log = logging.getLogger()
|
||||
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
import re
|
||||
import ansiwrap
|
||||
from datetime import datetime
|
||||
from .util import split_title, colorize, highlight_tags_with_background_color
|
||||
import re
|
||||
|
||||
import ansiwrap
|
||||
|
||||
from .util import colorize, highlight_tags_with_background_color, split_title
|
||||
|
||||
|
||||
class Entry:
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
#!/usr/bin/env python
|
||||
# encoding: utf-8
|
||||
|
||||
from __future__ import absolute_import, unicode_literals
|
||||
from . import Journal
|
||||
import codecs
|
||||
import os
|
||||
import fnmatch
|
||||
import os
|
||||
|
||||
from . import Journal
|
||||
|
||||
|
||||
def get_files(journal_config):
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
from datetime import datetime
|
||||
import logging
|
||||
import os
|
||||
import sys
|
||||
import re
|
||||
import sys
|
||||
|
||||
from datetime import datetime
|
||||
from jrnl import Entry, util, time
|
||||
from jrnl import Entry, time, util
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
@ -234,8 +234,14 @@ class Journal:
|
|||
|
||||
self.entries = result
|
||||
|
||||
def delete_entries(self, entries_to_delete):
|
||||
"""Deletes specific entries from a journal."""
|
||||
for entry in entries_to_delete:
|
||||
self.entries.remove(entry)
|
||||
|
||||
def prompt_delete_entries(self):
|
||||
"""Prompts for deletion of entries in a journal."""
|
||||
"""Prompts for deletion of each of the entries in a journal.
|
||||
Returns the entries the user wishes to delete."""
|
||||
|
||||
to_delete = []
|
||||
|
||||
|
@ -248,8 +254,7 @@ class Journal:
|
|||
if ask_delete(entry):
|
||||
to_delete.append(entry)
|
||||
|
||||
self.entries = [entry for entry in self.entries if entry not in to_delete]
|
||||
self.write()
|
||||
return to_delete
|
||||
|
||||
def new_entry(self, raw, date=None, sort=True):
|
||||
"""Constructs a new entry from some raw text input.
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
#!/usr/bin/env python
|
||||
from . import cli
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
cli.run()
|
||||
|
|
|
@ -1 +1 @@
|
|||
__version__ = "v2.4"
|
||||
__version__ = "v2.4.3-beta"
|
||||
|
|
62
jrnl/cli.py
62
jrnl/cli.py
|
@ -19,17 +19,16 @@
|
|||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
"""
|
||||
|
||||
from .Journal import PlainJournal, open_journal
|
||||
from .EncryptedJournal import EncryptedJournal
|
||||
from . import util
|
||||
from . import install
|
||||
from . import plugins
|
||||
from .util import ERROR_COLOR, RESET_COLOR, UserAbort
|
||||
import jrnl
|
||||
import argparse
|
||||
import sys
|
||||
import re
|
||||
import logging
|
||||
import re
|
||||
import sys
|
||||
|
||||
import jrnl
|
||||
|
||||
from . import install, plugins, util
|
||||
from .Journal import PlainJournal, open_journal
|
||||
from .util import ERROR_COLOR, RESET_COLOR, UserAbort
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
logging.getLogger("keyring.backend").setLevel(logging.ERROR)
|
||||
|
@ -194,11 +193,14 @@ def parse_args(args=None):
|
|||
help="Opens an interactive interface for deleting entries.",
|
||||
)
|
||||
|
||||
if not args:
|
||||
args = []
|
||||
|
||||
# Handle '-123' as a shortcut for '-n 123'
|
||||
num = re.compile(r"^-(\d+)$")
|
||||
if args is None:
|
||||
args = sys.argv[1:]
|
||||
return parser.parse_args([num.sub(r"-n \1", a) for a in args])
|
||||
args = [num.sub(r"-n \1", arg) for arg in args]
|
||||
|
||||
return parser.parse_args(args)
|
||||
|
||||
|
||||
def guess_mode(args, config):
|
||||
|
@ -242,6 +244,8 @@ def guess_mode(args, config):
|
|||
|
||||
def encrypt(journal, filename=None):
|
||||
""" Encrypt into new file. If filename is not set, we encrypt the journal file itself. """
|
||||
from .EncryptedJournal import EncryptedJournal
|
||||
|
||||
journal.config["encrypt"] = True
|
||||
|
||||
new_journal = EncryptedJournal.from_journal(journal)
|
||||
|
@ -300,7 +304,11 @@ def configure_logger(debug=False):
|
|||
|
||||
|
||||
def run(manual_args=None):
|
||||
if manual_args is None:
|
||||
manual_args = sys.argv[1:]
|
||||
|
||||
args = parse_args(manual_args)
|
||||
|
||||
configure_logger(args.debug)
|
||||
if args.version:
|
||||
version_str = f"{jrnl.__title__} version {jrnl.__version__}"
|
||||
|
@ -335,6 +343,7 @@ def run(manual_args=None):
|
|||
config = util.scope_config(config, journal_name)
|
||||
|
||||
log.debug('Using journal "%s"', journal_name)
|
||||
|
||||
mode_compose, mode_export, mode_import = guess_mode(args, config)
|
||||
|
||||
# How to quit writing?
|
||||
|
@ -343,6 +352,13 @@ def run(manual_args=None):
|
|||
else:
|
||||
_exit_multiline_code = "press Ctrl+D"
|
||||
|
||||
# This is where we finally open the journal!
|
||||
try:
|
||||
journal = open_journal(journal_name, config)
|
||||
except KeyboardInterrupt:
|
||||
print("[Interrupted while opening journal]", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
if mode_compose and not args.text:
|
||||
if not sys.stdin.isatty():
|
||||
# Piping data into jrnl
|
||||
|
@ -374,13 +390,6 @@ def run(manual_args=None):
|
|||
else:
|
||||
sys.exit()
|
||||
|
||||
# This is where we finally open the journal!
|
||||
try:
|
||||
journal = open_journal(journal_name, config)
|
||||
except KeyboardInterrupt:
|
||||
print("[Interrupted while opening journal]", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
# Import mode
|
||||
if mode_import:
|
||||
plugins.get_importer(args.import_).import_(journal, args.input)
|
||||
|
@ -478,5 +487,16 @@ def run(manual_args=None):
|
|||
journal.write()
|
||||
|
||||
elif args.delete:
|
||||
journal.prompt_delete_entries()
|
||||
journal.write()
|
||||
if journal.entries:
|
||||
entries_to_delete = journal.prompt_delete_entries()
|
||||
|
||||
if entries_to_delete:
|
||||
journal.entries = old_entries
|
||||
journal.delete_entries(entries_to_delete)
|
||||
|
||||
journal.write()
|
||||
else:
|
||||
print(
|
||||
"No entries deleted, because the search returned no results.",
|
||||
file=sys.stderr,
|
||||
)
|
||||
|
|
|
@ -1,16 +1,16 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
import glob
|
||||
import os
|
||||
import xdg.BaseDirectory
|
||||
from . import util
|
||||
from . import upgrade
|
||||
from . import __version__
|
||||
from .util import UserAbort, verify_config
|
||||
import yaml
|
||||
import logging
|
||||
import os
|
||||
import sys
|
||||
|
||||
import xdg.BaseDirectory
|
||||
import yaml
|
||||
|
||||
from . import __version__, util
|
||||
from .util import UserAbort, verify_config
|
||||
|
||||
if "win32" not in sys.platform:
|
||||
# readline is not included in Windows Active Python
|
||||
import readline
|
||||
|
@ -96,20 +96,23 @@ def load_or_install_jrnl():
|
|||
log.debug("Reading configuration from file %s", config_path)
|
||||
config = util.load_config(config_path)
|
||||
|
||||
try:
|
||||
upgrade.upgrade_jrnl_if_necessary(config_path)
|
||||
except upgrade.UpgradeValidationException:
|
||||
print("Aborting upgrade.", file=sys.stderr)
|
||||
print(
|
||||
"Please tell us about this problem at the following URL:",
|
||||
file=sys.stderr,
|
||||
)
|
||||
print(
|
||||
"https://github.com/jrnl-org/jrnl/issues/new?title=UpgradeValidationException",
|
||||
file=sys.stderr,
|
||||
)
|
||||
print("Exiting.", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
if util.is_old_version(config_path):
|
||||
from . import upgrade
|
||||
|
||||
try:
|
||||
upgrade.upgrade_jrnl(config_path)
|
||||
except upgrade.UpgradeValidationException:
|
||||
print("Aborting upgrade.", file=sys.stderr)
|
||||
print(
|
||||
"Please tell us about this problem at the following URL:",
|
||||
file=sys.stderr,
|
||||
)
|
||||
print(
|
||||
"https://github.com/jrnl-org/jrnl/issues/new?title=UpgradeValidationException",
|
||||
file=sys.stderr,
|
||||
)
|
||||
print("Exiting.", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
upgrade_config(config)
|
||||
verify_config(config)
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
#!/usr/bin/env python
|
||||
# encoding: utf-8
|
||||
|
||||
from .text_exporter import TextExporter
|
||||
from .fancy_exporter import FancyExporter
|
||||
from .jrnl_importer import JRNLImporter
|
||||
from .json_exporter import JSONExporter
|
||||
from .markdown_exporter import MarkdownExporter
|
||||
from .tag_exporter import TagExporter
|
||||
from .template_exporter import __all__ as template_exporters
|
||||
from .text_exporter import TextExporter
|
||||
from .xml_exporter import XMLExporter
|
||||
from .yaml_exporter import YAMLExporter
|
||||
from .template_exporter import __all__ as template_exporters
|
||||
from .fancy_exporter import FancyExporter
|
||||
|
||||
__exporters = [
|
||||
JSONExporter,
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
#!/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
|
||||
|
||||
from .text_exporter import TextExporter
|
||||
|
||||
|
||||
class FancyExporter(TextExporter):
|
||||
"""This Exporter can convert entries and journals into text with unicode box drawing characters."""
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
#!/usr/bin/env python
|
||||
# encoding: utf-8
|
||||
|
||||
from .text_exporter import TextExporter
|
||||
import json
|
||||
|
||||
from .text_exporter import TextExporter
|
||||
from .util import get_tags_count
|
||||
|
||||
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
#!/usr/bin/env python
|
||||
# encoding: utf-8
|
||||
|
||||
from .text_exporter import TextExporter
|
||||
import re
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
from ..util import WARNING_COLOR, RESET_COLOR
|
||||
|
||||
from ..util import RESET_COLOR, WARNING_COLOR
|
||||
from .text_exporter import TextExporter
|
||||
|
||||
|
||||
class MarkdownExporter(TextExporter):
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import re
|
||||
|
||||
import yaml
|
||||
|
||||
VAR_RE = r"[_a-zA-Z][a-zA-Z0-9_]*"
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
#!/usr/bin/env python
|
||||
# encoding: utf-8
|
||||
|
||||
from .text_exporter import TextExporter
|
||||
from .template import Template
|
||||
import os
|
||||
from glob import glob
|
||||
import os
|
||||
|
||||
from .template import Template
|
||||
from .text_exporter import TextExporter
|
||||
|
||||
|
||||
class GenericTemplateExporter(TextExporter):
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
#!/usr/bin/env python
|
||||
# encoding: utf-8
|
||||
|
||||
from ..util import slugify
|
||||
import os
|
||||
from ..util import ERROR_COLOR, RESET_COLOR
|
||||
|
||||
from ..util import ERROR_COLOR, RESET_COLOR, slugify
|
||||
|
||||
|
||||
class TextExporter:
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
#!/usr/bin/env python
|
||||
# encoding: utf-8
|
||||
|
||||
from xml.dom import minidom
|
||||
|
||||
from .json_exporter import JSONExporter
|
||||
from .util import get_tags_count
|
||||
from xml.dom import minidom
|
||||
|
||||
|
||||
class XMLExporter(JSONExporter):
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
#!/usr/bin/env python
|
||||
# encoding: utf-8
|
||||
|
||||
from .text_exporter import TextExporter
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
from ..util import WARNING_COLOR, ERROR_COLOR, RESET_COLOR
|
||||
|
||||
from ..util import ERROR_COLOR, RESET_COLOR, WARNING_COLOR
|
||||
from .text_exporter import TextExporter
|
||||
|
||||
|
||||
class YAMLExporter(TextExporter):
|
||||
|
|
25
jrnl/time.py
25
jrnl/time.py
|
@ -1,18 +1,22 @@
|
|||
from datetime import datetime
|
||||
from dateutil.parser import parse as dateparse
|
||||
|
||||
try:
|
||||
import parsedatetime.parsedatetime_consts as pdt
|
||||
except ImportError:
|
||||
import parsedatetime as pdt
|
||||
|
||||
FAKE_YEAR = 9999
|
||||
DEFAULT_FUTURE = datetime(FAKE_YEAR, 12, 31, 23, 59, 59)
|
||||
DEFAULT_PAST = datetime(FAKE_YEAR, 1, 1, 0, 0)
|
||||
|
||||
consts = pdt.Constants(usePyICU=False)
|
||||
consts.DOWParseStyle = -1 # "Monday" will be either today or the last Monday
|
||||
CALENDAR = pdt.Calendar(consts)
|
||||
|
||||
def __get_pdt_calendar():
|
||||
try:
|
||||
import parsedatetime.parsedatetime_consts as pdt
|
||||
except ImportError:
|
||||
import parsedatetime as pdt
|
||||
|
||||
consts = pdt.Constants(usePyICU=False)
|
||||
consts.DOWParseStyle = -1 # "Monday" will be either today or the last Monday
|
||||
calendar = pdt.Calendar(consts)
|
||||
|
||||
return calendar
|
||||
|
||||
|
||||
def parse(
|
||||
|
@ -34,6 +38,8 @@ def parse(
|
|||
year_present = False
|
||||
while not date:
|
||||
try:
|
||||
from dateutil.parser import parse as dateparse
|
||||
|
||||
date = dateparse(date_str, default=default_date)
|
||||
if date.year == FAKE_YEAR:
|
||||
date = datetime(datetime.now().year, date.timetuple()[1:6])
|
||||
|
@ -46,7 +52,8 @@ def parse(
|
|||
y, m, d, H, M, S = default_date.timetuple()[:6]
|
||||
default_date = datetime(y, m, d - 1, H, M, S)
|
||||
else:
|
||||
date, flag = CALENDAR.parse(date_str)
|
||||
calendar = __get_pdt_calendar()
|
||||
date, flag = calendar.parse(date_str)
|
||||
|
||||
if not flag: # Oops, unparsable.
|
||||
try: # Try and parse this as a single year
|
||||
|
|
|
@ -1,11 +1,9 @@
|
|||
import os
|
||||
import sys
|
||||
|
||||
from . import __version__
|
||||
from . import Journal
|
||||
from . import util
|
||||
from . import Journal, __version__, util
|
||||
from .EncryptedJournal import EncryptedJournal
|
||||
from .util import UserAbort
|
||||
import os
|
||||
|
||||
|
||||
def backup(filename, binary=False):
|
||||
|
@ -36,12 +34,7 @@ def check_exists(path):
|
|||
return os.path.exists(path)
|
||||
|
||||
|
||||
def upgrade_jrnl_if_necessary(config_path):
|
||||
with open(config_path, "r", encoding="utf-8") as f:
|
||||
config_file = f.read()
|
||||
if not config_file.strip().startswith("{"):
|
||||
return
|
||||
|
||||
def upgrade_jrnl(config_path):
|
||||
config = util.load_config(config_path)
|
||||
|
||||
print(
|
||||
|
|
80
jrnl/util.py
80
jrnl/util.py
|
@ -1,21 +1,23 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
import sys
|
||||
import os
|
||||
import getpass as gp
|
||||
import yaml
|
||||
import logging
|
||||
import os
|
||||
import re
|
||||
import shlex
|
||||
from string import punctuation, whitespace
|
||||
import subprocess
|
||||
import sys
|
||||
import tempfile
|
||||
import textwrap
|
||||
from typing import Callable, Optional
|
||||
import unicodedata
|
||||
|
||||
import colorama
|
||||
import yaml
|
||||
|
||||
if "win32" in sys.platform:
|
||||
colorama.init()
|
||||
import re
|
||||
import tempfile
|
||||
import subprocess
|
||||
import unicodedata
|
||||
import shlex
|
||||
from string import punctuation, whitespace
|
||||
import logging
|
||||
from typing import Optional, Callable
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
@ -32,11 +34,10 @@ SENTENCE_SPLITTER = re.compile(
|
|||
[\'\u2019\"\u201D]? # an optional right quote,
|
||||
[\]\)]* # optional closing brackets and
|
||||
\s+ # a sequence of required spaces.
|
||||
| # Otherwise,
|
||||
\n # a sentence also terminates newlines.
|
||||
)""",
|
||||
re.VERBOSE,
|
||||
)
|
||||
SENTENCE_SPLITTER_ONLY_NEWLINE = re.compile("\n")
|
||||
|
||||
|
||||
class UserAbort(Exception):
|
||||
|
@ -58,9 +59,6 @@ def create_password(
|
|||
|
||||
if yesno("Do you want to store the password in your keychain?", default=True):
|
||||
set_keychain(journal_name, pw)
|
||||
else:
|
||||
set_keychain(journal_name, None)
|
||||
|
||||
return pw
|
||||
|
||||
|
||||
|
@ -106,7 +104,13 @@ def set_keychain(journal_name, password):
|
|||
except keyring.errors.PasswordDeleteError:
|
||||
pass
|
||||
else:
|
||||
keyring.set_password("jrnl", journal_name, password)
|
||||
try:
|
||||
keyring.set_password("jrnl", journal_name, password)
|
||||
except keyring.errors.NoKeyringError:
|
||||
print(
|
||||
"Keyring backend not found. Please install one of the supported backends by visiting: https://pypi.org/project/keyring/",
|
||||
file=sys.stderr,
|
||||
)
|
||||
|
||||
|
||||
def yesno(prompt, default=True):
|
||||
|
@ -122,6 +126,16 @@ def load_config(config_path):
|
|||
return yaml.load(f, Loader=yaml.FullLoader)
|
||||
|
||||
|
||||
def is_config_json(config_path):
|
||||
with open(config_path, "r", encoding="utf-8") as f:
|
||||
config_file = f.read()
|
||||
return config_file.strip().startswith("{")
|
||||
|
||||
|
||||
def is_old_version(config_path):
|
||||
return is_config_json(config_path)
|
||||
|
||||
|
||||
def scope_config(config, journal_name):
|
||||
if journal_name not in config["journals"]:
|
||||
return config
|
||||
|
@ -171,10 +185,17 @@ def get_text_from_editor(config, template=""):
|
|||
|
||||
try:
|
||||
subprocess.call(
|
||||
shlex.split(config["editor"], posix="win" not in sys.platform) + [tmpfile]
|
||||
shlex.split(config["editor"], posix="win32" not in sys.platform) + [tmpfile]
|
||||
)
|
||||
except AttributeError:
|
||||
subprocess.call(config["editor"] + [tmpfile])
|
||||
except Exception as e:
|
||||
error_msg = f"""
|
||||
{ERROR_COLOR}{str(e)}{RESET_COLOR}
|
||||
|
||||
Please check the 'editor' key in your config file for errors:
|
||||
{repr(config['editor'])}
|
||||
"""
|
||||
print(textwrap.dedent(error_msg).strip(), file=sys.stderr)
|
||||
exit(1)
|
||||
|
||||
with open(tmpfile, "r", encoding="utf-8") as f:
|
||||
raw = f.read()
|
||||
|
@ -224,14 +245,7 @@ def highlight_tags_with_background_color(entry, text, color, is_title=False):
|
|||
|
||||
config = entry.journal.config
|
||||
if config["highlight"]: # highlight tags
|
||||
if entry.journal.search_tags:
|
||||
text_fragments = []
|
||||
for tag in entry.journal.search_tags:
|
||||
text_fragments.extend(
|
||||
re.split(re.compile(f"({re.escape(tag)})", re.IGNORECASE), text)
|
||||
)
|
||||
else:
|
||||
text_fragments = re.split(entry.tag_regex(config["tagsymbols"]), text)
|
||||
text_fragments = re.split(entry.tag_regex(config["tagsymbols"]), text)
|
||||
|
||||
# Colorizing tags inside of other blocks of text
|
||||
final_text = ""
|
||||
|
@ -269,7 +283,9 @@ def slugify(string):
|
|||
|
||||
def split_title(text):
|
||||
"""Splits the first sentence off from a text."""
|
||||
punkt = SENTENCE_SPLITTER.search(text)
|
||||
if not punkt:
|
||||
return text, ""
|
||||
return text[: punkt.end()].strip(), text[punkt.end() :].strip()
|
||||
sep = SENTENCE_SPLITTER_ONLY_NEWLINE.search(text.lstrip())
|
||||
if not sep:
|
||||
sep = SENTENCE_SPLITTER.search(text)
|
||||
if not sep:
|
||||
return text, ""
|
||||
return text[: sep.end()].strip(), text[sep.end() :].strip()
|
||||
|
|
|
@ -18,6 +18,7 @@ nav:
|
|||
- Quickstart: installation.md
|
||||
- Basic Usage: usage.md
|
||||
- Encryption: encryption.md
|
||||
- Privacy and Security: security.md
|
||||
- Import and Export: export.md
|
||||
- Advanced Usage: advanced.md
|
||||
- Recipes: recipes.md
|
||||
|
|
112
poetry.lock
generated
112
poetry.lock
generated
|
@ -93,7 +93,7 @@ description = "Composable command line interface toolkit"
|
|||
name = "click"
|
||||
optional = false
|
||||
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
|
||||
version = "7.1.1"
|
||||
version = "7.1.2"
|
||||
|
||||
[[package]]
|
||||
category = "main"
|
||||
|
@ -109,7 +109,7 @@ description = "cryptography is a package which provides cryptographic recipes an
|
|||
name = "cryptography"
|
||||
optional = false
|
||||
python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*"
|
||||
version = "2.9"
|
||||
version = "2.9.2"
|
||||
|
||||
[package.dependencies]
|
||||
cffi = ">=1.8,<1.11.3 || >1.11.3"
|
||||
|
@ -164,7 +164,7 @@ description = "A very fast and expressive template engine."
|
|||
name = "jinja2"
|
||||
optional = false
|
||||
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
|
||||
version = "2.11.1"
|
||||
version = "2.11.2"
|
||||
|
||||
[package.dependencies]
|
||||
MarkupSafe = ">=0.23"
|
||||
|
@ -172,13 +172,21 @@ MarkupSafe = ">=0.23"
|
|||
[package.extras]
|
||||
i18n = ["Babel (>=0.8)"]
|
||||
|
||||
[[package]]
|
||||
category = "dev"
|
||||
description = "Lightweight pipelining: using Python functions as pipeline jobs."
|
||||
name = "joblib"
|
||||
optional = false
|
||||
python-versions = "*"
|
||||
version = "0.14.1"
|
||||
|
||||
[[package]]
|
||||
category = "main"
|
||||
description = "Store and access your passwords safely."
|
||||
name = "keyring"
|
||||
optional = false
|
||||
python-versions = ">=3.6"
|
||||
version = "21.2.0"
|
||||
version = "21.2.1"
|
||||
|
||||
[package.dependencies]
|
||||
SecretStorage = ">=3"
|
||||
|
@ -191,7 +199,7 @@ version = "*"
|
|||
|
||||
[package.extras]
|
||||
docs = ["sphinx", "jaraco.packaging (>=3.2)", "rst.linker (>=1.9)"]
|
||||
testing = ["pytest (>=3.5,<3.7.3 || >3.7.3)", "pytest-checkdocs (>=1.2.3)", "pytest-flake8", "pytest-black-multipy", "pytest-cov"]
|
||||
testing = ["pytest (>=3.5,<3.7.3 || >3.7.3)", "pytest-checkdocs (>=1.2.3)", "pytest-flake8", "pytest-black (>=0.3.7)", "pytest-cov"]
|
||||
|
||||
[[package]]
|
||||
category = "dev"
|
||||
|
@ -272,13 +280,16 @@ description = "Natural Language Toolkit"
|
|||
name = "nltk"
|
||||
optional = false
|
||||
python-versions = "*"
|
||||
version = "3.4.5"
|
||||
version = "3.5"
|
||||
|
||||
[package.dependencies]
|
||||
six = "*"
|
||||
click = "*"
|
||||
joblib = "*"
|
||||
regex = "*"
|
||||
tqdm = "*"
|
||||
|
||||
[package.extras]
|
||||
all = ["pyparsing", "scikit-learn", "python-crfsuite", "matplotlib", "scipy", "gensim", "requests", "twython", "numpy"]
|
||||
all = ["requests", "numpy", "python-crfsuite", "scikit-learn", "twython", "pyparsing", "scipy", "matplotlib", "gensim"]
|
||||
corenlp = ["requests"]
|
||||
machine_learning = ["gensim", "numpy", "python-crfsuite", "scikit-learn", "scipy"]
|
||||
plot = ["matplotlib"]
|
||||
|
@ -372,7 +383,7 @@ description = "World timezone definitions, modern and historical"
|
|||
name = "pytz"
|
||||
optional = false
|
||||
python-versions = "*"
|
||||
version = "2019.3"
|
||||
version = "2020.1"
|
||||
|
||||
[[package]]
|
||||
category = "main"
|
||||
|
@ -452,6 +463,17 @@ optional = false
|
|||
python-versions = ">= 3.5"
|
||||
version = "6.0.4"
|
||||
|
||||
[[package]]
|
||||
category = "dev"
|
||||
description = "Fast, Extensible Progress Meter"
|
||||
name = "tqdm"
|
||||
optional = false
|
||||
python-versions = ">=2.6, !=3.0.*, !=3.1.*"
|
||||
version = "4.46.0"
|
||||
|
||||
[package.extras]
|
||||
dev = ["py-make (>=0.1.0)", "twine", "argopt", "pydoc-markdown"]
|
||||
|
||||
[[package]]
|
||||
category = "dev"
|
||||
description = "a fork of Python 2 and 3 ast modules with type comment support"
|
||||
|
@ -485,7 +507,7 @@ docs = ["sphinx", "jaraco.packaging (>=3.2)", "rst.linker (>=1.9)"]
|
|||
testing = ["jaraco.itertools", "func-timeout"]
|
||||
|
||||
[metadata]
|
||||
content-hash = "128eb801852bc15aa7dcf3395a806560c0c82416c04a3435712a861081fbc46f"
|
||||
content-hash = "561dafcf089c8db70bf9cbc2a2ea96ab3727792a2cfc7590f487a11db76fa3fb"
|
||||
python-versions = ">=3.6.0, <3.9.0"
|
||||
|
||||
[metadata.files]
|
||||
|
@ -543,33 +565,33 @@ cffi = [
|
|||
{file = "cffi-1.14.0.tar.gz", hash = "sha256:2d384f4a127a15ba701207f7639d94106693b6cd64173d6c8988e2c25f3ac2b6"},
|
||||
]
|
||||
click = [
|
||||
{file = "click-7.1.1-py2.py3-none-any.whl", hash = "sha256:e345d143d80bf5ee7534056164e5e112ea5e22716bbb1ce727941f4c8b471b9a"},
|
||||
{file = "click-7.1.1.tar.gz", hash = "sha256:8a18b4ea89d8820c5d0c7da8a64b2c324b4dabb695804dbfea19b9be9d88c0cc"},
|
||||
{file = "click-7.1.2-py2.py3-none-any.whl", hash = "sha256:dacca89f4bfadd5de3d7489b7c8a566eee0d3676333fbb50030263894c38c0dc"},
|
||||
{file = "click-7.1.2.tar.gz", hash = "sha256:d2b5255c7c6349bc1bd1e59e08cd12acbbd63ce649f2588755783aa94dfb6b1a"},
|
||||
]
|
||||
colorama = [
|
||||
{file = "colorama-0.4.3-py2.py3-none-any.whl", hash = "sha256:7d73d2a99753107a36ac6b455ee49046802e59d9d076ef8e47b61499fa29afff"},
|
||||
{file = "colorama-0.4.3.tar.gz", hash = "sha256:e96da0d330793e2cb9485e9ddfd918d456036c7149416295932478192f4436a1"},
|
||||
]
|
||||
cryptography = [
|
||||
{file = "cryptography-2.9-cp27-cp27m-macosx_10_9_intel.whl", hash = "sha256:ef9a55013676907df6c9d7dd943eb1770d014f68beaa7e73250fb43c759f4585"},
|
||||
{file = "cryptography-2.9-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:2a2ad24d43398d89f92209289f15265107928f22a8d10385f70def7a698d6a02"},
|
||||
{file = "cryptography-2.9-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:95e1296e0157361fe2f5f0ed307fd31f94b0ca13372e3673fa95095a627636a1"},
|
||||
{file = "cryptography-2.9-cp27-cp27m-win32.whl", hash = "sha256:192ca04a36852a994ef21df13cca4d822adbbdc9d5009c0f96f1d2929e375d4f"},
|
||||
{file = "cryptography-2.9-cp27-cp27m-win_amd64.whl", hash = "sha256:ed1d0760c7e46436ec90834d6f10477ff09475c692ed1695329d324b2c5cd547"},
|
||||
{file = "cryptography-2.9-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:19ae795137682a9778892fb4390c07811828b173741bce91e30f899424b3934d"},
|
||||
{file = "cryptography-2.9-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:d1bf5a1a0d60c7f9a78e448adcb99aa101f3f9588b16708044638881be15d6bc"},
|
||||
{file = "cryptography-2.9-cp35-abi3-macosx_10_9_intel.whl", hash = "sha256:1b9b535d6b55936a79dbe4990b64bb16048f48747c76c29713fea8c50eca2acf"},
|
||||
{file = "cryptography-2.9-cp35-abi3-manylinux1_x86_64.whl", hash = "sha256:7a279f33a081d436e90e91d1a7c338553c04e464de1c9302311a5e7e4b746088"},
|
||||
{file = "cryptography-2.9-cp35-abi3-manylinux2010_x86_64.whl", hash = "sha256:49870684da168b90110bbaf86140d4681032c5e6a2461adc7afdd93be5634216"},
|
||||
{file = "cryptography-2.9-cp35-cp35m-win32.whl", hash = "sha256:6b91cab3841b4c7cb70e4db1697c69f036c8bc0a253edc0baa6783154f1301e4"},
|
||||
{file = "cryptography-2.9-cp35-cp35m-win_amd64.whl", hash = "sha256:587f98ce27ac4547177a0c6fe0986b8736058daffe9160dcf5f1bd411b7fbaa1"},
|
||||
{file = "cryptography-2.9-cp36-cp36m-win32.whl", hash = "sha256:cc20316e3f5a6b582fc3b029d8dc03aabeb645acfcb7fc1d9848841a33265748"},
|
||||
{file = "cryptography-2.9-cp36-cp36m-win_amd64.whl", hash = "sha256:3be7a5722d5bfe69894d3f7bbed15547b17619f3a88a318aab2e37f457524164"},
|
||||
{file = "cryptography-2.9-cp37-cp37m-win32.whl", hash = "sha256:7598974f6879a338c785c513e7c5a4329fbc58b9f6b9a6305035fca5b1076552"},
|
||||
{file = "cryptography-2.9-cp37-cp37m-win_amd64.whl", hash = "sha256:5aca6f00b2f42546b9bdf11a69f248d1881212ce5b9e2618b04935b87f6f82a1"},
|
||||
{file = "cryptography-2.9-cp38-cp38-win32.whl", hash = "sha256:9fc9da390e98cb6975eadf251b6e5fa088820141061bf041cd5c72deba1dc526"},
|
||||
{file = "cryptography-2.9-cp38-cp38-win_amd64.whl", hash = "sha256:6b744039b55988519cc183149cceb573189b3e46e16ccf6f8c46798bb767c9dc"},
|
||||
{file = "cryptography-2.9.tar.gz", hash = "sha256:0cacd3ef5c604b8e5f59bf2582c076c98a37fe206b31430d0cd08138aff0986e"},
|
||||
{file = "cryptography-2.9.2-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:daf54a4b07d67ad437ff239c8a4080cfd1cc7213df57d33c97de7b4738048d5e"},
|
||||
{file = "cryptography-2.9.2-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:3b3eba865ea2754738616f87292b7f29448aec342a7c720956f8083d252bf28b"},
|
||||
{file = "cryptography-2.9.2-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:c447cf087cf2dbddc1add6987bbe2f767ed5317adb2d08af940db517dd704365"},
|
||||
{file = "cryptography-2.9.2-cp27-cp27m-win32.whl", hash = "sha256:f118a95c7480f5be0df8afeb9a11bd199aa20afab7a96bcf20409b411a3a85f0"},
|
||||
{file = "cryptography-2.9.2-cp27-cp27m-win_amd64.whl", hash = "sha256:c4fd17d92e9d55b84707f4fd09992081ba872d1a0c610c109c18e062e06a2e55"},
|
||||
{file = "cryptography-2.9.2-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:d0d5aeaedd29be304848f1c5059074a740fa9f6f26b84c5b63e8b29e73dfc270"},
|
||||
{file = "cryptography-2.9.2-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:1e4014639d3d73fbc5ceff206049c5a9a849cefd106a49fa7aaaa25cc0ce35cf"},
|
||||
{file = "cryptography-2.9.2-cp35-abi3-macosx_10_9_x86_64.whl", hash = "sha256:96c080ae7118c10fcbe6229ab43eb8b090fccd31a09ef55f83f690d1ef619a1d"},
|
||||
{file = "cryptography-2.9.2-cp35-abi3-manylinux1_x86_64.whl", hash = "sha256:e993468c859d084d5579e2ebee101de8f5a27ce8e2159959b6673b418fd8c785"},
|
||||
{file = "cryptography-2.9.2-cp35-abi3-manylinux2010_x86_64.whl", hash = "sha256:88c881dd5a147e08d1bdcf2315c04972381d026cdb803325c03fe2b4a8ed858b"},
|
||||
{file = "cryptography-2.9.2-cp35-cp35m-win32.whl", hash = "sha256:651448cd2e3a6bc2bb76c3663785133c40d5e1a8c1a9c5429e4354201c6024ae"},
|
||||
{file = "cryptography-2.9.2-cp35-cp35m-win_amd64.whl", hash = "sha256:726086c17f94747cedbee6efa77e99ae170caebeb1116353c6cf0ab67ea6829b"},
|
||||
{file = "cryptography-2.9.2-cp36-cp36m-win32.whl", hash = "sha256:091d31c42f444c6f519485ed528d8b451d1a0c7bf30e8ca583a0cac44b8a0df6"},
|
||||
{file = "cryptography-2.9.2-cp36-cp36m-win_amd64.whl", hash = "sha256:bb1f0281887d89617b4c68e8db9a2c42b9efebf2702a3c5bf70599421a8623e3"},
|
||||
{file = "cryptography-2.9.2-cp37-cp37m-win32.whl", hash = "sha256:18452582a3c85b96014b45686af264563e3e5d99d226589f057ace56196ec78b"},
|
||||
{file = "cryptography-2.9.2-cp37-cp37m-win_amd64.whl", hash = "sha256:22e91636a51170df0ae4dcbd250d318fd28c9f491c4e50b625a49964b24fe46e"},
|
||||
{file = "cryptography-2.9.2-cp38-cp38-win32.whl", hash = "sha256:844a76bc04472e5135b909da6aed84360f522ff5dfa47f93e3dd2a0b84a89fa0"},
|
||||
{file = "cryptography-2.9.2-cp38-cp38-win_amd64.whl", hash = "sha256:1dfa985f62b137909496e7fc182dac687206d8d089dd03eaeb28ae16eec8e7d5"},
|
||||
{file = "cryptography-2.9.2.tar.gz", hash = "sha256:a0c30272fb4ddda5f5ffc1089d7405b7a71b0b0f51993cb4e5dbb4590b2fc229"},
|
||||
]
|
||||
future = [
|
||||
{file = "future-0.18.2.tar.gz", hash = "sha256:b1bead90b70cf6ec3f0710ae53a525360fa360d306a86583adc6bf83a4db537d"},
|
||||
|
@ -583,12 +605,16 @@ jeepney = [
|
|||
{file = "jeepney-0.4.3.tar.gz", hash = "sha256:3479b861cc2b6407de5188695fa1a8d57e5072d7059322469b62628869b8e36e"},
|
||||
]
|
||||
jinja2 = [
|
||||
{file = "Jinja2-2.11.1-py2.py3-none-any.whl", hash = "sha256:b0eaf100007721b5c16c1fc1eecb87409464edc10469ddc9a22a27a99123be49"},
|
||||
{file = "Jinja2-2.11.1.tar.gz", hash = "sha256:93187ffbc7808079673ef52771baa950426fd664d3aad1d0fa3e95644360e250"},
|
||||
{file = "Jinja2-2.11.2-py2.py3-none-any.whl", hash = "sha256:f0a4641d3cf955324a89c04f3d94663aa4d638abe8f733ecd3582848e1c37035"},
|
||||
{file = "Jinja2-2.11.2.tar.gz", hash = "sha256:89aab215427ef59c34ad58735269eb58b1a5808103067f7bb9d5836c651b3bb0"},
|
||||
]
|
||||
joblib = [
|
||||
{file = "joblib-0.14.1-py2.py3-none-any.whl", hash = "sha256:bdb4fd9b72915ffb49fde2229ce482dd7ae79d842ed8c2b4c932441495af1403"},
|
||||
{file = "joblib-0.14.1.tar.gz", hash = "sha256:0630eea4f5664c463f23fbf5dcfc54a2bc6168902719fa8e19daf033022786c8"},
|
||||
]
|
||||
keyring = [
|
||||
{file = "keyring-21.2.0-py3-none-any.whl", hash = "sha256:8179b1cdcdcbc221456b5b74e6b7cfa06f8dd9f239eb81892166d9223d82c5ba"},
|
||||
{file = "keyring-21.2.0.tar.gz", hash = "sha256:197fd5903901030ef7b82fe247f43cfed2c157a28e7747d1cfcf4bc5e699dd03"},
|
||||
{file = "keyring-21.2.1-py3-none-any.whl", hash = "sha256:3401234209015144a5d75701e71cb47239e552b0882313e9f51e8976f9e27843"},
|
||||
{file = "keyring-21.2.1.tar.gz", hash = "sha256:c53e0e5ccde3ad34284a40ce7976b5b3a3d6de70344c3f8ee44364cc340976ec"},
|
||||
]
|
||||
livereload = [
|
||||
{file = "livereload-2.6.1-py2.py3-none-any.whl", hash = "sha256:78d55f2c268a8823ba499305dcac64e28ddeb9a92571e12d543cd304faf5817b"},
|
||||
|
@ -630,6 +656,11 @@ markupsafe = [
|
|||
{file = "MarkupSafe-1.1.1-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:ba59edeaa2fc6114428f1637ffff42da1e311e29382d81b339c1817d37ec93c6"},
|
||||
{file = "MarkupSafe-1.1.1-cp37-cp37m-win32.whl", hash = "sha256:b00c1de48212e4cc9603895652c5c410df699856a2853135b3967591e4beebc2"},
|
||||
{file = "MarkupSafe-1.1.1-cp37-cp37m-win_amd64.whl", hash = "sha256:9bf40443012702a1d2070043cb6291650a0841ece432556f784f004937f0f32c"},
|
||||
{file = "MarkupSafe-1.1.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:6788b695d50a51edb699cb55e35487e430fa21f1ed838122d722e0ff0ac5ba15"},
|
||||
{file = "MarkupSafe-1.1.1-cp38-cp38-manylinux1_i686.whl", hash = "sha256:cdb132fc825c38e1aeec2c8aa9338310d29d337bebbd7baa06889d09a60a1fa2"},
|
||||
{file = "MarkupSafe-1.1.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:13d3144e1e340870b25e7b10b98d779608c02016d5184cfb9927a9f10c689f42"},
|
||||
{file = "MarkupSafe-1.1.1-cp38-cp38-win32.whl", hash = "sha256:596510de112c685489095da617b5bcbbac7dd6384aeebeda4df6025d0256a81b"},
|
||||
{file = "MarkupSafe-1.1.1-cp38-cp38-win_amd64.whl", hash = "sha256:e8313f01ba26fbbe36c7be1966a7b7424942f670f38e666995b88d012765b9be"},
|
||||
{file = "MarkupSafe-1.1.1.tar.gz", hash = "sha256:29872e92839765e546828bb7754a68c418d927cd064fd4708fab9fe9c8bb116b"},
|
||||
]
|
||||
mkdocs = [
|
||||
|
@ -637,8 +668,7 @@ mkdocs = [
|
|||
{file = "mkdocs-1.1.tar.gz", hash = "sha256:9243291392f59e20b655e4e46210233453faf97787c2cf72176510e868143174"},
|
||||
]
|
||||
nltk = [
|
||||
{file = "nltk-3.4.5.win32.exe", hash = "sha256:a08bdb4b8a1c13de16743068d9eb61c8c71c2e5d642e8e08205c528035843f82"},
|
||||
{file = "nltk-3.4.5.zip", hash = "sha256:bed45551259aa2101381bbdd5df37d44ca2669c5c3dad72439fa459b29137d94"},
|
||||
{file = "nltk-3.5.zip", hash = "sha256:845365449cd8c5f9731f7cb9f8bd6fd0767553b9d53af9eb1b3abf7700936b35"},
|
||||
]
|
||||
parse = [
|
||||
{file = "parse-1.15.0.tar.gz", hash = "sha256:a6d4e2c2f1fbde6717d28084a191a052950f758c0cbd83805357e6575c2b95c0"},
|
||||
|
@ -672,8 +702,8 @@ python-dateutil = [
|
|||
{file = "python_dateutil-2.8.1-py2.py3-none-any.whl", hash = "sha256:75bb3f31ea686f1197762692a9ee6a7550b59fc6ca3a1f4b5d7e32fb98e2da2a"},
|
||||
]
|
||||
pytz = [
|
||||
{file = "pytz-2019.3-py2.py3-none-any.whl", hash = "sha256:1c557d7d0e871de1f5ccd5833f60fb2550652da6be2693c1e02300743d21500d"},
|
||||
{file = "pytz-2019.3.tar.gz", hash = "sha256:b02c06db6cf09c12dd25137e563b31700d3b80fcc4ad23abb7a315f2789819be"},
|
||||
{file = "pytz-2020.1-py2.py3-none-any.whl", hash = "sha256:a494d53b6d39c3c6e44c3bec237336e14305e4f29bbf800b599253057fbb79ed"},
|
||||
{file = "pytz-2020.1.tar.gz", hash = "sha256:c35965d010ce31b23eeb663ed3cc8c906275d6be1a34393a1d73a41febf4a048"},
|
||||
]
|
||||
pywin32-ctypes = [
|
||||
{file = "pywin32-ctypes-0.2.0.tar.gz", hash = "sha256:24ffc3b341d457d48e8922352130cf2644024a4ff09762a2261fd34c36ee5942"},
|
||||
|
@ -747,6 +777,10 @@ tornado = [
|
|||
{file = "tornado-6.0.4-cp38-cp38-win_amd64.whl", hash = "sha256:c58d56003daf1b616336781b26d184023ea4af13ae143d9dda65e31e534940b9"},
|
||||
{file = "tornado-6.0.4.tar.gz", hash = "sha256:0fe2d45ba43b00a41cd73f8be321a44936dc1aba233dee979f17a042b83eb6dc"},
|
||||
]
|
||||
tqdm = [
|
||||
{file = "tqdm-4.46.0-py2.py3-none-any.whl", hash = "sha256:acdafb20f51637ca3954150d0405ff1a7edde0ff19e38fb99a80a66210d2a28f"},
|
||||
{file = "tqdm-4.46.0.tar.gz", hash = "sha256:4733c4a10d0f2a4d098d801464bdaf5240c7dadd2a7fde4ee93b0a0efd9fb25e"},
|
||||
]
|
||||
typed-ast = [
|
||||
{file = "typed_ast-1.4.1-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:73d785a950fc82dd2a25897d525d003f6378d1cb23ab305578394694202a58c3"},
|
||||
{file = "typed_ast-1.4.1-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:aaee9905aee35ba5905cfb3c62f3e83b3bec7b39413f0a7f19be4e547ea01ebb"},
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[tool.poetry]
|
||||
name = "jrnl"
|
||||
version = "v2.4"
|
||||
version = "v2.4.3-beta"
|
||||
description = "Collect your thoughts and notes without leaving the command line."
|
||||
authors = [
|
||||
"Manuel Ebert <manuel@1450.me>",
|
||||
|
@ -22,7 +22,7 @@ cryptography = "^2.7"
|
|||
passlib = "^1.7"
|
||||
parsedatetime = "^2.4"
|
||||
keyring = ">19.0, <22.0"
|
||||
pytz = "^2019.1"
|
||||
pytz = ">=2019.1, <2021.0"
|
||||
tzlocal = ">1.5, <3.0"
|
||||
asteval = "^0.9.14"
|
||||
colorama = "^0.4.1"
|
||||
|
@ -40,6 +40,15 @@ pyflakes = "^2.2.0"
|
|||
[tool.poetry.scripts]
|
||||
jrnl = 'jrnl.cli:run'
|
||||
|
||||
[tool.isort]
|
||||
multi_line_output = 3
|
||||
include_trailing_comma = true
|
||||
force_grid_wrap = 0
|
||||
use_parentheses = true
|
||||
line_length = 88
|
||||
known_first_party = ["jrnl", "behave"]
|
||||
force_sort_within_sections = true
|
||||
|
||||
[build-system]
|
||||
requires = ["poetry>=0.12"]
|
||||
build-backend = "poetry.masonry.api"
|
||||
|
|
Loading…
Add table
Reference in a new issue