summaryrefslogtreecommitdiff
path: root/jtlib/app.py
blob: ddbb94a58e8a3a304473ba5ec9ae6674576308a2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
# 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 <http://www.gnu.org/licenses/>.


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.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 %s to '
            'indicate where the filename goes',
            default='sensible-editor %s')

        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(
            ['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()
        cliapp.Application.process_args(self, args)

    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'] % 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)