How can one close HTML tags in Vim quickly?

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.

e> is just a method on Array (NSArray is implicitly bridged to Swift’s Array). It takes one argument: a closure that takes one object in the array and returns a Bool. In your closure, just return true for any objects you want in the filtered array.

64105 次浏览

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.

This may be a matter of style, but there's a bit of a divide in our dev team and I wondered if anyone else had any ideas on the matter...

The xml vim plugin adds code folding and nested tag matching to these features.

Basically, we have some debug print statements which we turn off during normal development. Personally I prefer to do the following:

//---- SomeSourceFile.cpp ----


#define DEBUG_ENABLED (0)


...


SomeFunction()
{
int someVariable = 5;


#if(DEBUG_ENABLED)
printf("Debugging: someVariable == %d", someVariable);
#endif
}

Some of the team prefer the following though:

// #define DEBUG_ENABLED


...


SomeFunction()
{
int someVariable = 5;


#ifdef DEBUG_ENABLED
printf("Debugging: someVariable == %d", someVariable);
#endif
}

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 :)

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.

Alternatively, you can declare a global constant, and use the C++ if, instead of the preprocessor #if. The compiler should optimize the unused branches away for you, and your code will be cleaner.

I like minimal things,

imap ,/ </<C-X><C-O>
now if you type..

#if and #define MY_MACRO (0)

<p>abcde|

Using #if means that you created a "define" macro, i.e., something that will be searched in the code to be replaced by "(0)". This is the "macro hell" I hate to see in C++, because it pollutes the code with potential code modifications.

and type ^j

For example:

#define MY_MACRO (0)


int doSomething(int p_iValue)
{
return p_iValue + 1 ;
}


int main(int argc, char **argv)
{
int MY_MACRO = 25 ;
doSomething(MY_MACRO) ;


return 0;
}

then it close the tag like this..

gives the following error on g++:

main.cpp|408|error: lvalue required as left operand of assignment|
||=== Build finished: 1 errors, 0 warnings ===|

<p>abcde</p>|

; }

Only one error.

gives the following error on g++:

main.cpp|408|error: lvalue required as left operand of assignment|
||=== Build finished: 1 errors, 0 warnings ===|

Which means that your macro successfully interacted with your C++ code: The call to the function was successful. In this simple case, it is amusing. But my own experience with macros playing silently with my code is not full of joy and fullfilment, so...

#ifdef and #define MY_MACRO

Only one error.

Which means that your macro successfully interacted with your C++ code: The call to the function was successful. In this simple case, it is amusing. But my own experience with macros playing silently with my code is not full of joy and fullfilment, so...

#ifdef and #define MY_MACRO

Using #ifdef means you "define" something. Not that you give it a value. It is still polluting, but at least, it will be "replaced by nothing", and not seen by C++ code as lagitimate code statement. The same code above, with a simple define, it:

#define MY_MACRO


int doSomething(int p_iValue)
{
return p_iValue + 1 ;
}


int main(int argc, char **argv)
{
int MY_MACRO = 25 ;
doSomething(MY_MACRO) ;


return 0;
}

Gives the following warnings:

main.cpp||In function ‘int main(int, char**)’:|
main.cpp|406|error: expected unqualified-id before ‘=’ token|
main.cpp|399|error: too few arguments to function ‘int doSomething(int)’|
main.cpp|407|error: at this point in file|
||=== Build finished: 3 errors, 0 warnings ===|

So...

Conclusion

I'd rather live without macros in my code, but for multiple reasons (defining header guards, or debug macros), I can't.

But at least, I like to make them the least interactive possible with my legitimate C++ code. Which means using #define without value, using #ifdef and #ifndef (or even #if defined as suggested by Jim Buck), and most of all, giving them names so long and so alien no one in his/her right mind will use it "by chance", and that in no way it will affect legitimate C++ code.

Post Scriptum

Now, as I'm re-reading my post, I wonder if I should not try to find some value that won't ever ever be correct C++ to add to my define. Something like

#define MY_MACRO @@@@@@@@@@@@@@@@@@

that could be used with #ifdef and #ifndef, but not let code compile if used inside a function... I tried this successfully on g++, and it gave the error:

main.cpp|410|error: stray ‘@’ in program|

Interesting. :-)

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">
<a href=""></a>
</p>
<p id="foo2">
<a href=""></a>
</p>
<p id="foo3">
<a href=""></a>
</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'
---------------------
<a href="http://www.google.com/">Google</a>
---------------------

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

Here is yet another simple solution based on easily foundable Web writing:

  1. Auto closing an HTML tag

    :iabbrev </ </<C-X><C-O>

  2. Turning completion on

    autocmd FileType xml set omnifunc=xmlcomplete#CompleteTags

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]

Using #ifdef means you "define" something. Not that you give it a value. It is still polluting, but at least, it will be "replaced by nothing", and not seen by C++ code as lagitimate code statement. The same code above, with a simple define, it:

#define MY_MACRO


int doSomething(int p_iValue)
{
return p_iValue + 1 ;
}


int main(int argc, char **argv)
{
int MY_MACRO = 25 ;
doSomething(MY_MACRO) ;


return 0;
}

Result:

<div class="foo">|<div>

where | indicates cursor position

Gives the following warnings:

main.cpp||In function ‘int main(int, char**)’:|
main.cpp|406|error: expected unqualified-id before ‘=’ token|
main.cpp|399|error: too few arguments to function ‘int doSomething(int)’|
main.cpp|407|error: at this point in file|
||=== Build finished: 3 errors, 0 warnings ===|

So...

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 >>.

And now if you press > again, the content will be:

<table>
|
</table>

My initial reaction was #ifdef, of course, but I think #if actually has some significant advantages for this - here's why:

Note: | is the cursor here

ode>#define to a global constant. #defines are usually frowned on by most C++ programmers.

And, Third, you say you've a divide in your team. My guess is this means different members have already adopted different approaches, and you need to standardise. Ruling that #if is the preferred choice means that code using #ifdef will compile -and run- even when DEBUG_ENABLED is false. And it's much easier to track down and remove debug output that is produced when it shouldn't be than vice-versa.

First, you can use DEBUG_ENABLED in preprocessor and compiled tests. Example - Often, I want longer timeouts when debug is enabled, so using #if, I can write this

  DoSomethingSlowWithTimeout(DEBUG_ENABLED? 5000 : 1000);

... instead of ...

#ifdef DEBUG_MODE
DoSomethingSlowWithTimeout(5000);
#else
DoSomethingSlowWithTimeout(1000);
#endif

Oh, and a minor readability point. You should be able to use true/false rather than 0/1 in your #define, and because the value is a single lexical token, it's the one time you don't need parentheses around it.

#define DEBUG_ENABLED true

Second, you're in a better position if you want to migrate from a #define to a global constant. #defines are usually frowned on by most C++ programmers.

instead of

#define DEBUG_ENABLED (1)