idnits 2.17.1 draft-ietf-netmod-artwork-folding-08.txt: Checking boilerplate required by RFC 5378 and the IETF Trust (see https://trustee.ietf.org/license-info): ---------------------------------------------------------------------------- No issues found here. Checking nits according to https://www.ietf.org/id-info/1id-guidelines.txt: ---------------------------------------------------------------------------- No issues found here. Checking nits according to https://www.ietf.org/id-info/checklist : ---------------------------------------------------------------------------- No issues found here. Miscellaneous warnings: ---------------------------------------------------------------------------- == The copyright year in the IETF Trust and authors Copyright Line does not match the current year -- The document date (August 2, 2019) is 1729 days in the past. Is this intentional? -- Found something which looks like a code comment -- if you have code sections in the document, please surround them with '' and '' lines. Checking references for intended status: Best Current Practice ---------------------------------------------------------------------------- (See RFCs 3967 and 4897 for information about using normative references to lower-maturity documents in RFCs) -- Obsolete informational reference (is this intentional?): RFC 7749 (Obsoleted by RFC 7991) Summary: 0 errors (**), 0 flaws (~~), 1 warning (==), 3 comments (--). Run idnits with the --verbose option for more detailed information about the items above. -------------------------------------------------------------------------------- 2 NETMOD Working Group K. Watsen 3 Internet-Draft Watsen Networks 4 Intended status: Best Current Practice A. Farrel 5 Expires: February 3, 2020 Old Dog Consulting 6 Q. Wu 7 Huawei Technologies 8 August 2, 2019 10 Handling Long Lines in Inclusions in Internet-Drafts and RFCs 11 draft-ietf-netmod-artwork-folding-08 13 Abstract 15 This document defines two strategies for handling long lines in 16 width-bounded text content. One strategy is based on the historic 17 use of a single backslash ('\') character to indicate where line- 18 folding has occurred, with the continuation occurring with the first 19 non-space (' ') character on the next line. The second strategy 20 extends the first strategy by adding a second backslash character to 21 identify where the continuation begins and thereby able to handle 22 cases not supported by the first strategy. Both strategies use a 23 self-describing header enabling automated reconstitution of the 24 original content. 26 Status of This Memo 28 This Internet-Draft is submitted in full conformance with the 29 provisions of BCP 78 and BCP 79. 31 Internet-Drafts are working documents of the Internet Engineering 32 Task Force (IETF). Note that other groups may also distribute 33 working documents as Internet-Drafts. The list of current Internet- 34 Drafts is at https://datatracker.ietf.org/drafts/current/. 36 Internet-Drafts are draft documents valid for a maximum of six months 37 and may be updated, replaced, or obsoleted by other documents at any 38 time. It is inappropriate to use Internet-Drafts as reference 39 material or to cite them other than as "work in progress." 41 This Internet-Draft will expire on February 3, 2020. 43 Copyright Notice 45 Copyright (c) 2019 IETF Trust and the persons identified as the 46 document authors. All rights reserved. 48 This document is subject to BCP 78 and the IETF Trust's Legal 49 Provisions Relating to IETF Documents 50 (https://trustee.ietf.org/license-info) in effect on the date of 51 publication of this document. Please review these documents 52 carefully, as they describe your rights and restrictions with respect 53 to this document. Code Components extracted from this document must 54 include Simplified BSD License text as described in Section 4.e of 55 the Trust Legal Provisions and are provided without warranty as 56 described in the Simplified BSD License. 58 Table of Contents 60 1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . 3 61 2. Applicability Statement . . . . . . . . . . . . . . . . . . . 4 62 3. Requirements Language . . . . . . . . . . . . . . . . . . . . 4 63 4. Goals . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4 64 4.1. Automated Folding of Long Lines in Text Content . . . . . 4 65 4.2. Automated Reconstitution of the Original Text Content . . 5 66 5. Limitations . . . . . . . . . . . . . . . . . . . . . . . . . 5 67 5.1. Not Recommended for Graphical Artwork . . . . . . . . . . 5 68 5.2. Doesn't Work as Well as Format-Specific Options . . . . . 5 69 6. Two Folding Strategies . . . . . . . . . . . . . . . . . . . 6 70 6.1. Comparison . . . . . . . . . . . . . . . . . . . . . . . 6 71 6.2. Recommendation . . . . . . . . . . . . . . . . . . . . . 6 72 7. The Single Backslash Strategy ('\') . . . . . . . . . . . . . 6 73 7.1. Folded Structure . . . . . . . . . . . . . . . . . . . . 6 74 7.1.1. Header . . . . . . . . . . . . . . . . . . . . . . . 7 75 7.1.2. Body . . . . . . . . . . . . . . . . . . . . . . . . 7 76 7.2. Algorithm . . . . . . . . . . . . . . . . . . . . . . . . 7 77 7.2.1. Folding . . . . . . . . . . . . . . . . . . . . . . . 7 78 7.2.2. Unfolding . . . . . . . . . . . . . . . . . . . . . . 9 79 8. The Double Backslash Strategy ('\\') . . . . . . . . . . . . 9 80 8.1. Folded Structure . . . . . . . . . . . . . . . . . . . . 9 81 8.1.1. Header . . . . . . . . . . . . . . . . . . . . . . . 9 82 8.1.2. Body . . . . . . . . . . . . . . . . . . . . . . . . 10 83 8.2. Algorithm . . . . . . . . . . . . . . . . . . . . . . . . 10 84 8.2.1. Folding . . . . . . . . . . . . . . . . . . . . . . . 10 85 8.2.2. Unfolding . . . . . . . . . . . . . . . . . . . . . . 12 86 9. Examples . . . . . . . . . . . . . . . . . . . . . . . . . . 12 87 9.1. Example Showing Boundary Conditions . . . . . . . . . . . 12 88 9.1.1. Using '\' . . . . . . . . . . . . . . . . . . . . . . 12 89 9.1.2. Using '\\' . . . . . . . . . . . . . . . . . . . . . 13 90 9.2. Example Showing Multiple Wraps of a Single Line . . . . . 13 91 9.2.1. Using '\' . . . . . . . . . . . . . . . . . . . . . . 13 92 9.2.2. Using '\\' . . . . . . . . . . . . . . . . . . . . . 14 93 9.3. Example Showing "Smart" Folding . . . . . . . . . . . . . 14 94 9.3.1. Using '\' . . . . . . . . . . . . . . . . . . . . . . 14 95 9.3.2. Using '\\' . . . . . . . . . . . . . . . . . . . . . 15 97 9.4. Example Showing "Forced" Folding . . . . . . . . . . . . 16 98 9.4.1. Using '\' . . . . . . . . . . . . . . . . . . . . . . 17 99 9.4.2. Using '\\' . . . . . . . . . . . . . . . . . . . . . 17 100 10. Security Considerations . . . . . . . . . . . . . . . . . . . 17 101 11. IANA Considerations . . . . . . . . . . . . . . . . . . . . . 18 102 12. References . . . . . . . . . . . . . . . . . . . . . . . . . 18 103 12.1. Normative References . . . . . . . . . . . . . . . . . . 18 104 12.2. Informative References . . . . . . . . . . . . . . . . . 18 105 Appendix A. POSIX Shell Script: rfcfold . . . . . . . . . . . . 19 106 Acknowledgements . . . . . . . . . . . . . . . . . . . . . . . . 28 107 Authors' Addresses . . . . . . . . . . . . . . . . . . . . . . . 28 109 1. Introduction 111 [RFC7994] sets out the requirements for plain-text RFCs and states 112 that each line of an RFC (and hence of an Internet-Draft) must be 113 limited to 72 characters followed by the character sequence that 114 denotes an end-of-line (EOL). 116 Internet-Drafts and RFCs often include example text or code 117 fragments. Many times the example text or code exceeds the 72 118 character line-length limit. The `xml2rfc` utility does not attempt 119 to wrap the content of such inclusions, simply issuing a warning 120 whenever lines exceed 69 characters. According to the RFC Editor, 121 there is currently no convention in place for how to handle long 122 lines in such inclusions, other than advising authors to clearly 123 indicate what manipulation has occurred. 125 This document defines two strategies for handling long lines in 126 width-bounded text content. One strategy is based on the historic 127 use of a single backslash ('\') character to indicate where line- 128 folding has occurred, with the continuation occurring with the first 129 non-space (' ') character on the next line. The second strategy 130 extends the first strategy by adding a second backslash character to 131 identify where the continuation begins and thereby able to handle 132 cases not supported by the first strategy. Both strategies use a 133 self-describing header enabling automated reconstitution of the 134 original content. 136 The strategies defined in this document work on any text content, but 137 are primarily intended for a structured sequence of lines, such as 138 would be referenced by the element defined in 139 Section 2.48 of [RFC7991], rather than for two-dimensional imagery, 140 such as would be referenced by the element defined in 141 Section 2.5 of [RFC7991]. 143 Note that text files are represented as lines having their first 144 character in column 1, and a line length of N where the last 145 character is in the Nth column and is immediately followed by an end 146 of line character sequence. 148 2. Applicability Statement 150 The formats and algorithms defined in this document may be used in 151 any context, whether for IETF documents or in other situations where 152 structured folding is desired. 154 Within the IETF, this work primarily targets the xml2rfc v3 155 element (Section 2.48 of [RFC7991]) and the xml2rfc v2 156 element (Section 2.5 of [RFC7749]) that, for lack of a 157 better option, is currently used for both source code and artwork. 158 This work may be also be used for the xml2rfc v3 element 159 (Section 2.5 of [RFC7991]) but, as described in Section 5.1, it is 160 generally not recommended. 162 3. Requirements Language 164 The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", 165 "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and 166 "OPTIONAL" in this document are to be interpreted as described in BCP 167 14 [RFC2119] [RFC8174] when, and only when, they appear in all 168 capitals, as shown here. 170 4. Goals 172 4.1. Automated Folding of Long Lines in Text Content 174 Automated folding of long lines is needed in order to support draft 175 compilations that entail a) validation of source input files (e.g., 176 XML, JSON, ABNF, ASN.1) and/or b) dynamic generation of output, using 177 a tool that doesn't observe line lengths, that is stitched into the 178 final document to be submitted. 180 Generally, in order for tooling to be able to process input files, 181 the files must be in their original/natural state, which may entail 182 them having some long lines. Thus, these source files need to be 183 modified before inclusion in the document in order to satisfy the 184 line length limits. This modification SHOULD be automated to reduce 185 effort and errors resulting from manual processing. 187 Similarly, dynamically generated output (e.g., tree diagrams) must 188 also be modified, if necessary, in order for the resulting document 189 to satisfy the line length limits. When needed, this effort again 190 SHOULD be automated to reduce effort and errors resulting from manual 191 processing. 193 4.2. Automated Reconstitution of the Original Text Content 195 Automated reconstitution of the exact original text content is needed 196 to support validation of text-based content extracted from documents. 198 For instance, already YANG [RFC7950] modules are extracted from 199 Internet-Drafts and validated as part of the draft-submission 200 process. Additionally, the desire to validate instance examples 201 (i.e., XML/JSON documents) contained within Internet-Drafts has been 202 discussed ([yang-doctors-thread]). 204 5. Limitations 206 5.1. Not Recommended for Graphical Artwork 208 While the solution presented in this document works on any kind of 209 text-based content, it is most useful on content that represents 210 source code (XML, JSON, etc.) or, more generally, on content that has 211 not been laid out in two dimensions (e.g., diagrams). 213 Fundamentally, the issue is whether the text content remains readable 214 once folded. Text content that is unpredictable is especially 215 susceptible to looking bad when folded; falling into this category 216 are most UML diagrams, YANG tree diagrams, and ASCII art in general. 218 It is NOT RECOMMENDED to use the solution presented in this document 219 on graphical artwork. 221 5.2. Doesn't Work as Well as Format-Specific Options 223 The solution presented in this document works generically for all 224 text-based content, as it only views content as plain text. However, 225 various formats sometimes have built-in mechanisms that are better 226 suited to prevent long lines. 228 For instance, both the `pyang` and `yanglint` utilities have the 229 command line option "--tree-line-length" that can be used to indicate 230 a desired maximum line length for when generating tree diagrams 231 [RFC8340]. 233 In another example, some source formats (e.g., YANG [RFC7950]) allow 234 any quoted string to be broken up into substrings separated by a 235 concatenation character (e.g., '+'), any of which can be on a 236 different line. 238 It is RECOMMENDED that authors do as much as possible within the 239 selected format to avoid long lines. 241 6. Two Folding Strategies 243 This document defines two nearly identical strategies for folding 244 text-based content. 246 The Single Backslash Strategy ('\'): Uses a backslash ('\') 247 character at the end of the line where folding occurs, and 248 assumes that the continuation begins at the character that is 249 not a space character (' ') on the following line. 251 The Double Backslash Strategy ('\\'): Uses a backslash ('\') 252 character at the end of the line where folding occurs, and 253 assumes that the continuation begins after a second backslash 254 ('\') character on the following line. 256 6.1. Comparison 258 The first strategy produces more readable output, however it is 259 significantly more likely to encounter unfoldable input (e.g., there 260 exists a line anywhere in the input ending with a backslash 261 character, or there exists a long line containing only space 262 characters) and, for long lines that can be folded, automation 263 implementations may encounter scenarios that will produce errors 264 without special care. 266 The second strategy produces less readable output, but is unlikely to 267 encounter unfoldable input, there are no long lines that cannot be 268 folded, and no special care is required for when folding a long line. 270 6.2. Recommendation 272 It is RECOMMENDED for implementations to first attempt to fold 273 content using the single backslash strategy and, only in the unlikely 274 event that it cannot fold the input or the folding logic is unable to 275 cope with a contingency occurring on the desired folding column, then 276 fallback to the double backslash strategy. 278 7. The Single Backslash Strategy ('\') 280 7.1. Folded Structure 282 Text content that has been folded as specified by this strategy MUST 283 adhere to the following structure. 285 7.1.1. Header 287 The header is two lines long. 289 The first line is the following 45-character string that MAY be 290 surrounded by any number of printable characters. This first line 291 cannot itself be folded. 293 NOTE: '\' line wrapping per BCP XX (RFC XXXX) 295 [Note to RFC Editor: Please replace XX and XXXX with the numbers 296 assigned to this document and delete this note. Please make this 297 change in multiple places in this document.] 299 The second line is a blank line. This line provides visual 300 separation for readability. 302 7.1.2. Body 304 The character encoding is the same as described in Section 2 of 305 [RFC7994], except that, per [RFC7991], tab characters are prohibited. 307 Lines that have a backslash ('\') occurring as the last character in 308 a line are considered "folded". 310 Really long lines may be folded multiple times. 312 7.2. Algorithm 314 This section describes a process for folding and unfolding long lines 315 when they are encountered in text content. 317 The steps are complete, but implementations MAY achieve the same 318 result in other ways. 320 When a larger document contains multiple instances of text content 321 that may need to be folded or unfolded, another process must insert/ 322 extract the individual text content instances to/from the larger 323 document prior to utilizing the algorithms described in this section. 324 For example, the `xiax` utility [xiax] does this. 326 7.2.1. Folding 328 Determine the desired maximum line length from input to the line- 329 wrapping process, such as from a command line parameter. If no value 330 is explicitly specified, the value "69" SHOULD be used. 332 Ensure that the desired maximum line length is not less than the 333 minimum header, which is 45 characters. If the desired maximum line 334 length is less than this minimum, exit (this text-based content 335 cannot be folded). 337 Scan the text content for horizontal tab characters. If any 338 horizontal tab characters appear, either resolve them to space 339 characters or exit, forcing the input provider to convert them to 340 space characters themselves first. 342 Scan the text content to ensure at least one line exceeds the desired 343 maximum. If no line exceeds the desired maximum, exit (this text 344 content does not need to be folded). 346 Scan the text content to ensure no existing lines already end with a 347 backslash ('\') character, as this would lead to an ambiguous result. 348 If such a line is found, and its width is less than the desired 349 maximum, then it SHOULD be flagged for forced folding (folding even 350 though unnecessary). If the folding implementation doesn't support 351 forced foldings, it MUST exit. 353 If this text content needs to and can be folded, insert the header 354 described in Section 7.1.1, ensuring that any additional printable 355 characters surrounding the header does not result in a line exceeding 356 the desired maximum. 358 For each line in the text content, from top-to-bottom, if the line 359 exceeds the desired maximum, or requires a forced folding, then fold 360 the line by: 362 1. Determine where the fold will occur. This location MUST be 363 before or at the desired maximum column, and MUST NOT be chosen 364 such that the character immediately after the fold is a space (' 365 ') character. If no such location can be found, then exit (this 366 text content cannot be folded). 368 2. At the location where the fold is to occur, insert a backslash 369 ('\') character followed by the end of line character sequence. 371 3. On the following line, insert any number of space (' ') 372 characters. 374 The result of the previous operation is that the next line starts 375 with an arbitrary number of space (' ') characters, followed by the 376 character that was previously occupying the position where the fold 377 occurred. 379 Continue in this manner until reaching the end of the text content. 380 Note that this algorithm naturally addresses the case where the 381 remainder of a folded line is still longer than the desired maximum, 382 and hence needs to be folded again, ad infinitum. 384 The process described in this section is illustrated by the 385 "fold_it_1()" function in Appendix A. 387 7.2.2. Unfolding 389 Scan the beginning of the text content for the header described in 390 Section 7.1.1. If the header is not present, starting on the first 391 line of the text content, exit (this text contents does not need to 392 be unfolded). 394 Remove the 2-line header from the text content. 396 For each line in the text content, from top-to-bottom, if the line 397 has a backslash ('\') character immediately followed by the end of 398 line character sequence, then the line can be unfolded. Remove the 399 backslash ('\') character, the end of line character sequence, and 400 any leading space (' ') characters, which will bring up the next 401 line. Then continue to scan each line in the text content starting 402 with the current line (in case it was multiply folded). 404 Continue in this manner until reaching the end of the text content. 406 The process described in this section is illustrated by the 407 "unfold_it_1()" function in Appendix A. 409 8. The Double Backslash Strategy ('\\') 411 8.1. Folded Structure 413 Text content that has been folded as specified by this strategy MUST 414 adhere to the following structure. 416 8.1.1. Header 418 The header is two lines long. 420 The first line is the following 46-character string that MAY be 421 surrounded by any number of printable characters. This first line 422 cannot itself be folded. 424 NOTE: '\\' line wrapping per BCP XX (RFC XXXX) 426 [Note to RFC Editor: Please replace XX and XXXX with the numbers 427 assigned to this document and delete this note. Please make this 428 change in multiple places in this document.] 430 The second line is a blank line. This line provides visual 431 separation for readability. 433 8.1.2. Body 435 The character encoding is the same as described in Section 2 of 436 [RFC7994], except that, per [RFC7991], tab characters are prohibited. 438 Lines that have a backslash ('\') occurring as the last character in 439 a line immediately followed by the end of line character sequence, 440 when the subsequent line starts with a backslash ('\') as the first 441 non-space (' ') character, are considered "folded". 443 Really long lines may be folded multiple times. 445 8.2. Algorithm 447 This section describes a process for folding and unfolding long lines 448 when they are encountered in text content. 450 The steps are complete, but implementations MAY achieve the same 451 result in other ways. 453 When a larger document contains multiple instances of text content 454 that may need to be folded or unfolded, another process must insert/ 455 extract the individual text content instances to/from the larger 456 document prior to utilizing the algorithms described in this section. 457 For example, the `xiax` utility [xiax] does this. 459 8.2.1. Folding 461 Determine the desired maximum line length from input to the line- 462 wrapping process, such as from a command line parameter. If no value 463 is explicitly specified, the value "69" SHOULD be used. 465 Ensure that the desired maximum line length is not less than the 466 minimum header, which is 46 characters. If the desired maximum line 467 length is less than this minimum, exit (this text-based content 468 cannot be folded). 470 Scan the text content for horizontal tab characters. If any 471 horizontal tab characters appear, either resolve them to space 472 characters or exit, forcing the input provider to convert them to 473 space characters themselves first. 475 Scan the text content to see if any line exceeds the desired maximum. 476 If no line exceeds the desired maximum, exit (this text content does 477 not need to be folded). 479 Scan the text content to ensure no existing lines already end with a 480 backslash ('\') character while the subsequent line starts with a 481 backslash ('\') character as the first non-space (' ') character, as 482 this could lead to an ambiguous result. If such a line is found, and 483 its width is less than the desired maximum, then it SHOULD be flagged 484 for forced folding (folding even though unnecessary). If the folding 485 implementation doesn't support forced foldings, it MUST exit. 487 If this text content needs to and can be folded, insert the header 488 described in Section 8.1.1, ensuring that any additional printable 489 characters surrounding the header does not result in a line exceeding 490 the desired maximum. 492 For each line in the text content, from top-to-bottom, if the line 493 exceeds the desired maximum, or requires a forced folding, then fold 494 the line by: 496 1. Determine where the fold will occur. This location MUST be 497 before or at the desired maximum column. 499 2. At the location where the fold is to occur, insert a first 500 backslash ('\') character followed by the end of line character 501 sequence. 503 3. On the following line, insert any number of space (' ') 504 characters followed by a second backslash ('\') character. 506 The result of the previous operation is that the next line starts 507 with an arbitrary number of space (' ') characters, followed by a 508 backslash ('\') character, immediately followed by the character that 509 was previously occupying the position where the fold occurred. 511 Continue in this manner until reaching the end of the text content. 512 Note that this algorithm naturally addresses the case where the 513 remainder of a folded line is still longer than the desired maximum, 514 and hence needs to be folded again, ad infinitum. 516 The process described in this section is illustrated by the 517 "fold_it_2()" function in Appendix A. 519 8.2.2. Unfolding 521 Scan the beginning of the text content for the header described in 522 Section 8.1.1. If the header is not present, starting on the first 523 line of the text content, exit (this text content does not need to be 524 unfolded). 526 Remove the 2-line header from the text content. 528 For each line in the text content, from top-to-bottom, if the line 529 has a backslash ('\') character immediately followed by the end of 530 line character sequence, and if the next line has a backslash ('\') 531 character as the first non-space (' ') character, then the lines can 532 be unfolded. Remove the first backslash ('\') character, the end of 533 line character sequence, any leading space (' ') characters, and the 534 second backslash ('\') character, which will bring up the next line. 535 Then continue to scan each line in the text content starting with the 536 current line (in case it was multiply folded). 538 Continue in this manner until reaching the end of the text content. 540 The process described in this section is illustrated by the 541 "unfold_it_2()" function in Appendix A. 543 9. Examples 545 The following self-documenting examples illustrate folded text-based 546 content. 548 The source text content cannot be presented here, as it would again 549 be folded. Alas, only the results can be provided. 551 9.1. Example Showing Boundary Conditions 553 This example illustrates boundary condition. The input contains 554 seven lines, each line one character longer than the previous line. 555 Numbers for counting purposes. The default desired maximum column 556 value "69" is used. 558 9.1.1. Using '\' 559 =========== NOTE: '\' line wrapping per BCP XX (RFC XXXX) =========== 561 123456789012345678901234567890123456789012345678901234567890123456 562 1234567890123456789012345678901234567890123456789012345678901234567 563 12345678901234567890123456789012345678901234567890123456789012345678 564 123456789012345678901234567890123456789012345678901234567890123456789 565 12345678901234567890123456789012345678901234567890123456789012345678\ 566 90 567 12345678901234567890123456789012345678901234567890123456789012345678\ 568 901 569 12345678901234567890123456789012345678901234567890123456789012345678\ 570 9012 572 9.1.2. Using '\\' 574 ========== NOTE: '\\' line wrapping per BCP XX (RFC XXXX) =========== 576 123456789012345678901234567890123456789012345678901234567890123456 577 1234567890123456789012345678901234567890123456789012345678901234567 578 12345678901234567890123456789012345678901234567890123456789012345678 579 123456789012345678901234567890123456789012345678901234567890123456789 580 12345678901234567890123456789012345678901234567890123456789012345678\ 581 \90 582 12345678901234567890123456789012345678901234567890123456789012345678\ 583 \901 584 12345678901234567890123456789012345678901234567890123456789012345678\ 585 \9012 587 9.2. Example Showing Multiple Wraps of a Single Line 589 This example illustrates what happens when very long line needs to be 590 folded multiple times. The input contains one line containing 280 591 characters. Numbers for counting purposes. The default desired 592 maximum column value "69" is used. 594 9.2.1. Using '\' 596 =========== NOTE: '\' line wrapping per BCP XX (RFC XXXX) =========== 598 12345678901234567890123456789012345678901234567890123456789012345678\ 599 90123456789012345678901234567890123456789012345678901234567890123456\ 600 78901234567890123456789012345678901234567890123456789012345678901234\ 601 56789012345678901234567890123456789012345678901234567890123456789012\ 602 34567890 604 9.2.2. Using '\\' 606 ========== NOTE: '\\' line wrapping per BCP XX (RFC XXXX) =========== 608 12345678901234567890123456789012345678901234567890123456789012345678\ 609 \9012345678901234567890123456789012345678901234567890123456789012345\ 610 \6789012345678901234567890123456789012345678901234567890123456789012\ 611 \3456789012345678901234567890123456789012345678901234567890123456789\ 612 \01234567890 614 9.3. Example Showing "Smart" Folding 616 This example illustrates how readability can be improved via "smart" 617 folding, whereby folding occurs at format-specific locations and 618 format-specific indentations are used. 620 The text content was manually folded, since the script in the 621 appendix does not implement smart folding. 623 Note that the headers are surrounded by different printable 624 characters than shown in the script-generated examples. 626 9.3.1. Using '\' 628 [NOTE: '\' line wrapping per BCP XX (RFC XXXX)] 630 634 635 config-modules 636 637 ietf-interfaces 638 2018-02-20 639 \ 640 urn:ietf:params:xml:ns:yang:ietf-interfaces\ 641 642 643 ... 644 645 ... 646 648 Below is the equivalent to the above, but it was folded using the 649 script in the appendix. 651 =========== NOTE: '\' line wrapping per BCP XX (RFC XXXX) =========== 653 657 658 config-modules 659 660 ietf-interfaces 661 2018-02-20 662 urn:ietf:params:xml:ns:yang:ietf-interfaces 664 665 ... 666 667 ... 668 670 9.3.2. Using '\\' 672 [NOTE: '\\' line wrapping per BCP XX (RFC XXXX)] 674 678 679 config-modules 680 681 ietf-interfaces 682 2018-02-20 683 \ 684 \urn:ietf:params:xml:ns:yang:ietf-interfaces\ 685 \ 686 687 ... 688 689 ... 690 692 Below is the equivalent to the above, but it was folded using the 693 script in the appendix. 695 ========== NOTE: '\\' line wrapping per BCP XX (RFC XXXX) =========== 697 701 702 config-modules 703 704 ietf-interfaces 705 2018-02-20 706 urn:ietf:params:xml:ns:yang:ietf-interfaces 708 709 ... 710 711 ... 712 714 9.4. Example Showing "Forced" Folding 716 This example illustrates how invalid sequences in lines that do not 717 have to be folded can be handled via forced folding, whereby the 718 folding occurs even though unnecessary. 720 The following line exceeds a 68-char max, thus demands folding 721 123456789012345678901234567890123456789012345678901234567890123456789 723 This line ends with a backslash \ 725 This line ends with a backslash \ 726 \ This line begins with a backslash 728 Following is an indented 3x3 block of backslashes: 729 \\\ 730 \\\ 731 \\\ 733 The samples below were manually folded, since the script in the 734 appendix does not implement forced folding. 736 Note that the headers are prefixed by a pound ('#') character, rather 737 than surrounded by equal ('=') characters as shown in the script- 738 generated examples. 740 9.4.1. Using '\' 742 # NOTE: '\' line wrapping per BCP XX (RFC XXXX) 744 The following line exceeds a 68-char max, thus demands folding 745 1234567890123456789012345678901234567890123456789012345678901234567\ 746 89 748 This line ends with a backslash \\ 750 This line ends with a backslash \\ 752 \ This line begins with a backslash 754 Following is an indented 3x3 block of backslashes: 755 \\\\ 757 \\\\ 759 \\\ 761 9.4.2. Using '\\' 763 # NOTE: '\\' line wrapping per BCP XX (RFC XXXX) 765 The following line exceeds a 68-char max, thus demands folding 766 1234567890123456789012345678901234567890123456789012345678901234567\ 767 \89 769 This line ends with a backslash \ 771 This line ends with a backslash \\ 772 \ 773 \ This line begins with a backslash 775 Following is an indented 3x3 block of backslashes: 776 \\\\ 777 \ 778 \\\\ 779 \ 780 \\\ 782 10. Security Considerations 784 This BCP has no Security Considerations. 786 11. IANA Considerations 788 This BCP has no IANA Considerations. 790 12. References 792 12.1. Normative References 794 [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate 795 Requirement Levels", BCP 14, RFC 2119, 796 DOI 10.17487/RFC2119, March 1997, 797 . 799 [RFC8174] Leiba, B., "Ambiguity of Uppercase vs Lowercase in RFC 800 2119 Key Words", BCP 14, RFC 8174, DOI 10.17487/RFC8174, 801 May 2017, . 803 12.2. Informative References 805 [RFC7749] Reschke, J., "The "xml2rfc" Version 2 Vocabulary", 806 RFC 7749, DOI 10.17487/RFC7749, February 2016, 807 . 809 [RFC7950] Bjorklund, M., Ed., "The YANG 1.1 Data Modeling Language", 810 RFC 7950, DOI 10.17487/RFC7950, August 2016, 811 . 813 [RFC7991] Hoffman, P., "The "xml2rfc" Version 3 Vocabulary", 814 RFC 7991, DOI 10.17487/RFC7991, December 2016, 815 . 817 [RFC7994] Flanagan, H., "Requirements for Plain-Text RFCs", 818 RFC 7994, DOI 10.17487/RFC7994, December 2016, 819 . 821 [RFC8340] Bjorklund, M. and L. Berger, Ed., "YANG Tree Diagrams", 822 BCP 215, RFC 8340, DOI 10.17487/RFC8340, March 2018, 823 . 825 [xiax] "The `xiax` Python Package", 826 . 828 [yang-doctors-thread] 829 "[yang-doctors] automating yang doctor reviews", 830 . 833 Appendix A. POSIX Shell Script: rfcfold 835 This non-normative appendix section includes a shell script that can 836 both fold and unfold text content using both the single and double 837 backslash strategies described in Section 7 and Section 8 838 respectively. 840 This script is intended to be applied to a single text content 841 instance. If it is desired to fold or unfold text content instances 842 within a larger document (e.g., an Internet draft or RFC), then 843 another tool must be used to extract the content from the larger 844 document before utilizing this script. 846 For readability purposes, this script forces the minimally supported 847 line length to be eight characters longer than the raw header text 848 defined in Section 7.1.1 and Section 8.1.1 so as to ensure that the 849 header can be wrapped by a space (' ') character and three equal 850 ('=') characters on each side of the raw header text. 852 This script does not implement the whitespace-avoidance logic 853 described in Section 7.2.1. In such case, the script will exit with 854 one of the following message: 856 Error: infile has a space character occuring on the 857 folding column. This file cannot be folded using the 858 '\' strategy. 860 This script does not implement the "forced folding" logic described 861 in Section 7.2.1 or Section 8.2.1. In such cases the script will 862 exit with one of the following message: 864 Error: infile has a line ending with a '\' character 865 This file cannot be folded using the '\' strategy. 867 Error: infile has a line ending with a '\' character 868 followed by a '\' character as the first non-space 869 character on the next line. This script cannot fold 870 this file using '\\' strategy without there being 871 false positives produced in the unfolding (i.e., this 872 script does not attempt to proactively force-fold such 873 lines, as described in RFC XXXX). 875 Shell-level end-of-line backslash ('\') characters have been 876 purposely added to the script so as to ensure that the script is 877 itself not folded in this document, thus simplify the ability to 878 copy/paste the script for local use. As should be evident by the 879 lack of the mandatory header described in Section 7.1.1, these 880 backslashes do not designate a folded line, such as described in 881 Section 7. 883 885 #!/bin/bash --posix 887 # This script may need some adjustments to work on a given system. 888 # For instance, the utilities `pcregrep` and `gsed` may need to 889 # be installed. Also, please be advised that `bash` (not `sh`) 890 # must be used. 892 # Copyright (c) 2019 IETF Trust, Kent Watsen, and Erik Auerswald. 893 # All rights reserved. 894 # 895 # Redistribution and use in source and binary forms, with or without 896 # modification, are permitted provided that the following conditions 897 # are met: 898 # 899 # * Redistributions of source code must retain the above copyright 900 # notice, this list of conditions and the following disclaimer. 901 # 902 # * Redistributions in binary form must reproduce the above 903 # copyright notice, this list of conditions and the following 904 # disclaimer in the documentation and/or other materials 905 # provided with the distribution. 906 # 907 # * Neither the name of Internet Society, IETF or IETF Trust, nor 908 # the names of specific contributors, may be used to endorse or 909 # promote products derived from this software without specific 910 # prior written permission. 911 # 912 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 913 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 914 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 915 # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 916 # COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 917 # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 918 # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 919 # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 920 # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 921 # STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 922 # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 923 # ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 925 print_usage() { 926 printf "\n" 927 printf "Folds or unfolds the input text file according to BCP XX" 928 printf " (RFC XXXX).\n" 929 printf "\n" 930 printf "Usage: rfcfold [-s ] [-c ] [-r] -i " 931 printf " -o \n" 932 printf "\n" 933 printf " -s: strategy to use, '1' or '2' (default: try 1," 934 printf " else 2)\n" 935 printf " -c: column to fold on (default: 69)\n" 936 printf " -r: reverses the operation\n" 937 printf " -i: the input filename\n" 938 printf " -o: the output filename\n" 939 printf " -d: show debug messages\n" 940 printf " -q: quiet (suppress error messages)\n" 941 printf " -h: show this message\n" 942 printf "\n" 943 printf "Exit status code: 1 on error, 0 on success, -1 on no-op.\n" 944 printf "\n" 945 } 947 # global vars, do not edit 948 strategy=0 # auto 949 debug=0 950 quiet=0 951 reversed=0 952 infile="" 953 outfile="" 954 maxcol=69 # default, may be overridden by param 955 hdr_txt_1="NOTE: '\\' line wrapping per BCP XX (RFC XXXX)" 956 hdr_txt_2="NOTE: '\\\\' line wrapping per BCP XX (RFC XXXX)" 957 equal_chars="=======================================================" 958 space_chars=" " 959 temp_dir="" 961 # determine name of [g]sed binary 962 type gsed > /dev/null 2>&1 && SED=gsed || SED=sed 964 # warn if a non-GNU sed utility is used 965 "$SED" --version < /dev/null 2> /dev/null \ 966 | grep GNU >/dev/null 2>&1 || echo 'Warning: not using GNU `sed`.' 968 # verify the availability of pcregrep 969 type pcregrep > /dev/null 2>&1 || { 970 echo 'Error: missing utility `pcregrep`' 971 exit 1 972 } 974 cleanup() { 975 rm -rf "$temp_dir" 977 } 978 trap 'cleanup' EXIT 980 fold_it_1() { 981 # ensure input file doesn't contain the fold-sequence already 982 pcregrep -M "\\\\\n" $infile >> /dev/null 2>&1 983 if [[ $? -eq 0 ]]; then 984 if [[ $quiet -eq 0 ]]; then 985 echo 986 echo "Error: infile $infile has a line ending with a '\\'" 987 echo "character. This file cannot be folded using the '\\'" 988 echo "strategy." 989 echo 990 fi 991 return 1 992 fi 994 # where to fold 995 foldcol=`expr "$maxcol" - 1` # for the inserted '\' char 997 # ensure input file doesn't contain whitespace on the fold column 998 grep "^.\{$foldcol\} " $infile >> /dev/null 2>&1 999 if [[ $? -eq 0 ]]; then 1000 if [[ $quiet -eq 0 ]]; then 1001 echo 1002 echo "Error: infile has a space character occuring on the" 1003 echo "folding column. This file cannot be folded using the" 1004 echo "'\\' strategy." 1005 echo 1006 fi 1007 return 1 1008 fi 1010 # center header text 1011 length=`expr ${#hdr_txt_1} + 2` 1012 left_sp=`expr \( "$maxcol" - "$length" \) / 2` 1013 right_sp=`expr "$maxcol" - "$length" - "$left_sp"` 1014 header=`printf "%.*s %s %.*s" "$left_sp" "$equal_chars"\ 1015 "$hdr_txt_1" "$right_sp" "$equal_chars"` 1017 # generate outfile 1018 echo "$header" > $outfile 1019 echo "" >> $outfile 1020 "$SED" 's/\(.\{'"$foldcol"'\}\)\(..\)/\1\\\n\2/;t M;b;:M;P;D;'\ 1021 < $infile >> $outfile 2>/dev/null 1022 if [[ $? -ne 0 ]]; then 1023 return 1 1024 fi 1025 return 0 1026 } 1028 fold_it_2() { 1029 # where to fold 1030 foldcol=`expr "$maxcol" - 1` # for the inserted '\' char 1032 # ensure input file doesn't contain the fold-sequence already 1033 pcregrep -M "\\\\\n[\ ]*\\\\" $infile >> /dev/null 2>&1 1034 if [[ $? -eq 0 ]]; then 1035 if [[ $quiet -eq 0 ]]; then 1036 echo 1037 echo "Error: infile has a line ending with a '\\' character" 1038 echo "followed by a '\\' character as the first non-space" 1039 echo "character on the next line. This script cannot fold" 1040 echo "this file using '\\\\' strategy without there being" 1041 echo "false positives produced in the unfolding (i.e., this" 1042 echo "script does not attempt to proactively force-fold such" 1043 echo "lines, as described in RFC XXXX)." 1044 echo 1045 fi 1046 return 1 1047 fi 1049 # center header text 1050 length=`expr ${#hdr_txt_2} + 2` 1051 left_sp=`expr \( "$maxcol" - "$length" \) / 2` 1052 right_sp=`expr "$maxcol" - "$length" - "$left_sp"` 1053 header=`printf "%.*s %s %.*s" "$left_sp" "$equal_chars"\ 1054 "$hdr_txt_2" "$right_sp" "$equal_chars"` 1056 # generate outfile 1057 echo "$header" > $outfile 1058 echo "" >> $outfile 1059 "$SED" 's/\(.\{'"$foldcol"'\}\)\(..\)/\1\\\n\\\2/;t M;b;:M;P;D;'\ 1060 < $infile >> $outfile 2>/dev/null 1061 if [[ $? -ne 0 ]]; then 1062 return 1 1063 fi 1064 return 0 1065 } 1067 fold_it() { 1068 # ensure input file doesn't contain a TAB 1069 grep $'\t' $infile >> /dev/null 2>&1 1070 if [[ $? -eq 0 ]]; then 1071 if [[ $quiet -eq 0 ]]; then 1072 echo 1073 echo "Error: infile contains a TAB character, which is" 1074 echo "not allowed." 1075 echo 1076 fi 1077 return 1 1078 fi 1080 # check if file needs folding 1081 testcol=`expr "$maxcol" + 1` 1082 grep ".\{$testcol\}" $infile >> /dev/null 2>&1 1083 if [ $? -ne 0 ]; then 1084 if [[ $debug -eq 1 ]]; then 1085 echo "nothing to do" 1086 fi 1087 cp $infile $outfile 1088 return -1 1089 fi 1091 if [[ $strategy -eq 1 ]]; then 1092 fold_it_1 1093 return $? 1094 fi 1095 if [[ $strategy -eq 2 ]]; then 1096 fold_it_2 1097 return $? 1098 fi 1099 quiet_sav=$quiet 1100 quiet=1 1101 fold_it_1 1102 result=$? 1103 quiet=$quiet_sav 1104 if [[ $result -ne 0 ]]; then 1105 if [[ $debug -eq 1 ]]; then 1106 echo "Folding strategy 1 didn't succeed, trying strategy 2..." 1107 fi 1108 fold_it_2 1109 return $? 1110 fi 1111 return 0 1112 } 1114 unfold_it_1() { 1115 temp_dir=`mktemp -d` 1117 # output all but the first two lines (the header) to wip file 1118 awk "NR>2" $infile > $temp_dir/wip 1120 # unfold wip file 1121 "$SED" '{H;$!d};x;s/^\n//;s/\\\n *//g' $temp_dir/wip > $outfile 1123 return 0 1124 } 1126 unfold_it_2() { 1127 temp_dir=`mktemp -d` 1129 # output all but the first two lines (the header) to wip file 1130 awk "NR>2" $infile > $temp_dir/wip 1132 # unfold wip file 1133 "$SED" '{H;$!d};x;s/^\n//;s/\\\n *\\//g' $temp_dir/wip > $outfile 1135 return 0 1136 } 1138 unfold_it() { 1139 # check if file needs unfolding 1140 line=`head -n 1 $infile` 1141 result=`echo $line | fgrep "$hdr_txt_1"` 1142 if [ $? -eq 0 ]; then 1143 unfold_it_1 1144 return $? 1145 fi 1146 result=`echo $line | fgrep "$hdr_txt_2"` 1147 if [ $? -eq 0 ]; then 1148 unfold_it_2 1149 return $? 1150 fi 1151 if [[ $debug -eq 1 ]]; then 1152 echo "nothing to do" 1153 fi 1154 cp $infile $outfile 1155 return -1 1156 } 1158 process_input() { 1159 while [ "$1" != "" ]; do 1160 if [ "$1" == "-h" -o "$1" == "--help" ]; then 1161 print_usage 1162 exit 1 1163 fi 1164 if [ "$1" == "-d" ]; then 1165 debug=1 1166 fi 1167 if [ "$1" == "-q" ]; then 1168 quiet=1 1170 fi 1171 if [ "$1" == "-s" ]; then 1172 strategy="$2" 1173 shift 1174 fi 1175 if [ "$1" == "-c" ]; then 1176 maxcol="$2" 1177 shift 1178 fi 1179 if [ "$1" == "-r" ]; then 1180 reversed=1 1181 fi 1182 if [ "$1" == "-i" ]; then 1183 infile="$2" 1184 shift 1185 fi 1186 if [ "$1" == "-o" ]; then 1187 outfile="$2" 1188 shift 1189 fi 1190 shift 1191 done 1193 if [[ -z "$infile" ]]; then 1194 if [[ $quiet -eq 0 ]]; then 1195 echo 1196 echo "Error: infile parameter missing (use -h for help)" 1197 echo 1198 fi 1199 exit 1 1200 fi 1202 if [[ -z "$outfile" ]]; then 1203 if [[ $quiet -eq 0 ]]; then 1204 echo 1205 echo "Error: outfile parameter missing (use -h for help)" 1206 echo 1207 exit 1 1208 fi 1209 fi 1211 if [[ ! -f "$infile" ]]; then 1212 if [[ $quiet -eq 0 ]]; then 1213 echo 1214 echo "Error: specified file \"$infile\" is does not exist." 1215 echo 1216 exit 1 1217 fi 1219 fi 1221 if [[ $strategy -eq 2 ]]; then 1222 min_supported=`expr ${#hdr_txt_2} + 8` 1223 else 1224 min_supported=`expr ${#hdr_txt_1} + 8` 1225 fi 1226 if [[ $maxcol -lt $min_supported ]]; then 1227 if [[ $quiet -eq 0 ]]; then 1228 echo 1229 echo "Error: the folding column cannot be less than" 1230 echo "$min_supported." 1231 echo 1232 fi 1233 exit 1 1234 fi 1236 # this is only because the code otherwise runs out of equal_chars 1237 max_supported=`expr ${#equal_chars} + 1 + ${#hdr_txt_1} + 1\ 1238 + ${#equal_chars}` 1239 if [[ $maxcol -gt $max_supported ]]; then 1240 if [[ $quiet -eq 0 ]]; then 1241 echo 1242 echo "Error: the folding column cannot be more than" 1243 echo "$max_supported." 1244 echo 1245 fi 1246 exit 1 1247 fi 1248 } 1250 main() { 1251 if [ "$#" == "0" ]; then 1252 print_usage 1253 exit 1 1254 fi 1256 process_input $@ 1258 if [[ $reversed -eq 0 ]]; then 1259 fold_it 1260 code=$? 1261 else 1262 unfold_it 1263 code=$? 1264 fi 1265 exit $code 1266 } 1267 main "$@" 1269 1271 Acknowledgements 1273 The authors thank the RFC Editor for confirming that there was 1274 previously no set convention for handling long lines in sourcecode 1275 inclusions, thus instigating this work. 1277 The authors thank the following folks for their various contributions 1278 while producing this document (sorted by first name): Benoit Claise, 1279 Erik Auerswald, Gianmarco Bruno, Italo Busi, Joel Jaeggli, Jonathan 1280 Hansford, Lou Berger, Martin Bjorklund, and Rob Wilton. 1282 Special acknowledgement to Erik Auerswald for his contributions to 1283 the `rfcfold` script, especially for greatly improving the `sed` one- 1284 liners used therein. 1286 Authors' Addresses 1288 Kent Watsen 1289 Watsen Networks 1291 EMail: kent+ietf@watsen.net 1293 Adrian Farrel 1294 Old Dog Consulting 1296 EMail: adrian@olddog.co.uk 1298 Qin Wu 1299 Huawei Technologies 1301 EMail: bill.wu@huawei.com