diff options
| author | Basil L. Contovounesios | 2020-05-28 00:53:42 +0100 |
|---|---|---|
| committer | Basil L. Contovounesios | 2020-06-02 14:58:25 +0100 |
| commit | b07e3b1d97e73c5cf0cd60edf4838b555530bbf0 (patch) | |
| tree | 6d0265225716fe97e25a2483e763236cce842238 | |
| parent | 0260d2d2dbb2607e7310bdb518b7b6c0f58f5f98 (diff) | |
| download | emacs-b07e3b1d97e73c5cf0cd60edf4838b555530bbf0.tar.gz emacs-b07e3b1d97e73c5cf0cd60edf4838b555530bbf0.zip | |
Improve format-spec documentation (bug#41571)
* doc/lispref/text.texi (Interpolated Strings): Move from here...
* doc/lispref/strings.texi (Custom Format Strings): ...to here,
renaming the node and clarifying the documentation.
(Formatting Strings): End node with sentence referring to the next
one.
* lisp/format-spec.el (format-spec): Clarify docstring.
| -rw-r--r-- | doc/lispref/strings.texi | 176 | ||||
| -rw-r--r-- | doc/lispref/text.texi | 64 | ||||
| -rw-r--r-- | lisp/format-spec.el | 49 |
3 files changed, 206 insertions, 83 deletions
diff --git a/doc/lispref/strings.texi b/doc/lispref/strings.texi index 70c3b3cf4be..4a7bda57c4e 100644 --- a/doc/lispref/strings.texi +++ b/doc/lispref/strings.texi | |||
| @@ -28,6 +28,7 @@ keyboard character events. | |||
| 28 | * Text Comparison:: Comparing characters or strings. | 28 | * Text Comparison:: Comparing characters or strings. |
| 29 | * String Conversion:: Converting to and from characters and strings. | 29 | * String Conversion:: Converting to and from characters and strings. |
| 30 | * Formatting Strings:: @code{format}: Emacs's analogue of @code{printf}. | 30 | * Formatting Strings:: @code{format}: Emacs's analogue of @code{printf}. |
| 31 | * Custom Format Strings:: Formatting custom @code{format} specifications. | ||
| 31 | * Case Conversion:: Case conversion functions. | 32 | * Case Conversion:: Case conversion functions. |
| 32 | * Case Tables:: Customizing case conversion. | 33 | * Case Tables:: Customizing case conversion. |
| 33 | @end menu | 34 | @end menu |
| @@ -1122,6 +1123,181 @@ may be problematic; for example, @samp{%d} and @samp{%g} can mishandle | |||
| 1122 | NaNs and can lose precision and type, and @samp{#x%x} and @samp{#o%o} | 1123 | NaNs and can lose precision and type, and @samp{#x%x} and @samp{#o%o} |
| 1123 | can mishandle negative integers. @xref{Input Functions}. | 1124 | can mishandle negative integers. @xref{Input Functions}. |
| 1124 | 1125 | ||
| 1126 | The functions described in this section accept a fixed set of | ||
| 1127 | specification characters. The next section describes a function | ||
| 1128 | @code{format-spec} which can accept custom specification characters, | ||
| 1129 | such as @samp{%a} or @samp{%z}. | ||
| 1130 | |||
| 1131 | @node Custom Format Strings | ||
| 1132 | @section Custom Format Strings | ||
| 1133 | @cindex custom format string | ||
| 1134 | @cindex custom @samp{%}-sequence in format | ||
| 1135 | |||
| 1136 | Sometimes it is useful to allow users and Lisp programs alike to | ||
| 1137 | control how certain text is generated via custom format control | ||
| 1138 | strings. For example, a format string could control how to display | ||
| 1139 | someone's forename, surname, and email address. Using the function | ||
| 1140 | @code{format} described in the previous section, the format string | ||
| 1141 | could be something like @w{@code{"%s %s <%s>"}}. This approach | ||
| 1142 | quickly becomes impractical, however, as it can be unclear which | ||
| 1143 | specification character corresponds to which piece of information. | ||
| 1144 | |||
| 1145 | A more convenient format string for such cases would be something like | ||
| 1146 | @w{@code{"%f %l <%e>"}}, where each specification character carries | ||
| 1147 | more semantic information and can easily be rearranged relative to | ||
| 1148 | other specification characters, making such format strings more easily | ||
| 1149 | customizable by the user. | ||
| 1150 | |||
| 1151 | The function @code{format-spec} described in this section performs a | ||
| 1152 | similar function to @code{format}, except it operates on format | ||
| 1153 | control strings that use arbitrary specification characters. | ||
| 1154 | |||
| 1155 | @defun format-spec template spec-alist &optional only-present | ||
| 1156 | This function returns a string produced from the format string | ||
| 1157 | @var{template} according to conversions specified in @var{spec-alist}, | ||
| 1158 | which is an alist (@pxref{Association Lists}) of the form | ||
| 1159 | @w{@code{(@var{letter} . @var{replacement})}}. Each specification | ||
| 1160 | @code{%@var{letter}} in @var{template} will be replaced by | ||
| 1161 | @var{replacement} when formatting the resulting string. | ||
| 1162 | |||
| 1163 | The characters in @var{template}, other than the format | ||
| 1164 | specifications, are copied directly into the output, including their | ||
| 1165 | text properties, if any. Any text properties of the format | ||
| 1166 | specifications are copied to their replacements. | ||
| 1167 | |||
| 1168 | Using an alist to specify conversions gives rise to some useful | ||
| 1169 | properties: | ||
| 1170 | |||
| 1171 | @itemize @bullet | ||
| 1172 | @item | ||
| 1173 | If @var{spec-alist} contains more unique @var{letter} keys than there | ||
| 1174 | are unique specification characters in @var{template}, the unused keys | ||
| 1175 | are simply ignored. | ||
| 1176 | @item | ||
| 1177 | If @var{spec-alist} contains more than one association with the same | ||
| 1178 | @var{letter}, the closest one to the start of the list is used. | ||
| 1179 | @item | ||
| 1180 | If @var{template} contains the same specification character more than | ||
| 1181 | once, then the same @var{replacement} found in @var{spec-alist} is | ||
| 1182 | used as a basis for all of that character's substitutions. | ||
| 1183 | @item | ||
| 1184 | The order of specifications in @var{template} need not correspond to | ||
| 1185 | the order of associations in @var{spec-alist}. | ||
| 1186 | @end itemize | ||
| 1187 | |||
| 1188 | The optional argument @var{only-present} indicates how to handle | ||
| 1189 | specification characters in @var{template} that are not found in | ||
| 1190 | @var{spec-alist}. If it is @code{nil} or omitted, the function | ||
| 1191 | signals an error. Otherwise, those format specifications and any | ||
| 1192 | occurrences of @samp{%%} in @var{template} are left verbatim in the | ||
| 1193 | output, including their text properties, if any. | ||
| 1194 | @end defun | ||
| 1195 | |||
| 1196 | The syntax of format specifications accepted by @code{format-spec} is | ||
| 1197 | similar, but not identical, to that accepted by @code{format}. In | ||
| 1198 | both cases, a format specification is a sequence of characters | ||
| 1199 | beginning with @samp{%} and ending with an alphabetic letter such as | ||
| 1200 | @samp{s}. | ||
| 1201 | |||
| 1202 | Unlike @code{format}, which assigns specific meanings to a fixed set | ||
| 1203 | of specification characters, @code{format-spec} accepts arbitrary | ||
| 1204 | specification characters and treats them all equally. For example: | ||
| 1205 | |||
| 1206 | @example | ||
| 1207 | @group | ||
| 1208 | (setq my-site-info | ||
| 1209 | (list (cons ?s system-name) | ||
| 1210 | (cons ?t (symbol-name system-type)) | ||
| 1211 | (cons ?c system-configuration) | ||
| 1212 | (cons ?v emacs-version) | ||
| 1213 | (cons ?e invocation-name) | ||
| 1214 | (cons ?p (number-to-string (emacs-pid))) | ||
| 1215 | (cons ?a user-mail-address) | ||
| 1216 | (cons ?n user-full-name))) | ||
| 1217 | |||
| 1218 | (format-spec "%e %v (%c)" my-site-info) | ||
| 1219 | @result{} "emacs 27.1 (x86_64-pc-linux-gnu)" | ||
| 1220 | |||
| 1221 | (format-spec "%n <%a>" my-site-info) | ||
| 1222 | @result{} "Emacs Developers <emacs-devel@@gnu.org>" | ||
| 1223 | @end group | ||
| 1224 | @end example | ||
| 1225 | |||
| 1226 | A format specification can include any number of the following flag | ||
| 1227 | characters immediately after the @samp{%} to modify aspects of the | ||
| 1228 | substitution. | ||
| 1229 | |||
| 1230 | @table @samp | ||
| 1231 | @item 0 | ||
| 1232 | This flag causes any padding specified by the width to consist of | ||
| 1233 | @samp{0} characters instead of spaces. | ||
| 1234 | |||
| 1235 | @item - | ||
| 1236 | This flag causes any padding specified by the width to be inserted on | ||
| 1237 | the right rather than the left. | ||
| 1238 | |||
| 1239 | @item < | ||
| 1240 | This flag causes the substitution to be truncated on the left to the | ||
| 1241 | given width, if specified. | ||
| 1242 | |||
| 1243 | @item > | ||
| 1244 | This flag causes the substitution to be truncated on the right to the | ||
| 1245 | given width, if specified. | ||
| 1246 | |||
| 1247 | @item ^ | ||
| 1248 | This flag converts the substituted text to upper case (@pxref{Case | ||
| 1249 | Conversion}). | ||
| 1250 | |||
| 1251 | @item _ | ||
| 1252 | This flag converts the substituted text to lower case (@pxref{Case | ||
| 1253 | Conversion}). | ||
| 1254 | @end table | ||
| 1255 | |||
| 1256 | The result of using contradictory flags (for instance, both upper and | ||
| 1257 | lower case) is undefined. | ||
| 1258 | |||
| 1259 | As is the case with @code{format}, a format specification can include | ||
| 1260 | a width, which is a decimal number that appears after any flags. If a | ||
| 1261 | substitution contains fewer characters than its specified width, it is | ||
| 1262 | padded on the left: | ||
| 1263 | |||
| 1264 | @example | ||
| 1265 | @group | ||
| 1266 | (format-spec "%8a is padded on the left with spaces" | ||
| 1267 | '((?a . "alpha"))) | ||
| 1268 | @result{} " alpha is padded on the left with spaces" | ||
| 1269 | @end group | ||
| 1270 | @end example | ||
| 1271 | |||
| 1272 | Here is a more complicated example that combines several | ||
| 1273 | aforementioned features: | ||
| 1274 | |||
| 1275 | @example | ||
| 1276 | @group | ||
| 1277 | (setq my-battery-info | ||
| 1278 | (list (cons ?p "73") ; Percentage | ||
| 1279 | (cons ?L "Battery") ; Status | ||
| 1280 | (cons ?t "2:23") ; Remaining time | ||
| 1281 | (cons ?c "24330") ; Capacity | ||
| 1282 | (cons ?r "10.6"))) ; Rate of discharge | ||
| 1283 | |||
| 1284 | (format-spec "%>^-3L : %3p%% (%05t left)" my-battery-info) | ||
| 1285 | @result{} "BAT : 73% (02:23 left)" | ||
| 1286 | |||
| 1287 | (format-spec "%>^-3L : %3p%% (%05t left)" | ||
| 1288 | (cons (cons ?L "AC") | ||
| 1289 | my-battery-info)) | ||
| 1290 | @result{} "AC : 73% (02:23 left)" | ||
| 1291 | @end group | ||
| 1292 | @end example | ||
| 1293 | |||
| 1294 | As the examples in this section illustrate, @code{format-spec} is | ||
| 1295 | often used for selectively formatting an assortment of different | ||
| 1296 | pieces of information. This is useful in programs that provide | ||
| 1297 | user-customizable format strings, as the user can choose to format | ||
| 1298 | with a regular syntax and in any desired order only a subset of the | ||
| 1299 | information that the program makes available. | ||
| 1300 | |||
| 1125 | @node Case Conversion | 1301 | @node Case Conversion |
| 1126 | @section Case Conversion in Lisp | 1302 | @section Case Conversion in Lisp |
| 1127 | @cindex upper case | 1303 | @cindex upper case |
diff --git a/doc/lispref/text.texi b/doc/lispref/text.texi index de436fa9e61..a14867e1d1a 100644 --- a/doc/lispref/text.texi +++ b/doc/lispref/text.texi | |||
| @@ -58,7 +58,6 @@ the character after point. | |||
| 58 | of another buffer. | 58 | of another buffer. |
| 59 | * Decompression:: Dealing with compressed data. | 59 | * Decompression:: Dealing with compressed data. |
| 60 | * Base 64:: Conversion to or from base 64 encoding. | 60 | * Base 64:: Conversion to or from base 64 encoding. |
| 61 | * Interpolated Strings:: Formatting Customizable Strings. | ||
| 62 | * Checksum/Hash:: Computing cryptographic hashes. | 61 | * Checksum/Hash:: Computing cryptographic hashes. |
| 63 | * GnuTLS Cryptography:: Cryptographic algorithms imported from GnuTLS. | 62 | * GnuTLS Cryptography:: Cryptographic algorithms imported from GnuTLS. |
| 64 | * Parsing HTML/XML:: Parsing HTML and XML. | 63 | * Parsing HTML/XML:: Parsing HTML and XML. |
| @@ -4662,69 +4661,6 @@ If optional argument @var{base64url} is non-@code{nil}, then padding | |||
| 4662 | is optional, and the URL variant of base 64 encoding is used. | 4661 | is optional, and the URL variant of base 64 encoding is used. |
| 4663 | @end defun | 4662 | @end defun |
| 4664 | 4663 | ||
| 4665 | |||
| 4666 | @node Interpolated Strings | ||
| 4667 | @section Formatting Customizable Strings | ||
| 4668 | |||
| 4669 | It is, in some circumstances, useful to present users with a string to | ||
| 4670 | be customized that can then be expanded programmatically. For | ||
| 4671 | instance, @code{erc-header-line-format} is @code{"%n on %t (%m,%l) | ||
| 4672 | %o"}, and each of those characters after the percent signs are | ||
| 4673 | expanded when the header line is computed. To do this, the | ||
| 4674 | @code{format-spec} function is used: | ||
| 4675 | |||
| 4676 | @defun format-spec format specification &optional only-present | ||
| 4677 | @var{format} is the format specification string as in the example | ||
| 4678 | above. @var{specification} is an alist that has elements where the | ||
| 4679 | @code{car} is a character and the @code{cdr} is the substitution. | ||
| 4680 | |||
| 4681 | If @var{only-present} is @code{nil}, errors will be signaled if a | ||
| 4682 | format character has been used that's not present in | ||
| 4683 | @var{specification}. If it's non-@code{nil}, that format | ||
| 4684 | specification is left verbatim in the result. | ||
| 4685 | @end defun | ||
| 4686 | |||
| 4687 | Here's a trivial example: | ||
| 4688 | |||
| 4689 | @example | ||
| 4690 | (format-spec "su - %u %l" | ||
| 4691 | `((?u . ,(user-login-name)) | ||
| 4692 | (?l . "ls"))) | ||
| 4693 | @result{} "su - foo ls" | ||
| 4694 | @end example | ||
| 4695 | |||
| 4696 | In addition to allowing padding/limiting to a certain length, the | ||
| 4697 | following modifiers can be used: | ||
| 4698 | |||
| 4699 | @table @asis | ||
| 4700 | @item @samp{0} | ||
| 4701 | Pad with zeros instead of the default spaces. | ||
| 4702 | |||
| 4703 | @item @samp{-} | ||
| 4704 | Pad to the right. | ||
| 4705 | |||
| 4706 | @item @samp{^} | ||
| 4707 | Use upper case. | ||
| 4708 | |||
| 4709 | @item @samp{_} | ||
| 4710 | Use lower case. | ||
| 4711 | |||
| 4712 | @item @samp{<} | ||
| 4713 | If the length needs to be limited, remove characters from the left. | ||
| 4714 | |||
| 4715 | @item @samp{>} | ||
| 4716 | Same as previous, but remove characters from the right. | ||
| 4717 | @end table | ||
| 4718 | |||
| 4719 | If contradictory modifiers are used (for instance, both upper and | ||
| 4720 | lower case), then what happens is undefined. | ||
| 4721 | |||
| 4722 | As an example, @samp{"%<010b"} means ``insert the @samp{b} expansion, | ||
| 4723 | but pad with leading zeros if it's less than ten characters, and if | ||
| 4724 | it's more than ten characters, shorten by removing characters from the | ||
| 4725 | left.'' | ||
| 4726 | |||
| 4727 | |||
| 4728 | @node Checksum/Hash | 4664 | @node Checksum/Hash |
| 4729 | @section Checksum/Hash | 4665 | @section Checksum/Hash |
| 4730 | @cindex MD5 checksum | 4666 | @cindex MD5 checksum |
diff --git a/lisp/format-spec.el b/lisp/format-spec.el index f418cea4259..9278bd74c42 100644 --- a/lisp/format-spec.el +++ b/lisp/format-spec.el | |||
| @@ -29,35 +29,46 @@ | |||
| 29 | 29 | ||
| 30 | (defun format-spec (format specification &optional only-present) | 30 | (defun format-spec (format specification &optional only-present) |
| 31 | "Return a string based on FORMAT and SPECIFICATION. | 31 | "Return a string based on FORMAT and SPECIFICATION. |
| 32 | FORMAT is a string containing `format'-like specs like \"su - %u %k\", | 32 | FORMAT is a string containing `format'-like specs like \"su - %u %k\". |
| 33 | while SPECIFICATION is an alist mapping from format spec characters | 33 | SPECIFICATION is an alist mapping format specification characters |
| 34 | to values. | 34 | to their substitutions. |
| 35 | 35 | ||
| 36 | For instance: | 36 | For instance: |
| 37 | 37 | ||
| 38 | (format-spec \"su - %u %l\" | 38 | (format-spec \"su - %u %l\" |
| 39 | `((?u . ,(user-login-name)) | 39 | \\=`((?u . ,(user-login-name)) |
| 40 | (?l . \"ls\"))) | 40 | (?l . \"ls\"))) |
| 41 | 41 | ||
| 42 | Each format spec can have modifiers, where \"%<010b\" means \"if | 42 | Each %-spec may contain optional flag and width modifiers, as |
| 43 | the expansion is shorter than ten characters, zero-pad it, and if | 43 | follows: |
| 44 | it's longer, chop off characters from the left side\". | ||
| 45 | 44 | ||
| 46 | The following modifiers are allowed: | 45 | %<flags><width>character |
| 47 | 46 | ||
| 48 | * 0: Use zero-padding. | 47 | The following flags are allowed: |
| 49 | * -: Pad to the right. | ||
| 50 | * ^: Upper-case the expansion. | ||
| 51 | * _: Lower-case the expansion. | ||
| 52 | * <: Limit the length by removing chars from the left. | ||
| 53 | * >: Limit the length by removing chars from the right. | ||
| 54 | 48 | ||
| 55 | Any text properties on a %-spec itself are propagated to the text | 49 | * 0: Pad to the width, if given, with zeros instead of spaces. |
| 56 | that it generates. | 50 | * -: Pad to the width, if given, on the right instead of the left. |
| 51 | * <: Truncate to the width, if given, on the left. | ||
| 52 | * >: Truncate to the width, if given, on the right. | ||
| 53 | * ^: Convert to upper case. | ||
| 54 | * _: Convert to lower case. | ||
| 57 | 55 | ||
| 58 | If ONLY-PRESENT, format spec characters not present in | 56 | The width modifier behaves like the corresponding one in `format' |
| 59 | SPECIFICATION are ignored, and the \"%\" characters are left | 57 | when applied to %s. |
| 60 | where they are, including \"%%\" strings." | 58 | |
| 59 | For example, \"%<010b\" means \"substitute into the output the | ||
| 60 | value associated with ?b in SPECIFICATION, either padding it with | ||
| 61 | leading zeros or truncating leading characters until it's ten | ||
| 62 | characters wide\". | ||
| 63 | |||
| 64 | Any text properties of FORMAT are copied to the result, with any | ||
| 65 | text properties of a %-spec itself copied to its substitution. | ||
| 66 | |||
| 67 | ONLY-PRESENT indicates how to handle %-spec characters not | ||
| 68 | present in SPECIFICATION. If it is nil or omitted, emit an | ||
| 69 | error; otherwise leave those %-specs and any occurrences of | ||
| 70 | \"%%\" in FORMAT verbatim in the result, including their text | ||
| 71 | properties, if any." | ||
| 61 | (with-temp-buffer | 72 | (with-temp-buffer |
| 62 | (insert format) | 73 | (insert format) |
| 63 | (goto-char (point-min)) | 74 | (goto-char (point-min)) |