Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>Let me propose the following quite general Ex command solving the issue.<sup>1</sup></p> <pre><code>:g/^\s*\h/d|let@"=substitute(@"[:-2],'\s\+and\s\+',',','')|ki|/\n\s*\h\|\%$/kj| \ 'i,'js/^\s*\(\d\+\)\s\+-\s\+The/\=@".','.submatch(1).','/|'i,'js/\s\+//g </code></pre> <p>At the top level, this is the <code>:global</code> command that enumerates the lines starting with zero or more whitespace characters followed by a Latin letter or an underscore (see <code>:help /\h</code>). The lines matching this pattern are supposed to be the header lines containing section and title names. The rest of the command, after the pattern describing the header lines, are instructions to be executed for each of those lines.</p> <p>The actions to be performed on the headers can be divided into three steps.</p> <ol> <li><p>Delete the current header line, at the same time extracting section and title names from it.</p> <pre><code>:d|let@"=substitute(@"[:-2],'\s\+and\s\+',',','') </code></pre> <p>First, remove the current line, saving it into the unnamed register, using the <code>:delete</code> command. Then, update the contents of that register (referred to as <code>@"</code>; see <code>:help @r</code> and <code>:help ""</code>) to be result of the substitution changing the word <code>and</code> surrounded by whitespace characters, to a single comma. The actual replacement is carried out by the <code>substitute()</code> function.</p> <p>However, the input is not the exact string containing the whole header line, but its prefix leaving out the last character, which is a newline symbol. The <code>[:-2]</code> notation is a short form of the <code>[0:-2]</code> subscript expression that designates the substring from the very first byte to the second one counting from the end (see <code>:help expr-[:]</code>). This way, the unnamed register holds the section and the title names separated by comma.</p></li> <li><p>Determine the range of dependent subsection lines.</p> <pre><code>:ki|/\n\s*\h\|\%$/kj </code></pre> <p>After the first step, the subsection records belonging to the just parsed header line are located starting from the current line (the one followed the header) until the next header line or, if there is no such line below, the end of buffer. The numbers of these lines are stored in the marks <code>i</code> and <code>j</code>, respectively. (See <code>:helpg ^A mark is</code> for description of marks.)</p> <p>The marks are placed using the <code>:k</code> command that sets a specified mark at the last line of a given range which is the current line, by default. So, unlike the first line of the considered block, the last one requires a specific line range to point out its location. A particular form of range, denoting the next line where a given pattern matches, is used in this case (see <code>:help :range</code>). The pattern defining the location of the line to be found, is composed in such a way that it matches a line immediately preceding a header (a line starting with possible whitespace followed by an alphabetical character), or the very last line. (See <code>:help pattern</code> for details about syntax of Vim regular expressions.)</p></li> <li><p>Transform the delineated subsection lines according to desired format, prepending section and title names found in the corresponding header line.</p> <pre><code>:'i,'js/^\s*\(\d\+\)\s\+-\s\+The/\=@".','.submatch(1).','/|'i,'js/\s\+//g </code></pre> <p>This step comprised of the two <code>:substitute</code> commands that are run over the range of lines delimited by the locations labelled by the marks <code>i</code> and <code>j</code> (see <code>:help [range]</code>).</p> <p>The first substitution command matches the beginning of a subsection line—an identifier followed by a hyphen and the word <code>The</code>, all floating in a whitespace—and replaces it with the contents of the unnamed register, holding the section and title names concatenated with a comma, the matched identifier, and another comma. The second substitution finalizes the transformation by squeezing all whitespace characters on the line to gum the subsection name and the following letter together.</p> <p>To construct the replacement string in the first <code>:substitute</code> command, the substitute-with-an-expression feature is used (see <code>:help sub-replace-\=</code>). The substitution part of the command should start with <code>\=</code> for Vim to interpret the remaining text not in a regular way, but as an expression (see <code>:help expression</code>). The result of that expression's evaluation becomes the substitution string. Note the use of the <code>submatch()</code> function in the substitute expression to retrieve the text of a submatch by its number.</p></li> </ol> <hr> <p><sup>1</sup> The command is wrapped for better readability, its one-line version is listed below for ease of copy-pasting into Vim command line. Note that the wrapped command can be used in a Vim script without any change.</p> <pre><code>:g/^\s*\h/d|let@"=substitute(@"[:-2],'\s\+and\s\+',',','')|ki|/\n\s*\h\|\%$/kj|'i,'js/^\s*\(\d\+\)\s\+-\s\+The/\=@".','.submatch(1).','/|'i,'js/\s\+//g </code></pre>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload