Refactor option setting
This commit is contained in:
parent
6b164b07e3
commit
12c1f68343
3 changed files with 80 additions and 44 deletions
15
README.md
15
README.md
|
@ -3,7 +3,20 @@
|
||||||
This little script allows simple interaction between `taskwarrior` and a `jrnl` file.
|
This little script allows simple interaction between `taskwarrior` and a `jrnl` file.
|
||||||
It parses the `jrnl` file and logs accomplished tasks in `taskwarrior`.
|
It parses the `jrnl` file and logs accomplished tasks in `taskwarrior`.
|
||||||
|
|
||||||
To accomplish this it borrows a little from the [todotxt](http://todotxt.org/) syntax ---
|
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`
|
namely the idea of (A) (B) (C) prioritization and `x task done syntax`
|
||||||
(i.e. starting a line with `x ` means it represents an accomplished task).
|
(i.e. starting a line with `x ` means it represents an accomplished task).
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
Point the file to your `jrnl` file (ideally it needs to be a single file) and
|
||||||
|
set the syntax which declares a `todo` entry within it.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./open-todo-txt.py -f ~/.local/share/jrnl/journal.txt -b 'todotxt'
|
||||||
|
```
|
||||||
|
|
||||||
|
The commandline above sets the script to work on a specific `jrnl` file
|
||||||
|
and only work on entries which have exactly `todotxt` as their title.
|
||||||
|
The settings above are also the default settings of the script.
|
||||||
|
|
||||||
|
|
|
@ -9,60 +9,33 @@ import re
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
import subprocess
|
import subprocess
|
||||||
import argparse
|
import options
|
||||||
|
|
||||||
TODOTXT_FILE = "/home/marty/documents/records/todo.md"
|
|
||||||
TODO_BLOCK_TITLE = "todotxt"
|
|
||||||
|
|
||||||
parser = argparse.ArgumentParser()
|
|
||||||
parser.add_argument(
|
|
||||||
"-n", "--dryrun", help="only simulate and print changes", action="store_true"
|
|
||||||
)
|
|
||||||
parser.add_argument(
|
|
||||||
"-L",
|
|
||||||
"--nologging",
|
|
||||||
help="don't log done todo items to taskwarrior",
|
|
||||||
action="store_true",
|
|
||||||
)
|
|
||||||
args = parser.parse_args()
|
|
||||||
|
|
||||||
# set options
|
|
||||||
def is_dryrun():
|
|
||||||
if args.dryrun:
|
|
||||||
return True
|
|
||||||
return False
|
|
||||||
|
|
||||||
|
|
||||||
def is_logging_done_to_tw():
|
def get_todo_block_date(line, todo_block_title):
|
||||||
if args.nologging:
|
|
||||||
return False
|
|
||||||
return True
|
|
||||||
|
|
||||||
|
|
||||||
def get_todo_block_date(line):
|
|
||||||
result = re.search(
|
result = re.search(
|
||||||
rf"^\[(\d{{4}}-\d{{2}}-\d{{2}}).*\] ({re.escape(TODO_BLOCK_TITLE)}$)?",
|
rf"^\[(\d{{4}}-\d{{2}}-\d{{2}}).*\] ({re.escape(todo_block_title)}$)?",
|
||||||
line,
|
line,
|
||||||
)
|
)
|
||||||
# we are entering todotxt data block
|
# we are entering todotxt data block
|
||||||
if result and result[2]:
|
if result and result[2]:
|
||||||
return result[1]
|
return result[1]
|
||||||
# we are in block but not one for todotxt
|
# we enter block but not one for todotxt
|
||||||
elif result and not result[2]:
|
elif result and not result[2]:
|
||||||
return False
|
return False
|
||||||
# nothing changed, we didn't cross a date line
|
# nothing changed, we didn't cross a date line
|
||||||
return "same"
|
return "same"
|
||||||
|
|
||||||
|
|
||||||
def parse_file(fname):
|
def parse_file(options):
|
||||||
curdate = "1970-01-01"
|
fname = options.jrnl_fname
|
||||||
lines_to_delete = []
|
lines_to_delete = []
|
||||||
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
|
||||||
|
|
||||||
todo_block = get_todo_block_date(line)
|
todo_block = get_todo_block_date(line, options.todo_block_title)
|
||||||
if todo_block == False:
|
if todo_block == False:
|
||||||
continue
|
continue
|
||||||
if todo_block != "same":
|
if todo_block != "same":
|
||||||
|
@ -70,12 +43,12 @@ def parse_file(fname):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
completed_task = re.search(r"^x ((?:\([A-D]\))? ?.*)$", line)
|
completed_task = re.search(r"^x ((?:\([A-D]\))? ?.*)$", line)
|
||||||
if completed_task and is_logging_done_to_tw():
|
if completed_task and options.taskwarrior_log_done:
|
||||||
log_done_to_taskwarrior(completed_task[1], curdate)
|
log_done_to_taskwarrior(completed_task[1], curdate, options.dryrun)
|
||||||
lines_to_delete.append(line_number)
|
lines_to_delete.append(line_number)
|
||||||
|
|
||||||
if lines_to_delete:
|
if lines_to_delete:
|
||||||
delete_logged_tasks_from_file(TODOTXT_FILE, lines_to_delete)
|
delete_logged_tasks_from_file(fname, lines_to_delete, options.dryrun)
|
||||||
|
|
||||||
|
|
||||||
def get_prio_string(task_string):
|
def get_prio_string(task_string):
|
||||||
|
@ -92,7 +65,7 @@ def get_prio_string(task_string):
|
||||||
return prio_string
|
return prio_string
|
||||||
|
|
||||||
|
|
||||||
def log_done_to_taskwarrior(task_string, date):
|
def log_done_to_taskwarrior(task_string, date, dryrun):
|
||||||
overrides = ["rc.context=none", "rc.verbose=nothing", "rc.hooks=0"]
|
overrides = ["rc.context=none", "rc.verbose=nothing", "rc.hooks=0"]
|
||||||
|
|
||||||
cmd = [
|
cmd = [
|
||||||
|
@ -105,15 +78,15 @@ def log_done_to_taskwarrior(task_string, date):
|
||||||
get_prio_string(task_string),
|
get_prio_string(task_string),
|
||||||
]
|
]
|
||||||
|
|
||||||
if is_dryrun():
|
if dryrun:
|
||||||
print(cmd)
|
print(cmd)
|
||||||
return
|
return
|
||||||
|
|
||||||
subprocess.Popen(cmd)
|
subprocess.Popen(cmd)
|
||||||
|
|
||||||
|
|
||||||
def delete_logged_tasks_from_file(fname, lines):
|
def delete_logged_tasks_from_file(fname, lines, dryrun):
|
||||||
if is_dryrun():
|
if dryrun:
|
||||||
print(f"deleting lines: {lines}")
|
print(f"deleting lines: {lines}")
|
||||||
return
|
return
|
||||||
|
|
||||||
|
@ -129,5 +102,6 @@ def delete_logged_tasks_from_file(fname, lines):
|
||||||
os.rename(repl_file, fname)
|
os.rename(repl_file, fname)
|
||||||
|
|
||||||
|
|
||||||
parse_file(TODOTXT_FILE)
|
if __name__ == "__main__":
|
||||||
sys.exit(0)
|
parse_file(options.init())
|
||||||
|
sys.exit(0)
|
||||||
|
|
49
options.py
Normal file
49
options.py
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
import os
|
||||||
|
import argparse
|
||||||
|
from dataclasses import dataclass
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class Options:
|
||||||
|
jrnl_fname: str = f"{os.path.expanduser('~')}/documents/records/todo.md"
|
||||||
|
todo_block_title: str = "todotxt"
|
||||||
|
dryrun: bool = False
|
||||||
|
taskwarrior_log_done: bool = True
|
||||||
|
|
||||||
|
|
||||||
|
def init():
|
||||||
|
opt = Options()
|
||||||
|
parse_cmdline_args(opt)
|
||||||
|
print_dryrun(opt)
|
||||||
|
return opt
|
||||||
|
|
||||||
|
|
||||||
|
def print_dryrun(options):
|
||||||
|
print(options)
|
||||||
|
|
||||||
|
|
||||||
|
def parse_cmdline_args(options):
|
||||||
|
parser = argparse.ArgumentParser()
|
||||||
|
parser.add_argument(
|
||||||
|
"-n", "--dryrun", help="only simulate and print changes", action="store_true"
|
||||||
|
)
|
||||||
|
parser.add_argument("-f", "--file", help="the jrnl file to ingest")
|
||||||
|
parser.add_argument("-b", "--blocktitle", help="the jrnl file to ingest")
|
||||||
|
parser.add_argument(
|
||||||
|
"-L",
|
||||||
|
"--nologging",
|
||||||
|
help="don't log done todo items to taskwarrior",
|
||||||
|
action="store_true",
|
||||||
|
)
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
if args.dryrun:
|
||||||
|
options.dryrun = True
|
||||||
|
if args.nologging:
|
||||||
|
options.taskwarrior_log_done = False
|
||||||
|
if args.file:
|
||||||
|
options.jrnl_fname = args.file
|
||||||
|
if args.blocktitle:
|
||||||
|
options.todo_block_title = args.blocktitle
|
||||||
|
|
||||||
|
return options
|
Loading…
Reference in a new issue