1
|
|
|
import argparse |
2
|
|
|
import re |
3
|
|
|
import textwrap |
4
|
|
|
|
5
|
|
|
from .commands import postconfig_decrypt |
6
|
|
|
from .commands import postconfig_encrypt |
7
|
|
|
from .commands import postconfig_import |
8
|
|
|
from .commands import postconfig_list |
9
|
|
|
from .commands import preconfig_diagnostic |
10
|
|
|
from .commands import preconfig_version |
11
|
|
|
from .output import deprecated_cmd |
12
|
|
|
from .plugins import EXPORT_FORMATS |
13
|
|
|
from .plugins import IMPORT_FORMATS |
14
|
|
|
from .plugins import util |
15
|
|
|
|
16
|
|
|
|
17
|
|
|
class WrappingFormatter(argparse.RawTextHelpFormatter): |
18
|
|
|
"""Used in help screen""" |
19
|
|
|
|
20
|
|
|
def _split_lines(self, text, width): |
21
|
|
|
text = text.split("\n\n") |
22
|
|
|
text = map(lambda t: self._whitespace_matcher.sub(" ", t).strip(), text) |
23
|
|
|
text = map(lambda t: textwrap.wrap(t, width=56), text) |
24
|
|
|
text = [item for sublist in text for item in sublist] |
25
|
|
|
return text |
26
|
|
|
|
27
|
|
|
|
28
|
|
|
def parse_args(args=[]): |
29
|
|
|
""" |
30
|
|
|
Argument parsing that is doable before the config is available. |
31
|
|
|
Everything else goes into "text" for later parsing. |
32
|
|
|
""" |
33
|
|
|
parser = argparse.ArgumentParser( |
34
|
|
|
formatter_class=WrappingFormatter, |
35
|
|
|
add_help=False, |
36
|
|
|
description="Collect your thoughts and notes without leaving the command line", |
37
|
|
|
epilog=textwrap.dedent( |
38
|
|
|
""" |
39
|
|
|
Thank you to all of our contributors! Come see the whole list of code and |
40
|
|
|
financial contributors at https://github.com/jrnl-org/jrnl. And special |
41
|
|
|
thanks to Bad Lip Reading for the Yoda joke in the Writing section above.""" |
42
|
|
|
), |
43
|
|
|
) |
44
|
|
|
|
45
|
|
|
optional = parser.add_argument_group("Optional Arguments") |
46
|
|
|
optional.add_argument( |
47
|
|
|
"--debug", |
48
|
|
|
dest="debug", |
49
|
|
|
action="store_true", |
50
|
|
|
help="Print information useful for troubleshooting", |
51
|
|
|
) |
52
|
|
|
|
53
|
|
|
standalone = parser.add_argument_group( |
54
|
|
|
"Standalone Commands", |
55
|
|
|
"These commands will exit after they complete. You may only run one at a time.", |
56
|
|
|
) |
57
|
|
|
standalone.add_argument("--help", action="help", help="Show this help message") |
58
|
|
|
standalone.add_argument("-h", action="help", help=argparse.SUPPRESS) |
59
|
|
|
standalone.add_argument( |
60
|
|
|
"--version", |
61
|
|
|
action="store_const", |
62
|
|
|
const=preconfig_version, |
63
|
|
|
dest="preconfig_cmd", |
64
|
|
|
help="Print version information", |
65
|
|
|
) |
66
|
|
|
standalone.add_argument( |
67
|
|
|
"-v", |
68
|
|
|
action="store_const", |
69
|
|
|
const=preconfig_version, |
70
|
|
|
dest="preconfig_cmd", |
71
|
|
|
help=argparse.SUPPRESS, |
72
|
|
|
) |
73
|
|
|
standalone.add_argument( |
74
|
|
|
"--diagnostic", |
75
|
|
|
action="store_const", |
76
|
|
|
const=preconfig_diagnostic, |
77
|
|
|
dest="preconfig_cmd", |
78
|
|
|
help=argparse.SUPPRESS, |
79
|
|
|
) |
80
|
|
|
standalone.add_argument( |
81
|
|
|
"--list", |
82
|
|
|
action="store_const", |
83
|
|
|
const=postconfig_list, |
84
|
|
|
dest="postconfig_cmd", |
85
|
|
|
help="List all configured journals", |
86
|
|
|
) |
87
|
|
|
standalone.add_argument( |
88
|
|
|
"--ls", |
89
|
|
|
action="store_const", |
90
|
|
|
const=postconfig_list, |
91
|
|
|
dest="postconfig_cmd", |
92
|
|
|
help=argparse.SUPPRESS, |
93
|
|
|
) |
94
|
|
|
standalone.add_argument( |
95
|
|
|
"-ls", |
96
|
|
|
action="store_const", |
97
|
|
|
const=lambda **kwargs: deprecated_cmd( |
98
|
|
|
"-ls", "--list or --ls", callback=postconfig_list, **kwargs |
99
|
|
|
), |
100
|
|
|
dest="postconfig_cmd", |
101
|
|
|
help=argparse.SUPPRESS, |
102
|
|
|
) |
103
|
|
|
standalone.add_argument( |
104
|
|
|
"--encrypt", |
105
|
|
|
help="Encrypt selected journal with a password", |
106
|
|
|
action="store_const", |
107
|
|
|
metavar="TYPE", |
108
|
|
|
const=postconfig_encrypt, |
109
|
|
|
dest="postconfig_cmd", |
110
|
|
|
) |
111
|
|
|
standalone.add_argument( |
112
|
|
|
"--decrypt", |
113
|
|
|
help="Decrypt selected journal and store it in plain text", |
114
|
|
|
action="store_const", |
115
|
|
|
metavar="TYPE", |
116
|
|
|
const=postconfig_decrypt, |
117
|
|
|
dest="postconfig_cmd", |
118
|
|
|
) |
119
|
|
|
standalone.add_argument( |
120
|
|
|
"--import", |
121
|
|
|
action="store_const", |
122
|
|
|
metavar="TYPE", |
123
|
|
|
const=postconfig_import, |
124
|
|
|
dest="postconfig_cmd", |
125
|
|
|
help=f""" |
126
|
|
|
Import entries from another journal. |
127
|
|
|
|
128
|
|
|
Optional parameters: |
129
|
|
|
|
130
|
|
|
--file FILENAME (default: uses stdin) |
131
|
|
|
|
132
|
|
|
--format [{util.oxford_list(IMPORT_FORMATS)}] (default: jrnl) |
133
|
|
|
""", |
134
|
|
|
) |
135
|
|
|
standalone.add_argument( |
136
|
|
|
"--file", |
137
|
|
|
metavar="FILENAME", |
138
|
|
|
dest="filename", |
139
|
|
|
help=argparse.SUPPRESS, |
140
|
|
|
default=None, |
141
|
|
|
) |
142
|
|
|
standalone.add_argument("-i", dest="filename", help=argparse.SUPPRESS) |
143
|
|
|
|
144
|
|
|
compose_msg = """ |
145
|
|
|
To add a new entry into your journal, simply write it on the command line: |
146
|
|
|
|
147
|
|
|
jrnl yesterday: I was walking and I found this big log. |
148
|
|
|
|
149
|
|
|
The date and the following colon ("yesterday:") are optional. If you leave |
150
|
|
|
them out, "now" will be used: |
151
|
|
|
|
152
|
|
|
jrnl Then I rolled the log over. |
153
|
|
|
|
154
|
|
|
Also, you can mark extra special entries ("star" them) with an asterisk: |
155
|
|
|
|
156
|
|
|
jrnl *And underneath was a tiny little stick. |
157
|
|
|
|
158
|
|
|
Please note that asterisks might be a special character in your shell, so you |
159
|
|
|
might have to escape them. When in doubt about escaping, put quotes around |
160
|
|
|
your entire entry: |
161
|
|
|
|
162
|
|
|
jrnl "saturday at 2am: *Then I was like 'That log had a child!'" """ |
163
|
|
|
|
164
|
|
|
composing = parser.add_argument_group( |
165
|
|
|
"Writing", textwrap.dedent(compose_msg).strip() |
166
|
|
|
) |
167
|
|
|
composing.add_argument("text", metavar="", nargs="*") |
168
|
|
|
|
169
|
|
|
read_msg = ( |
170
|
|
|
"To find entries from your journal, use any combination of the below filters." |
171
|
|
|
) |
172
|
|
|
reading = parser.add_argument_group("Searching", textwrap.dedent(read_msg)) |
173
|
|
|
reading.add_argument( |
174
|
|
|
"-on", dest="on_date", metavar="DATE", help="Show entries on this date" |
175
|
|
|
) |
176
|
|
|
reading.add_argument( |
177
|
|
|
"-from", |
178
|
|
|
dest="start_date", |
179
|
|
|
metavar="DATE", |
180
|
|
|
help="Show entries after, or on, this date", |
181
|
|
|
) |
182
|
|
|
reading.add_argument( |
183
|
|
|
"-to", |
184
|
|
|
dest="end_date", |
185
|
|
|
metavar="DATE", |
186
|
|
|
help="Show entries before, or on, this date (alias: -until)", |
187
|
|
|
) |
188
|
|
|
reading.add_argument("-until", dest="end_date", help=argparse.SUPPRESS) |
189
|
|
|
reading.add_argument( |
190
|
|
|
"-contains", |
191
|
|
|
dest="contains", |
192
|
|
|
metavar="TEXT", |
193
|
|
|
help="Show entries containing specific text (put quotes around text with spaces)", |
194
|
|
|
) |
195
|
|
|
reading.add_argument( |
196
|
|
|
"-and", |
197
|
|
|
dest="strict", |
198
|
|
|
action="store_true", |
199
|
|
|
help='Show only entries that match all conditions, like saying "x AND y" (default: OR)', |
200
|
|
|
) |
201
|
|
|
reading.add_argument( |
202
|
|
|
"-starred", |
203
|
|
|
dest="starred", |
204
|
|
|
action="store_true", |
205
|
|
|
help="Show only starred entries (marked with *)", |
206
|
|
|
) |
207
|
|
|
reading.add_argument( |
208
|
|
|
"-n", |
209
|
|
|
dest="limit", |
210
|
|
|
default=None, |
211
|
|
|
metavar="NUMBER", |
212
|
|
|
help="Show a maximum of NUMBER entries (note: '-n 3' and '-3' have the same effect)", |
213
|
|
|
nargs="?", |
214
|
|
|
type=int, |
215
|
|
|
) |
216
|
|
|
reading.add_argument( |
217
|
|
|
"-not", |
218
|
|
|
dest="excluded", |
219
|
|
|
nargs="?", |
220
|
|
|
default=[], |
221
|
|
|
metavar="TAG", |
222
|
|
|
action="append", |
223
|
|
|
help="Exclude entries with this tag", |
224
|
|
|
) |
225
|
|
|
|
226
|
|
|
search_options_msg = """ These help you do various tasks with the selected entries from your search. |
227
|
|
|
If used on their own (with no search), they will act on your entire journal""" |
228
|
|
|
exporting = parser.add_argument_group( |
229
|
|
|
"Searching Options", textwrap.dedent(search_options_msg) |
230
|
|
|
) |
231
|
|
|
exporting.add_argument( |
232
|
|
|
"--edit", |
233
|
|
|
dest="edit", |
234
|
|
|
help="Opens the selected entries in your configured editor", |
235
|
|
|
action="store_true", |
236
|
|
|
) |
237
|
|
|
exporting.add_argument( |
238
|
|
|
"--delete", |
239
|
|
|
dest="delete", |
240
|
|
|
action="store_true", |
241
|
|
|
help="Interactively deletes selected entries", |
242
|
|
|
) |
243
|
|
|
exporting.add_argument( |
244
|
|
|
"--format", |
245
|
|
|
metavar="TYPE", |
246
|
|
|
dest="export", |
247
|
|
|
choices=EXPORT_FORMATS, |
248
|
|
|
help=f""" |
249
|
|
|
Display selected entries in an alternate format. |
250
|
|
|
|
251
|
|
|
TYPE can be: {util.oxford_list(EXPORT_FORMATS)}. |
252
|
|
|
|
253
|
|
|
Optional parameters: |
254
|
|
|
|
255
|
|
|
--file FILENAME Write output to file instead of stdout |
256
|
|
|
""", |
257
|
|
|
default=False, |
258
|
|
|
) |
259
|
|
|
exporting.add_argument( |
260
|
|
|
"--export", |
261
|
|
|
metavar="TYPE", |
262
|
|
|
dest="export", |
263
|
|
|
choices=EXPORT_FORMATS, |
264
|
|
|
help=argparse.SUPPRESS, |
265
|
|
|
) |
266
|
|
|
exporting.add_argument( |
267
|
|
|
"--tags", |
268
|
|
|
dest="tags", |
269
|
|
|
action="store_true", |
270
|
|
|
help="Alias for '--format tags'. Returns a list of all tags and number of occurences", |
271
|
|
|
) |
272
|
|
|
exporting.add_argument( |
273
|
|
|
"--short", |
274
|
|
|
dest="short", |
275
|
|
|
action="store_true", |
276
|
|
|
help="Show only titles or line containing the search tags", |
277
|
|
|
) |
278
|
|
|
exporting.add_argument( |
279
|
|
|
"-s", |
280
|
|
|
dest="short", |
281
|
|
|
action="store_true", |
282
|
|
|
help=argparse.SUPPRESS, |
283
|
|
|
) |
284
|
|
|
exporting.add_argument( |
285
|
|
|
"-o", |
286
|
|
|
dest="filename", |
287
|
|
|
help=argparse.SUPPRESS, |
288
|
|
|
) |
289
|
|
|
|
290
|
|
|
# Handle '-123' as a shortcut for '-n 123' |
291
|
|
|
num = re.compile(r"^-(\d+)$") |
292
|
|
|
args = [num.sub(r"-n \1", arg) for arg in args] |
293
|
|
|
|
294
|
|
|
return parser.parse_intermixed_args(args) |
295
|
|
|
|