summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLars Wirzenius <liw@liw.fi>2014-11-22 19:27:33 +0200
committerLars Wirzenius <liw@liw.fi>2014-11-22 19:27:33 +0200
commitdb41106352188f30ed2b814f22442a6fe63bbb60 (patch)
tree6af62472943d6ca55dc90e6bc2f1267bc2bb6e9b
parentc3c6f20cca633d6cc31d34ee1cffe4e2c4a2987b (diff)
parent3f49554a438bc153852d1dacc1db54e78a303c12 (diff)
downloadjt-db41106352188f30ed2b814f22442a6fe63bbb60.tar.gz
Merge in some refactorings
-rwxr-xr-xcheck1
-rwxr-xr-xjt389
2 files changed, 233 insertions, 157 deletions
diff --git a/check b/check
index 19b680a..4431b7a 100755
--- a/check
+++ b/check
@@ -21,3 +21,4 @@ set -eu
yarn -s yarns/yarn.sh yarns/*.yarn "$@"
+copyright-statement-lint jt
diff --git a/jt b/jt
index e17d4c8..6b82994 100755
--- a/jt
+++ b/jt
@@ -1,5 +1,5 @@
#!/usr/bin/python
-# Copyright 2010-2013 Lars Wirzenius
+# Copyright 2010-2014 Lars Wirzenius
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -39,6 +39,221 @@ template = '''\
'''
+class DraftsDirectory(object):
+
+ def __init__(self, dirname):
+ self.dirname = dirname
+
+ def create_if_missing(self):
+ if not os.path.exists(self.dirname):
+ os.mkdir(self.dirname)
+
+ def get_draft_pathname(self, draft_id):
+ return os.path.join(self.dirname, '%s.mdwn' % draft_id)
+
+ def get_draft_attachments_dirname(self, draft_id):
+ return os.path.join(self.dirname, '%s' % draft_id)
+
+ def create_draft(self, content):
+ draft_id = self._pick_available_draft_id()
+ pathname = self.get_draft_pathname(draft_id)
+ with open(pathname, 'w') as f:
+ f.write(content)
+ return draft_id
+
+ def _pick_available_draft_id(self):
+ for i in range(1000):
+ pathname = self.get_draft_pathname(i)
+ if not os.path.exists(pathname):
+ return i
+ else:
+ raise cliapp.AppException('ERROR: too many existing drafts')
+
+ def get_drafts(self):
+ for basename in os.listdir(self.dirname):
+ # .# is what Emacs autosave files start with.
+ if basename.endswith('.mdwn') and not basename.startswith('.#'):
+ yield basename[:-len('.mdwn')], os.path.join(self.dirname, basename)
+
+ def remove_draft(self, draft_id):
+ filename = self.get_draft_pathname(draft_id)
+ os.remove(filename)
+
+ dirname = self.get_draft_attachments_dirname(draft_id)
+ if os.path.exists(dirname):
+ shutil.rmtree(dirname)
+
+
+class Command(object):
+
+ def __init__(self, app):
+ self._app = app
+
+ def run(self, args):
+ raise NotImplementedError()
+
+
+class NewCommand(Command):
+
+ def run(self, args):
+ if not args:
+ raise cliapp.AppException('Usage: journal-note new TITLE')
+
+ self._app.settings.require('source')
+ self._app.settings.require('layout')
+
+ values = {
+ 'title': args[0],
+ 'date': time.strftime('%Y-%m-%d %H:%M')
+ }
+
+ drafts_dir = DraftsDirectory(self._app.drafts_dir())
+ drafts_dir.create_if_missing()
+ draft_id = drafts_dir.create_draft(template % values)
+ self._app.edit_file(drafts_dir.get_draft_pathname(draft_id))
+
+
+class ListCommand(Command):
+
+ def run(self, args):
+ drafts_dir = DraftsDirectory(self._app.drafts_dir())
+ for draft_id, filename in drafts_dir.get_drafts():
+ print draft_id, self._app.get_draft_title(filename) or ""
+
+
+class EditCommand(Command):
+
+ def run(self, args):
+ if len(args) > 1:
+ raise cliapp.AppException('Must be given at most one draft ID')
+ drafts_dir = DraftsDirectory(self._app.drafts_dir())
+ draft_id, pathname = self._app.choose_draft(drafts_dir, args)
+ self._app.edit_file(pathname)
+
+
+class AttachCommand(Command):
+
+ def run(self, args):
+ if len(args) < 2:
+ raise cliapp.AppException('Usage: journal-note attach ID file...')
+
+ drafts_dir = DraftsDirectory(self._app.draft_dir())
+ dirname = drafts_dir.get_draft_attachments_dirname(args[0])
+ if not os.path.exists(dirname):
+ os.mkdir(dirname)
+ for filename in args[1:]:
+ shutil.copy(filename, dirname)
+
+
+class RemoveCommand(Command):
+
+ def run(self, args):
+ if not args:
+ raise cliapp.AppException('Usage: journal-note remove ID')
+ drafts_dir = DraftsDirectory(self._app.drafts_dir())
+ drafts_dir.remove_draft(args[0])
+
+
+class FinishCommand(Command):
+
+ def run(self, args):
+ drafts_dir = DraftsDirectory(self._app.drafts_dir())
+ draft_id, draft_mdwn = self._app.choose_draft(drafts_dir, args)
+ draft_attch = drafts_dir.get_draft_attachments_dirname(draft_id)
+
+ pub_attch = os.path.join(
+ self._published_dir(), self._published_basename(draft_mdwn))
+ pub_mdwn = pub_attch + '.mdwn'
+
+ if os.path.exists(pub_mdwn):
+ raise cliapp.AppException('%s already exists' % pub_mdwn)
+
+ if not os.path.exists(self._published_dir()):
+ os.makedirs(self._published_dir())
+ os.rename(draft_mdwn, pub_mdwn)
+ if os.path.exists(draft_attch):
+ os.rename(draft_attch, pub_attch)
+
+ if self._app.settings['git']:
+ if os.path.exists(pub_attch):
+ self.commit_to_git([pub_mdwn, pub_attch])
+ else:
+ self.commit_to_git([pub_mdwn])
+ if self._app.settings['push']:
+ self.push_git()
+
+ def _published_dir(self):
+ subdirs = {
+ 'liw': 'notes',
+ 'ct': 'log/%d' % time.localtime().tm_year,
+ 'pkb': time.strftime('notes/%Y/%m/%d'),
+ }
+
+ subdir = subdirs[self._app.settings['layout']]
+ return os.path.join(self._app.settings['source'], subdir)
+
+ def _published_basename(self, draft_mdwn):
+ if self._app.settings['layout'] in ('liw', 'ct'):
+ basename = time.strftime('%Y-%m-%d-%H:%M:%S')
+ elif self._app.settings['layout'] == 'pkb':
+ title = self._app.get_draft_title(draft_mdwn)
+ if not title:
+ raise Exception("%s has no title" % draft_mdwn)
+ basename = self._app.summarise_title(title)
+ else:
+ raise Exception(
+ 'Setting --layout=%s is unknown' % self._app.settings['layout'])
+
+ return basename
+
+ def _commit_to_git(self, pathnames):
+ cliapp.runcmd(
+ ['git', 'add'] + pathname,
+ cwd=self._app.settings['source'])
+
+ cliapp.runcmd(
+ ['git', 'commit', '-m', 'Publish log entry'],
+ cwd=self._app.settings['source'])
+
+ def _push_git(self):
+ cliapp.runcmd(
+ ['git', 'push', 'origin', 'HEAD'],
+ cwd=self._app.settings['source'])
+
+
+class NewPersonCommand(Command):
+
+ def run(self, args):
+ if len(args) != 1:
+ raise cliapp.AppException(
+ 'Need the name of a person (in Last, First form)')
+
+ def normalise(name):
+ s = name.lower()
+ s = ' '.join(s.split(','))
+ s = '.'.join(s.split())
+ return s
+
+ name = args[0]
+ basename = normalise(name)
+ pathname = os.path.join(
+ self._app.settings['source'], 'people', basename + '.mdwn')
+
+ if os.path.exists(pathname):
+ raise cliapp.AppException('File %s already exists' % pathname)
+
+ with open(pathname, 'w') as f:
+ f.write('''\
+[[!meta title="%(name)s"]]
+
+[[!inline archive=yes pages="link(.)"]]
+''' %
+ {
+ 'name': name,
+ 'basename': basename,
+ })
+
+
class JournalTool(cliapp.Application):
cmd_synopsis = {
@@ -84,42 +299,11 @@ class JournalTool(cliapp.Application):
def cmd_new(self, args):
'''Create a new journal entry draft.'''
-
- if not args:
- raise cliapp.AppException('Usage: journal-note new TITLE')
-
- self.settings.require('source')
- self.settings.require('layout')
-
- if not self.settings['source']:
- raise cliapp.AppException(
- 'The --source setting is empty or missing.')
-
- if not os.path.exists(self.drafts_dir()):
- os.mkdir(self.drafts_dir())
-
- for i in range(1000):
- name = self.draft_name(i)
- if not os.path.exists(name):
- break
- else:
- raise cliapp.AppException('ERROR: too many existing drafts')
-
- values = {
- 'title': args[0],
- 'date': time.strftime('%Y-%m-%d %H:%M')
- }
- f = open(name, 'w')
- f.write(template % values)
- f.close()
- self.edit_file(name)
+ NewCommand(self).run(args)
def drafts_dir(self):
return os.path.join(self.settings['source'], 'drafts')
- def draft_name(self, draft_id):
- return os.path.join(self.drafts_dir(), '%s.mdwn' % draft_id)
-
def edit_file(self, pathname):
safe_pathname = cliapp.shell_quote(pathname)
cmdline = ['sh', '-c', self.settings['editor'] % pathname]
@@ -127,16 +311,7 @@ class JournalTool(cliapp.Application):
def cmd_list(self, args):
'''List journal entry drafts.'''
-
- for draft_id, filename in self.find_drafts():
- print draft_id, self.get_draft_title(filename) or ""
-
- def find_drafts(self):
- drafts_dir = self.drafts_dir()
- for name in os.listdir(drafts_dir):
- # .# is what Emacs autosave files start with.
- if name.endswith('.mdwn') and not name.startswith('.#'):
- yield name[:-len('.mdwn')], os.path.join(drafts_dir, name)
+ ListCommand(self).run(args)
def get_draft_title(self, filename):
with open(filename) as f:
@@ -153,111 +328,37 @@ class JournalTool(cliapp.Application):
def cmd_edit(self, args):
'''Edit a draft journal entry.'''
+ EditCommand(self).run(args)
- filename = self.choose_draft(args)
- self.edit_file(filename)
-
- def choose_draft(self, args):
+ def choose_draft(self, drafts_dir, args):
if len(args) == 0:
- drafts = list(self.find_drafts())
+ drafts = list(drafts_dir.get_drafts())
if len(drafts) == 1:
draft_id, filename = drafts[0]
- return filename
+ return draft_id, filename
+ elif len(drafts) == 0:
+ raise cliapp.AppException('No drafts to choose from')
else:
raise cliapp.AppException('Cannot choose entry draft automatically')
elif len(args) == 1:
- filename = self.draft_name(args[0])
- if not os.path.exists(filename):
+ pathname = drafts_dir.get_draft_pathname(args[0])
+ if not os.path.exists(pathname):
raise cliapp.AppException('draft %s does not exist' % args[0])
- return filename
+ return args[0], pathname
elif len(args) > 1:
- raise cliapp.AppException('Must give only one draft number')
+ raise cliapp.AppException('Must give at most one draft number')
def cmd_attach(self, args):
'''Attach files to a journal entry draft.'''
-
- if len(args) < 2:
- raise cliapp.AppException('Usage: journal-note attach ID file...')
-
- filename = self.draft_name(args[0])
-
- dirname, ext = os.path.splitext(filename)
- assert ext == '.mdwn'
-
- if not os.path.exists(dirname):
- os.mkdir(dirname)
- for filename in args[1:]:
- shutil.copy(filename, dirname)
+ AttachCommand(self).run(args)
def cmd_remove(self, args):
'''Remove a draft.'''
-
- if not args:
- raise cliapp.AppException('Usage: journal-note remove ID')
- filename = self.draft_name(args[0])
- os.remove(filename)
-
- dirname, ext = os.path.splitext(filename)
- assert ext == '.mdwn'
- if os.path.exists(dirname):
- shutil.rmtree(dirname)
+ RemoveCommand(self).run(args)
def cmd_finish(self, args):
'''Publish a draft journal entry.'''
-
- draft_mdwn = self.choose_draft(args)
- draft_attch, ext = os.path.splitext(draft_mdwn)
- assert ext == '.mdwn'
-
- pub_attch = os.path.join(
- self.published_dir(), self.published_basename(draft_mdwn))
- pub_mdwn = pub_attch + '.mdwn'
-
- if os.path.exists(pub_mdwn):
- raise cliapp.AppException('%s already exists' % pub_mdwn)
-
- if not os.path.exists(self.published_dir()):
- os.makedirs(self.published_dir())
- os.rename(draft_mdwn, pub_mdwn)
- if os.path.exists(draft_attch):
- os.rename(draft_attch, pub_attch)
-
- if self.settings['git']:
- argv = ['git', 'add', pub_mdwn]
- if os.path.exists(pub_attch):
- argv.append(pub_attch)
- cliapp.runcmd(argv, cwd=self.settings['source'])
- cliapp.runcmd(
- ['git', 'commit', '-m', 'Publish log entry'],
- cwd=self.settings['source'])
- if self.settings['push']:
- cliapp.runcmd(
- ['git', 'push', 'origin', 'HEAD'],
- cwd=self.settings['source'])
-
- def published_dir(self):
- subdirs = {
- 'liw': 'notes',
- 'ct': 'log/%d' % time.localtime().tm_year,
- 'pkb': time.strftime('notes/%Y/%m/%d'),
- }
-
- subdir = subdirs[self.settings['layout']]
- return os.path.join(self.settings['source'], subdir)
-
- def published_basename(self, draft_mdwn):
- if self.settings['layout'] in ('liw', 'ct'):
- basename = time.strftime('%Y-%m-%d-%H:%M:%S')
- elif self.settings['layout'] == 'pkb':
- title = self.get_draft_title(draft_mdwn)
- if not title:
- raise Exception("%s has no title" % draft_mdwn)
- basename = self.summarise_title(title)
- else:
- raise Exception(
- 'Setting --layout=%s is unknown' % self.settings['layout'])
-
- return basename
+ FinishCommand(self).run(args)
def summarise_title(self, title):
basename = ''
@@ -276,33 +377,7 @@ class JournalTool(cliapp.Application):
'''
- if len(args) != 1:
- raise cliapp.AppException(
- 'Need the name of a person (in Last, First form)')
-
- def normalise(name):
- s = name.lower()
- s = ' '.join(s.split(','))
- s = '.'.join(s.split())
- return s
-
- name = args[0]
- basename = normalise(name)
- pathname = os.path.join(
- self.settings['source'], 'people', basename + '.mdwn')
+ NewPersonCommand(self).run(args)
- if os.path.exists(pathname):
- raise cliapp.AppException('File %s already exists' % pathname)
-
- with open(pathname, 'w') as f:
- f.write('''\
-[[!meta title="%(name)s"]]
-
-[[!inline archive=yes pages="link(.)"]]
-''' %
- {
- 'name': name,
- 'basename': basename,
- })
JournalTool(version=__version__).run()