idnits 2.17.1 draft-ietf-netmod-artwork-folding-06.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 (June 27, 2019) is 1765 days in the past. Is this intentional? 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 (==), 2 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: December 29, 2019 Old Dog Consulting 6 Q. Wu 7 Huawei Technologies 8 June 27, 2019 10 Handling Long Lines in Inclusions in Internet-Drafts and RFCs 11 draft-ietf-netmod-artwork-folding-06 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 December 29, 2019. 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 . . . . . . . . . . . . . . . . . . . . . . 11 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 '\\' . . . . . . . . . . . . . . . . . . . . . 13 93 9.3. Example Showing "Smart" Folding . . . . . . . . . . . . . 13 94 9.3.1. Using '\' . . . . . . . . . . . . . . . . . . . . . . 14 95 9.3.2. Using '\\' . . . . . . . . . . . . . . . . . . . . . 15 97 10. Security Considerations . . . . . . . . . . . . . . . . . . . 16 98 11. IANA Considerations . . . . . . . . . . . . . . . . . . . . . 16 99 12. References . . . . . . . . . . . . . . . . . . . . . . . . . 16 100 12.1. Normative References . . . . . . . . . . . . . . . . . . 16 101 12.2. Informative References . . . . . . . . . . . . . . . . . 16 102 Appendix A. POSIX Shell Script: rfcfold . . . . . . . . . . . . 18 103 Acknowledgements . . . . . . . . . . . . . . . . . . . . . . . . 26 104 Authors' Addresses . . . . . . . . . . . . . . . . . . . . . . . 26 106 1. Introduction 108 [RFC7994] sets out the requirements for plain-text RFCs and states 109 that each line of an RFC (and hence of an Internet-Draft) must be 110 limited to 72 characters followed by the character sequence that 111 denotes an end-of-line (EOL). 113 Internet-Drafts and RFCs often include example text or code 114 fragments. Many times the example text or code exceeds the 72 115 character line-length limit. The `xml2rfc` utility does not attempt 116 to wrap the content of such inclusions, simply issuing a warning 117 whenever lines exceed 69 characters. According to the RFC Editor, 118 there is currently no convention in place for how to handle long 119 lines in such inclusions, other than advising authors to clearly 120 indicate what manipulation has occurred. 122 This document defines two strategies for handling long lines in 123 width-bounded text content. One strategy is based on the historic 124 use of a single backslash ('\') character to indicate where line- 125 folding has occurred, with the continuation occurring with the first 126 non-space (' ') character on the next line. The second strategy 127 extends the first strategy by adding a second backslash character to 128 identify where the continuation begins and thereby able to handle 129 cases not supported by the first strategy. Both strategies use a 130 self-describing header enabling automated reconstitution of the 131 original content. 133 The strategies defined in this document work on any text content, but 134 are primarily intended for a structured sequence of lines, such as 135 would be referenced by the element defined in 136 Section 2.48 of [RFC7991], rather than for two-dimensional imagery, 137 such as would be referenced by the element defined in 138 Section 2.5 of [RFC7991]. 140 Note that text files are represented as lines having their first 141 character in column 1, and a line length of N where the last 142 character is in the Nth column and is immediately followed by an end 143 of line character sequence. 145 2. Applicability Statement 147 The formats and algorithms defined in this document may be used in 148 any context, whether for IETF documents or in other situations where 149 structured folding is desired. 151 Within the IETF, this work primarily targets the xml2rfc v3 152 element (Section 2.48 of [RFC7991]) and the xml2rfc v2 153 element (Section 2.5 of [RFC7749]) that, for lack of a 154 better option, is currently used for both source code and artwork. 155 This work may be also be used for the xml2rfc v3 element 156 (Section 2.5 of [RFC7991]) but, as described in Section 5.1, it is 157 generally not recommended. 159 3. Requirements Language 161 The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", 162 "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and 163 "OPTIONAL" in this document are to be interpreted as described in BCP 164 14 [RFC2119] [RFC8174] when, and only when, they appear in all 165 capitals, as shown here. 167 4. Goals 169 4.1. Automated Folding of Long Lines in Text Content 171 Automated folding of long lines is needed in order to support draft 172 compilations that entail a) validation of source input files (e.g., 173 XML, JSON, ABNF, ASN.1) and/or b) dynamic generation of output, using 174 a tool that doesn't observe line lengths, that is stitched into the 175 final document to be submitted. 177 Generally, in order for tooling to be able to process input files, 178 the files must be in their original/natural state, which may entail 179 them having some long lines. Thus, these source files need to be 180 modified before inclusion in the document in order to satisfy the 181 line length limits. This modification SHOULD be automated to reduce 182 effort and errors resulting from manual processing. 184 Similarly, dynamically generated output (e.g., tree diagrams) must 185 also be modified, if necessary, in order for the resulting document 186 to satisfy the line length limits. When needed, this effort again 187 SHOULD be automated to reduce effort and errors resulting from manual 188 processing. 190 4.2. Automated Reconstitution of the Original Text Content 192 Automated reconstitution of the exact original text content is needed 193 to support validation of text-based content extracted from documents. 195 For instance, already YANG [RFC7950] modules are extracted from 196 Internet-Drafts and validated as part of the draft-submission 197 process. Additionally, the desire to validate instance examples 198 (i.e., XML/JSON documents) contained within Internet-Drafts has been 199 discussed ([yang-doctors-thread]). 201 5. Limitations 203 5.1. Not Recommended for Graphical Artwork 205 While the solution presented in this document works on any kind of 206 text-based content, it is most useful on content that represents 207 source code (XML, JSON, etc.) or, more generally, on content that has 208 not been laid out in two dimensions (e.g., diagrams). 210 Fundamentally, the issue is whether the text content remains readable 211 once folded. Text content that is unpredictable is especially 212 susceptible to looking bad when folded; falling into this category 213 are most UML diagrams, YANG tree diagrams, and ASCII art in general. 215 It is NOT RECOMMENDED to use the solution presented in this document 216 on graphical artwork. 218 5.2. Doesn't Work as Well as Format-Specific Options 220 The solution presented in this document works generically for all 221 text-based content, as it only views content as plain text. However, 222 various formats sometimes have built-in mechanisms that are better 223 suited to prevent long lines. 225 For instance, both the `pyang` and `yanglint` utilities have the 226 command line option "--tree-line-length" that can be used to indicate 227 a desired maximum line length for when generating tree diagrams 228 [RFC8340]. 230 In another example, some source formats (e.g., YANG [RFC7950]) allow 231 any quoted string to be broken up into substrings separated by a 232 concatenation character (e.g., '+'), any of which can be on a 233 different line. 235 It is RECOMMENDED that authors do as much as possible within the 236 selected format to avoid long lines. 238 6. Two Folding Strategies 240 This document defines two nearly identical strategies for folding 241 text-based content. 243 The Single Backslash Strategy ('\'): Uses a backslash ('\') 244 character at the end of the line where folding occurs, and 245 assumes that the continuation begins at the character that is 246 not a space character (' ') on the following line. 248 The Double Backslash Strategy ('\\'): Uses a backslash ('\') 249 character at the end of the line where folding occurs, and 250 assumes that the continuation begins after a second backslash 251 ('\') character on the following line. 253 6.1. Comparison 255 The first strategy produces more readable output, however it is 256 significantly more likely to encounter unfoldable input (e.g., there 257 exists a line anywhere in the input ending with a backslash 258 character, or there exists a long line containing only space 259 characters) and, for long lines that can be folded, automation 260 implementations may encounter scenarios that will produce errors 261 without special care. 263 The second strategy produces less readable output, but is unlikely to 264 encounter unfoldable input, there are no long lines that cannot be 265 folded, and no special care is required for when folding a long line. 267 6.2. Recommendation 269 It is RECOMMENDED for implementations to first attempt to fold 270 content using the single backslash strategy and, only in the unlikely 271 event that it cannot fold the input or the folding logic is unable to 272 cope with a contingency occurring on the desired folding column, then 273 fallback to the double backslash strategy. 275 7. The Single Backslash Strategy ('\') 277 7.1. Folded Structure 279 Text content that has been folded as specified by this strategy MUST 280 adhere to the following structure. 282 7.1.1. Header 284 The header is two lines long. 286 The first line is the following 45-character string that MAY be 287 surrounded by any number of printable characters. This first line 288 cannot itself be folded. 290 NOTE: '\' line wrapping per BCP XX (RFC XXXX) 292 [Note to RFC Editor: Please replace XX and XXXX with the numbers 293 assigned to this document and delete this note. Please make this 294 change in multiple places in this document.] 296 The second line is a blank line. This line provides visual 297 separation for readability. 299 7.1.2. Body 301 The character encoding is the same as described in Section 2 of 302 [RFC7994], except that, per [RFC7991], tab characters are prohibited. 304 Lines that have a backslash ('\') occurring as the last character in 305 a line are considered "folded". 307 Really long lines may be folded multiple times. 309 7.2. Algorithm 311 This section describes a process for folding and unfolding long lines 312 when they are encountered in text content. 314 The steps are complete, but implementations MAY achieve the same 315 result in other ways. 317 When a larger document contains multiple instances of text content 318 that may need to be folded or unfolded, another process must insert/ 319 extract the individual text content instances to/from the larger 320 document prior to utilizing the algorithms described in this section. 321 For example, the `xiax` utility [xiax] does this. 323 7.2.1. Folding 325 Determine the desired maximum line length from input to the line- 326 wrapping process, such as from a command line parameter. If no value 327 is explicitly specified, the value "69" SHOULD be used. 329 Ensure that the desired maximum line length is not less than the 330 minimum header, which is 45 characters. If the desired maximum line 331 length is less than this minimum, exit (this text-based content 332 cannot be folded). 334 Scan the text content for horizontal tab characters. If any 335 horizontal tab characters appear, either resolve them to space 336 characters or exit, forcing the input provider to convert them to 337 space characters themselves first. 339 Scan the text content to ensure at least one line exceeds the desired 340 maximum. If no line exceeds the desired maximum, exit (this text 341 content does not need to be folded). 343 Scan the text content to ensure no existing lines already end with a 344 backslash ('\') character, as this would lead to an ambiguous result. 345 If such a line is found, exit (this text content cannot be folded). 347 If this text content needs to and can be folded, insert the header 348 described in Section 7.1.1, ensuring that any additional printable 349 characters surrounding the header does not result in a line exceeding 350 the desired maximum. 352 For each line in the text content, from top-to-bottom, if the line 353 exceeds the desired maximum, then fold the line by: 355 1. Determine where the fold will occur. This location MUST be 356 before or at the desired maximum column, and MUST NOT be chosen 357 such that the character immediately after the fold is a space (' 358 ') character. If no such location can be found, then exit (this 359 text content cannot be folded) 361 2. At the location where the fold is to occur, insert a backslash 362 ('\') character followed by the end of line character sequence. 364 3. On the following line, insert any number of space (' ') 365 characters. 367 The result of the previous operation is that the next line starts 368 with an arbitrary number of space (' ') characters, followed by the 369 character that was previously occupying the position where the fold 370 occurred. 372 Continue in this manner until reaching the end of the text content. 373 Note that this algorithm naturally addresses the case where the 374 remainder of a folded line is still longer than the desired maximum, 375 and hence needs to be folded again, ad infinitum. 377 The process described in this section is illustrated by the 378 "fold_it_1()" function in Appendix A. 380 7.2.2. Unfolding 382 Scan the beginning of the text content for the header described in 383 Section 7.1.1. If the header is not present, starting on the first 384 line of the text content, exit (this text contents does not need to 385 be unfolded). 387 Remove the 2-line header from the text content. 389 For each line in the text content, from top-to-bottom, if the line 390 has a backslash ('\') character immediately followed by the end of 391 line character sequence, then the line can be unfolded. Remove the 392 backslash ('\') character, the end of line character sequence, and 393 any leading space (' ') characters, which will bring up the next 394 line. Then continue to scan each line in the text content starting 395 with the current line (in case it was multiply folded). 397 Continue in this manner until reaching the end of the text content. 399 The process described in this section is illustrated by the 400 "unfold_it_1()" function in Appendix A. 402 8. The Double Backslash Strategy ('\\') 404 8.1. Folded Structure 406 Text content that has been folded as specified by this strategy MUST 407 adhere to the following structure. 409 8.1.1. Header 411 The header is two lines long. 413 The first line is the following 46-character string that MAY be 414 surrounded by any number of printable characters. This first line 415 cannot itself be folded. 417 NOTE: '\\' line wrapping per BCP XX (RFC XXXX) 419 [Note to RFC Editor: Please replace XX and XXXX with the numbers 420 assigned to this document and delete this note. Please make this 421 change in multiple places in this document.] 423 The second line is a blank line. This line provides visual 424 separation for readability. 426 8.1.2. Body 428 The character encoding is the same as described in Section 2 of 429 [RFC7994], except that, per [RFC7991], tab characters are prohibited. 431 Lines that have a backslash ('\') occurring as the last character in 432 a line immediately followed by the end of line character sequence, 433 when the subsequent line starts with a backslash ('\') as the first 434 non-space (' ') character, are considered "folded". 436 Really long lines may be folded multiple times. 438 8.2. Algorithm 440 This section describes a process for folding and unfolding long lines 441 when they are encountered in text content. 443 The steps are complete, but implementations MAY achieve the same 444 result in other ways. 446 When a larger document contains multiple instances of text content 447 that may need to be folded or unfolded, another process must insert/ 448 extract the individual text content instances to/from the larger 449 document prior to utilizing the algorithms described in this section. 450 For example, the `xiax` utility [xiax] does this. 452 8.2.1. Folding 454 Determine the desired maximum line length from input to the line- 455 wrapping process, such as from a command line parameter. If no value 456 is explicitly specified, the value "69" SHOULD be used. 458 Ensure that the desired maximum line length is not less than the 459 minimum header, which is 46 characters. If the desired maximum line 460 length is less than this minimum, exit (this text-based content 461 cannot be folded). 463 Scan the text content for horizontal tab characters. If any 464 horizontal tab characters appear, either resolve them to space 465 characters or exit, forcing the input provider to convert them to 466 space characters themselves first. 468 Scan the text content to see if any line exceeds the desired maximum. 469 If no line exceeds the desired maximum, exit (this text content does 470 not need to be folded). 472 Scan the text content to ensure no existing lines already end with a 473 backslash ('\') character while the subsequent line starts with a 474 backslash ('\') character as the first non-space (' ') character, as 475 this could lead to an ambiguous result. If such a line is found, and 476 its width is less than the desired maximum, then it SHOULD be flagged 477 for forced folding (folding even though unnecessary). If the folding 478 implementation doesn't support forced foldings, it MUST exit. 480 If this text content needs to and can be folded, insert the header 481 described in Section 8.1.1, ensuring that any additional printable 482 characters surrounding the header does not result in a line exceeding 483 the desired maximum. 485 For each line in the text content, from top-to-bottom, if the line 486 exceeds the desired maximum, or requires a forced folding, then fold 487 the line by: 489 1. Determine where the fold will occur. This location MUST be 490 before or at the desired maximum column. 492 2. At the location where the fold is to occur, insert a first 493 backslash ('\') character followed by the end of line character 494 sequence. 496 3. On the following line, insert any number of space (' ') 497 characters followed by a second backslash ('\') character. 499 The result of the previous operation is that the next line starts 500 with an arbitrary number of space (' ') characters, followed by a 501 backslash ('\') character, immediately followed by the character that 502 was previously occupying the position where the fold occurred. 504 Continue in this manner until reaching the end of the text content. 505 Note that this algorithm naturally addresses the case where the 506 remainder of a folded line is still longer than the desired maximum, 507 and hence needs to be folded again, ad infinitum. 509 The process described in this section is illustrated by the 510 "fold_it_2()" function in Appendix A. 512 8.2.2. Unfolding 514 Scan the beginning of the text content for the header described in 515 Section 8.1.1. If the header is not present, starting on the first 516 line of the text content, exit (this text content does not need to be 517 unfolded). 519 Remove the 2-line header from the text content. 521 For each line in the text content, from top-to-bottom, if the line 522 has a backslash ('\') character immediately followed by the end of 523 line character sequence, and if the next line has a backslash ('\') 524 character as the first non-space (' ') character, then the lines can 525 be unfolded. Remove the first backslash ('\') character, the end of 526 line character sequence, any leading space (' ') characters, and the 527 second backslash ('\') character, which will bring up the next line. 528 Then continue to scan each line in the text content starting with the 529 current line (in case it was multiply folded). 531 Continue in this manner until reaching the end of the text content. 533 The process described in this section is illustrated by the 534 "unfold_it_2()" function in Appendix A. 536 9. Examples 538 The following self-documenting examples illustrate folded text-based 539 content. 541 The source text content cannot be presented here, as it would again 542 be folded. Alas, only the results can be provided. 544 9.1. Example Showing Boundary Conditions 546 This example illustrates boundary condition. The input contains 547 seven lines, each line one character longer than the previous line. 548 Numbers for counting purposes. The default desired maximum column 549 value "69" is used. 551 9.1.1. Using '\' 553 =========== NOTE: '\' line wrapping per BCP XX (RFC XXXX) =========== 555 123456789012345678901234567890123456789012345678901234567890123456 556 1234567890123456789012345678901234567890123456789012345678901234567 557 12345678901234567890123456789012345678901234567890123456789012345678 558 123456789012345678901234567890123456789012345678901234567890123456789 559 12345678901234567890123456789012345678901234567890123456789012345678\ 560 90 561 12345678901234567890123456789012345678901234567890123456789012345678\ 562 901 563 12345678901234567890123456789012345678901234567890123456789012345678\ 564 9012 566 9.1.2. Using '\\' 568 ========== NOTE: '\\' line wrapping per BCP XX (RFC XXXX) =========== 570 123456789012345678901234567890123456789012345678901234567890123456 571 1234567890123456789012345678901234567890123456789012345678901234567 572 12345678901234567890123456789012345678901234567890123456789012345678 573 123456789012345678901234567890123456789012345678901234567890123456789 574 12345678901234567890123456789012345678901234567890123456789012345678\ 575 \90 576 12345678901234567890123456789012345678901234567890123456789012345678\ 577 \901 578 12345678901234567890123456789012345678901234567890123456789012345678\ 579 \9012 581 9.2. Example Showing Multiple Wraps of a Single Line 583 This example illustrates what happens when very long line needs to be 584 folded multiple times. The input contains one line containing 280 585 characters. Numbers for counting purposes. The default desired 586 maximum column value "69" is used. 588 9.2.1. Using '\' 590 =========== NOTE: '\' line wrapping per BCP XX (RFC XXXX) =========== 592 12345678901234567890123456789012345678901234567890123456789012345678\ 593 90123456789012345678901234567890123456789012345678901234567890123456\ 594 78901234567890123456789012345678901234567890123456789012345678901234\ 595 56789012345678901234567890123456789012345678901234567890123456789012\ 596 34567890 598 9.2.2. Using '\\' 600 ========== NOTE: '\\' line wrapping per BCP XX (RFC XXXX) =========== 602 12345678901234567890123456789012345678901234567890123456789012345678\ 603 \9012345678901234567890123456789012345678901234567890123456789012345\ 604 \6789012345678901234567890123456789012345678901234567890123456789012\ 605 \3456789012345678901234567890123456789012345678901234567890123456789\ 606 \01234567890 608 9.3. Example Showing "Smart" Folding 610 This example illustrates how readability can be improved via "smart" 611 folding, whereby folding occurs at format-specific locations and 612 format-specific indentations are used. 614 The text content was manually folded, since the script in the 615 appendix does not implement smart folding. 617 Note that the header is surrounded by different printable characters 618 then shown in the script-generated examples. 620 9.3.1. Using '\' 622 [NOTE: '\' line wrapping per BCP XX (RFC XXXX)] 624 628 629 config-modules 630 631 ietf-interfaces 632 2018-02-20 633 \ 634 urn:ietf:params:xml:ns:yang:ietf-interfaces\ 635 636 637 ... 638 639 ... 640 642 Below is the equivalent to the above, but it was folded using the 643 script in the appendix. 645 =========== NOTE: '\' line wrapping per BCP XX (RFC XXXX) =========== 647 651 652 config-modules 653 654 ietf-interfaces 655 2018-02-20 656 urn:ietf:params:xml:ns:yang:ietf-interfaces 658 659 ... 660 661 ... 662 664 9.3.2. Using '\\' 666 [NOTE: '\\' line wrapping per BCP XX (RFC XXXX)] 668 672 673 config-modules 674 675 ietf-interfaces 676 2018-02-20 677 \ 678 \urn:ietf:params:xml:ns:yang:ietf-interfaces\ 679 \ 680 681 ... 682 683 ... 684 686 Below is the equivalent to the above, but it was folded using the 687 script in the appendix. 689 ========== NOTE: '\\' line wrapping per BCP XX (RFC XXXX) =========== 691 695 696 config-modules 697 698 ietf-interfaces 699 2018-02-20 700 urn:ietf:params:xml:ns:yang:ietf-interfaces 702 703 ... 704 705 ... 706 708 10. Security Considerations 710 This BCP has no Security Considerations. 712 11. IANA Considerations 714 This BCP has no IANA Considerations. 716 12. References 718 12.1. Normative References 720 [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate 721 Requirement Levels", BCP 14, RFC 2119, 722 DOI 10.17487/RFC2119, March 1997, 723 . 725 [RFC8174] Leiba, B., "Ambiguity of Uppercase vs Lowercase in RFC 726 2119 Key Words", BCP 14, RFC 8174, DOI 10.17487/RFC8174, 727 May 2017, . 729 12.2. Informative References 731 [RFC7749] Reschke, J., "The "xml2rfc" Version 2 Vocabulary", 732 RFC 7749, DOI 10.17487/RFC7749, February 2016, 733 . 735 [RFC7950] Bjorklund, M., Ed., "The YANG 1.1 Data Modeling Language", 736 RFC 7950, DOI 10.17487/RFC7950, August 2016, 737 . 739 [RFC7991] Hoffman, P., "The "xml2rfc" Version 3 Vocabulary", 740 RFC 7991, DOI 10.17487/RFC7991, December 2016, 741 . 743 [RFC7994] Flanagan, H., "Requirements for Plain-Text RFCs", 744 RFC 7994, DOI 10.17487/RFC7994, December 2016, 745 . 747 [RFC8340] Bjorklund, M. and L. Berger, Ed., "YANG Tree Diagrams", 748 BCP 215, RFC 8340, DOI 10.17487/RFC8340, March 2018, 749 . 751 [xiax] "The `xiax` Python Package", 752 . 754 [yang-doctors-thread] 755 "[yang-doctors] automating yang doctor reviews", 756 . 759 Appendix A. POSIX Shell Script: rfcfold 761 This non-normative appendix section includes a shell script that can 762 both fold and unfold text content using both the single and double 763 backslash strategies described in Section 7 and Section 8 764 respectively. 766 This script is intended to be applied to a single text content 767 instance. If it is desired to fold or unfold text content instances 768 within a larger document (e.g., an Internet draft or RFC), then 769 another tool must be used to extract the content from the larger 770 document before utilizing this script. 772 For readability purposes, this script forces the minimally supported 773 line length to be eight characters longer than the raw header text 774 defined in Section 7.1.1 and Section 8.1.1 so as to ensure that the 775 header can be wrapped by a space (' ') character and three equal 776 ('=') characters on each side of the raw header text. 778 This script does not implement the "forced folding" logic described 779 in Section 8.2.1. In such cases the script will exit with the 780 message: 782 Error: infile has a line ending with a '\' character 783 followed by a '\' character as the first non-space 784 character on the next line. This script cannot fold 785 this file using '\\' strategy without there being 786 false positives produced in the unfolding (i.e., this 787 script does not attempt to proactively force-fold such 788 lines, as described in RFC XXXX). 790 Shell-level end-of-line backslash ('\') characters have been 791 purposely added to the script so as to ensure that the script is 792 itself not folded in this document, thus simplify the ability to 793 copy/paste the script for local use. As should be evident by the 794 lack of the mandatory header described in Section 7.1.1, these 795 backslashes do not designate a folded line, such as described in 796 Section 7. 798 800 #!/bin/bash --posix 801 # must use `bash` (not `sh`) 803 # This script may need some adjustments to work on a given system. 804 # For instance, the utilities `pcregrep` and `gsed` may need to 805 # be installed. 807 print_usage() { 808 echo 809 echo "Folds the text file, only if needed, at the specified" 810 echo "column, according to BCP XX." 811 echo 812 echo "Usage: $0 [-s ] [-c ] [-r] -i " 813 echo " -o " 814 echo 815 echo " -s: strategy to use, '1' or '2' (default: try 1, else 2)" 816 echo " -c: column to fold on (default: 69)" 817 echo " -r: reverses the operation" 818 echo " -i: the input filename" 819 echo " -o: the output filename" 820 echo " -d: show debug messages" 821 echo " -q: quiet (suppress error messages)" 822 echo " -h: show this message" 823 echo 824 echo "Exit status code: zero on success, non-zero otherwise." 825 echo 826 } 828 # global vars, do not edit 829 strategy=0 # auto 830 debug=0 831 quiet=0 832 reversed=0 833 infile="" 834 outfile="" 835 maxcol=69 # default, may be overridden by param 836 hdr_txt_1="NOTE: '\\' line wrapping per BCP XX (RFC XXXX)" 837 hdr_txt_2="NOTE: '\\\\' line wrapping per BCP XX (RFC XXXX)" 838 equal_chars="==============================================" 839 space_chars=" " 840 temp_dir="" 842 # determine name of [g]sed binary 843 type gsed > /dev/null 2>&1 && SED=gsed || SED=sed 845 # warn if a non-GNU sed utility is used 846 "$SED" --version < /dev/null 2> /dev/null \ 847 | grep GNU >/dev/null 2>&1 || echo 'Warning: not using GNU sed' 849 # verify the availability of pcregrep 850 type pcregrep > /dev/null 2>&1 || { 851 echo 'Error: missing utility `pcregrep`' 852 exit 1 853 } 854 cleanup() { 855 rm -rf "$temp_dir" 856 } 857 trap 'cleanup' EXIT 859 fold_it_1() { 860 # ensure input file doesn't contain the fold-sequence already 861 pcregrep -M "\\\\\n" $infile >> /dev/null 2>&1 862 if [[ $? -eq 0 ]]; then 863 if [[ $quiet -eq 0 ]]; then 864 echo 865 echo "Error: infile $infile has a line ending with a '\\'" 866 echo "character. This file cannot be folded using the '\\'" 867 echo "strategy." 868 echo 869 fi 870 return 1 871 fi 873 # where to fold 874 foldcol=`expr "$maxcol" - 1` # for the inserted '\' char 876 # ensure input file doesn't contain whitespace on the fold column 877 grep "^.\{$foldcol\} " $infile >> /dev/null 2>&1 878 if [[ $? -eq 0 ]]; then 879 if [[ $quiet -eq 0 ]]; then 880 echo 881 echo "Error: infile has a space character occuring on the" 882 echo "folding column. This file cannot be folded using the" 883 echo "'\\' strategy." 884 echo 885 fi 886 return 1 887 fi 889 # center header text 890 length=`expr ${#hdr_txt_1} + 2` 891 left_sp=`expr \( "$maxcol" - "$length" \) / 2` 892 right_sp=`expr "$maxcol" - "$length" - "$left_sp"` 893 header=`printf "%.*s %s %.*s" "$left_sp" "$equal_chars"\ 894 "$hdr_txt_1" "$right_sp" "$equal_chars"` 896 # generate outfile 897 echo "$header" > $outfile 898 echo "" >> $outfile 899 "$SED" 's/\(.\{'"$foldcol"'\}\)\(..\)/\1\\\n\2/;t M;b;:M;P;D;'\ 900 < $infile >> $outfile 2>/dev/null 901 if [[ $? -ne 0 ]]; then 902 return 1 903 fi 904 return 0 905 } 907 fold_it_2() { 908 # where to fold 909 foldcol=`expr "$maxcol" - 1` # for the inserted '\' char 911 # ensure input file doesn't contain the fold-sequence already 912 pcregrep -M "\\\\\n[\ ]*\\\\" $infile >> /dev/null 2>&1 913 if [[ $? -eq 0 ]]; then 914 if [[ $quiet -eq 0 ]]; then 915 echo 916 echo "Error: infile has a line ending with a '\\' character" 917 echo "followed by a '\\' character as the first non-space" 918 echo "character on the next line. This script cannot fold" 919 echo "this file using '\\\\' strategy without there being" 920 echo "false positives produced in the unfolding (i.e., this" 921 echo "script does not attempt to proactively force-fold such" 922 echo "lines, as described in RFC XXXX)." 923 echo 924 fi 925 return 1 926 fi 928 # center header text 929 length=`expr ${#hdr_txt_2} + 2` 930 left_sp=`expr \( "$maxcol" - "$length" \) / 2` 931 right_sp=`expr "$maxcol" - "$length" - "$left_sp"` 932 header=`printf "%.*s %s %.*s" "$left_sp" "$equal_chars"\ 933 "$hdr_txt_2" "$right_sp" "$equal_chars"` 935 # generate outfile 936 echo "$header" > $outfile 937 echo "" >> $outfile 938 "$SED" 's/\(.\{'"$foldcol"'\}\)\(..\)/\1\\\n\\\2/;t M;b;:M;P;D;'\ 939 < $infile >> $outfile 2>/dev/null 940 if [[ $? -ne 0 ]]; then 941 return 1 942 fi 943 return 0 944 } 946 fold_it() { 947 # ensure input file doesn't contain a TAB 948 grep $'\t' $infile >> /dev/null 2>&1 949 if [[ $? -eq 0 ]]; then 950 if [[ $quiet -eq 0 ]]; then 951 echo 952 echo "Error: infile contains a TAB character, which is" 953 echo "not allowed." 954 echo 955 fi 956 return 1 957 fi 959 # check if file needs folding 960 testcol=`expr "$maxcol" + 1` 961 grep ".\{$testcol\}" $infile >> /dev/null 2>&1 962 if [ $? -ne 0 ]; then 963 if [[ $debug -eq 1 ]]; then 964 echo "nothing to do" 965 fi 966 cp $infile $outfile 967 return -1 968 fi 970 if [[ $strategy -eq 1 ]]; then 971 fold_it_1 972 return $? 973 fi 974 if [[ $strategy -eq 2 ]]; then 975 fold_it_2 976 return $? 977 fi 978 quiet_sav=$quiet 979 quiet=1 980 fold_it_1 981 result=$? 982 quiet=$quiet_sav 983 if [[ $result -ne 0 ]]; then 984 if [[ $debug -eq 1 ]]; then 985 echo "Folding strategy 1 didn't succeed, trying strategy 2..." 986 fi 987 fold_it_2 988 return $? 989 fi 990 return 0 991 } 993 unfold_it_1() { 994 temp_dir=`mktemp -d` 996 # output all but the first two lines (the header) to wip file 997 awk "NR>2" $infile > $temp_dir/wip 998 # unfold wip file 999 "$SED" ':S;$!N;s/\\\n *//;t S;P;D' $temp_dir/wip > $outfile 1001 return 0 1002 } 1004 unfold_it_2() { 1005 temp_dir=`mktemp -d` 1007 # output all but the first two lines (the header) to wip file 1008 awk "NR>2" $infile > $temp_dir/wip 1010 # unfold wip file 1011 "$SED" ':S;$!N;s/\\\n *\\//;t S;P;D' $temp_dir/wip > $outfile 1013 return 0 1014 } 1016 unfold_it() { 1017 # check if file needs unfolding 1018 line=`head -n 1 $infile` 1019 result=`echo $line | fgrep "$hdr_txt_1"` 1020 if [ $? -eq 0 ]; then 1021 unfold_it_1 1022 return $? 1023 fi 1024 result=`echo $line | fgrep "$hdr_txt_2"` 1025 if [ $? -eq 0 ]; then 1026 unfold_it_2 1027 return $? 1028 fi 1029 if [[ $debug -eq 1 ]]; then 1030 echo "nothing to do" 1031 fi 1032 cp $infile $outfile 1033 return -1 1034 } 1036 process_input() { 1037 while [ "$1" != "" ]; do 1038 if [ "$1" == "-h" -o "$1" == "--help" ]; then 1039 print_usage 1040 exit 1 1041 fi 1042 if [ "$1" == "-d" ]; then 1043 debug=1 1044 fi 1045 if [ "$1" == "-q" ]; then 1046 quiet=1 1047 fi 1048 if [ "$1" == "-s" ]; then 1049 strategy="$2" 1050 shift 1051 fi 1052 if [ "$1" == "-c" ]; then 1053 maxcol="$2" 1054 shift 1055 fi 1056 if [ "$1" == "-r" ]; then 1057 reversed=1 1058 fi 1059 if [ "$1" == "-i" ]; then 1060 infile="$2" 1061 shift 1062 fi 1063 if [ "$1" == "-o" ]; then 1064 outfile="$2" 1065 shift 1066 fi 1067 shift 1068 done 1070 if [[ -z "$infile" ]]; then 1071 if [[ $quiet -eq 0 ]]; then 1072 echo 1073 echo "Error: infile parameter missing (use -h for help)" 1074 echo 1075 fi 1076 exit 1 1077 fi 1079 if [[ -z "$outfile" ]]; then 1080 if [[ $quiet -eq 0 ]]; then 1081 echo 1082 echo "Error: outfile parameter missing (use -h for help)" 1083 echo 1084 exit 1 1085 fi 1086 fi 1088 if [[ ! -f "$infile" ]]; then 1089 if [[ $quiet -eq 0 ]]; then 1090 echo 1091 echo "Error: specified file \"$infile\" is does not exist." 1092 echo 1093 exit 1 1095 fi 1096 fi 1098 if [[ $strategy -eq 2 ]]; then 1099 min_supported=`expr ${#hdr_txt_2} + 8` 1100 else 1101 min_supported=`expr ${#hdr_txt_1} + 8` 1102 fi 1103 if [[ $maxcol -lt $min_supported ]]; then 1104 if [[ $quiet -eq 0 ]]; then 1105 echo 1106 echo "Error: the folding column cannot be less than" 1107 echo "$min_supported." 1108 echo 1109 fi 1110 exit 1 1111 fi 1113 # this is only because the code otherwise runs out of equal_chars 1114 max_supported=`expr ${#equal_chars} + 1 + ${#hdr_txt_1} + 1\ 1115 + ${#equal_chars}` 1116 if [[ $maxcol -gt $max_supported ]]; then 1117 if [[ $quiet -eq 0 ]]; then 1118 echo 1119 echo "Error: the folding column cannot be more than" 1120 echo "$max_supported." 1121 echo 1122 fi 1123 exit 1 1124 fi 1125 } 1127 main() { 1128 if [ "$#" == "0" ]; then 1129 print_usage 1130 exit 1 1131 fi 1133 process_input $@ 1135 if [[ $reversed -eq 0 ]]; then 1136 fold_it 1137 code=$? 1138 else 1139 unfold_it 1140 code=$? 1141 fi 1142 exit $code 1144 } 1146 main "$@" 1148 1150 Acknowledgements 1152 The authors thank the RFC Editor for confirming that there was 1153 previously no set convention for handling long lines in sourcecode 1154 inclusions, thus instigating this work. 1156 The authors thank the following folks for their various contributions 1157 while producing this document (sorted by first name): Benoit Claise, 1158 Erik Auerswald, Gianmarco Bruno, Italo Busi, Joel Jaeggli, Jonathan 1159 Hansford, Lou Berger, Martin Bjorklund, and Rob Wilton. 1161 Special acknowledgement to Erik Auerswald for his contributions to 1162 the `rfcfold` script, especially for greatly improving the `sed` one- 1163 liners used therein. 1165 Authors' Addresses 1167 Kent Watsen 1168 Watsen Networks 1170 EMail: kent+ietf@watsen.net 1172 Adrian Farrel 1173 Old Dog Consulting 1175 EMail: adrian@olddog.co.uk 1177 Qin Wu 1178 Huawei Technologies 1180 EMail: bill.wu@huawei.com