--- 1/draft-ietf-netmod-artwork-folding-05.txt 2019-06-27 15:13:11.087589469 -0700 +++ 2/draft-ietf-netmod-artwork-folding-06.txt 2019-06-27 15:13:11.131590581 -0700 @@ -1,21 +1,21 @@ NETMOD Working Group K. Watsen Internet-Draft Watsen Networks Intended status: Best Current Practice A. Farrel -Expires: December 22, 2019 Old Dog Consulting +Expires: December 29, 2019 Old Dog Consulting Q. Wu Huawei Technologies - June 20, 2019 + June 27, 2019 Handling Long Lines in Inclusions in Internet-Drafts and RFCs - draft-ietf-netmod-artwork-folding-05 + draft-ietf-netmod-artwork-folding-06 Abstract This document defines two strategies for handling long lines in width-bounded text content. One strategy is based on the historic use of a single backslash ('\') character to indicate where line- folding has occurred, with the continuation occurring with the first non-space (' ') character on the next line. The second strategy extends the first strategy by adding a second backslash character to identify where the continuation begins and thereby able to handle @@ -31,21 +31,21 @@ Internet-Drafts are working documents of the Internet Engineering Task Force (IETF). Note that other groups may also distribute working documents as Internet-Drafts. The list of current Internet- Drafts is at https://datatracker.ietf.org/drafts/current/. Internet-Drafts are draft documents valid for a maximum of six months and may be updated, replaced, or obsoleted by other documents at any time. It is inappropriate to use Internet-Drafts as reference material or to cite them other than as "work in progress." - This Internet-Draft will expire on December 22, 2019. + This Internet-Draft will expire on December 29, 2019. Copyright Notice Copyright (c) 2019 IETF Trust and the persons identified as the document authors. All rights reserved. This document is subject to BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents (https://trustee.ietf.org/license-info) in effect on the date of publication of this document. Please review these documents @@ -83,31 +83,31 @@ 8.2. Algorithm . . . . . . . . . . . . . . . . . . . . . . . . 10 8.2.1. Folding . . . . . . . . . . . . . . . . . . . . . . . 10 8.2.2. Unfolding . . . . . . . . . . . . . . . . . . . . . . 11 9. Examples . . . . . . . . . . . . . . . . . . . . . . . . . . 12 9.1. Example Showing Boundary Conditions . . . . . . . . . . . 12 9.1.1. Using '\' . . . . . . . . . . . . . . . . . . . . . . 12 9.1.2. Using '\\' . . . . . . . . . . . . . . . . . . . . . 13 9.2. Example Showing Multiple Wraps of a Single Line . . . . . 13 9.2.1. Using '\' . . . . . . . . . . . . . . . . . . . . . . 13 9.2.2. Using '\\' . . . . . . . . . . . . . . . . . . . . . 13 - 9.3. Example Showing Smart Folding . . . . . . . . . . . . . . 13 + 9.3. Example Showing "Smart" Folding . . . . . . . . . . . . . 13 9.3.1. Using '\' . . . . . . . . . . . . . . . . . . . . . . 14 9.3.2. Using '\\' . . . . . . . . . . . . . . . . . . . . . 15 10. Security Considerations . . . . . . . . . . . . . . . . . . . 16 11. IANA Considerations . . . . . . . . . . . . . . . . . . . . . 16 12. References . . . . . . . . . . . . . . . . . . . . . . . . . 16 12.1. Normative References . . . . . . . . . . . . . . . . . . 16 12.2. Informative References . . . . . . . . . . . . . . . . . 16 - Appendix A. POSIX Shell Script . . . . . . . . . . . . . . . . . 18 - Acknowledgements . . . . . . . . . . . . . . . . . . . . . . . . 25 + Appendix A. POSIX Shell Script: rfcfold . . . . . . . . . . . . 18 + Acknowledgements . . . . . . . . . . . . . . . . . . . . . . . . 26 Authors' Addresses . . . . . . . . . . . . . . . . . . . . . . . 26 1. Introduction [RFC7994] sets out the requirements for plain-text RFCs and states that each line of an RFC (and hence of an Internet-Draft) must be limited to 72 characters followed by the character sequence that denotes an end-of-line (EOL). Internet-Drafts and RFCs often include example text or code @@ -598,21 +598,21 @@ 9.2.2. Using '\\' ========== NOTE: '\\' line wrapping per BCP XX (RFC XXXX) =========== 12345678901234567890123456789012345678901234567890123456789012345678\ \9012345678901234567890123456789012345678901234567890123456789012345\ \6789012345678901234567890123456789012345678901234567890123456789012\ \3456789012345678901234567890123456789012345678901234567890123456789\ \01234567890 -9.3. Example Showing Smart Folding +9.3. Example Showing "Smart" Folding This example illustrates how readability can be improved via "smart" folding, whereby folding occurs at format-specific locations and format-specific indentations are used. The text content was manually folded, since the script in the appendix does not implement smart folding. Note that the header is surrounded by different printable characters then shown in the script-generated examples. @@ -749,58 +749,67 @@ . [xiax] "The `xiax` Python Package", . [yang-doctors-thread] "[yang-doctors] automating yang doctor reviews", . -Appendix A. POSIX Shell Script +Appendix A. POSIX Shell Script: rfcfold This non-normative appendix section includes a shell script that can both fold and unfold text content using both the single and double backslash strategies described in Section 7 and Section 8 respectively. This script is intended to be applied to a single text content - instance. If it is desired to fold or unfold test content instances + instance. If it is desired to fold or unfold text content instances within a larger document (e.g., an Internet draft or RFC), then another tool must be used to extract the content from the larger document before utilizing this script. For readability purposes, this script forces the minimally supported line length to be eight characters longer than the raw header text defined in Section 7.1.1 and Section 8.1.1 so as to ensure that the header can be wrapped by a space (' ') character and three equal ('=') characters on each side of the raw header text. This script does not implement the "forced folding" logic described in Section 8.2.1. In such cases the script will exit with the message: - Error: infile has a line ending with a '\\' character - followed by a '\\' character as the first non-space - character on the next line. This file cannot be folded. + Error: infile has a line ending with a '\' character + followed by a '\' character as the first non-space + character on the next line. This script cannot fold + this file using '\\' strategy without there being + false positives produced in the unfolding (i.e., this + script does not attempt to proactively force-fold such + lines, as described in RFC XXXX). Shell-level end-of-line backslash ('\') characters have been purposely added to the script so as to ensure that the script is itself not folded in this document, thus simplify the ability to copy/paste the script for local use. As should be evident by the lack of the mandatory header described in Section 7.1.1, these backslashes do not designate a folded line, such as described in Section 7. - #!/bin/bash --posix # must be `bash` (not `sh`) + #!/bin/bash --posix + # must use `bash` (not `sh`) + + # This script may need some adjustments to work on a given system. + # For instance, the utilities `pcregrep` and `gsed` may need to + # be installed. print_usage() { echo echo "Folds the text file, only if needed, at the specified" echo "column, according to BCP XX." echo echo "Usage: $0 [-s ] [-c ] [-r] -i " echo " -o " echo echo " -s: strategy to use, '1' or '2' (default: try 1, else 2)" @@ -823,36 +832,52 @@ reversed=0 infile="" outfile="" maxcol=69 # default, may be overridden by param hdr_txt_1="NOTE: '\\' line wrapping per BCP XX (RFC XXXX)" hdr_txt_2="NOTE: '\\\\' line wrapping per BCP XX (RFC XXXX)" equal_chars="==============================================" space_chars=" " temp_dir="" + # determine name of [g]sed binary + type gsed > /dev/null 2>&1 && SED=gsed || SED=sed + + # warn if a non-GNU sed utility is used + "$SED" --version < /dev/null 2> /dev/null \ + | grep GNU >/dev/null 2>&1 || echo 'Warning: not using GNU sed' + + # verify the availability of pcregrep + type pcregrep > /dev/null 2>&1 || { + echo 'Error: missing utility `pcregrep`' + exit 1 + } + cleanup() { + rm -rf "$temp_dir" + } + trap 'cleanup' EXIT + fold_it_1() { # ensure input file doesn't contain the fold-sequence already pcregrep -M "\\\\\n" $infile >> /dev/null 2>&1 if [[ $? -eq 0 ]]; then if [[ $quiet -eq 0 ]]; then echo echo "Error: infile $infile has a line ending with a '\\'" echo "character. This file cannot be folded using the '\\'" echo "strategy." echo fi return 1 fi - # stash some vars - testcol=`expr "$maxcol" + 1` + # where to fold foldcol=`expr "$maxcol" - 1` # for the inserted '\' char # ensure input file doesn't contain whitespace on the fold column grep "^.\{$foldcol\} " $infile >> /dev/null 2>&1 if [[ $? -eq 0 ]]; then if [[ $quiet -eq 0 ]]; then echo echo "Error: infile has a space character occuring on the" echo "folding column. This file cannot be folded using the" echo "'\\' strategy." @@ -864,70 +889,63 @@ # center header text length=`expr ${#hdr_txt_1} + 2` left_sp=`expr \( "$maxcol" - "$length" \) / 2` right_sp=`expr "$maxcol" - "$length" - "$left_sp"` header=`printf "%.*s %s %.*s" "$left_sp" "$equal_chars"\ "$hdr_txt_1" "$right_sp" "$equal_chars"` # generate outfile echo "$header" > $outfile echo "" >> $outfile - gsed "/.\{$testcol\}/s/\(.\{$foldcol\}\)/\1\\\\\n/g"\ - < $infile >> $outfile - + "$SED" 's/\(.\{'"$foldcol"'\}\)\(..\)/\1\\\n\2/;t M;b;:M;P;D;'\ + < $infile >> $outfile 2>/dev/null + if [[ $? -ne 0 ]]; then + return 1 + fi return 0 } fold_it_2() { - if [ "$temp_dir" == "" ]; then - temp_dir=`mktemp -d` - fi + # where to fold + foldcol=`expr "$maxcol" - 1` # for the inserted '\' char # ensure input file doesn't contain the fold-sequence already pcregrep -M "\\\\\n[\ ]*\\\\" $infile >> /dev/null 2>&1 if [[ $? -eq 0 ]]; then if [[ $quiet -eq 0 ]]; then echo echo "Error: infile has a line ending with a '\\' character" echo "followed by a '\\' character as the first non-space" - echo "character on the next line. This file cannot be folded" - echo "using the '\\\\' strategy." + echo "character on the next line. This script cannot fold" + echo "this file using '\\\\' strategy without there being" + echo "false positives produced in the unfolding (i.e., this" + echo "script does not attempt to proactively force-fold such" + echo "lines, as described in RFC XXXX)." echo fi return 1 fi # center header text length=`expr ${#hdr_txt_2} + 2` left_sp=`expr \( "$maxcol" - "$length" \) / 2` right_sp=`expr "$maxcol" - "$length" - "$left_sp"` header=`printf "%.*s %s %.*s" "$left_sp" "$equal_chars"\ "$hdr_txt_2" "$right_sp" "$equal_chars"` - # fold using recursive passes ('g' used in fold_it_1 didn't work) - if [ -z "$1" ]; then - # init recursive env - cp $infile $temp_dir/wip - fi - testcol=`expr "$maxcol" + 1` - foldcol=`expr "$maxcol" - 1` # for the inserted '\' char - gsed "/.\{$testcol\}/s/\(.\{$foldcol\}\)/\1\\\\\n\\\\/" \ - < $temp_dir/wip >> $temp_dir/wip2 - diff $temp_dir/wip $temp_dir/wip2 > /dev/null 2>&1 - if [ $? -eq 1 ]; then - mv $temp_dir/wip2 $temp_dir/wip - fold_it_2 "recursing" - else + # generate outfile echo "$header" > $outfile echo "" >> $outfile - cat $temp_dir/wip2 >> $outfile - rm -rf $temp_dir + "$SED" 's/\(.\{'"$foldcol"'\}\)\(..\)/\1\\\n\\\2/;t M;b;:M;P;D;'\ + < $infile >> $outfile 2>/dev/null + if [[ $? -ne 0 ]]; then + return 1 fi return 0 } fold_it() { # ensure input file doesn't contain a TAB grep $'\t' $infile >> /dev/null 2>&1 if [[ $? -eq 0 ]]; then if [[ $quiet -eq 0 ]]; then echo @@ -941,29 +959,30 @@ # check if file needs folding testcol=`expr "$maxcol" + 1` grep ".\{$testcol\}" $infile >> /dev/null 2>&1 if [ $? -ne 0 ]; then if [[ $debug -eq 1 ]]; then echo "nothing to do" fi cp $infile $outfile return -1 fi + if [[ $strategy -eq 1 ]]; then fold_it_1 return $? fi if [[ $strategy -eq 2 ]]; then fold_it_2 return $? fi - quiet_sav=$quite + quiet_sav=$quiet quiet=1 fold_it_1 result=$? quiet=$quiet_sav if [[ $result -ne 0 ]]; then if [[ $debug -eq 1 ]]; then echo "Folding strategy 1 didn't succeed, trying strategy 2..." fi fold_it_2 return $? @@ -969,41 +988,35 @@ return $? fi return 0 } unfold_it_1() { temp_dir=`mktemp -d` # output all but the first two lines (the header) to wip file awk "NR>2" $infile > $temp_dir/wip - # unfold wip file - gsed ":x; /.*\\\\$/N; s/\\\\\n[ ]*//; tx" $temp_dir/wip > $outfile + "$SED" ':S;$!N;s/\\\n *//;t S;P;D' $temp_dir/wip > $outfile - # clean up and return - rm -rf $temp_dir return 0 } unfold_it_2() { temp_dir=`mktemp -d` # output all but the first two lines (the header) to wip file awk "NR>2" $infile > $temp_dir/wip # unfold wip file - gsed ":x; /.*\\\\$/N; s/\\\\\n[ ]*\\\\//; tx" $temp_dir/wip \ - > $outfile + "$SED" ':S;$!N;s/\\\n *\\//;t S;P;D' $temp_dir/wip > $outfile - # clean up and return - rm -rf $temp_dir return 0 } unfold_it() { # check if file needs unfolding line=`head -n 1 $infile` result=`echo $line | fgrep "$hdr_txt_1"` if [ $? -eq 0 ]; then unfold_it_1 return $? @@ -1120,36 +1133,41 @@ process_input $@ if [[ $reversed -eq 0 ]]; then fold_it code=$? else unfold_it code=$? fi exit $code + } main "$@" Acknowledgements + The authors thank the RFC Editor for confirming that there was + previously no set convention for handling long lines in sourcecode + inclusions, thus instigating this work. + The authors thank the following folks for their various contributions - (sorted by first name): Benoit Claise, Gianmarco Bruno, Italo Busi, - Joel Jaeggli, Jonathan Hansford, Lou Berger, Martin Bjorklund, and - Rob Wilton. + while producing this document (sorted by first name): Benoit Claise, + Erik Auerswald, Gianmarco Bruno, Italo Busi, Joel Jaeggli, Jonathan + Hansford, Lou Berger, Martin Bjorklund, and Rob Wilton. - The authors additionally thank the RFC Editor for confirming that - there is no set convention today for handling long lines in artwork/ - sourcecode inclusions. + Special acknowledgement to Erik Auerswald for his contributions to + the `rfcfold` script, especially for greatly improving the `sed` one- + liners used therein. Authors' Addresses Kent Watsen Watsen Networks EMail: kent+ietf@watsen.net Adrian Farrel Old Dog Consulting