From ee908c00deb92d2acffbb92be761b2eb169e8a89 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sun, 4 Jul 2021 18:21:41 +0100 Subject: [PATCH] Add documentation for the overview of `package fmt` --- core/fmt/doc.odin | 141 ++++++++++++++++++++++++++++++++++++++++++++++ core/fmt/fmt.odin | 3 +- 2 files changed, 143 insertions(+), 1 deletion(-) create mode 100644 core/fmt/doc.odin diff --git a/core/fmt/doc.odin b/core/fmt/doc.odin new file mode 100644 index 000000000..5984da950 --- /dev/null +++ b/core/fmt/doc.odin @@ -0,0 +1,141 @@ +/* +package fmt implemented formatted I/O with procedures similar to C's printf and Python's format. +The format 'verbs' are derived from C's but simpler. + +Printing + +The verbs: + +General: + %v the value in a default format + %#v an expanded format of %v with newlines and indentation + %T an Odin-syntax representation of the type of the value + %% a literal percent sign; consumes no value + {{ a literal open brace; consumes no value + }} a literal close brace; consumes no value + {:v} equivalent to %v (Python-like formatting syntax) + +Boolean: + %t the word "true" or "false" +Integer: + %b base 2 + %c the character represented by the corresponding Unicode code point + %r synonym for %c + %o base 8 + %d base 10 + %i base 10 + %z base 12 + %x base 16, with lower-case letters for a-f + %X base 16, with upper-case letters for A-F + %U Unicode format: U+1234; same as "U+%04X" +Floating-point, complex numbers, and quaternions: + %e scientific notation, e.g. -1.23456e+78 + %E scientific notation, e.g. -1.23456E+78 + %f decimal point but no exponent, e.g. 123.456 + %F synonym for %f + %h hexadecimal (lower-case) representation with 0h prefix (0h01234abcd) + %H hexadecimal (upper-case) representation with 0H prefix (0h01234ABCD) +String and slice of bytes + %s the uninterpreted bytes of the string or slice + %q a double-quoted string safely escaped with Odin syntax + %x base 16, lower-case, two characters per byte + %X base 16, upper-case, two characters per byte +Slice and dynamic array: + %p address of the 0th element in base 16 notation (upper-case), with leading 0x +Pointer: + %p base 16 notation (upper-case), with leading 0x + The %b, %d, %o, %z, %x, %X verbs also work with pointers, + treating it as if it was an integer +Enums: + %s prints the name of the enum field + The %i, %d, %f verbs also work with enums, + treating it as if it was a number + +For compound values, the elements are printed using these rules recursively; laid out like the following: + struct: {name0 = field0, name1 = field1, ...} + array [elem0, elem1, elem2, ...] + enumerated array [key0 = elem0, key1 = elem1, key2 = elem2, ...] + maps: map[key0 = value0, key1 = value1, ...] + bit sets {key0 = elem0, key1 = elem1, ...} + pointer to above: &{}, &[], &map[] + +Width is specified by an optional decimal number immediately preceding the verb. +If not present, the width is whatever is necessary to represent the value. +Precision is specified after the (optional) width followed by a period followed by a decimal number. +If no period is present, a default precision is used. +A period with no following number specifies a precision of 0. +Examples: + %f default width, default precision + %8f width 8, default precision + %.3f default width, precision 2 + %8.3f width 8, precision 3 + %8.f width 8, precision 0 + +Width and precision are measured in units of Unicode code points (runes). +n.b. C's printf uses units of bytes + + +Other flags: + + always print a sign for numeric values + - pad with spaces on the right rather the left (left-justify the field) + # alternate format: + add leading 0b for binary (%#b) + add leading 0o for octal (%#o) + add leading 0z for dozenal (%#z) + add leading 0x or 0X for hexadecimal (%#x or %#X) + remove leading 0x for %p (%#p) + + ' ' (space) leave a space for elided sign in numbers (% d) + 0 pad with leading zeros rather than spaces + + +Flags are ignored by verbs that don't expect them + + +For each printf-like procedure, there is a print function that takes no +format, and is equivalent to doing %v for every value and inserts a separator +between each value (default is a single space). +Another procedure println which has the same functionality as print but appends a newline. + +Explicit argument indices: + +In printf-like procedures, the default behaviour is for each formatting verb to format successive +arguments passed in the call. However, the notation [n] immediately before the verb indicates that +the nth zero-index argument is to be formatted instead. +The same notation before an '*' for a width or precision selecting the argument index holding the value. +Python-like syntax with argument indices differs for the selecting the argument index: {N:v} + +Examples: + fmt.printf("%[1]d %[0]d\n", 13, 37); // C-like syntax + fmt.printf("{1:d} {0:d}\n", 13, 37); // Python-like syntax +prints "37 13", whilst: + fmt.printf("%[2]*.[1]*[0]f\n", 17.0, 2, 6); // C-like syntax + fmt.printf("%{0:[2]*.[1]*f}\n", 17.0, 2, 6); // Python-like syntax +equivalent to: + fmt.printf("%6.2f\n", 17.0, 2, 6); // C-like syntax + fmt.printf("{:6.2f}\n", 17.0, 2, 6); // Python-like syntax +prints "17.00" + +Format errors: + +If an invalid argument is given for a verb, such as providing a string to %d, the generated string +will contain a description of the problem. For example: + + Bad enum value: + %!(BAD ENUM VALUE) + Too many arguments: + %!(EXTRA , , ...) + Too few arguments: + %!(MISSING ARGUMENT) + Invalid width or precision + %!(BAD WIDTH) + %!(BAD PRECISION) + Missing verb: + %!(NO VERB) + Invalid or invalid use of argument index: + %!(BAD ARGUMENT NUMBER) + Missing close brace when using Python-like formatting syntax: + %!(MISSING CLOSE BRACE) + +*/ +package fmt diff --git a/core/fmt/fmt.odin b/core/fmt/fmt.odin index 3b3716a15..96a120c2f 100644 --- a/core/fmt/fmt.odin +++ b/core/fmt/fmt.odin @@ -1013,6 +1013,7 @@ fmt_pointer :: proc(fi: ^Info, p: rawptr, verb: rune) { case 'b': _fmt_int(fi, u, 2, false, 8*size_of(rawptr), __DIGITS_UPPER); case 'o': _fmt_int(fi, u, 8, false, 8*size_of(rawptr), __DIGITS_UPPER); case 'i', 'd': _fmt_int(fi, u, 10, false, 8*size_of(rawptr), __DIGITS_UPPER); + case 'z': _fmt_int(fi, u, 12, false, 8*size_of(rawptr), __DIGITS_UPPER); case 'x': _fmt_int(fi, u, 16, false, 8*size_of(rawptr), __DIGITS_UPPER); case 'X': _fmt_int(fi, u, 16, false, 8*size_of(rawptr), __DIGITS_UPPER); @@ -1082,7 +1083,7 @@ fmt_enum :: proc(fi: ^Info, v: any, verb: rune) { case 's', 'v': str, ok := enum_value_to_string(v); if !ok { - str = "!%(BAD ENUM VALUE)"; + str = "%!(BAD ENUM VALUE)"; } io.write_string(fi.writer, str); }