# Copyright 2010-2015 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 # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . import cliapp import os import time import jinja2 import jtlib class JournalTool(cliapp.Application): def add_settings(self): self.settings.string( ['profile', 'p'], 'also use section PROFILE in configuration files, ' 'in addition to [config]', metavar='PROFILE') self.settings.choice( ['layout'], ['pkb', 'ct'], 'use journal layout (one of pkb, ct)', metavar='LAYOUT') self.settings.string( ['source'], 'use journal source tree in DIR', metavar='DIR') self.settings.boolean( ['git'], 'add entries to git automatically', default=True) self.settings.string( ['editor'], 'editor to launch for journal entries. Must include {editor} to ' 'indicate where the filename goes', default='sensible-editor {editor}') self.settings.boolean( ['push'], 'push finished articles with git?') self.settings.string( ['topic'], 'new entry belongs to TOPIC', metavar='TOPIC') self.settings.string_list( ['templates'], 'look for templates also in DIR', metavar='DIR') self.settings.string( ['new-note-template'], 'use FILE as the template for new journal notes', metavar='FILE') self.settings.string( ['notes-dir'], 'put new notes in subdirectory DIR', metavar='DIR', default='notes') self.settings.string( ['pretend-time'], 'pretend that the time is NOW (form: YYYY-MM-DD HH:MM:DD form)', metavar='NOW') def process_args(self, args): self.merge_profile() if self.settings['pretend-time']: self.now_tuple = time.strptime( self.settings['pretend-time'], '%Y-%m-%d %H:%M:%S') else: self.now_tuple = time.localtime() self.layout = self.create_layout() cliapp.Application.process_args(self, args) def create_layout(self): layouts = { 'pkb': jtlib.PkbLayout(), 'ct': jtlib.CtLayout(), } layout = layouts[self.settings['layout']] layout.set_settings(self.settings) layout.set_time_tuple(self.now_tuple) return layout def merge_profile(self): profile = self.settings['profile'] if profile: section = 'profile %s' % profile cp = self.settings.as_cp() if section not in cp.sections(): raise cliapp.AppException('Unknown profile %s' % profile) for key in cp.options(section): if key not in self.settings: raise cliapp.AppException( 'Profile %s uses unknown setting %s' % (profile, key)) value = cp.get(section, key) self.settings.set_from_raw_string( 'profile %s' % profile, key, value) def drafts_dir(self): return os.path.join(self.settings['source'], 'drafts') def edit_file(self, pathname): safe_pathname = cliapp.shell_quote(pathname) cmdline = [ 'sh', '-c', self.settings['editor'].format(editor=safe_pathname)] self.runcmd(cmdline, stdin=None, stdout=None, stderr=None) def choose_draft(self, drafts_dir, args): if len(args) == 0: drafts = list(drafts_dir.get_drafts()) if len(drafts) == 1: draft_id, filename = drafts[0] 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: 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 args[0], pathname elif len(args) > 1: raise cliapp.AppException('Must give at most one draft number') def read_template(self, basename): default = os.path.join(self.app_directory(), 'templates') for dirname in self.settings['templates'] + [default]: filename = os.path.join(dirname, basename) if os.path.exists(filename): with open(filename) as f: return f.read() def render_template(self, basename, vars): text = self.read_template(basename) utext = unicode(text, 'utf8') uvars = dict( (unicode(k, 'utf8'), unicode(v, 'utf8')) for k, v in vars.items()) template = jinja2.Template(utext) return template.render(**uvars)