Compare commits

..

No commits in common. "426925c6a775853a32c68952066f09749e7b0432" and "cb742395cc6f7fe6693ed31d15919b664644f06c" have entirely different histories.

4 changed files with 40 additions and 123 deletions

13
.gitlab-ci.yml Normal file
View file

@ -0,0 +1,13 @@
# You can override the included template(s) by including variable overrides
# SAST customization: https://docs.gitlab.com/ee/user/application_security/sast/#customizing-the-sast-settings
# Secret Detection customization: https://docs.gitlab.com/ee/user/application_security/secret_detection/#customizing-settings
# Dependency Scanning customization: https://docs.gitlab.com/ee/user/application_security/dependency_scanning/#customizing-the-dependency-scanning-settings
# Note that environment variables can be set in several places
# See https://docs.gitlab.com/ee/ci/variables/#cicd-variable-precedence
stages:
- test
sast:
stage: test
include:
- template: Security/SAST.gitlab-ci.yml

View file

@ -12,52 +12,13 @@ More specifically, it:
(marked with an empty `[ ] ` at the beginning of their line) (marked with an empty `[ ] ` at the beginning of their line)
* adds an entry for today's date if none exists yet and populates it with due/overdue tasks from `taskwarrior` * adds an entry for today's date if none exists yet and populates it with due/overdue tasks from `taskwarrior`
To accomplish this it borrows a little from the [todo.txt](http://todotxt.org/) syntax ---
namely the idea of (A) (B) (C) prioritization and `x task done syntax`
(i.e. starting a line with `x ` or `[x] ` means it represents an accomplished task).
All three of these operations *only* operate on entries which are marked with a special title (`todotxt` by default), All three of these operations *only* operate on entries which are marked with a special title (`todotxt` by default),
though this can be changed through a regex option. though this can be changed through a regex option.
That means, it is also entirely possible to have other entries (with the same date) which will simply be ignored by the script. That means, it is also entirely possible to have other entries (with the same date) which will simply be ignored by the script.
Lastly, it transfers what I call 'ideas' to `taskwarrior`. To accomplish this it borrows a little from the [todo.txt](http://todotxt.org/) syntax ---
These are small tidbits and notions I jot down during the day (hence, 'ideas') namely the idea of (A) (B) (C) prioritization and `x task done syntax`
and marked as such by starting the line either with `idea: ` or the `taskwarrior` equivalent `+idea `. (i.e. starting a line with `x ` or `[x] ` means it represents an accomplished task).
I want them transferred to `taskwarrior` so they don't get lost overall,
but they should be
a) not bound to a specific date, even when written in a specific `jrnl` entry, and
b) specifically marked as vague ideas in `taskwarrior`.
For now, they will be applied the fixed tags `+idea +maybe` in `taskwarrior` and simply
transferred date-less.
An example `jrnl` file:
```jrnl
[2021-10-30 10:16] todotxt
This is just a test entry. It shows how tasks in todo blocks are handled.
[ ] This is an incomplete task - it will be transferred directly to tw.
[x] This is a completed task - it will be logged as completed in tw.
[ ] (A) This is an incomplete task which will get assigned high priority in taskwarrior.
x This is also a completed task, as long as the x is the first thing on the line with a space behind.
x All four of these tasks will be transferred to tw, and their lines deleted from this file.
idea: This is an idea and it will be transferred to tw with corresponding tags, then deleted from this file.
This is not a task but a normal line and will remain in the file.
xAs will this,
[ ]As will this.
[ ] This will be transferred again, however.
[2021-10-29 10:16] Another entry
This is a regular jrnl entry, since it is missing the correct title.
By default it looks for `todotxt` titles,
but the title can be freely set for the script (`-b` option).
jrnlwarrior will not look for incomplete or completed tasks within this block at all.
[x] This is a completed task, but it will not be transferred to taskwarrior.
[ ] Neither will this incomplete task.
+idea This idea however *will* be transferred, since ideas are looked for in *all* entries.
```
## Usage ## Usage
@ -88,21 +49,21 @@ lines to be removed from the file and any to-do entries added to the file.
It will not change your `jrnl` file in any way. It will not change your `jrnl` file in any way.
If you want to switch off one of the three ways this script connects the two, If you want to switch off one of the three ways this script connects the two,
you can use the `-L`, `-I`, `-T`, `-D` options which turn off [*L*]ogging completed to `taskwarrior`, [*I*]nserting incomplete to `taskwarrior`, creating new `jrnl` entries for [*T*]oday's tasks, or moving hatched i[*D*]eas to `taskwarrior` respectively. you can use the `-L`, `-I`, `-T` options which turn off logging, adding, or creating entries respectively.
```bash ```bash
./jrnlwarrior.py -DIT ./jrnlwarrior.py -I -T
``` ```
The above invocation will *only* log completed tasks to `taskwarrior`. The above invocation will *only* log completed tasks to `taskwarrior`.
Adding new to-dos, ideas and creating today entries is turned off. Adding new to-dos and creating today entries is turned off.
```bash ```bash
./jrnlwarrior.py -T ./jrnlwarrior.py -T
``` ```
This will create a one-way connection to `taskwarrior`, This will create a one-way connection to `taskwarrior`,
by transferring both new and completed tasks and ideas to the program. by transferring both new and completed tasks to the program.
However, tasks to be done today will not be transferred back to this file. However, tasks to be done today will not be transferred back to this file.
## Scope ## Scope

View file

@ -8,7 +8,7 @@
import re import re
import os import os
import sys import sys
import subprocess from subprocess import Popen, PIPE, check_output
import options as opts import options as opts
import json import json
from datetime import datetime from datetime import datetime
@ -35,15 +35,11 @@ def process_file(options):
fname = options.jrnl_fname fname = options.jrnl_fname
lines_to_delete = [] lines_to_delete = []
today_exists = False today_exists = False
curdate = ""
with open(fname) as file: with open(fname) as file:
line_number = 0 line_number = 0
for line in file: for line in file:
line_number += 1 line_number += 1
if handle_idea(line, options):
lines_to_delete.append(line_number)
todo_block = get_todo_block_date(line, options.todo_block_title) todo_block = get_todo_block_date(line, options.todo_block_title)
if todo_block == False: if todo_block == False:
curdate = "" curdate = ""
@ -63,11 +59,11 @@ def process_file(options):
if is_today(curdate): if is_today(curdate):
today_exists = True today_exists = True
if lines_to_delete: if lines_to_delete:
delete_lines_from_file(fname, lines_to_delete, options.dryrun) delete_lines_from_file(fname, lines_to_delete, options.dryrun)
if not today_exists and options.taskwarrior_fill_today: if not today_exists and options.taskwarrior_fill_today:
add_today(fname, options) add_today(fname, options)
def handle_completed_tasks(line, date, options): def handle_completed_tasks(line, date, options):
@ -95,7 +91,7 @@ def log_completed_to_taskwarrior(task_string, date, options):
if options.dryrun: if options.dryrun:
print(cmd) print(cmd)
return return
subprocess.run(cmd) Popen(cmd)
def handle_open_tasks(line, date, options): def handle_open_tasks(line, date, options):
@ -123,34 +119,7 @@ def add_incomplete_to_taskwarrior(task_string, date, options):
if options.dryrun: if options.dryrun:
print(cmd) print(cmd)
return return
subprocess.run(cmd) Popen(cmd)
def handle_idea(line, options):
completed_task = re.search(
rf"^{options.regex_task_idea} (.*)",
line,
)
if completed_task and options.taskwarrior_add_ideas:
add_idea_to_taskwarrior(completed_task[1], options)
return True
return False
def add_idea_to_taskwarrior(idea_string, options):
overrides = options.taskwarrior_overrides
cmd = [
"task",
*overrides,
"add",
"+idea",
"+maybe",
idea_string,
]
if options.dryrun:
print(cmd)
return
subprocess.run(cmd)
def get_prio_string(task_string): def get_prio_string(task_string):
@ -191,23 +160,21 @@ def is_today(cur_date):
def add_today(fname, options): def add_today(fname, options):
cmd = ["task", *options.taskwarrior_overrides, "+TODAY or +OVERDUE", "export"] cmd = ["task", "+TODAY or +OVERDUE", "export"]
due_json = json.loads(subprocess.run(cmd, capture_output=True).stdout)
tasks = f"[{TODAY} 09:00] {options.todo_block_title}\n" tasks = f"[{TODAY} 09:00] {options.todo_block_title}\n"
for task in due_json: for task in json.loads(check_output(cmd)):
tasks += f"{task['description']}\n" tasks += f"{task['description']}\n"
tasks += "\n"
if options.dryrun: if options.dryrun:
print(f"\nWRITING TODAY:\n{tasks}") print(f"\nWRITING TODAY:\n{tasks}")
return return
repl_fname = fname + ".bak" repl_file = fname + ".bak"
with open(fname, "r") as read_file, open(repl_fname, "w") as write_file: with open(fname) as read_file, open(repl_file, "w") as write_file:
write_file.write(tasks) write_file.write(tasks + "\n")
write_file.write(read_file.read()) for line in read_file:
os.rename(repl_fname, fname) write_file.write(line)
os.rename(repl_file, fname)
if __name__ == "__main__": if __name__ == "__main__":

View file

@ -1,5 +1,4 @@
import os import os
import sys
import argparse import argparse
from dataclasses import dataclass, field from dataclasses import dataclass, field
from typing import List from typing import List
@ -7,15 +6,13 @@ from typing import List
@dataclass @dataclass
class Options: class Options:
jrnl_fname: str = field( # can be changed
default_factory=lambda: f"{os.environ.get('XDG_DATA_HOME', os.environ.get('HOME'))}/jrnl/journal.txt" jrnl_fname: str = f"{os.path.expanduser('~')}/documents/records/todo.md"
)
todo_block_title: str = "todotxt" todo_block_title: str = "todotxt"
dryrun: bool = False dryrun: bool = False
taskwarrior_log_completed: bool = True taskwarrior_log_completed: bool = True
taskwarrior_add_incomplete: bool = True taskwarrior_add_incomplete: bool = True
taskwarrior_fill_today: bool = True taskwarrior_fill_today: bool = True
taskwarrior_add_ideas: bool = True
# can not yet be changed # can not yet be changed
taskwarrior_overrides: List = field( taskwarrior_overrides: List = field(
@ -27,18 +24,13 @@ class Options:
) )
regex_task_completed: str = r"(?:x|\[x\])" regex_task_completed: str = r"(?:x|\[x\])"
regex_task_incomplete: str = r"\[ \]" regex_task_incomplete: str = r"\[ \]"
regex_task_idea: str = r"(?:idea:|\+idea)"
def init(): def init():
opt = Options() opt = Options()
parse_cmdline_args(opt)
parser = argparse.ArgumentParser()
create_cmdline_args(parser)
parse_cmdline_args(parser, opt)
if opt.dryrun: if opt.dryrun:
dryrun_show_options(opt) dryrun_show_options(opt)
validate_opts(opt)
return opt return opt
@ -46,7 +38,8 @@ def dryrun_show_options(options):
print(options) print(options)
def create_cmdline_args(parser): def parse_cmdline_args(options):
parser = argparse.ArgumentParser()
parser.add_argument( parser.add_argument(
"-n", "--dryrun", help="only simulate and print changes", action="store_true" "-n", "--dryrun", help="only simulate and print changes", action="store_true"
) )
@ -70,15 +63,6 @@ def create_cmdline_args(parser):
help="don't add today's todo items as entry to file", help="don't add today's todo items as entry to file",
action="store_true", action="store_true",
) )
parser.add_argument(
"-D",
"--noidea",
help="don't add ideas as maybe items to taskwarrior",
action="store_true",
)
def parse_cmdline_args(parser, options):
args = parser.parse_args() args = parser.parse_args()
if args.dryrun: if args.dryrun:
@ -87,8 +71,6 @@ def parse_cmdline_args(parser, options):
options.taskwarrior_log_completed = False options.taskwarrior_log_completed = False
if args.noincomplete: if args.noincomplete:
options.taskwarrior_add_incomplete = False options.taskwarrior_add_incomplete = False
if args.noidea:
options.taskwarrior_add_ideas = False
if args.nofilltoday: if args.nofilltoday:
options.taskwarrior_fill_today = False options.taskwarrior_fill_today = False
if args.file: if args.file:
@ -97,9 +79,3 @@ def parse_cmdline_args(parser, options):
options.todo_block_title = args.blocktitle options.todo_block_title = args.blocktitle
return options return options
def validate_opts(options):
if not os.path.isfile(options.jrnl_fname):
print(f"{options.jrnl_fname} does not seem to be a file. Aborting.")
sys.exit(1)