|
| 1 | +# Design Proposal: Choosing a Code Mode Introducer |
| 2 | + |
| 3 | +Status: **Proposed** |
| 4 | + |
| 5 | +<details> |
| 6 | + <summary>Metadata</summary> |
| 7 | + <dl> |
| 8 | + <dt>Contributors</dt> |
| 9 | + <dd>@aphillips</dd> |
| 10 | + <dt>First proposed</dt> |
| 11 | + <dd>2023-11-10</dd> |
| 12 | + <dt>Pull Requests</dt> |
| 13 | + <dd>#000</dd> |
| 14 | + </dl> |
| 15 | +</details> |
| 16 | + |
| 17 | +## Objective |
| 18 | + |
| 19 | +_What is this proposal trying to achieve?_ |
| 20 | + |
| 21 | +It must be possible to reliably parse messages. |
| 22 | + |
| 23 | +Our current syntax features unquoted patterns for simple messages |
| 24 | +and unquoted code tokens with quoted patterns for complex messages. |
| 25 | +Determining whether a message will have code tokens requires some |
| 26 | +special character sequence, either part of the code itself or |
| 27 | +prepended to the message. |
| 28 | +This proposal examines the options for determining code mode. |
| 29 | + |
| 30 | +## Background |
| 31 | + |
| 32 | +_What context is helpful to understand this proposal?_ |
| 33 | + |
| 34 | +## Use-Cases |
| 35 | + |
| 36 | +_What use-cases do we see? Ideally, quote concrete examples._ |
| 37 | + |
| 38 | +As a developer, I want to create messages with the minimal amount of special syntax. |
| 39 | +I don't want to have to type additional characters that add no value. |
| 40 | +I want the syntax to be logical and as consistent as possible. |
| 41 | + |
| 42 | +As a translator, I don't want to have to learn special syntax to support features such as declarations. |
| 43 | + |
| 44 | +As a user, I want my messages to be robust. |
| 45 | +Minor edits and changes should not result in syntax errors. |
| 46 | + |
| 47 | +As a user, I want to be able to see which messages are complex at a glance |
| 48 | +and to parse messages into their component parts visually as easily as possible. |
| 49 | + |
| 50 | +## Requirements |
| 51 | + |
| 52 | +_What properties does the solution have to manifest to enable the use-cases above?_ |
| 53 | + |
| 54 | +## Constraints |
| 55 | + |
| 56 | +_What prior decisions and existing conditions limit the possible design?_ |
| 57 | + |
| 58 | +Some of the options use a new sigil as part of the introducer. |
| 59 | +For various reasons, `#` has been used recently as a placeholder for this sigil. |
| 60 | +There are concerns that this character is not suitable, since it is used as a comment |
| 61 | +introducer in a number of formats. |
| 62 | +See for example [#520](https://github.com/unicode-org/message-format-wg/issues/520). |
| 63 | +The actual sigil used needs to be an ASCII character in the reserved or private use |
| 64 | +set (with syntax adjustments if we use up a private-use one). |
| 65 | +Most of the options below have been changed to use `^`, using |
| 66 | +Apple's experimental syntax as a model for sigil choice. |
| 67 | + |
| 68 | +It should be noted that an introducer sigil should be as rare as possible in normal text. |
| 69 | +This tends to run against common punctuation marks `&`, `%`, `!`, and `?`. |
| 70 | + |
| 71 | +```abnf |
| 72 | +reserved-start = "!" / "@" / "#" / "%" / "*" / "<" / ">" / "/" / "?" / "~" |
| 73 | +private-start = "^" / "&" |
| 74 | +``` |
| 75 | + |
| 76 | +## Proposed Design |
| 77 | + |
| 78 | +_Describe the proposed solution. Consider syntax, formatting, errors, registry, tooling, interchange._ |
| 79 | + |
| 80 | +We need to choose one of these (or another option not yet considered). |
| 81 | +Presentation at UTW did not produce any opinions. |
| 82 | + |
| 83 | +Based on the pro/cons below, I would suggest Option D is possibly the best option? |
| 84 | + |
| 85 | +## Alternatives Considered |
| 86 | + |
| 87 | +_What other solutions are available?_ |
| 88 | +_How do they compare against the requirements?_ |
| 89 | +_What other properties they have?_ |
| 90 | + |
| 91 | +There are the following designs being considered: |
| 92 | + |
| 93 | +### Option A. Use Pattern Quotes for Messages (current design) |
| 94 | + |
| 95 | +Complex messages are quoted with double curly brackets. |
| 96 | +The closing curly brackets might be optional. |
| 97 | + |
| 98 | +Sample pattern: |
| 99 | +``` |
| 100 | +{{ |
| 101 | +input {$var} |
| 102 | +match {$var} |
| 103 | +when * {{Pattern}} |
| 104 | +}} |
| 105 | +``` |
| 106 | +Sample quoted pattern with no declarations or match: |
| 107 | +``` |
| 108 | +{{{{Pattern}}}} |
| 109 | +``` |
| 110 | + |
| 111 | +Pros: |
| 112 | +- Uses a sigil `{` already present in the syntax |
| 113 | +- No additional escapes |
| 114 | +- Consistent with other parts of the syntax? |
| 115 | + |
| 116 | +Cons: |
| 117 | +- Somewhat verbose |
| 118 | +- Closing portion of the syntax adds no value; |
| 119 | + could be a source of unintentional syntax errors |
| 120 | +- Messages commonly end with four `}}}}` |
| 121 | + |
| 122 | +> [!NOTE] Other enclosing sequences are also an option, notably `{%...%}` (or similar). |
| 123 | +> This does reduce the number of curly brackets in a row. |
| 124 | +
|
| 125 | +### Option B. Use a Sigil |
| 126 | + |
| 127 | +Complex messages start with a special sigil character. |
| 128 | + |
| 129 | +``` |
| 130 | +^input {$var} |
| 131 | +match {$var} |
| 132 | +when * {{Pattern}} |
| 133 | +``` |
| 134 | +Sample quoted pattern with no declarations or match: |
| 135 | +``` |
| 136 | +^{{Pattern}} |
| 137 | +``` |
| 138 | + |
| 139 | +Pros: |
| 140 | +- Requires minimum additional typing |
| 141 | + |
| 142 | +Cons: |
| 143 | +- Requires an additional sigil |
| 144 | +- Requires an additional escape for simple pattern start |
| 145 | +- Has no other purpose in the syntax |
| 146 | + |
| 147 | +### Option C. Use a Double Sigil |
| 148 | + |
| 149 | +Like Option B, except the sigil is doubled. |
| 150 | + |
| 151 | +``` |
| 152 | +^^input {$var} |
| 153 | +match {$var} |
| 154 | +when * {{Pattern}} |
| 155 | +``` |
| 156 | +Sample quoted pattern with no declarations or match: |
| 157 | +``` |
| 158 | +^^{{Pattern}} |
| 159 | +``` |
| 160 | + |
| 161 | +Pros: |
| 162 | +- Less likely to conflict with a simple pattern |
| 163 | + |
| 164 | +Cons: |
| 165 | +- Requires an additional sigil |
| 166 | +- Requires an additional escape for simple pattern start |
| 167 | +- Has no other purpose in the syntax |
| 168 | + |
| 169 | +### Option D. Sigilized Keywords |
| 170 | + |
| 171 | +Instead of quoting the message, adds a sigil to keywords that |
| 172 | +start statements, that is, `.input`, `.local` and `.match`. |
| 173 | +The keyword `when` might be considered separately. |
| 174 | + |
| 175 | +The sigil used was changed to `.` as a result of the 2023-11-13 teleconference |
| 176 | +discussion of sigils. Others considered were `~`, `@`, `&`, and `%`. |
| 177 | +Originally this was `#` for similarity to `#define` (etc.) in other environments. |
| 178 | + |
| 179 | +``` |
| 180 | +.input {$var} |
| 181 | +.local $foo = {$bar} |
| 182 | +.match {$var} |
| 183 | +when * {{Pattern}} |
| 184 | +``` |
| 185 | +Sample quoted pattern with no declarations or match: |
| 186 | +``` |
| 187 | +{{Pattern}} |
| 188 | +``` |
| 189 | + |
| 190 | +Pros: |
| 191 | +- Sigil is part of the keyword, not something separate; note that the |
| 192 | + need for escaping is reduced by attaching the sigil to the keyword, |
| 193 | + since `.input` or `.local` or `.match` are unlikely to be message starters |
| 194 | +- Requires minimum additional typing |
| 195 | +- Adds no characters to messages that consist of only a quoted pattern; |
| 196 | + that is, quoting the pattern consists only of adding the `{{`/`}}` quotes |
| 197 | +- Maybe makes single-line messages easier to parse visually??? |
| 198 | + |
| 199 | +Cons: |
| 200 | +- Requires an additional sigil |
| 201 | +- Requires an additional escape for simple pattern start |
| 202 | + |
| 203 | +### Option E. Special Sequence |
| 204 | + |
| 205 | +Like Option A except the sequence is closed locally (not at the end of the message). |
| 206 | +The suggested sequence is `{#}` but might be `{}` or `{{}}` also. |
| 207 | + |
| 208 | +``` |
| 209 | +{^}input {$var} |
| 210 | +match {$var} |
| 211 | +when * {{Pattern}} |
| 212 | +``` |
| 213 | +Sample quoted pattern with no declarations or match: |
| 214 | +``` |
| 215 | +{^}{{Pattern}} |
| 216 | +``` |
| 217 | + |
| 218 | +Pros: |
| 219 | +- Less likely to conflict with a simple pattern |
| 220 | +- Requires no additional sigil |
| 221 | +- Requires no additional escape |
| 222 | + |
| 223 | +Cons: |
| 224 | +- Has no other purpose in the syntax |
| 225 | +- Looks like something should happen inside it |
| 226 | +- Most additional typing |
| 227 | + |
| 228 | +### Option F. Preamble |
| 229 | + |
| 230 | +In this option, all declarations are placed in a dedicated block at the beginning of the message. |
| 231 | +The preamble is the "front-matter" of the message, containing the message's logic. |
| 232 | +`when` clauses are not part of the preamble. |
| 233 | + |
| 234 | +The preamble can be delimited with `{% ... %}`: |
| 235 | + |
| 236 | + {%input {$var} match {$var}%} when * {{Pattern}} |
| 237 | + |
| 238 | +Alternatively, it can be delimited with a new kind of delimiter, to make it visually distinct from placeholders and patterns: |
| 239 | + |
| 240 | + [[input {$var} match {$var}]] when * {{Pattern}} |
| 241 | + |
| 242 | +We could also consider dropping the `when` keywords: |
| 243 | + |
| 244 | + [[input {$var} match {$var}]] * {{Pattern}} |
| 245 | + |
| 246 | +Pros: |
| 247 | +- Provides a clear conceptual distinction between declarations and variants. |
| 248 | +- Visually, all code is grouped together. |
| 249 | +- Unnests variant patterns. |
| 250 | + |
| 251 | +Cons: |
| 252 | +- If `[[ ... ]]` is used to delimit the preamble, it will require `[[` to be escaped at the beginning of simple patterns. |
| 253 | + |
0 commit comments