##// END OF EJS Templates
templatefilters: add filter to convert date to local date (issue1674)...
Henrik Stuart -
r8591:08c93b07 default
parent child Browse files
Show More
@@ -1,420 +1,421 b''
1 1 # help.py - help data for mercurial
2 2 #
3 3 # Copyright 2006 Matt Mackall <mpm@selenic.com>
4 4 #
5 5 # This software may be used and distributed according to the terms of the
6 6 # GNU General Public License version 2, incorporated herein by reference.
7 7
8 8 from i18n import _
9 9
10 10 helptable = (
11 11 (["dates"], _("Date Formats"),
12 12 _(r'''
13 13 Some commands allow the user to specify a date, e.g.:
14 14 * backout, commit, import, tag: Specify the commit date.
15 15 * log, revert, update: Select revision(s) by date.
16 16
17 17 Many date formats are valid. Here are some examples:
18 18
19 19 "Wed Dec 6 13:18:29 2006" (local timezone assumed)
20 20 "Dec 6 13:18 -0600" (year assumed, time offset provided)
21 21 "Dec 6 13:18 UTC" (UTC and GMT are aliases for +0000)
22 22 "Dec 6" (midnight)
23 23 "13:18" (today assumed)
24 24 "3:39" (3:39AM assumed)
25 25 "3:39pm" (15:39)
26 26 "2006-12-06 13:18:29" (ISO 8601 format)
27 27 "2006-12-6 13:18"
28 28 "2006-12-6"
29 29 "12-6"
30 30 "12/6"
31 31 "12/6/6" (Dec 6 2006)
32 32
33 33 Lastly, there is Mercurial's internal format:
34 34
35 35 "1165432709 0" (Wed Dec 6 13:18:29 2006 UTC)
36 36
37 37 This is the internal representation format for dates. unixtime is
38 38 the number of seconds since the epoch (1970-01-01 00:00 UTC).
39 39 offset is the offset of the local timezone, in seconds west of UTC
40 40 (negative if the timezone is east of UTC).
41 41
42 42 The log command also accepts date ranges:
43 43
44 44 "<{datetime}" - at or before a given date/time
45 45 ">{datetime}" - on or after a given date/time
46 46 "{datetime} to {datetime}" - a date range, inclusive
47 47 "-{days}" - within a given number of days of today
48 48 ''')),
49 49
50 50 (["patterns"], _("File Name Patterns"),
51 51 _(r'''
52 52 Mercurial accepts several notations for identifying one or more
53 53 files at a time.
54 54
55 55 By default, Mercurial treats filenames as shell-style extended
56 56 glob patterns.
57 57
58 58 Alternate pattern notations must be specified explicitly.
59 59
60 60 To use a plain path name without any pattern matching, start it
61 61 with "path:". These path names must completely match starting at
62 62 the current repository root.
63 63
64 64 To use an extended glob, start a name with "glob:". Globs are
65 65 rooted at the current directory; a glob such as "*.c" will only
66 66 match files in the current directory ending with ".c".
67 67
68 68 The supported glob syntax extensions are "**" to match any string
69 69 across path separators and "{a,b}" to mean "a or b".
70 70
71 71 To use a Perl/Python regular expression, start a name with "re:".
72 72 Regexp pattern matching is anchored at the root of the repository.
73 73
74 74 Plain examples:
75 75
76 76 path:foo/bar a name bar in a directory named foo in the root of
77 77 the repository
78 78 path:path:name a file or directory named "path:name"
79 79
80 80 Glob examples:
81 81
82 82 glob:*.c any name ending in ".c" in the current directory
83 83 *.c any name ending in ".c" in the current directory
84 84 **.c any name ending in ".c" in any subdirectory of the
85 85 current directory including itself.
86 86 foo/*.c any name ending in ".c" in the directory foo
87 87 foo/**.c any name ending in ".c" in any subdirectory of foo
88 88 including itself.
89 89
90 90 Regexp examples:
91 91
92 92 re:.*\.c$ any name ending in ".c", anywhere in the repository
93 93
94 94 ''')),
95 95
96 96 (['environment', 'env'], _('Environment Variables'),
97 97 _(r'''
98 98 HG::
99 99 Path to the 'hg' executable, automatically passed when running
100 100 hooks, extensions or external tools. If unset or empty, this is
101 101 the hg executable's name if it's frozen, or an executable named
102 102 'hg' (with %PATHEXT% [defaulting to COM/EXE/BAT/CMD] extensions on
103 103 Windows) is searched.
104 104
105 105 HGEDITOR::
106 106 This is the name of the editor to run when committing. See EDITOR.
107 107
108 108 (deprecated, use .hgrc)
109 109
110 110 HGENCODING::
111 111 This overrides the default locale setting detected by Mercurial.
112 112 This setting is used to convert data including usernames,
113 113 changeset descriptions, tag names, and branches. This setting can
114 114 be overridden with the --encoding command-line option.
115 115
116 116 HGENCODINGMODE::
117 117 This sets Mercurial's behavior for handling unknown characters
118 118 while transcoding user input. The default is "strict", which
119 119 causes Mercurial to abort if it can't map a character. Other
120 120 settings include "replace", which replaces unknown characters, and
121 121 "ignore", which drops them. This setting can be overridden with
122 122 the --encodingmode command-line option.
123 123
124 124 HGMERGE::
125 125 An executable to use for resolving merge conflicts. The program
126 126 will be executed with three arguments: local file, remote file,
127 127 ancestor file.
128 128
129 129 (deprecated, use .hgrc)
130 130
131 131 HGRCPATH::
132 132 A list of files or directories to search for hgrc files. Item
133 133 separator is ":" on Unix, ";" on Windows. If HGRCPATH is not set,
134 134 platform default search path is used. If empty, only the .hg/hgrc
135 135 from the current repository is read.
136 136
137 137 For each element in HGRCPATH:
138 138 * if it's a directory, all files ending with .rc are added
139 139 * otherwise, the file itself will be added
140 140
141 141 HGUSER::
142 142 This is the string used as the author of a commit. If not set,
143 143 available values will be considered in this order:
144 144
145 145 * HGUSER (deprecated)
146 146 * hgrc files from the HGRCPATH
147 147 * EMAIL
148 148 * interactive prompt
149 149 * LOGNAME (with '@hostname' appended)
150 150
151 151 (deprecated, use .hgrc)
152 152
153 153 EMAIL::
154 154 May be used as the author of a commit; see HGUSER.
155 155
156 156 LOGNAME::
157 157 May be used as the author of a commit; see HGUSER.
158 158
159 159 VISUAL::
160 160 This is the name of the editor to use when committing. See EDITOR.
161 161
162 162 EDITOR::
163 163 Sometimes Mercurial needs to open a text file in an editor for a
164 164 user to modify, for example when writing commit messages. The
165 165 editor it uses is determined by looking at the environment
166 166 variables HGEDITOR, VISUAL and EDITOR, in that order. The first
167 167 non-empty one is chosen. If all of them are empty, the editor
168 168 defaults to 'vi'.
169 169
170 170 PYTHONPATH::
171 171 This is used by Python to find imported modules and may need to be
172 172 set appropriately if this Mercurial is not installed system-wide.
173 173 ''')),
174 174
175 175 (['revs', 'revisions'], _('Specifying Single Revisions'),
176 176 _(r'''
177 177 Mercurial supports several ways to specify individual revisions.
178 178
179 179 A plain integer is treated as a revision number. Negative integers
180 180 are treated as topological offsets from the tip, with -1 denoting
181 181 the tip. As such, negative numbers are only useful if you've
182 182 memorized your local tree numbers and want to save typing a single
183 183 digit. This editor suggests copy and paste.
184 184
185 185 A 40-digit hexadecimal string is treated as a unique revision
186 186 identifier.
187 187
188 188 A hexadecimal string less than 40 characters long is treated as a
189 189 unique revision identifier, and referred to as a short-form
190 190 identifier. A short-form identifier is only valid if it is the
191 191 prefix of exactly one full-length identifier.
192 192
193 193 Any other string is treated as a tag name, which is a symbolic
194 194 name associated with a revision identifier. Tag names may not
195 195 contain the ":" character.
196 196
197 197 The reserved name "tip" is a special tag that always identifies
198 198 the most recent revision.
199 199
200 200 The reserved name "null" indicates the null revision. This is the
201 201 revision of an empty repository, and the parent of revision 0.
202 202
203 203 The reserved name "." indicates the working directory parent. If
204 204 no working directory is checked out, it is equivalent to null. If
205 205 an uncommitted merge is in progress, "." is the revision of the
206 206 first parent.
207 207 ''')),
208 208
209 209 (['mrevs', 'multirevs'], _('Specifying Multiple Revisions'),
210 210 _(r'''
211 211 When Mercurial accepts more than one revision, they may be
212 212 specified individually, or provided as a topologically continuous
213 213 range, separated by the ":" character.
214 214
215 215 The syntax of range notation is [BEGIN]:[END], where BEGIN and END
216 216 are revision identifiers. Both BEGIN and END are optional. If
217 217 BEGIN is not specified, it defaults to revision number 0. If END
218 218 is not specified, it defaults to the tip. The range ":" thus means
219 219 "all revisions".
220 220
221 221 If BEGIN is greater than END, revisions are treated in reverse
222 222 order.
223 223
224 224 A range acts as a closed interval. This means that a range of 3:5
225 225 gives 3, 4 and 5. Similarly, a range of 9:6 gives 9, 8, 7, and 6.
226 226 ''')),
227 227
228 228 (['diffs'], _('Diff Formats'),
229 229 _(r'''
230 230 Mercurial's default format for showing changes between two
231 231 versions of a file is compatible with the unified format of GNU
232 232 diff, which can be used by GNU patch and many other standard
233 233 tools.
234 234
235 235 While this standard format is often enough, it does not encode the
236 236 following information:
237 237
238 238 - executable status and other permission bits
239 239 - copy or rename information
240 240 - changes in binary files
241 241 - creation or deletion of empty files
242 242
243 243 Mercurial also supports the extended diff format from the git VCS
244 244 which addresses these limitations. The git diff format is not
245 245 produced by default because a few widespread tools still do not
246 246 understand this format.
247 247
248 248 This means that when generating diffs from a Mercurial repository
249 249 (e.g. with "hg export"), you should be careful about things like
250 250 file copies and renames or other things mentioned above, because
251 251 when applying a standard diff to a different repository, this
252 252 extra information is lost. Mercurial's internal operations (like
253 253 push and pull) are not affected by this, because they use an
254 254 internal binary format for communicating changes.
255 255
256 256 To make Mercurial produce the git extended diff format, use the
257 257 --git option available for many commands, or set 'git = True' in
258 258 the [diff] section of your hgrc. You do not need to set this
259 259 option when importing diffs in this format or using them in the mq
260 260 extension.
261 261 ''')),
262 262 (['templating'], _('Template Usage'),
263 263 _(r'''
264 264 Mercurial allows you to customize output of commands through
265 265 templates. You can either pass in a template from the command
266 266 line, via the --template option, or select an existing
267 267 template-style (--style).
268 268
269 269 You can customize output for any "log-like" command: log,
270 270 outgoing, incoming, tip, parents, heads and glog.
271 271
272 272 Three styles are packaged with Mercurial: default (the style used
273 273 when no explicit preference is passed), compact and changelog.
274 274 Usage:
275 275
276 276 $ hg log -r1 --style changelog
277 277
278 278 A template is a piece of text, with markup to invoke variable
279 279 expansion:
280 280
281 281 $ hg log -r1 --template "{node}\n"
282 282 b56ce7b07c52de7d5fd79fb89701ea538af65746
283 283
284 284 Strings in curly braces are called keywords. The availability of
285 285 keywords depends on the exact context of the templater. These
286 286 keywords are usually available for templating a log-like command:
287 287
288 288 - author: String. The unmodified author of the changeset.
289 289 - branches: String. The name of the branch on which the changeset
290 290 was committed. Will be empty if the branch name was default.
291 291 - date: Date information. The date when the changeset was committed.
292 292 - desc: String. The text of the changeset description.
293 293 - diffstat: String. Statistics of changes with the following
294 294 format: "modified files: +added/-removed lines"
295 295 - files: List of strings. All files modified, added, or removed by
296 296 this changeset.
297 297 - file_adds: List of strings. Files added by this changeset.
298 298 - file_mods: List of strings. Files modified by this changeset.
299 299 - file_dels: List of strings. Files removed by this changeset.
300 300 - node: String. The changeset identification hash, as a
301 301 40-character hexadecimal string.
302 302 - parents: List of strings. The parents of the changeset.
303 303 - rev: Integer. The repository-local changeset revision number.
304 304 - tags: List of strings. Any tags associated with the changeset.
305 305
306 306 The "date" keyword does not produce human-readable output. If you
307 307 want to use a date in your output, you can use a filter to process
308 308 it. Filters are functions which return a string based on the input
309 309 variable. You can also use a chain of filters to get the desired
310 310 output:
311 311
312 312 $ hg tip --template "{date|isodate}\n"
313 313 2008-08-21 18:22 +0000
314 314
315 315 List of filters:
316 316
317 317 - addbreaks: Any text. Add an XHTML "<br />" tag before the end of
318 318 every line except the last.
319 319 - age: Date. Returns a human-readable date/time difference between
320 320 the given date/time and the current date/time.
321 321 - basename: Any text. Treats the text as a path, and returns the
322 322 last component of the path after splitting by the path
323 323 separator (ignoring trailing seprators). For example,
324 324 "foo/bar/baz" becomes "baz" and "foo/bar//" becomes "bar".
325 325 - stripdir: Treat the text as path and strip a directory level, if
326 326 possible. For example, "foo" and "foo/bar" becomes "foo".
327 327 - date: Date. Returns a date in a Unix date format, including
328 328 the timezone: "Mon Sep 04 15:13:13 2006 0700".
329 329 - domain: Any text. Finds the first string that looks like an
330 330 email address, and extracts just the domain component.
331 331 Example: 'User <user@example.com>' becomes 'example.com'.
332 332 - email: Any text. Extracts the first string that looks like an
333 333 email address. Example: 'User <user@example.com>' becomes
334 334 'user@example.com'.
335 335 - escape: Any text. Replaces the special XML/XHTML characters "&",
336 336 "<" and ">" with XML entities.
337 337 - fill68: Any text. Wraps the text to fit in 68 columns.
338 338 - fill76: Any text. Wraps the text to fit in 76 columns.
339 339 - firstline: Any text. Returns the first line of text.
340 340 - nonempty: Any text. Returns '(none)' if the string is empty.
341 341 - hgdate: Date. Returns the date as a pair of numbers:
342 342 "1157407993 25200" (Unix timestamp, timezone offset).
343 343 - isodate: Date. Returns the date in ISO 8601 format.
344 - localdate: Date. Converts a date to local date.
344 345 - obfuscate: Any text. Returns the input text rendered as a
345 346 sequence of XML entities.
346 347 - person: Any text. Returns the text before an email address.
347 348 - rfc822date: Date. Returns a date using the same format used
348 349 in email headers.
349 350 - short: Changeset hash. Returns the short form of a changeset
350 351 hash, i.e. a 12-byte hexadecimal string.
351 352 - shortdate: Date. Returns a date like "2006-09-18".
352 353 - strip: Any text. Strips all leading and trailing whitespace.
353 354 - tabindent: Any text. Returns the text, with every line except
354 355 the first starting with a tab character.
355 356 - urlescape: Any text. Escapes all "special" characters. For
356 357 example, "foo bar" becomes "foo%20bar".
357 358 - user: Any text. Returns the user portion of an email address.
358 359 ''')),
359 360
360 361 (['urls'], _('URL Paths'),
361 362 _(r'''
362 363 Valid URLs are of the form:
363 364
364 365 local/filesystem/path (or file://local/filesystem/path)
365 366 http://[user[:pass]@]host[:port]/[path]
366 367 https://[user[:pass]@]host[:port]/[path]
367 368 ssh://[user[:pass]@]host[:port]/[path]
368 369
369 370 Paths in the local filesystem can either point to Mercurial
370 371 repositories or to bundle files (as created by 'hg bundle' or
371 372 'hg incoming --bundle').
372 373
373 374 An optional identifier after # indicates a particular branch, tag,
374 375 or changeset to use from the remote repository.
375 376
376 377 Some features, such as pushing to http:// and https:// URLs are
377 378 only possible if the feature is explicitly enabled on the remote
378 379 Mercurial server.
379 380
380 381 Some notes about using SSH with Mercurial:
381 382 - SSH requires an accessible shell account on the destination
382 383 machine and a copy of hg in the remote path or specified with as
383 384 remotecmd.
384 385 - path is relative to the remote user's home directory by default.
385 386 Use an extra slash at the start of a path to specify an absolute path:
386 387 ssh://example.com//tmp/repository
387 388 - Mercurial doesn't use its own compression via SSH; the right
388 389 thing to do is to configure it in your ~/.ssh/config, e.g.:
389 390 Host *.mylocalnetwork.example.com
390 391 Compression no
391 392 Host *
392 393 Compression yes
393 394 Alternatively specify "ssh -C" as your ssh command in your hgrc
394 395 or with the --ssh command line option.
395 396
396 397 These URLs can all be stored in your hgrc with path aliases under
397 398 the [paths] section like so:
398 399 [paths]
399 400 alias1 = URL1
400 401 alias2 = URL2
401 402 ...
402 403
403 404 You can then use the alias for any command that uses a URL (for
404 405 example 'hg pull alias1' would pull from the 'alias1' path).
405 406
406 407 Two path aliases are special because they are used as defaults
407 408 when you do not provide the URL to a command:
408 409
409 410 default:
410 411 When you create a repository with hg clone, the clone command
411 412 saves the location of the source repository as the new
412 413 repository's 'default' path. This is then used when you omit
413 414 path from push- and pull-like commands (including incoming and
414 415 outgoing).
415 416
416 417 default-push:
417 418 The push command will look for a path named 'default-push', and
418 419 prefer it over 'default' if both are defined.
419 420 ''')),
420 421 )
@@ -1,209 +1,210 b''
1 1 # template-filters.py - common template expansion filters
2 2 #
3 3 # Copyright 2005-2008 Matt Mackall <mpm@selenic.com>
4 4 #
5 5 # This software may be used and distributed according to the terms of the
6 6 # GNU General Public License version 2, incorporated herein by reference.
7 7
8 8 import cgi, re, os, time, urllib, textwrap
9 9 import util, encoding
10 10
11 11 def stringify(thing):
12 12 '''turn nested template iterator into string.'''
13 13 if hasattr(thing, '__iter__') and not isinstance(thing, str):
14 14 return "".join([stringify(t) for t in thing if t is not None])
15 15 return str(thing)
16 16
17 17 agescales = [("second", 1),
18 18 ("minute", 60),
19 19 ("hour", 3600),
20 20 ("day", 3600 * 24),
21 21 ("week", 3600 * 24 * 7),
22 22 ("month", 3600 * 24 * 30),
23 23 ("year", 3600 * 24 * 365)]
24 24
25 25 agescales.reverse()
26 26
27 27 def age(date):
28 28 '''turn a (timestamp, tzoff) tuple into an age string.'''
29 29
30 30 def plural(t, c):
31 31 if c == 1:
32 32 return t
33 33 return t + "s"
34 34 def fmt(t, c):
35 35 return "%d %s" % (c, plural(t, c))
36 36
37 37 now = time.time()
38 38 then = date[0]
39 39 if then > now:
40 40 return 'in the future'
41 41
42 42 delta = max(1, int(now - then))
43 43 for t, s in agescales:
44 44 n = delta / s
45 45 if n >= 2 or s == 1:
46 46 return fmt(t, n)
47 47
48 48 para_re = None
49 49 space_re = None
50 50
51 51 def fill(text, width):
52 52 '''fill many paragraphs.'''
53 53 global para_re, space_re
54 54 if para_re is None:
55 55 para_re = re.compile('(\n\n|\n\\s*[-*]\\s*)', re.M)
56 56 space_re = re.compile(r' +')
57 57
58 58 def findparas():
59 59 start = 0
60 60 while True:
61 61 m = para_re.search(text, start)
62 62 if not m:
63 63 w = len(text)
64 64 while w > start and text[w-1].isspace(): w -= 1
65 65 yield text[start:w], text[w:]
66 66 break
67 67 yield text[start:m.start(0)], m.group(1)
68 68 start = m.end(1)
69 69
70 70 return "".join([space_re.sub(' ', textwrap.fill(para, width)) + rest
71 71 for para, rest in findparas()])
72 72
73 73 def firstline(text):
74 74 '''return the first line of text'''
75 75 try:
76 76 return text.splitlines(1)[0].rstrip('\r\n')
77 77 except IndexError:
78 78 return ''
79 79
80 80 def nl2br(text):
81 81 '''replace raw newlines with xhtml line breaks.'''
82 82 return text.replace('\n', '<br/>\n')
83 83
84 84 def obfuscate(text):
85 85 text = unicode(text, encoding.encoding, 'replace')
86 86 return ''.join(['&#%d;' % ord(c) for c in text])
87 87
88 88 def domain(author):
89 89 '''get domain of author, or empty string if none.'''
90 90 f = author.find('@')
91 91 if f == -1: return ''
92 92 author = author[f+1:]
93 93 f = author.find('>')
94 94 if f >= 0: author = author[:f]
95 95 return author
96 96
97 97 def person(author):
98 98 '''get name of author, or else username.'''
99 99 f = author.find('<')
100 100 if f == -1: return util.shortuser(author)
101 101 return author[:f].rstrip()
102 102
103 103 def indent(text, prefix):
104 104 '''indent each non-empty line of text after first with prefix.'''
105 105 lines = text.splitlines()
106 106 num_lines = len(lines)
107 107 def indenter():
108 108 for i in xrange(num_lines):
109 109 l = lines[i]
110 110 if i and l.strip():
111 111 yield prefix
112 112 yield l
113 113 if i < num_lines - 1 or text.endswith('\n'):
114 114 yield '\n'
115 115 return "".join(indenter())
116 116
117 117 def permissions(flags):
118 118 if "l" in flags:
119 119 return "lrwxrwxrwx"
120 120 if "x" in flags:
121 121 return "-rwxr-xr-x"
122 122 return "-rw-r--r--"
123 123
124 124 def xmlescape(text):
125 125 text = (text
126 126 .replace('&', '&amp;')
127 127 .replace('<', '&lt;')
128 128 .replace('>', '&gt;')
129 129 .replace('"', '&quot;')
130 130 .replace("'", '&#39;')) # &apos; invalid in HTML
131 131 return re.sub('[\x00-\x08\x0B\x0C\x0E-\x1F]', ' ', text)
132 132
133 133 _escapes = [
134 134 ('\\', '\\\\'), ('"', '\\"'), ('\t', '\\t'), ('\n', '\\n'),
135 135 ('\r', '\\r'), ('\f', '\\f'), ('\b', '\\b'),
136 136 ]
137 137
138 138 def jsonescape(s):
139 139 for k, v in _escapes:
140 140 s = s.replace(k, v)
141 141 return s
142 142
143 143 def json(obj):
144 144 if obj is None or obj is False or obj is True:
145 145 return {None: 'null', False: 'false', True: 'true'}[obj]
146 146 elif isinstance(obj, int) or isinstance(obj, float):
147 147 return str(obj)
148 148 elif isinstance(obj, str):
149 149 return '"%s"' % jsonescape(obj)
150 150 elif isinstance(obj, unicode):
151 151 return json(obj.encode('utf-8'))
152 152 elif hasattr(obj, 'keys'):
153 153 out = []
154 154 for k, v in obj.iteritems():
155 155 s = '%s: %s' % (json(k), json(v))
156 156 out.append(s)
157 157 return '{' + ', '.join(out) + '}'
158 158 elif hasattr(obj, '__iter__'):
159 159 out = []
160 160 for i in obj:
161 161 out.append(json(i))
162 162 return '[' + ', '.join(out) + ']'
163 163 else:
164 164 raise TypeError('cannot encode type %s' % obj.__class__.__name__)
165 165
166 166 def stripdir(text):
167 167 '''Treat the text as path and strip a directory level, if possible.'''
168 168 dir = os.path.dirname(text)
169 169 if dir == "":
170 170 return os.path.basename(text)
171 171 else:
172 172 return dir
173 173
174 174 def nonempty(str):
175 175 return str or "(none)"
176 176
177 177 filters = {
178 178 "addbreaks": nl2br,
179 179 "basename": os.path.basename,
180 180 "stripdir": stripdir,
181 181 "age": age,
182 182 "date": lambda x: util.datestr(x),
183 183 "domain": domain,
184 184 "email": util.email,
185 185 "escape": lambda x: cgi.escape(x, True),
186 186 "fill68": lambda x: fill(x, width=68),
187 187 "fill76": lambda x: fill(x, width=76),
188 188 "firstline": firstline,
189 189 "tabindent": lambda x: indent(x, '\t'),
190 190 "hgdate": lambda x: "%d %d" % x,
191 191 "isodate": lambda x: util.datestr(x, '%Y-%m-%d %H:%M %1%2'),
192 192 "isodatesec": lambda x: util.datestr(x, '%Y-%m-%d %H:%M:%S %1%2'),
193 193 "json": json,
194 194 "jsonescape": jsonescape,
195 "localdate": lambda x: (x[0], util.makedate()[1]),
195 196 "nonempty": nonempty,
196 197 "obfuscate": obfuscate,
197 198 "permissions": permissions,
198 199 "person": person,
199 200 "rfc822date": lambda x: util.datestr(x, "%a, %d %b %Y %H:%M:%S %1%2"),
200 201 "rfc3339date": lambda x: util.datestr(x, "%Y-%m-%dT%H:%M:%S%1:%2"),
201 202 "short": lambda x: x[:12],
202 203 "shortdate": util.shortdate,
203 204 "stringify": stringify,
204 205 "strip": lambda x: x.strip(),
205 206 "urlescape": lambda x: urllib.quote(x),
206 207 "user": lambda x: util.shortuser(x),
207 208 "stringescape": lambda x: x.encode('string_escape'),
208 209 "xmlescape": xmlescape,
209 210 }
General Comments 0
You need to be logged in to leave comments. Login now