Skip to content

Instantly share code, notes, and snippets.

@seanlane
Created May 10, 2018 17:59
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save seanlane/549bb151c6df45722efa5494e934a1c8 to your computer and use it in GitHub Desktop.
Save seanlane/549bb151c6df45722efa5494e934a1c8 to your computer and use it in GitHub Desktop.
Python script I use for Personal and Work journaling
#!/usr/bin/env python3
import argparse, datetime, os, re, sys, tempfile, time
from subprocess import call
EDITOR = os.environ.get('EDITOR') if os.environ.get('EDITOR') else 'vim'
def create_header():
"""
Create the template for a new personal journal entry
returns list of strings (lines) to be joined
"""
content = [
'---',
'date: {}'.format(time.strftime('%Y-%m-%d', cur_date)),
'time: {}'.format(time.strftime('%H:%M:%S%z', cur_date))
]
try:
import requests
resp = requests.get(url='http://ip-api.com/json') # Find location based on Public IP address
data = resp.json()
content.append('location: {}, {}, {}'.format(data['city'], data['regionName'], data['country']))
except Exception as e:
print('Exception occurred: {}'.format(e))
print("Couldn't get location, skipping. Should probably figure this out sometime.")
content.append('---')
return content
def work_template(base_path):
"""
Create the template for a new work journal entry
Most of this work is to simply copy the To Do list from the last entry and
paste it into this new entry, and add other sections around it.
base_path: Parent directory of entries
"""
content = create_header()
content.extend([
'',
'# Done',
'', '', ''
])
try:
files = {x[0]: {'dirs': x[1], 'files': x[2]} for x in os.walk(base_path)}
latest_year = sorted(files[base_path]['dirs'])[-1]
latest_month = sorted(files[os.path.join(base_path, latest_year)]['dirs'])[-1]
latest_date = sorted([x for x in
files[os.path.join(base_path, os.path.join(latest_year, latest_month))]['files']
if '.md' in x])[-1]
last_entry_path = os.path.join(base_path,
os.path.join(latest_year,
os.path.join(latest_month, latest_date)))
with open(last_entry_path, 'r') as f:
start_todo_section = re.compile(r"^[ \t]*\#+[ \t]*To[ \t]*Do[ \t]*$")
next_section = re.compile(r"^[ \t]*\#+.*$")
todo_section = False
content.append('# To Do')
for line in f:
if start_todo_section.search(line):
todo_section = True
elif todo_section and next_section.search(line):
break
elif todo_section:
if line.strip():
content.append(line.rstrip())
except Exception as e:
print('Exception occurred: {}'.format(e))
print("Couldn't get previous To Do section, continuing")
content.extend(['', '# Other', '', '', ''])
return '\n'.join(content)
def personal_template():
"""
Create the template for a new work journal entry
base_path: Parent directory of entries
"""
content = '\n'.join(create_header())
with open(os.path.join(os.path.dirname(sys.argv[0]), 'template.md')) as f:
content = content + '\n' + ''.join(f.readlines())
return content
def edit_content(content_in):
initial_message = str.encode(content_in) # if you want to set up the file somehow
with tempfile.NamedTemporaryFile(suffix=".tmp") as tf:
tf.write(initial_message)
tf.flush()
call([EDITOR, '+set backupcopy=yes', tf.name])
# do the parsing with `tf` using regular File operations.
# for instance:
tf.seek(0)
edited_message = tf.read().decode("utf-8")
return edited_message
parser = argparse.ArgumentParser(description="Sean's jrnl script")
parser.add_argument('--work', action='store_true', help="Process work entry")
parser.add_argument('path', help="Root directory of entries")
args = parser.parse_args()
cur_date = time.localtime()
base_dir = os.path.expanduser(args.path)
dir_path = os.path.join(base_dir, os.path.join(str(cur_date.tm_year), time.strftime('%m-%B', cur_date)))
file_path = os.path.join(dir_path, time.strftime('%Y-%m-%d.md', cur_date))
# If there already exists an entry for today, load the contents and edit it
if os.path.exists(file_path):
with open(file_path) as f:
source = f.read()
## Allow user to edit template
updated_content = edit_content(source)
## Check if anything changed, if not don't bother saving
if source == updated_content:
sys.exit(0)
with open(file_path, 'w') as f:
f.write(updated_content)
sys.exit(0)
# If it's before 4AM local time and there is an entry for the previous day, edit that one
if cur_date.tm_hour < 4:
# Get date for yesterday
yes_date = (datetime.datetime.fromtimestamp(time.mktime(cur_date)).date() - datetime.timedelta(days=1)).timetuple()
temp_dir_path = os.path.join(base_dir, os.path.join(str(cur_date.tm_year), time.strftime('%m-%B', cur_date)))
temp_file_path = os.path.join(temp_dir_path, time.strftime('%Y-%m-%d.md', cur_date))
if os.path.exists(temp_file_path):
with open(temp_file_path) as f:
source = f.read()
## Allow user to edit template
updated_content = edit_content(source)
## Check if anything changed, if not don't bother saving
if source == updated_content:
sys.exit(0)
with open(temp_file_path, 'w') as f:
f.write(updated_content)
sys.exit(0)
# Otherwise, make a new entry as required
## First generate source template
if args.work:
source = ''.join(work_template(base_dir))
else:
source = ''.join(personal_template())
## Allow user to edit template
updated_content = edit_content(source)
## Check if anything changed, if not don't bother saving
if source == updated_content:
sys.exit(0)
if not os.path.exists(dir_path):
os.makedirs(dir_path, mode=0o755, exist_ok=True)
with open(file_path, 'w') as f:
f.write(updated_content)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment