X-Git-Url: https://git.distorted.org.uk/~mdw/chopwood/blobdiff_plain/a2916c0635fec5b45ad742904db9f5769b48f53d..efe96413119f689752c6395c68531b17b70c2743:/format.py?ds=inline diff --git a/format.py b/format.py index 231f922..2b90cb9 100644 --- a/format.py +++ b/format.py @@ -296,7 +296,7 @@ class NextArg (BaseArg): else: return None NEXTARG = NextArg() -## Because a `NextArg' collectors are used so commonly, and they're all the +## Because `NextArg' collectors are used so commonly, and they're all the ## same, we make a distinguished one and try to use that instead. Nothing ## goes badly wrong if you don't use this, but you'll use more memory than ## strictly necessary. @@ -389,6 +389,8 @@ def parse_arg(): A `+' means `the next pushed-back or positional argument'. It's useful to be able to say this explicitly so that indexing and attribute references can be attached to it: for example, in `~={thing}@[~={+.attr}A~]'. + Similarly, `@' designates the same argument, except that it is not + consumed. An integer argument selects the positional argument with that index; a negative index counts backwards from the end, as is usual in Python. @@ -526,7 +528,7 @@ VARNEXT = VariableParameter(NEXTARG) ## whether the `@' and `:' modifiers were set in the control string. ## GETARG is the collector for the operation's argument(s). The PARAMS ## are a list of parameter collectors. Finally, CHAR is the directive -## character (so directives with siilar behaviour can use the same +## character (so directives with similar behaviour can use the same ## class). class FormatLiteral (object): @@ -772,7 +774,45 @@ def compile(control): """ Parse the whole CONTROL string, returning the corresponding formatting operator. + + A format control string consists of formatting directives, introduced by + the `~' character, and literal text. Literal text is simply output as-is. + Formatting directives may read /arguments/ which are provided as additional + inputs to the `format' function, and are typically items to be written to + the output in some form, and /parameters/, which control the formatting of + the arguments, and may be supplied in the control string, or themselves + read from arguments. A directive may also carry up to two flags, `@' and + `:'. + + The effects of the directive are determined by the corresponding formatting + operation, an object found by looking up the directive's identifying + character in `COMPILE.opmaps', which is a list of dictionaries. The + character is converted to upper-case (if it is alphabetic), and then the + dictionaries are examined in order: the first match found wins. See the + description of the `Formatting protocol' for details of how formatting + operations work. + + A formatting directive has the following syntax. + + DIRECTIVE ::= `~' [PARAMS] [`=' ARG] FLAGS CHAR + + PARAMS ::= PARAM [`,' PARAMS] + + PARAM ::= EMPTY | INT | `#' | `'' CHAR | `v' | `!' ARG + + FLAGS ::= [[ `@' | `:' ]]* + + (The useful but unusual notation [[ X | Y | ... ]]* denotes a sequence of + items drawn from the listed alternatives, each appearing at most once. See + the function `parse_arg' for the syntax of ARG.) + + An empty PARAM is equivalent to omitting the parameter; `#' is the number + of remaining positional arguments; `!ARG' reads the parameter value from + the argument; `v' is equivalent to `!+', as a convenient abbreviation and + for Common Lisp compatibility. The `=ARG' notation indicates which + argument(s) should be processed by the operation: the default is `=+' """ + if not isinstance(control, basestring): return control pp = [] with COMPILE.bind(control = control, start = 0, end = len(control), delim = ''): @@ -833,10 +873,7 @@ def format(out, control, *args, **kw): raise TypeError, out ## Turn the control argument into a formatting operation. - if isinstance(control, basestring): - op = compile(control) - else: - op = control + op = compile(control) ## Invoke the formatting operation in the correct environment. with FORMAT.bind(write = write, pushback = [], @@ -1221,7 +1258,7 @@ class FormatIteration (BaseFormatOperation): then the enclosed directives are applied once even if the argument sequence is empty. - If the formatting directives are empty then a formatting string is fetched + If the formatting directives are empty then a formatting control is fetched using the argument collector associated with the closing delimiter. """ @@ -1310,7 +1347,7 @@ class FormatRecursive (BaseFormatOperation): """ ~?: Recursive formatting. - Without `@', read a pair of arguments: use the first as a format string, + Without `@', read a pair of arguments: use the first as a format control, and apply it to the arguments extracted from the second (which may be a sequence or a map).