How to fold/unfold HTML tags with Vim - html

Is there some plugin to fold HTML tags in Vim?
Or there is another way to setup a shortcut to fold or unfold html tags?
I would like to fold/unfold html tags just like I do with indentation folding.

I have found zfat (or, equally, zfit) works well for folding with HTML documents. za will toggle (open or close) an existing fold. zR opens all the folds in the current document, zM effectively re-enables all existing folds marked in the document.
If you find yourself using folds extensively, you could make some handy keybindings for yourself in your .vimrc.

If you indent your HTML the following should work:
set foldmethod=indent
The problem with this, I find, is there are too many folds. To get around this I use zO and zc to open and close nested folds, respectively.
See help fold-indent for more information:
The folds are automatically defined by the indent of the lines.
The foldlevel is computed from the indent of the line, divided by the
'shiftwidth' (rounded down). A sequence of lines with the same or higher fold
level form a fold, with the lines with a higher level forming a nested fold.
The nesting of folds is limited with 'foldnestmax'.
Some lines are ignored and get the fold level of the line above or below it,
whichever is lower. These are empty or white lines and lines starting
with a character in 'foldignore'. White space is skipped before checking for
characters in 'foldignore'. For C use "#" to ignore preprocessor lines.
When you want to ignore lines in another way, use the 'expr' method. The
indent() function can be used in 'foldexpr' to get the indent of a line.

Folding html with foldmethod syntax, which is simpler.
This answer is based on HTML syntax folding in vim. author is #Ingo Karcat.
set your fold method to be syntax with the following:
vim command line :set foldmethod=syntax
or put the setting in ~/.vim/after/ftplugin/html.vim
setlocal foldmethod=syntax
Also note so far, the default syntax script only folds a multi-line
tag itself, not the text between the opening and closing tag.
So, this gets folded:
<div
class="foo"
id="bar"
>
And this doesn't
<div>
<b>text between here</b>
</div>
To get folded between tags, you need extend the syntax script, via
the following, best place into ~/.vim/after/syntax/html.vim
The syntax folding is performed between all but void html elements
(those which don't have a closing sibling, like <br>)
syntax region htmlFold start="<\z(\<\(area\|base\|br\|col\|command\|embed\|hr\|img\|input\|keygen\|link\|meta\|para\|source\|track\|wbr\>\)\#![a-z-]\+\>\)\%(\_s*\_[^/]\?>\|\_s\_[^>]*\_[^>/]>\)" end="</\z1\_s*>" fold transparent keepend extend containedin=htmlHead,htmlH\d

Install js-beautify command(JavaScript version)
npm -g install js-beautify
wget --no-check-certificate https://www.google.com.hk/ -O google.index.html
js-beautify -f google.index.html -o google.index.bt.html
http://www.google.com.hk orignal html:
js-beautify and vim fold:

Add on to answer by James Lai.
Initially my foldmethod=syntax so zfat won't work.
Solution is to set the foldemethod to manual
:setlocal foldmethod=manual
to check which foldmethod in use,
:setlocal foldmethod?

Firstly set foldmethod=syntax and try zfit to fold start tag and zo to unfold tags, It works well on my vim.

Related

Ignore any blank space or line break in git-diff

I have the same HTML file rendered in two different ways and want to compare it using git diff, taking care of ignoring every white-space, tab, line-break, carriage-return, or anything that is not strictly the source code of my files.
I'm actually trying this:
git diff --no-index --color --ignore-all-space <file1> <file2>
but when some html tags are collapsed all on one line (instead of one per line and tabulated) git-diff detect is as a difference (while for me it is not).
<html><head><title>TITLE</title><meta ......
is different from
<html>
<head>
<title>TITLE</title>
<meta ......
What option do I miss to accomplish what I need and threat as if it was the same?
git diff supports comparing files line by line or word by word, and also supports defining what makes a word. Here you can define every non-space character as a word to do the comparison. In this way, it will ignore all spaces including white-spcae, tab, line-break and carrige-return as what you need.
To achieve it, there's a perfect option --word-diff-regex, and just set it --word-diff-regex=[^[:space:]]. Refer to doc for detail.
git diff --no-index --word-diff-regex=[^[:space:]] <file1> <file2>
Here's an example. I created two files, with a.html as follows:
<html><head><title>TITLE</title><meta>
With b.html as follows:
<html>
<head>
<title>TI==TLE</title>
<meta>
By running
git diff --no-index --word-diff-regex=[^[:space:]] a.html b.html
It highlights the difference of TITLE and TI{+==+}TLE in the two files in plain mode as follows. You can also specify --word-diff=<mode> to display results in different modes. The mode can be color, plain, porcelain and none, and with plain as default.
diff --git a/d.html b/a.html
index df38a78..306ed3e 100644
--- a/d.html
+++ b/a.html
## -1 +1,4 ##
<html>
<head>
<title>TI{+==+}TLE</title>
<meta>
Executing command git diff --help gives some options like
--ignore-cr-at-eol
Ignore carriage-return at the end of line when doing a comparison.
--ignore-space-at-eol
Ignore changes in whitespace at EOL.
-b, --ignore-space-change
Ignore changes in amount of whitespace. This ignores whitespace at line end, and considers all other sequences of one or more whitespace
characters to be equivalent.
-w, --ignore-all-space
Ignore whitespace when comparing lines. This ignores differences even if one line has whitespace where the other line has none.
--ignore-blank-lines
Ignore changes whose lines are all blank.
Which you can combine according to your need, Below command worked for me
git diff --ignore-blank-lines --ignore-all-space --ignore-cr-at-eol
This does the trick for me:
git diff --ignore-blank-lines
git-diff compares files line by line
It checks the first line of your file1 with that in file2, since they are not same it reports an error.
Ignoring white space means that foo bar will match foobar if on the same line. Since your files span multiple lines in one and only one line in other, the files will always differ
If you really want to check that the files contain the exact same non-whitespace characters, you could try something like this:
diff <(perl -ne 's/\s*//xg; print' file1) <(perl -ne 's/\s*//g; print' file2)
Hope it solves your problem!

Emmet - Wrap with Abbreviation - Token that represents the wrapped text i.e. {original text}

I'm attempting to convert a list of URLs into HTML links as lazily as possible:
www.annaandsally.com.au
www.babylush.com.au
www.babysgotstyle.com.au
... etc
Using wrap in abbreviation, I'd like to do something like: a[href="http://${1}/"]*
The expanded abbreviation would result in:
www.annaandsally.com.au
www.babylush.com.au
www.babysgotstyle.com.au
... etc
The missing piece of the puzzle is an abbreviation token that represents the text being wrapped.
Any idea if this can be done?
If they are already on their own lines (which in the question, they look like they are), a simple Find and Replace with RegEx turned on will work. The Params are as follows:
Find What:
(.+)
Replace With:
$1
Before
After
Sergey from Emmet was kind enough to point me in the right direction. The $# token contains the original content:
a[href="http://$#/"]*>{$#}
By specifying $# as the href attribute, the original content is no longer 'wrapped' and must be be reinserted via {$#}.
http://docs.emmet.io/actions/wrap-with-abbreviation/#controlling-output-position

Align indent to parenthesis after linebreak in Sublime Text

I like to keep my lines below 80 columns, so I often want to refactor a line that looks like this:
object.function(a_long_argument, another_long_argument, and_a_third)
to this:
object.function(a_long_argument,
another_long_argument,
and_a_third)
But when I press Enter after the first "," in Sublime it just linebreaks and indents the cursor a few spaces. I want it to align to the paranthesis or [] or {} that I am in, like Emacs does so beautifully.
Is there an option for this? Is there a plugin for this? Do I have to write my own?
I have tried searching for it, but I have not found anything.
EDIT:
Even better would be a shortcut or plugin or something for selecting a few rows, or the entire buffer, and let it try to auto-linebreak at good spots. Refactor comments too. If it has to be language specific, I want it primarily for Python and C++.
Sublime's indent_to_bracket will wrap the cursor for you. Just add the following line to either your User/Preferences.sublime-settings or User/Python.sublime-settings file:
"indent_to_bracket": true
Unfortunately this currently only seems to work with parentheses, curly braces and square brackets still wrap to the previous line indent.

How to comment out HTML/XML element in VIM?

What's the best shortcut or plugin to comment out HTML/XML elements?
And also need to uncomment.
You can use a combination of matching XML tags, as can be seen in this question and Perl's search and replace.
For instance, given this snippet:
<TypeDef name="a">
<ArrayType high="14" low="0">
<UndefType type="node">
</UndefType>
</ArrayType>
</TypeDef>
Put the cursor on either the opening or closing TypeDef and type the following sequence:
vat:s/^\(.*\)$/<!-- \1 -->/
v - puts you into visual mode
at - selects the whole XML tag
:s/^\(.*\)$/<!-- \1 -->/ - surrounds each line with '<!-- ... -->', the comment delimiters for XML
Alternatively, you can just delete it like this:
dat
d - delete according to the following movements
at - as before
To delete id use then use vat:s/-->// to delete comments
I use the tComment plugin. You can find a detailed video tutorial here on how to install and use it.
The plugin is very useful as it allows you to toggle comments from both the command and input interface, and you can do so using both visual mode and motions (like gcw, or gc3w)
If you use emmet-vim, you can select the whole contents of the tag you would like to comment out by pressing v a t and then press Ctrl y /
To comment: vato<ESC>i<!-- <ESC>vatA --><ESC>
Position the cursor anywhere inside the HTML block. Not inside a nested one unless you want to comment that one.
Go to the opening tag: vato
Exit visual mode: Esc
Insert: i<!--
Exit insert mode: Esc
Go to closing tag: vat
Append: A -->
Exit insert mode: Esc
Note: You may use I to insert directly from visual mode, and it'll work with multi-line blocks, but for single line elements it'll mess up the indentation.
To uncomment: vat<ESC>4xvato<Esc>5X
Position the cursor anywhere inside the HTML block, ending comment delimiter excluded.
Go to the closing tag: vat
Exit visual mode: Esc
Delete 4 chars: 4x
Go to the opening tag vato
Delete preceding 5 chars: 5X
Using .vimrc or init.vim to create shorcuts
You may add these lines to your .vimrc (or init.vim in neovim) to remap shortcuts:
" Comment HTML element
nnoremap <silent> <leader>h :set lazyredraw<cr>mhvato<ESC>i<!-- <ESC>vatA --><ESC>`h:set nolazyredraw<cr>
" Uncomment HTML element
nnoremap <silent> <leader>H :set lazyredraw<cr>mhvat<ESC>4xvato<ESC>5X`h:set nolazyredraw<cr>
Warning:
You will need to undo if you try to uncomment a non-commented area for it will delete some characters. You could avoid this by replacing 4x with d2f- and 5X with dF!, but then you'd have issues with this kind of workaround and anything else in the same line that contains -...- or !.
If there are already comments in between the tags of the element to comment out, you will need to uncomment those first.
Notes:
Change <leader>h and <leader>H to what you'd like to use.
:set lazyredraw is to hide intermediate steps by not redrawing the screen and :set nolazyredraw to avoid possible visual glitches afterwards.
mh is to save current cursor position and `h is to jump back to that line and column. You may replace h with any other lower case letter.
Tip: Use :source $MYVIMRC to apply changes done to .vimrc (or init.vim) without having to restart vim.

How can one close HTML tags in Vim quickly?

It's been a while since I've had to do any HTML-like code in Vim, but recently I came across this again. Say I'm writing some simple HTML:
<html><head><title>This is a title</title></head></html>
How do I write those closing tags for title, head and html down quickly? I feel like I'm missing some really simple way here that does not involve me going through writing them all down one by one.
Of course I can use CtrlP to autocomplete the individual tag names but what gets me on my laptop keyboard is actually getting the brackets and slash right.
I find using the xmledit plugin pretty useful. it adds two pieces of functionality:
When you open a tag (e.g. type <p>), it expands the tag as soon as you type the closing > into <p></p> and places the cursor inside the tag in insert mode.
If you then immediately type another > (e.g. you type <p>>), it expands that into
<p>
</p>
and places the cursor inside the tag, indented once, in insert mode.
The xml vim plugin adds code folding and nested tag matching to these features.
Of course, you don't have to worry about closing tags at all if you write your HTML content in Markdown and use %! to filter your Vim buffer through the Markdown processor of your choice :)
I like minimal things,
imap ,/ </<C-X><C-O>
I find it more convinient to make vim write both opening and closing tag for me, instead of just the closing one. You can use excellent ragtag plugin by Tim Pope. Usage looks like this (let | mark cursor position)
you type:
span|
press CTRL+x SPACE
and you get
<span>|</span>
You can also use CTRL+x ENTER instead of CTRL+x SPACE, and you get
<span>
|
</span>
Ragtag can do more than just it (eg. insert <%= stuff around this %> or DOCTYPE). You probably want to check out other plugins by author of ragtag, especially surround.
Check this out..
closetag.vim
Functions and mappings to close open HTML/XML tags
https://www.vim.org/scripts/script.php?script_id=13
I use something similar.
If you're doing anything elaborate, sparkup is very good.
An example from their site:
ul > li.item-$*3 expands to:
<ul>
<li class="item-1"></li>
<li class="item-2"></li>
<li class="item-3"></li>
</ul>
with a <C-e>.
To do the example given in the question,
html > head > title{This is a title}
yields
<html>
<head>
<title>This is a title</title>
</head>
</html>
There is also a zencoding vim plugin: https://github.com/mattn/zencoding-vim
tutorial: https://github.com/mattn/zencoding-vim/blob/master/TUTORIAL
Update: this now called Emmet: http://emmet.io/
An excerpt from the tutorial:
1. Expand Abbreviation
Type abbreviation as 'div>p#foo$*3>a' and type '<c-y>,'.
---------------------
<div>
<p id="foo1">
</p>
<p id="foo2">
</p>
<p id="foo3">
</p>
</div>
---------------------
2. Wrap with Abbreviation
Write as below.
---------------------
test1
test2
test3
---------------------
Then do visual select(line wize) and type '<c-y>,'.
If you request 'Tag:', then type 'ul>li*'.
---------------------
<ul>
<li>test1</li>
<li>test2</li>
<li>test3</li>
</ul>
---------------------
...
12. Make anchor from URL
Move cursor to URL
---------------------
http://www.google.com/
---------------------
Type '<c-y>a'
---------------------
Google
---------------------
Mapping
I like to have my block tags (as opposed to inline) closed immediately and with as simple a shortcut as possible (I like to avoid special keys like CTRL where possible, though I do use closetag.vim to close my inline tags.) I like to use this shortcut when starting blocks of tags (thanks to #kimilhee; this is a take-off of his answer):
inoremap ><Tab> ><Esc>F<lyt>o</<C-r>"><Esc>O<Space>
Sample usage
Type—
<p>[Tab]
Result—
<p>
|
</p>
where | indicates cursor position.
Explanation
inoremap means create the mapping in insert mode
><Tab> means a closing angle brackets and a tab character; this is what is matched
><Esc> means end the first tag and escape from insert into normal mode
F< means find the last opening angle bracket
l means move the cursor right one (don't copy the opening angle bracket)
yt> means yank from cursor position to up until before the next closing angle bracket (i.e. copy tags contents)
o</ means start new line in insert mode and add an opening angle bracket and slash
<C-r>" means paste in insert mode from the default register (")
><Esc> means close the closing tag and escape from insert mode
O<Space> means start a new line in insert mode above the cursor and insert a space
Check out vim-closetag
It's a really simple script (also available as a vundle plugin) that closes (X)HTML tags for you. From it's README:
If this is the current content:
<table|
Now you press >, the content will be:
<table>|</table>
And now if you press > again, the content will be:
<table>
|
</table>
Note: | is the cursor here
Here is yet another simple solution based on easily foundable Web writing:
Auto closing an HTML tag
:iabbrev </ </<C-X><C-O>
Turning completion on
autocmd FileType xml set omnifunc=xmlcomplete#CompleteTags
allml (now Ragtag ) and Omni-completion ( <C-X><C-O> )
doesn't work in a file like .py or .java.
if you want to close tag automatically in those file,
you can map like this.
imap <C-j> <ESC>F<lyt>$a</^R">
( ^R is Contrl+R : you can type like this Control+v and then Control+r )
(| is cursor position )
now if you type..
<p>abcde|
and type ^j
then it close the tag like this..
<p>abcde</p>|
Building off of the excellent answer by #KeithPinson (sorry, not enough reputation points to comment on your answer yet), this alternative will prevent the autocomplete from copying anything extra that might be inside the html tag (e.g. classes, ids, etc...) but should not be copied to the closing tag.
UPDATE I have updated my response to work with filename.html.erb files.
I noticed my original response didn't work in files commonly used in Rails views, like some_file.html.erb when I was using embedded ruby (e.g. <p>Year: <%= #year %><p>). The code below will work with .html.erb files.
inoremap ><Tab> ><Esc>?<[a-z]<CR>lyiwo</<C-r>"><Esc>O
Sample usage
Type:
<div class="foo">[Tab]
Result:
<div class="foo">
|
<div>
where | indicates cursor position
And as an example of adding the closing tag inline instead of block style:
inoremap ><Tab> ><Esc>?<[a-z]<CR>lyiwh/[^%]><CR>la</<C-r>"><Esc>F<i
Sample usage
Type:
<div class="foo">[Tab]
Result:
<div class="foo">|<div>
where | indicates cursor position
It's true that both of the above examples rely on >[Tab] to signal a closing tag (meaning you would have to choose either inline or block style). Personally, I use the block-style with >[Tab] and the inline-style with >>.