2

I'm having trouble selecting sections in a file in a visual mode macro to separately perform some action on each section. Here's an example file:

[insert introduction here] ...
....

------
section ...
------

...
... ...

...... ....

...   ...

------
section .......
------

... ....

I can get to the top of each section, but then I have to manually figure out whether I'm in the last section of the file to decide whether to go to the next section or to the end of the file. How can I automate that for use in a macro?

Alternatively, are there better methods than visual mode that can be used in a macro that let me separately do the same action to each section in the file but not to the whole file at once?

  • Can you clarify what your file format is and what you're trying to select? Are you searching for the word "section" or for a line with a sequence of dashes? Can you share the commands you're currently using for a middle section or for the last section? That would help answer your question precisely... – filbranden Sep 3 '18 at 15:26
  • It's a custom format. It's specifically the word section at the start of a line. For a middle section, it was /^section /^Mv/^section /^M then the up key twice in a macro. For the last section, it's /^section /^MvG. – Chai T. Rex Sep 3 '18 at 16:37
1

So this might not be perfect but I found it already does a lot of what you want.

You can use the \%$ pattern to match the end of the file. (Also, \%^ to match the start of the file.) Which should help you match either two lines above the start of the next section, or the end of the file.

For example, this search should match what you're looking for:

/\n--*\nsection \|\%$

Breaking it down:

  • \n matches the end of a line, followed by
  • --* a line with one or more dashes (nothing else), then
  • \n another end of line, right after the dashes and finally
  • section the next line starting with the word "section" and a space.

All this, OR (\|):

  • \%$ matches the end of the file.

If you use this pattern, you'll see it cycle through the end of sections or the end of the file.

If you want a mapping to select a whole section, something like this might work:

:noremap \s :<c-u>execute "normal! ?\\v^section \|%^\rv/\\v\\n--*\\nsection \|%$\r"<cr>

This works in normal, visual and operator-pending mode. The mapping uses the \s key sequence (s for "section").

The searches are using the \v option for 'verymagic' mode in patterns to ensure consistency. The <c-u> at the start is to erase the implicit range :'<,'> when executing this macro in visual mode. It's using execute "normal! ..." so the whole expression is executed as a single command, which is important in operator-pending mode.

This macro works as:

  • Typing \s in normal mode, will switch to visual mode and highlight the section around where the cursor currently is.
  • Typing \s in visual mode, will highlight the section around where the current visual highlighting starts (visual mapping.)
  • Typing >\s will indent the current section, or d\s will delete the current section (operator-pending mapping.)

This is not perfect, as the ------ preceding a section ... does not belong to either the current or the next section, which can be easily seen when using d\s, which will leave two lines with dashes in a row. It should be possible to adjust the regular expressions to account for that, by either including it in the start of the section or in the end of the section (I think start of the section makes more sense, since the beginning or end of the file don't have any lines with dahses in them.)

Perhaps a slightly more complete macro is:

:noremap \s :<c-u>execute "normal! g_?\\v^--*\\nsection \|%^\rv/\\v\\n--*\\nsection \|%$\r"<cr>

The additional g_ makes the selection work when you're in the first line of the section (either the line with dashes, or the first line of the file, with the introduction.)

I hope you'll find this useful!

See also:

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.