idnits 2.17.1 draft-ietf-netmod-artwork-folding-04.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 17, 2019) is 1775 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 19, 2019 Old Dog Consulting 6 Q. Wu 7 Huawei Technologies 8 June 17, 2019 10 Handling Long Lines in Inclusions in Internet-Drafts and RFCs 11 draft-ietf-netmod-artwork-folding-04 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 19, 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 . . . . . . . . . . . . . . . . . 18 103 Acknowledgements . . . . . . . . . . . . . . . . . . . . . . . . 25 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 on top 357 of a space (' ') character. If no such location can be found, 358 then exit (this text content cannot be folded) 360 2. At the location where the fold is to occur, insert a backslash 361 ('\') character followed by the end of line character sequence. 363 3. On the following line, insert any number of space (' ') 364 characters. 366 The result of the previous operation is that the next line starts 367 with an arbitrary number of space (' ') characters, followed by the 368 character that was previously occupying the position where the fold 369 occurred. 371 Continue in this manner until reaching the end of the text content. 372 Note that this algorithm naturally addresses the case where the 373 remainder of a folded line is still longer than the desired maximum, 374 and hence needs to be folded again, ad infinitum. 376 The process described in this section is illustrated by the 377 "fold_it_1()" function in Appendix A. 379 7.2.2. Unfolding 381 Scan the beginning of the text content for the header described in 382 Section 7.1.1. If the header is not present, starting on the first 383 line of the text content, exit (this text contents does not need to 384 be unfolded). 386 Remove the 2-line header from the text content. 388 For each line in the text content, from top-to-bottom, if the line 389 has a backslash ('\') character immediately followed by the end of 390 line character sequence, then the line can be unfolded. Remove the 391 backslash ('\') character, the end of line character sequence, and 392 any leading space (' ') characters, which will bring up the next 393 line. Then continue to scan each line in the text content starting 394 with the current line (in case it was multiply folded). 396 Continue in this manner until reaching the end of the text content. 398 The process described in this section is illustrated by the 399 "unfold_it_1()" function in Appendix A. 401 8. The Double Backslash Strategy ('\\') 403 8.1. Folded Structure 405 Text content that has been folded as specified by this strategy MUST 406 adhere to the following structure. 408 8.1.1. Header 410 The header is two lines long. 412 The first line is the following 46-character string that MAY be 413 surrounded by any number of printable characters. This first line 414 cannot itself be folded. 416 NOTE: '\\' line wrapping per BCP XX (RFC XXXX) 418 [Note to RFC Editor: Please replace XX and XXXX with the numbers 419 assigned to this document and delete this note. Please make this 420 change in multiple places in this document.] 422 The second line is a blank line. This line provides visual 423 separation for readability. 425 8.1.2. Body 427 The character encoding is the same as described in Section 2 of 428 [RFC7994], except that, per [RFC7991], tab characters are prohibited. 430 Lines that have a backslash ('\') occurring as the last character in 431 a line immediately followed by the end of line character sequence, 432 when the subsequent line starts with a backslash ('\') as the first 433 non-space (' ') character, are considered "folded". 435 Really long lines may be folded multiple times. 437 8.2. Algorithm 439 This section describes a process for folding and unfolding long lines 440 when they are encountered in text content. 442 The steps are complete, but implementations MAY achieve the same 443 result in other ways. 445 When a larger document contains multiple instances of text content 446 that may need to be folded or unfolded, another process must insert/ 447 extract the individual text content instances to/from the larger 448 document prior to utilizing the algorithms described in this section. 449 For example, the `xiax` utility [xiax] does this. 451 8.2.1. Folding 453 Determine the desired maximum line length from input to the line- 454 wrapping process, such as from a command line parameter. If no value 455 is explicitly specified, the value "69" SHOULD be used. 457 Ensure that the desired maximum line length is not less than the 458 minimum header, which is 46 characters. If the desired maximum line 459 length is less than this minimum, exit (this text-based content 460 cannot be folded). 462 Scan the text content for horizontal tab characters. If any 463 horizontal tab characters appear, either resolve them to space 464 characters or exit, forcing the input provider to convert them to 465 space characters themselves first. 467 Scan the text content to see if any line exceeds the desired maximum. 468 If no line exceeds the desired maximum, exit (this text content does 469 not need to be folded). 471 Scan the text content to ensure no existing lines already end with a 472 backslash ('\') character while the subsequent line starts with a 473 backslash ('\') character as the first non-space (' ') character, as 474 this could lead to an ambiguous result. If such a line is found, and 475 its width is less than the desired maximum, then it SHOULD be flagged 476 for forced folding (folding even though unnecessary). If the folding 477 implementation doesn't support forced foldings, it MUST exit. 479 If this text content needs to and can be folded, insert the header 480 described in Section 8.1.1, ensuring that any additional printable 481 characters surrounding the header does not result in a line exceeding 482 the desired maximum. 484 For each line in the text content, from top-to-bottom, if the line 485 exceeds the desired maximum, or requires a forced folding, then fold 486 the line by: 488 1. Determine where the fold will occur. This location MUST be 489 before or at the desired maximum column. 491 2. At the location where the fold is to occur, insert a first 492 backslash ('\') character followed by the end of line character 493 sequence. 495 3. On the following line, insert any number of space (' ') 496 characters followed by a second backslash ('\') character. 498 The result of the previous operation is that the next line starts 499 with an arbitrary number of space (' ') characters, followed by a 500 backslash ('\') character, immediately followed by the character that 501 was previously occupying the position where the fold occurred. 503 Continue in this manner until reaching the end of the text content. 504 Note that this algorithm naturally addresses the case where the 505 remainder of a folded line is still longer than the desired maximum, 506 and hence needs to be folded again, ad infinitum. 508 The process described in this section is illustrated by the 509 "fold_it_2()" function in Appendix A. 511 8.2.2. Unfolding 513 Scan the beginning of the text content for the header described in 514 Section 8.1.1. If the header is not present, starting on the first 515 line of the text content, exit (this text content does not need to be 516 unfolded). 518 Remove the 2-line header from the text content. 520 For each line in the text content, from top-to-bottom, if the line 521 has a backslash ('\') character immediately followed by the end of 522 line character sequence, and if the next line has a backslash ('\') 523 character as the first non-space (' ') character, then the lines can 524 be unfolded. Remove the first backslash ('\') character, the end of 525 line character sequence, any leading space (' ') characters, and the 526 second backslash ('\') character, which will bring up the next line. 527 Then continue to scan each line in the text content starting with the 528 current line (in case it was multiply folded). 530 Continue in this manner until reaching the end of the text content. 532 The process described in this section is illustrated by the 533 "unfold_it_2()" function in Appendix A. 535 9. Examples 537 The following self-documenting examples illustrate folded text-based 538 content. 540 The source text content cannot be presented here, as it would again 541 be folded. Alas, only the results can be provided. 543 9.1. Example Showing Boundary Conditions 545 This example illustrates boundary condition. The input contains 546 seven lines, each line one character longer than the previous line. 547 Numbers for counting purposes. The default desired maximum column 548 value "69" is used. 550 9.1.1. Using '\' 552 =========== NOTE: '\' line wrapping per BCP XX (RFC XXXX) =========== 554 123456789012345678901234567890123456789012345678901234567890123456 555 1234567890123456789012345678901234567890123456789012345678901234567 556 12345678901234567890123456789012345678901234567890123456789012345678 557 123456789012345678901234567890123456789012345678901234567890123456789 558 12345678901234567890123456789012345678901234567890123456789012345678\ 559 90 560 12345678901234567890123456789012345678901234567890123456789012345678\ 561 901 562 12345678901234567890123456789012345678901234567890123456789012345678\ 563 9012 565 9.1.2. Using '\\' 567 ========== NOTE: '\\' line wrapping per BCP XX (RFC XXXX) =========== 569 123456789012345678901234567890123456789012345678901234567890123456 570 1234567890123456789012345678901234567890123456789012345678901234567 571 12345678901234567890123456789012345678901234567890123456789012345678 572 123456789012345678901234567890123456789012345678901234567890123456789 573 12345678901234567890123456789012345678901234567890123456789012345678\ 574 \90 575 12345678901234567890123456789012345678901234567890123456789012345678\ 576 \901 577 12345678901234567890123456789012345678901234567890123456789012345678\ 578 \9012 580 9.2. Example Showing Multiple Wraps of a Single Line 582 This example illustrates what happens when very long line needs to be 583 folded multiple times. The input contains one line containing 280 584 characters. Numbers for counting purposes. The default desired 585 maximum column value "69" is used. 587 9.2.1. Using '\' 589 =========== NOTE: '\' line wrapping per BCP XX (RFC XXXX) =========== 591 12345678901234567890123456789012345678901234567890123456789012345678\ 592 90123456789012345678901234567890123456789012345678901234567890123456\ 593 78901234567890123456789012345678901234567890123456789012345678901234\ 594 56789012345678901234567890123456789012345678901234567890123456789012\ 595 34567890 597 9.2.2. Using '\\' 599 ========== NOTE: '\\' line wrapping per BCP XX (RFC XXXX) =========== 601 12345678901234567890123456789012345678901234567890123456789012345678\ 602 \9012345678901234567890123456789012345678901234567890123456789012345\ 603 \6789012345678901234567890123456789012345678901234567890123456789012\ 604 \3456789012345678901234567890123456789012345678901234567890123456789\ 605 \01234567890 607 9.3. Example Showing Smart Folding 609 This example illustrates how readability can be improved via "smart" 610 folding, whereby folding occurs at format-specific locations and 611 format-specific indentations are used. 613 The text content was manually folded, since the script in the 614 appendix does not implement smart folding. 616 Note that the header is surrounded by different printable characters 617 then shown in the script-generated examples. 619 9.3.1. Using '\' 621 [NOTE: '\' line wrapping per BCP XX (RFC XXXX)] 623 627 628 config-modules 629 630 ietf-interfaces 631 2018-02-20 632 \ 633 urn:ietf:params:xml:ns:yang:ietf-interfaces\ 634 635 636 ... 637 638 ... 639 641 Below is the equivalent to the above, but it was folded using the 642 script in the appendix. 644 =========== NOTE: '\' line wrapping per BCP XX (RFC XXXX) =========== 646 650 651 config-modules 652 653 ietf-interfaces 654 2018-02-20 655 urn:ietf:params:xml:ns:yang:ietf-interfaces 657 658 ... 659 660 ... 661 663 9.3.2. Using '\\' 665 [NOTE: '\\' line wrapping per BCP XX (RFC XXXX)] 667 671 672 config-modules 673 674 ietf-interfaces 675 2018-02-20 676 \ 677 \urn:ietf:params:xml:ns:yang:ietf-interfaces\ 678 \ 679 680 ... 681 682 ... 683 685 Below is the equivalent to the above, but it was folded using the 686 script in the appendix. 688 ========== NOTE: '\\' line wrapping per BCP XX (RFC XXXX) =========== 690 694 695 config-modules 696 697 ietf-interfaces 698 2018-02-20 699 urn:ietf:params:xml:ns:yang:ietf-interfaces 701 702 ... 703 704 ... 705 707 10. Security Considerations 709 This BCP has no Security Considerations. 711 11. IANA Considerations 713 This BCP has no IANA Considerations. 715 12. References 717 12.1. Normative References 719 [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate 720 Requirement Levels", BCP 14, RFC 2119, 721 DOI 10.17487/RFC2119, March 1997, 722 . 724 [RFC8174] Leiba, B., "Ambiguity of Uppercase vs Lowercase in RFC 725 2119 Key Words", BCP 14, RFC 8174, DOI 10.17487/RFC8174, 726 May 2017, . 728 12.2. Informative References 730 [RFC7749] Reschke, J., "The "xml2rfc" Version 2 Vocabulary", 731 RFC 7749, DOI 10.17487/RFC7749, February 2016, 732 . 734 [RFC7950] Bjorklund, M., Ed., "The YANG 1.1 Data Modeling Language", 735 RFC 7950, DOI 10.17487/RFC7950, August 2016, 736 . 738 [RFC7991] Hoffman, P., "The "xml2rfc" Version 3 Vocabulary", 739 RFC 7991, DOI 10.17487/RFC7991, December 2016, 740 . 742 [RFC7994] Flanagan, H., "Requirements for Plain-Text RFCs", 743 RFC 7994, DOI 10.17487/RFC7994, December 2016, 744 . 746 [RFC8340] Bjorklund, M. and L. Berger, Ed., "YANG Tree Diagrams", 747 BCP 215, RFC 8340, DOI 10.17487/RFC8340, March 2018, 748 . 750 [xiax] "The `xiax` Python Package", 751 . 753 [yang-doctors-thread] 754 "[yang-doctors] automating yang doctor reviews", 755 . 758 Appendix A. POSIX Shell Script 760 This non-normative appendix section includes a shell script that can 761 both fold and unfold text content using both the single and double 762 backslash strategies described in Section 7 and Section 8 763 respectively. 765 This script is intended to be applied to a single text content 766 instance. If it is desired to fold or unfold test content instances 767 within a larger document (e.g., an Internet draft or RFC), then 768 another tool must be used to extract the content from the larger 769 document before utilizing this script. 771 For readability purposes, this script forces the minimally supported 772 line length to be eight characters longer than the raw header text 773 defined in Section 7.1.1 and Section 8.1.1 so as to ensure that the 774 header can be wrapped by a space (' ') character and three equal 775 ('=') characters on each side of the raw header text. 777 This script does not implement the "forced folding" logic described 778 in Section 8.2.1. In such cases the script will exit with the 779 message: 781 Error: infile has a line ending with a '\\' character 782 followed by a '\\' character as the first non-space 783 character on the next line. This file cannot be folded. 785 Shell-level end-of-line backslash ('\') characters have been 786 purposely added to the script so as to ensure that the script is 787 itself not folded in this document, thus simplify the ability to 788 copy/paste the script for local use. As should be evident by the 789 lack of the mandatory header described in Section 7.1.1, these 790 backslashes do not designate a folded line, such as described in 791 Section 7. 793 795 #!/bin/bash --posix # must be `bash` (not `sh`) 797 print_usage() { 798 echo 799 echo "Folds the text file, only if needed, at the specified" 800 echo "column, according to BCP XX." 801 echo 802 echo "Usage: $0 [-s ] [-c ] [-r] -i " 803 echo " -o " 804 echo 805 echo " -s: strategy to use, '1' or '2' (default: try 1, else 2)" 806 echo " -c: column to fold on (default: 69)" 807 echo " -r: reverses the operation" 808 echo " -i: the input filename" 809 echo " -o: the output filename" 810 echo " -d: show debug messages" 811 echo " -q: quiet (suppress error messages)" 812 echo " -h: show this message" 813 echo 814 echo "Exit status code: zero on success, non-zero otherwise." 815 echo 816 } 818 # global vars, do not edit 819 strategy=0 # auto 820 debug=0 821 quiet=0 822 reversed=0 823 infile="" 824 outfile="" 825 maxcol=69 # default, may be overridden by param 826 hdr_txt_1="NOTE: '\\' line wrapping per BCP XX (RFC XXXX)" 827 hdr_txt_2="NOTE: '\\\\' line wrapping per BCP XX (RFC XXXX)" 828 equal_chars="==============================================" 829 space_chars=" " 830 temp_dir="" 832 fold_it_1() { 833 # ensure input file doesn't contain the fold-sequence already 834 pcregrep -M "\\\\\n" $infile >> /dev/null 2>&1 835 if [[ $? -eq 0 ]]; then 836 if [[ $quiet -eq 0 ]]; then 837 echo 838 echo "Error: infile $infile has a line ending with a '\\'" 839 echo "character. This file cannot be folded using the '\\'" 840 echo "strategy." 841 echo 842 fi 843 return 1 844 fi 846 # stash some vars 847 testcol=`expr "$maxcol" + 1` 848 foldcol=`expr "$maxcol" - 1` # for the inserted '\' char 850 # ensure input file doesn't contain whitespace on the fold column 851 grep "^.\{$foldcol\} " $infile >> /dev/null 2>&1 852 if [[ $? -eq 0 ]]; then 853 if [[ $quiet -eq 0 ]]; then 854 echo 855 echo "Error: infile has a space character occuring on the" 856 echo "folding column. This file cannot be folded using the" 857 echo "'\\' strategy." 858 echo 859 fi 860 return 1 861 fi 863 # center header text 864 length=`expr ${#hdr_txt_1} + 2` 865 left_sp=`expr \( "$maxcol" - "$length" \) / 2` 866 right_sp=`expr "$maxcol" - "$length" - "$left_sp"` 867 header=`printf "%.*s %s %.*s" "$left_sp" "$equal_chars"\ 868 "$hdr_txt_1" "$right_sp" "$equal_chars"` 870 # generate outfile 871 echo "$header" > $outfile 872 echo "" >> $outfile 873 gsed "/.\{$testcol\}/s/\(.\{$foldcol\}\)/\1\\\\\n/g"\ 874 < $infile >> $outfile 876 return 0 877 } 879 fold_it_2() { 880 if [ "$temp_dir" == "" ]; then 881 temp_dir=`mktemp -d` 882 fi 884 # ensure input file doesn't contain the fold-sequence already 885 pcregrep -M "\\\\\n[\ ]*\\\\" $infile >> /dev/null 2>&1 886 if [[ $? -eq 0 ]]; then 887 if [[ $quiet -eq 0 ]]; then 888 echo 889 echo "Error: infile has a line ending with a '\\' character" 890 echo "followed by a '\\' character as the first non-space" 891 echo "character on the next line. This file cannot be folded" 892 echo "using the '\\\\' strategy." 893 echo 894 fi 895 return 1 896 fi 898 # center header text 899 length=`expr ${#hdr_txt_2} + 2` 900 left_sp=`expr \( "$maxcol" - "$length" \) / 2` 901 right_sp=`expr "$maxcol" - "$length" - "$left_sp"` 902 header=`printf "%.*s %s %.*s" "$left_sp" "$equal_chars"\ 903 "$hdr_txt_2" "$right_sp" "$equal_chars"` 905 # fold using recursive passes ('g' used in fold_it_1 didn't work) 906 if [ -z "$1" ]; then 907 # init recursive env 908 cp $infile $temp_dir/wip 909 fi 910 testcol=`expr "$maxcol" + 1` 911 foldcol=`expr "$maxcol" - 1` # for the inserted '\' char 912 gsed "/.\{$testcol\}/s/\(.\{$foldcol\}\)/\1\\\\\n\\\\/" \ 913 < $temp_dir/wip >> $temp_dir/wip2 914 diff $temp_dir/wip $temp_dir/wip2 > /dev/null 2>&1 915 if [ $? -eq 1 ]; then 916 mv $temp_dir/wip2 $temp_dir/wip 917 fold_it_2 "recursing" 918 else 919 echo "$header" > $outfile 920 echo "" >> $outfile 921 cat $temp_dir/wip2 >> $outfile 922 rm -rf $temp_dir 923 fi 924 return 0 925 } 927 fold_it() { 928 # ensure input file doesn't contain a TAB 929 grep $'\t' $infile >> /dev/null 2>&1 930 if [[ $? -eq 0 ]]; then 931 if [[ $quiet -eq 0 ]]; then 932 echo 933 echo "Error: infile contains a TAB character, which is" 934 echo "not allowed." 935 echo 936 fi 937 return 1 938 fi 940 # check if file needs folding 941 testcol=`expr "$maxcol" + 1` 942 grep ".\{$testcol\}" $infile >> /dev/null 2>&1 943 if [ $? -ne 0 ]; then 944 if [[ $debug -eq 1 ]]; then 945 echo "nothing to do" 946 fi 947 cp $infile $outfile 948 return -1 949 fi 950 if [[ $strategy -eq 1 ]]; then 951 fold_it_1 952 return $? 953 fi 954 if [[ $strategy -eq 2 ]]; then 955 fold_it_2 956 return $? 957 fi 958 quiet_sav=$quite 959 quiet=1 960 fold_it_1 961 result=$? 962 quiet=$quiet_sav 963 if [[ $result -ne 0 ]]; then 964 if [[ $debug -eq 1 ]]; then 965 echo "Folding strategy 1 didn't succeed, trying strategy 2..." 966 fi 967 fold_it_2 968 return $? 969 fi 970 return 0 971 } 973 unfold_it_1() { 974 temp_dir=`mktemp -d` 976 # output all but the first two lines (the header) to wip file 977 awk "NR>2" $infile > $temp_dir/wip 979 # unfold wip file 980 gsed ":x; /.*\\\\$/N; s/\\\\\n[ ]*//; tx" $temp_dir/wip > $outfile 982 # clean up and return 983 rm -rf $temp_dir 984 return 0 985 } 987 unfold_it_2() { 988 temp_dir=`mktemp -d` 990 # output all but the first two lines (the header) to wip file 991 awk "NR>2" $infile > $temp_dir/wip 993 # unfold wip file 994 gsed ":x; /.*\\\\$/N; s/\\\\\n[ ]*\\\\//; tx" $temp_dir/wip \ 995 > $outfile 997 # clean up and return 998 rm -rf $temp_dir 999 return 0 1000 } 1002 unfold_it() { 1003 # check if file needs unfolding 1004 line=`head -n 1 $infile` 1005 result=`echo $line | fgrep "$hdr_txt_1"` 1006 if [ $? -eq 0 ]; then 1007 unfold_it_1 1008 return $? 1009 fi 1010 result=`echo $line | fgrep "$hdr_txt_2"` 1011 if [ $? -eq 0 ]; then 1012 unfold_it_2 1013 return $? 1014 fi 1015 if [[ $debug -eq 1 ]]; then 1016 echo "nothing to do" 1017 fi 1018 cp $infile $outfile 1019 return -1 1020 } 1022 process_input() { 1023 while [ "$1" != "" ]; do 1024 if [ "$1" == "-h" -o "$1" == "--help" ]; then 1025 print_usage 1026 exit 1 1027 fi 1028 if [ "$1" == "-d" ]; then 1029 debug=1 1030 fi 1031 if [ "$1" == "-q" ]; then 1032 quiet=1 1033 fi 1034 if [ "$1" == "-s" ]; then 1035 strategy="$2" 1036 shift 1037 fi 1038 if [ "$1" == "-c" ]; then 1039 maxcol="$2" 1040 shift 1041 fi 1042 if [ "$1" == "-r" ]; then 1043 reversed=1 1044 fi 1045 if [ "$1" == "-i" ]; then 1046 infile="$2" 1047 shift 1048 fi 1049 if [ "$1" == "-o" ]; then 1050 outfile="$2" 1051 shift 1052 fi 1053 shift 1054 done 1056 if [[ -z "$infile" ]]; then 1057 if [[ $quiet -eq 0 ]]; then 1058 echo 1059 echo "Error: infile parameter missing (use -h for help)" 1060 echo 1061 fi 1062 exit 1 1063 fi 1065 if [[ -z "$outfile" ]]; then 1066 if [[ $quiet -eq 0 ]]; then 1067 echo 1068 echo "Error: outfile parameter missing (use -h for help)" 1069 echo 1070 exit 1 1071 fi 1072 fi 1074 if [[ ! -f "$infile" ]]; then 1075 if [[ $quiet -eq 0 ]]; then 1076 echo 1077 echo "Error: specified file \"$infile\" is does not exist." 1078 echo 1079 exit 1 1080 fi 1081 fi 1083 if [[ $strategy -eq 2 ]]; then 1084 min_supported=`expr ${#hdr_txt_2} + 8` 1085 else 1086 min_supported=`expr ${#hdr_txt_1} + 8` 1087 fi 1088 if [[ $maxcol -lt $min_supported ]]; then 1089 if [[ $quiet -eq 0 ]]; then 1090 echo 1091 echo "Error: the folding column cannot be less than" 1092 echo "$min_supported." 1093 echo 1095 fi 1096 exit 1 1097 fi 1099 # this is only because the code otherwise runs out of equal_chars 1100 max_supported=`expr ${#equal_chars} + 1 + ${#hdr_txt_1} + 1\ 1101 + ${#equal_chars}` 1102 if [[ $maxcol -gt $max_supported ]]; then 1103 if [[ $quiet -eq 0 ]]; then 1104 echo 1105 echo "Error: the folding column cannot be more than" 1106 echo "$max_supported." 1107 echo 1108 fi 1109 exit 1 1110 fi 1111 } 1113 main() { 1114 if [ "$#" == "0" ]; then 1115 print_usage 1116 exit 1 1117 fi 1119 process_input $@ 1121 if [[ $reversed -eq 0 ]]; then 1122 fold_it 1123 code=$? 1124 else 1125 unfold_it 1126 code=$? 1127 fi 1128 exit $code 1129 } 1131 main "$@" 1133 1135 Acknowledgements 1137 The authors thank the following folks for their various contributions 1138 (sorted by first name): Benoit Claise, Gianmarco Bruno, Italo Busi, 1139 Joel Jaeggli, Jonathan Hansford, Lou Berger, Martin Bjorklund, and 1140 Rob Wilton. 1142 The authors additionally thank the RFC Editor for confirming that 1143 there is no set convention today for handling long lines in artwork/ 1144 sourcecode inclusions. 1146 Authors' Addresses 1148 Kent Watsen 1149 Watsen Networks 1151 EMail: kent+ietf@watsen.net 1153 Adrian Farrel 1154 Old Dog Consulting 1156 EMail: adrian@olddog.co.uk 1158 Qin Wu 1159 Huawei Technologies 1161 EMail: bill.wu@huawei.com