diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml new file mode 100644 index 0000000..bf177e0 --- /dev/null +++ b/.gitlab-ci.yml @@ -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 + diff --git a/README.md b/README.md index acb0538..162ab38 100644 --- a/README.md +++ b/README.md @@ -12,52 +12,13 @@ More specifically, it: (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` -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), 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. -Lastly, it transfers what I call 'ideas' to `taskwarrior`. -These are small tidbits and notions I jot down during the day (hence, 'ideas') -and marked as such by starting the line either with `idea: ` or the `taskwarrior` equivalent `+idea `. -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. -``` +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). ## 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. 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 -./jrnlwarrior.py -DIT +./jrnlwarrior.py -I -T ``` 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 ./jrnlwarrior.py -T ``` 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. ## Scope diff --git a/jrnlwarrior.py b/jrnlwarrior.py index 7f206fe..546a5bf 100755 --- a/jrnlwarrior.py +++ b/jrnlwarrior.py @@ -8,7 +8,7 @@ import re import os import sys -import subprocess +from subprocess import Popen, PIPE, check_output import options as opts import json from datetime import datetime @@ -35,15 +35,11 @@ def process_file(options): fname = options.jrnl_fname lines_to_delete = [] today_exists = False - curdate = "" with open(fname) as file: line_number = 0 for line in file: 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) if todo_block == False: curdate = "" @@ -63,11 +59,11 @@ def process_file(options): if is_today(curdate): today_exists = True - if lines_to_delete: - delete_lines_from_file(fname, lines_to_delete, options.dryrun) + if lines_to_delete: + delete_lines_from_file(fname, lines_to_delete, options.dryrun) - if not today_exists and options.taskwarrior_fill_today: - add_today(fname, options) + if not today_exists and options.taskwarrior_fill_today: + add_today(fname, options) def handle_completed_tasks(line, date, options): @@ -95,7 +91,7 @@ def log_completed_to_taskwarrior(task_string, date, options): if options.dryrun: print(cmd) return - subprocess.run(cmd) + Popen(cmd) def handle_open_tasks(line, date, options): @@ -123,34 +119,7 @@ def add_incomplete_to_taskwarrior(task_string, date, options): if options.dryrun: print(cmd) return - subprocess.run(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) + Popen(cmd) def get_prio_string(task_string): @@ -191,23 +160,21 @@ def is_today(cur_date): def add_today(fname, options): - cmd = ["task", *options.taskwarrior_overrides, "+TODAY or +OVERDUE", "export"] - due_json = json.loads(subprocess.run(cmd, capture_output=True).stdout) - + cmd = ["task", "+TODAY or +OVERDUE", "export"] 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 += "\n" if options.dryrun: print(f"\nWRITING TODAY:\n{tasks}") return - repl_fname = fname + ".bak" - with open(fname, "r") as read_file, open(repl_fname, "w") as write_file: - write_file.write(tasks) - write_file.write(read_file.read()) - os.rename(repl_fname, fname) + repl_file = fname + ".bak" + with open(fname) as read_file, open(repl_file, "w") as write_file: + write_file.write(tasks + "\n") + for line in read_file: + write_file.write(line) + os.rename(repl_file, fname) if __name__ == "__main__": diff --git a/options.py b/options.py index 111242e..8f72fe2 100644 --- a/options.py +++ b/options.py @@ -1,5 +1,4 @@ import os -import sys import argparse from dataclasses import dataclass, field from typing import List @@ -7,15 +6,13 @@ from typing import List @dataclass class Options: - jrnl_fname: str = field( - default_factory=lambda: f"{os.environ.get('XDG_DATA_HOME', os.environ.get('HOME'))}/jrnl/journal.txt" - ) + # can be changed + jrnl_fname: str = f"{os.path.expanduser('~')}/documents/records/todo.md" todo_block_title: str = "todotxt" dryrun: bool = False taskwarrior_log_completed: bool = True taskwarrior_add_incomplete: bool = True taskwarrior_fill_today: bool = True - taskwarrior_add_ideas: bool = True # can not yet be changed taskwarrior_overrides: List = field( @@ -27,18 +24,13 @@ class Options: ) regex_task_completed: str = r"(?:x|\[x\])" regex_task_incomplete: str = r"\[ \]" - regex_task_idea: str = r"(?:idea:|\+idea)" def init(): opt = Options() - - parser = argparse.ArgumentParser() - create_cmdline_args(parser) - parse_cmdline_args(parser, opt) + parse_cmdline_args(opt) if opt.dryrun: dryrun_show_options(opt) - validate_opts(opt) return opt @@ -46,7 +38,8 @@ def dryrun_show_options(options): print(options) -def create_cmdline_args(parser): +def parse_cmdline_args(options): + parser = argparse.ArgumentParser() parser.add_argument( "-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", 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() if args.dryrun: @@ -87,8 +71,6 @@ def parse_cmdline_args(parser, options): options.taskwarrior_log_completed = False if args.noincomplete: options.taskwarrior_add_incomplete = False - if args.noidea: - options.taskwarrior_add_ideas = False if args.nofilltoday: options.taskwarrior_fill_today = False if args.file: @@ -97,9 +79,3 @@ def parse_cmdline_args(parser, options): options.todo_block_title = args.blocktitle 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)