6

I am cleaning up some minified css. I found this article helpful for adding a newline before/after a search match. This SO thread has a pretty exhaustive list of ways to indent with VIM, but it DOES NOT include a command-line pattern that will indent, like \r for ading a newline.
The answers in this SO thread rely on surrounding formatting with the ]p pattern or using macros, neither of which serve my purposes.


Here's my command to add a new line before and two new lines after all matches for }:

:/[}]

then

:%s//\r&\r\r/g

I do something similar for {. However, for all matches to ; I need to add a \r (newline) and indent a determined number of spaces. I don't want to rely on vim's auto indent settings. I want to indent a number of times that i set manually in the command string.

4
  • Could you give a before/after example for clarity?
    – Tumbler41
    Commented Dec 23, 2016 at 15:18
  • What do you mean? Where the links to the relevant threads not enough? Giving a detailed explanation of my incomplete command would be tangental to my question. If you want to understand :search and \r go to the thread i linked to.
    – Andrew
    Commented Dec 26, 2016 at 11:37
  • This one: vim.wikia.com/wiki/Add_a_newline_after_given_patterns
    – Andrew
    Commented Dec 26, 2016 at 11:37
  • I updated my answer based on my guess at the before/after @Tumbler41 asked for.
    – Rich
    Commented Jan 10, 2017 at 13:44

1 Answer 1

4

Two ways of doing this sort of thing are:

With a :substitute command

:%s/\(foo\)/\r    \1/g

This will add a newline and four spaces of "indent" before every matched foo

The \( and \) around the search expression /foo/ capture the match into a group, and then the \1 uses the captured group in the replacement. This obviously isn't necessary for simple values of /foo/.

With a :global command

You can also do this with the :normal and :global commands. For example the following command will indent all lines that match the regexp /foo/ and add a line above them:

:g/foo/normal >>O

This works similar to a :substitute command, but instead of making a substitution, it applies the normal mode operations indent (>>) followed by add a line above (O) to each matching line.

You can adjust the normal mode commands to perform different operations as necessary.

For more details:

:help :global
:help :normal

Using :s and :g to Unminify CSS

I'm a little unclear on precisely what you're trying to achieve, but if the goal is to e.g. turn this:

margin:0;padding:0;font-family:verdana;

into this:

    margin:0;
    padding:0;
    font-family:verdana;

^^^^ <- one level of indent

I'd do so with the following two commands:

:%s/;/;\r/g
:g/;/normal >>

If, for some reason, you need to add a specific number of spaces that doesn't match your shiftwidth settings, you could instead do:

:%s/;/;\r/g
:g/;/normal i    
             ^^^^ <- type four spaces after the `i`

Macros

In practice, for the specific case mentioned above, I'd probably have used a recursive macro:

  • qqq: Clear out the q register. Necessary for recursive macros,
  • qq: Start recording in the q register,
  • /;[^$]<cr>: Find the first semi-colon not followed by a newline,
  • :left<cr>: Remove any existing indentation (to remove automatic indentation),
  • >>: Add one level of indent,
  • na<cr><esc>: Jump back to the semi-colon,
  • @q: Recurse,
  • q: Finish recording,
  • @q: Run the macro.

You could also record a macro that runs on a single line and then apply it to every line with the global command.

qqqqq:left<cr>>>f;a<cr><esc>@qq@q
:g/;/norm @q

The macro versions look complicated written down, but because they just use normal editing commands recording them comes naturally (with a bit of practice) and using them is a lot faster than it looks.

5
  • Your first solution works, but the second only runs the search as global. Is there a key I'm supposed to press to get it to run the insertion?
    – Andrew
    Commented Dec 26, 2016 at 11:34
  • One more thing:` \1` adds an indent, right? Wait.. no.... where is the indent command?? That is the answer I'm looking for. It is replacing, not indenting. So I cannot add x number of indents per match with this command. Please re-read the question.
    – Andrew
    Commented Dec 26, 2016 at 11:42
  • 'I want to indent a number of times that i set manually in the command string."
    – Andrew
    Commented Dec 26, 2016 at 11:44
  • @AndÚ The spaces before the \1 are the indent. However many spaces/tabs you type will be the indent added.
    – Rich
    Commented Dec 26, 2016 at 22:12
  • @AndÚ In the second solution, there is no insertion. The global command runs the normal mode indent command >> and add line command O. If you need more indent, you can adjust the commands given, as stated.
    – Rich
    Commented Dec 26, 2016 at 22:18

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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