idnits 2.17.1 draft-ietf-netmod-artwork-folding-07.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 (July 23, 2019) is 1738 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: January 24, 2020 Old Dog Consulting 6 Q. Wu 7 Huawei Technologies 8 July 23, 2019 10 Handling Long Lines in Inclusions in Internet-Drafts and RFCs 11 draft-ietf-netmod-artwork-folding-07 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 January 24, 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 . . . . . . . . . . . . . . . . . . . . . . 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 . . . . . . . . . . . . . . . . . . . . . . . 27 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 802 # This script may need some adjustments to work on a given system. 803 # For instance, the utilities `pcregrep` and `gsed` may need to 804 # be installed. Also, please be advised that `bash` (not `sh`) 805 # must be used. 807 # Copyright (c) 2019 IETF Trust, Kent Watsen, and Erik Auerswald. 808 # All rights reserved. 809 # 810 # Redistribution and use in source and binary forms, with or without 811 # modification, are permitted provided that the following conditions 812 # are met: 813 # 814 # * Redistributions of source code must retain the above copyright 815 # notice, this list of conditions and the following disclaimer. 816 # 817 # * Redistributions in binary form must reproduce the above 818 # copyright notice, this list of conditions and the following 819 # disclaimer in the documentation and/or other materials 820 # provided with the distribution. 821 # 822 # * Neither the name of Internet Society, IETF or IETF Trust, nor 823 # the names of specific contributors, may be used to endorse or 824 # promote products derived from this software without specific 825 # prior written permission. 826 # 827 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 828 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 829 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 830 # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 831 # COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 832 # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 833 # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 834 # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 835 # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 836 # STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 837 # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 838 # ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 840 print_usage() { 841 printf "\n" 842 printf "Folds or unfolds the input text file according to BCP XX" 843 printf " (RFC XXXX).\n" 844 printf "\n" 845 printf "Usage: rfcfold [-s ] [-c ] [-r] -i " 846 printf " -o \n" 847 printf "\n" 848 printf " -s: strategy to use, '1' or '2' (default: try 1," 849 printf " else 2)\n" 850 printf " -c: column to fold on (default: 69)\n" 851 printf " -r: reverses the operation\n" 852 printf " -i: the input filename\n" 853 printf " -o: the output filename\n" 854 printf " -d: show debug messages\n" 855 printf " -q: quiet (suppress error messages)\n" 856 printf " -h: show this message\n" 857 printf "\n" 858 printf "Exit status code: 1 on error, 0 on success, -1 on no-op.\n" 859 printf "\n" 860 } 862 # global vars, do not edit 863 strategy=0 # auto 864 debug=0 865 quiet=0 866 reversed=0 867 infile="" 868 outfile="" 869 maxcol=69 # default, may be overridden by param 870 hdr_txt_1="NOTE: '\\' line wrapping per BCP XX (RFC XXXX)" 871 hdr_txt_2="NOTE: '\\\\' line wrapping per BCP XX (RFC XXXX)" 872 equal_chars="=======================================================" 873 space_chars=" " 874 temp_dir="" 876 # determine name of [g]sed binary 877 type gsed > /dev/null 2>&1 && SED=gsed || SED=sed 879 # warn if a non-GNU sed utility is used 880 "$SED" --version < /dev/null 2> /dev/null \ 881 | grep GNU >/dev/null 2>&1 || echo 'Warning: not using GNU `sed`.' 883 # verify the availability of pcregrep 884 type pcregrep > /dev/null 2>&1 || { 885 echo 'Error: missing utility `pcregrep`' 886 exit 1 887 } 889 cleanup() { 890 rm -rf "$temp_dir" 891 } 892 trap 'cleanup' EXIT 894 fold_it_1() { 895 # ensure input file doesn't contain the fold-sequence already 896 pcregrep -M "\\\\\n" $infile >> /dev/null 2>&1 897 if [[ $? -eq 0 ]]; then 898 if [[ $quiet -eq 0 ]]; then 899 echo 900 echo "Error: infile $infile has a line ending with a '\\'" 901 echo "character. This file cannot be folded using the '\\'" 902 echo "strategy." 903 echo 904 fi 905 return 1 906 fi 908 # where to fold 909 foldcol=`expr "$maxcol" - 1` # for the inserted '\' char 911 # ensure input file doesn't contain whitespace on the fold column 912 grep "^.\{$foldcol\} " $infile >> /dev/null 2>&1 913 if [[ $? -eq 0 ]]; then 914 if [[ $quiet -eq 0 ]]; then 915 echo 916 echo "Error: infile has a space character occuring on the" 917 echo "folding column. This file cannot be folded using the" 918 echo "'\\' strategy." 919 echo 920 fi 921 return 1 922 fi 924 # center header text 925 length=`expr ${#hdr_txt_1} + 2` 926 left_sp=`expr \( "$maxcol" - "$length" \) / 2` 927 right_sp=`expr "$maxcol" - "$length" - "$left_sp"` 928 header=`printf "%.*s %s %.*s" "$left_sp" "$equal_chars"\ 929 "$hdr_txt_1" "$right_sp" "$equal_chars"` 931 # generate outfile 932 echo "$header" > $outfile 933 echo "" >> $outfile 934 "$SED" 's/\(.\{'"$foldcol"'\}\)\(..\)/\1\\\n\2/;t M;b;:M;P;D;'\ 935 < $infile >> $outfile 2>/dev/null 936 if [[ $? -ne 0 ]]; then 937 return 1 938 fi 939 return 0 940 } 942 fold_it_2() { 943 # where to fold 944 foldcol=`expr "$maxcol" - 1` # for the inserted '\' char 946 # ensure input file doesn't contain the fold-sequence already 947 pcregrep -M "\\\\\n[\ ]*\\\\" $infile >> /dev/null 2>&1 948 if [[ $? -eq 0 ]]; then 949 if [[ $quiet -eq 0 ]]; then 950 echo 951 echo "Error: infile has a line ending with a '\\' character" 952 echo "followed by a '\\' character as the first non-space" 953 echo "character on the next line. This script cannot fold" 954 echo "this file using '\\\\' strategy without there being" 955 echo "false positives produced in the unfolding (i.e., this" 956 echo "script does not attempt to proactively force-fold such" 957 echo "lines, as described in RFC XXXX)." 958 echo 959 fi 960 return 1 961 fi 963 # center header text 964 length=`expr ${#hdr_txt_2} + 2` 965 left_sp=`expr \( "$maxcol" - "$length" \) / 2` 966 right_sp=`expr "$maxcol" - "$length" - "$left_sp"` 967 header=`printf "%.*s %s %.*s" "$left_sp" "$equal_chars"\ 968 "$hdr_txt_2" "$right_sp" "$equal_chars"` 970 # generate outfile 971 echo "$header" > $outfile 972 echo "" >> $outfile 973 "$SED" 's/\(.\{'"$foldcol"'\}\)\(..\)/\1\\\n\\\2/;t M;b;:M;P;D;'\ 974 < $infile >> $outfile 2>/dev/null 975 if [[ $? -ne 0 ]]; then 976 return 1 977 fi 978 return 0 979 } 981 fold_it() { 982 # ensure input file doesn't contain a TAB 983 grep $'\t' $infile >> /dev/null 2>&1 984 if [[ $? -eq 0 ]]; then 985 if [[ $quiet -eq 0 ]]; then 986 echo 987 echo "Error: infile contains a TAB character, which is" 988 echo "not allowed." 989 echo 990 fi 991 return 1 992 fi 994 # check if file needs folding 995 testcol=`expr "$maxcol" + 1` 996 grep ".\{$testcol\}" $infile >> /dev/null 2>&1 997 if [ $? -ne 0 ]; then 998 if [[ $debug -eq 1 ]]; then 999 echo "nothing to do" 1000 fi 1001 cp $infile $outfile 1002 return -1 1003 fi 1005 if [[ $strategy -eq 1 ]]; then 1006 fold_it_1 1007 return $? 1008 fi 1009 if [[ $strategy -eq 2 ]]; then 1010 fold_it_2 1011 return $? 1012 fi 1013 quiet_sav=$quiet 1014 quiet=1 1015 fold_it_1 1016 result=$? 1017 quiet=$quiet_sav 1018 if [[ $result -ne 0 ]]; then 1019 if [[ $debug -eq 1 ]]; then 1020 echo "Folding strategy 1 didn't succeed, trying strategy 2..." 1021 fi 1022 fold_it_2 1023 return $? 1024 fi 1025 return 0 1026 } 1028 unfold_it_1() { 1029 temp_dir=`mktemp -d` 1031 # output all but the first two lines (the header) to wip file 1032 awk "NR>2" $infile > $temp_dir/wip 1034 # unfold wip file 1035 "$SED" ':S;$!N;s/\\\n *//;t S;P;D' $temp_dir/wip > $outfile 1037 return 0 1038 } 1040 unfold_it_2() { 1041 temp_dir=`mktemp -d` 1043 # output all but the first two lines (the header) to wip file 1044 awk "NR>2" $infile > $temp_dir/wip 1046 # unfold wip file 1047 "$SED" ':S;$!N;s/\\\n *\\//;t S;P;D' $temp_dir/wip > $outfile 1049 return 0 1050 } 1052 unfold_it() { 1053 # check if file needs unfolding 1054 line=`head -n 1 $infile` 1055 result=`echo $line | fgrep "$hdr_txt_1"` 1056 if [ $? -eq 0 ]; then 1057 unfold_it_1 1058 return $? 1059 fi 1060 result=`echo $line | fgrep "$hdr_txt_2"` 1061 if [ $? -eq 0 ]; then 1062 unfold_it_2 1063 return $? 1064 fi 1065 if [[ $debug -eq 1 ]]; then 1066 echo "nothing to do" 1067 fi 1068 cp $infile $outfile 1069 return -1 1070 } 1072 process_input() { 1073 while [ "$1" != "" ]; do 1074 if [ "$1" == "-h" -o "$1" == "--help" ]; then 1075 print_usage 1076 exit 1 1077 fi 1078 if [ "$1" == "-d" ]; then 1079 debug=1 1080 fi 1081 if [ "$1" == "-q" ]; then 1082 quiet=1 1083 fi 1084 if [ "$1" == "-s" ]; then 1085 strategy="$2" 1086 shift 1087 fi 1088 if [ "$1" == "-c" ]; then 1089 maxcol="$2" 1090 shift 1091 fi 1092 if [ "$1" == "-r" ]; then 1093 reversed=1 1094 fi 1095 if [ "$1" == "-i" ]; then 1096 infile="$2" 1097 shift 1098 fi 1099 if [ "$1" == "-o" ]; then 1100 outfile="$2" 1101 shift 1102 fi 1103 shift 1104 done 1106 if [[ -z "$infile" ]]; then 1107 if [[ $quiet -eq 0 ]]; then 1108 echo 1109 echo "Error: infile parameter missing (use -h for help)" 1110 echo 1111 fi 1112 exit 1 1113 fi 1115 if [[ -z "$outfile" ]]; then 1116 if [[ $quiet -eq 0 ]]; then 1117 echo 1118 echo "Error: outfile parameter missing (use -h for help)" 1119 echo 1120 exit 1 1121 fi 1122 fi 1124 if [[ ! -f "$infile" ]]; then 1125 if [[ $quiet -eq 0 ]]; then 1126 echo 1127 echo "Error: specified file \"$infile\" is does not exist." 1128 echo 1129 exit 1 1130 fi 1131 fi 1133 if [[ $strategy -eq 2 ]]; then 1134 min_supported=`expr ${#hdr_txt_2} + 8` 1135 else 1136 min_supported=`expr ${#hdr_txt_1} + 8` 1137 fi 1138 if [[ $maxcol -lt $min_supported ]]; then 1139 if [[ $quiet -eq 0 ]]; then 1140 echo 1141 echo "Error: the folding column cannot be less than" 1142 echo "$min_supported." 1143 echo 1144 fi 1145 exit 1 1146 fi 1148 # this is only because the code otherwise runs out of equal_chars 1149 max_supported=`expr ${#equal_chars} + 1 + ${#hdr_txt_1} + 1\ 1150 + ${#equal_chars}` 1151 if [[ $maxcol -gt $max_supported ]]; then 1152 if [[ $quiet -eq 0 ]]; then 1153 echo 1154 echo "Error: the folding column cannot be more than" 1155 echo "$max_supported." 1156 echo 1157 fi 1158 exit 1 1159 fi 1160 } 1162 main() { 1163 if [ "$#" == "0" ]; then 1164 print_usage 1165 exit 1 1166 fi 1168 process_input $@ 1170 if [[ $reversed -eq 0 ]]; then 1171 fold_it 1172 code=$? 1173 else 1174 unfold_it 1175 code=$? 1176 fi 1177 exit $code 1178 } 1180 main "$@" 1182 1184 Acknowledgements 1186 The authors thank the RFC Editor for confirming that there was 1187 previously no set convention for handling long lines in sourcecode 1188 inclusions, thus instigating this work. 1190 The authors thank the following folks for their various contributions 1191 while producing this document (sorted by first name): Benoit Claise, 1192 Erik Auerswald, Gianmarco Bruno, Italo Busi, Joel Jaeggli, Jonathan 1193 Hansford, Lou Berger, Martin Bjorklund, and Rob Wilton. 1195 Special acknowledgement to Erik Auerswald for his contributions to 1196 the `rfcfold` script, especially for greatly improving the `sed` one- 1197 liners used therein. 1199 Authors' Addresses 1201 Kent Watsen 1202 Watsen Networks 1204 EMail: kent+ietf@watsen.net 1206 Adrian Farrel 1207 Old Dog Consulting 1209 EMail: adrian@olddog.co.uk 1211 Qin Wu 1212 Huawei Technologies 1214 EMail: bill.wu@huawei.com