29

I currently have a huge HTML file which doesn't have line breaks and just appears in a single line.

I want to format it in vim (macvim in particular). I tried the following options, but none of them has worked for me.

  • Selected the text and pressed = . This will only auto intend the code. But since the entire code is present in one line, it doesn't do anything
  • I tried this Plugin http://www.vim.org/scripts/script.php?script_id=3613 This kind of works but will insert linebreaks only for the current tag. I want the entire file to be formatted

Is there a way to do this either using a Plugin or otherwise?

Thanks!

Tim M.
  • 53,671
  • 14
  • 120
  • 163
Sudar
  • 18,954
  • 30
  • 85
  • 131
  • 2
    possible duplicate of [How do I tidy up an HTML file's indentation in VI?](http://stackoverflow.com/questions/815548/how-do-i-tidy-up-an-html-files-indentation-in-vi) – New Alexandria Feb 10 '14 at 17:00

4 Answers4

53

One way to start it is to split all tags onto their own lines.

:s/<[^>]*>/\r&\r/g
:g/^$/d

If you have floating < or > symbols (e.g. invalid HTML, JavaScript comparison operators, CSS direct descendant selector part), this won't work properly and you could switch to something like just doing end tags - <\/[^>]*>. It provides a solid start, anyway.

Demonstration:

With a idealised document like this,

<!DOCTYPE html><html><head><title>hello</title></head><body>world</body></html>

This produces this:

<!DOCTYPE html>
<html>
<head>
<title>
hello
</title>
</head>
<body>
world
</body>
</html>

Then, = will produce what you want:

<!DOCTYPE html>
<html>
    <head>
        <title>
            hello
        </title>
    </head>
    <body>
        world
    </body>
</html>
Chris Morgan
  • 86,207
  • 24
  • 208
  • 215
  • I like your approach. But there is one problem. The command ':s/<[^>]*>/\r&\r/g' put's only the first tag in the new line. Is it possible to make it run recursively? – Sudar Apr 03 '12 at 06:16
  • I presume that you left out the `/g` at the end. – Chris Morgan Apr 03 '12 at 06:34
  • No, I have not left out the /g at the end. I guess since the line count changes after the first replacement it doesn't continue. I even tried it on the sample html that you have – Sudar Apr 03 '12 at 06:37
  • 1
    If you have it all on a single line, what I have given works. If you have it already on multiple lines, you would need to do `:%s` instead of `:s`. – Chris Morgan Apr 03 '12 at 06:41
  • Sorry, it works now. I found the reason why it was not working initially. I have `gdefault` in my vimrc, which toggles the /g at the end. Thanks again for your time. – Sudar Apr 03 '12 at 06:45
  • @Sudar I have the same problem. How did you solve it? – Yves Oct 14 '16 at 19:30
  • @Thomas The above answer works for me. What is the issue that you are facing? – Sudar Oct 25 '16 at 10:45
  • @Sudar. Well, my issue is: the ending tag will get a new line but the starting tag won't. Something like: ` content #here a new line starts#`. I don't know why but when I do `:s/<[^>]*>/\r&/g`, it works. – Yves Oct 26 '16 at 00:46
4

For a better result, you should use specialized external format programs.

You can integrate both tidy and html-beautify automatically by installing the plugin vim-autoformat. After that, you can execute whichever formatter is installed with a single keystroke.

chtenb
  • 14,924
  • 14
  • 78
  • 116
1

It would be better to use the tidy utility, as described in this answer.

Good tools have already been written for this job

Community
  • 1
  • 1
New Alexandria
  • 6,951
  • 4
  • 57
  • 77
  • Unfortunately, tidy does _not_ put each tag on a new line, nor can it be configured to do that. For example, `` will not be split (but will, in fact, be condensed if it was split in the original document). – Colin Emonds Jun 13 '15 at 15:59
  • That's great in principle, but in practice there are many HTML validation issues you'll likely face here. Using Tidy as your base still smell like the right route. Formatting and indentation from there. – New Alexandria Jun 15 '15 at 02:21
0

Thank you. I solved HTML-formatting problem with Chris Morgan's answer like below:

:s/<[^>]*>/\r&\r/g
:g/^$/d
gg=G

And I'd like to define Vim mapping for doing the above procedure.

The Vim mapping is like below:

nnoremap <Leader>a :<C-u>s/<[^>]*>/\r&\r/g<CR>:<C-u>g/^$/d<CR>gg=G

Then, by typing a leader key and A key, HTML-formatting finishes.

bekkou68
  • 802
  • 1
  • 9
  • 20