Ⅰ. 插件描述

C&C++ ftplugins suite for Vim

Ⅱ. 基本信息

创建日期:  2002-07-09
使用用户:  7
Github星:  89
插件作者:  Luc Hermitte

Ⅲ. 安装方法


Plugin 'luchermitte/lh-cpp'
… 然后在Vim中运行以下命令:
:source %

对于Vundle版本 < 0.10.2,请用上面的Bundle替换Plugin。


NeoBundle 'luchermitte/lh-cpp'
… 然后在Vim中运行以下命令:
:source %


Plug 'luchermitte/lh-cpp'
… 然后在Vim中运行以下命令:
:source %


cd ~/.vim/bundle
git clone https://github.com/luchermitte/lh-cpp

Ⅳ. 文档说明

# lh-cpp Build Status Project Stats


lh-cpp is an heterogeneous suite of helpers for C and C++ programming.

It provides the following things:

An exhaustive list of all options is also available.
For help using this plugin for the first time, please take a look at :h lh-cpp-first-steps

Text insertion facilities


The insertion of pair of brackets-like characters is eased thanks to lh-brackets.

keysExpands into ..Surrounds the selection with ... 2Surrounds the current ...
[ after a [[[<cursor>]]«»n/an/a
] before ]]close all ]]n/an/a
<localleader>[ [<selection>]word
<localleader>{ {\n<selection>\n}«»line
<<<cursor>>«» after #include, or template on the same line
" (1 double quote)"<cursor>"«»11
"" "<selection>"word
'' (2 single quotes) '<selection>'word
;closes all parenthesis after the cursor -- if there is nothing else
  • 1 Not defined to avoid hijacking default vim key bindings.
  • 2 The visual mode mappings do not surround the current marker/placeholder selected, but trigger the INSERT-mode mappings instead.
  • 3 The exact behavior of this mapping has changed with release r719 (on Google Code). Now, no newline is inserted by default. However, hitting <cr> in the middle of a pair of curly-bracket will expand into {\n<cursor>\n}.
  • «» represents a marker/placeholder, it may be expanded with other characters like <++> depending on your preferences.
  • There is no way (yet) to deactivate this feature from the .vimrc

Code snippets

INSERT-mode snippets abbreviations

There exist, over the WWW, a lot of configurations and mappings regarding C programming. Once again you will find shortcuts for if, else, elif (I know it is not a C keyword, but else if are), for, while, do, switch, and main. In C++, snippets are also provided for try, catch, and namespace.
What is unique is the fact that when you type if in insert mode, it will automatically expand into ...

if () {

... in respect of the context. I.e.: within comments or strings (delimited by single or double quotes) if is not expanded. If keyword characters precede the typing, if is not expanded as well. Thus variables like tarif can be used without getting any headache.

Most of these same snippets, and a few variations, are
also provided as template-files for
This time, you just need to type the first letters of the snippet/template
name, and trigger the expansion (with <c-r><tab> by default). If several
snippets match (like c/for_, _c/fori_, _cpp/fori and cpp/for-iterator when
you try to expand fo), mu-template will ask you to choose which (matching)
snippet you want to expand.

Instruction surrounding mappings

In visual mode, ,if wraps the selection within the curly brackets and inserts if () just before. In normal mode ,if does the same thing under the consideration that the selection is considered to be the current line under the cursor. Actually, it is not ,if but <LocalLeader>if, with maplocalleader assigned by default to the coma ,.

Expression-condition surrounding mappings

In the same idea, <LocalLeader><LocalLeader>if surrounds the selection with if ( and ) {\n«»\n}«».

Other notes

All the three mode oriented mappings respect and force the indentation regarding the current setting and what was typed.

More precisely, regarding the value of the buffer relative option b:usemarks (_cf._ lh-brackets), if could be expanded into:

if () {

The exact style (Alman, Stroustroup, ...) regarding whether brackets are on a
new line, or not, can be tuned thanks to lh-dev :AddStyle feature.

Miscellaneous shortcuts

Note: in all the following mappings, , is actually the localleader that
lh-cpp sets to the comma characcter if it isn't set already.

  • tpl expands into template <<cursor>>«» ;
  • <m-t> inserts typedef, or typename depending on what is before the cursor ;
  • <m-r> inserts return, and tries to correctly place the semicolon, and a placeholder, depending on what follows the cursor ;
  • <c-x>be, <c-x>rbe replace (foo<cursor>) with (foo.begin(),foo.end()<cursor>) (or rbegin/rend) ;
  • <c->se: attempt to fill-in a switch-case from an enumerated type ;
  • ,sc | ,dc | ,rc | ,cc | ,lc surround the selection with ; static_cast<<cursor>>(<selection>), dynamic_cast, reinterpret_cast, const_cast, or boost::lexical_cast ;
  • ,,sc | ,,dc | ,,rc | ,,cc try to convert the C-cast selected into the C++-cast requested ;
  • #d expands into #define, #i into #ifdef, #e into endif, #n into #include ;
  • ,0 surrounds the selected lines with #if 0 ... #endif ;
  • ,1 surrounds the selected lines with #if 0 ... #else ... #endif ;
  • :KeepPoundIfPath 0 (or 1) will clean a #if 0/1...#else...#endif
    construct to match either the true or the false path.
  • pub expands into public:\n, pro expands into protected:\n, pri expands into private:\n ;
  • vir expands into virtual ;
  • firend is replaced by friend ;
  • <m-s> inserts std::, <m-b> inserts boost: ;
  • ?: expands into <cursor>? «» : «»; ;
  • <C-X>i will look for the symbol under the cursor (or selected) in the current ctag database and it will try to automatically include the header file where the symbol is defined.
  • <M-i> will look for the symbol under the cursor (or selected) in the current ctag database and it will try to automatically prepend it with its missing complete scope.
  • [[ and ][ and been overridden to jump to the start/end of the current
    function -- the default mappings were defined in C in mind, and they are
    unable of this. See the related v_if and o_if mappings from lh-dev -- see the demo.


  • All templates, snippets and wizards respect the naming convention set for
    the current project thanks to
    lh-dev styling feature
    -- see my project style template
    for an idea of what is supported and possible.
  • stream inserters, stream extractor, binary operators.
  • bool operator: almost portable hack to
    provide a boolean operator, strongly inspired by Matthew Wilson's
    _Imperfect C++_.
  • Generation of enums, and of switch-case statements from enum
  • constructors: copy-constructor,
    (see :h :Constructor).
  • Various standard types and
    functions (and a
    few from boost) have a snippet that'll automatically include the related
    header file there are are defined. NB: at this time, inclusions are not
    optimized as IncludeWhatYouUse would optimize them for us.
  • When a snippet/template requires header files, they will get included
    automatically (as long as the snippet specifies the headers files required)
    ; note: so far this feature cannot detect whether a required header file is
    already indirectly included through other included files.
  • Some snippets will try to detect the C++11 dialect (98/03/11/14/17) in
    order to adapt the result produced -- it will be done through the analysis
    of the option (bg):cpp_std_flavour , or
    the analysis of $CXXFLAGS, or through the analysis of CMake CXXFLAGS
    variables (this will require
    lh-cmake, and the project to be
    configured to CMake.)

I'll try to maintain an up-to-date documentation of the
snippets as most of them have options.

Wizards and other high-level features

  • class: builds a class skeleton based on the selected (simplified) semantics (value copyable, stack-based non copyable, entity non-copyable, entity clonable)
  • singleton: my very own way to define singletons based on my conclusions on this anti-pattern -- you may prefer Loki's or ACE's solutions
  • :DOX: analyses a function signature (parameters, return type, throw specification) and provide a default Doxygenized documentation
  • :GOTOIMPL, :MOVETOIMPL: search and jump to a function definition from its declaration, provide a default one in the ad'hoc implementation file if no definition is found
  • :ADDATTRIBUTE: old facility that helps define const-correct accessors and mutator, will be reworked. lh-refactor provides more ergonomic mappings for this purpose.
  • :CppDisplayUnmatchedFunctions, <c-x>u: shows the list of functions for which there is neither a declaration, nor a definition
  • :Override: Ask which inherited virtual function should be overridden in the current class (feature still in its very early stages)
  • :Constructor (that takes the following parameters: init, default, copy, assign), or :ConstructorInit, :ConstructorDefault, :ConstructorCopy, AssignmentOperator. They'll analyse the list of know attributes (from a ctags database) to generate the related construction functions.

Syntax highlighting

  • assign in condition (bad practice)
  • catch by value (bad practice)
  • throw specifications (do you really know what they are about, and still want them?), BTW they have been deprecated in C++11
  • C casts in C++ (bad practice)
  • cases that fall through the next one (code smell -- disabled by default)
  • function definitions


  • home like VC++: mappings that override <home> and <end> to mimic how these keys behave in VC++.
  • omap-param: defines the o-mappings ,i and ,a to select the current parameter (in a list of parameters).
  • SiR,
  • lh-cpp imports a C&C++ Folding plugin,
    which is still experimental.
  • lh-dev, which is required by
    lh-cpp, provides a few commands like :NameConvert that permits to change
    the naming style of a symbol. The possible styles are: upper_camel_case,
    lower_camel_case, snake/underscore, variable, local, global,
    member, constant, static, param, getter, setter)


ActivateAddons lh-cpp
  • or with vim-flavor which also supports
flavor 'LucHermitte/lh-cpp'
  • or you can clone the git repositories (expecting I haven't forgotten anything):
git clone git@github.com:LucHermitte/lh-vim-lib.git
git clone git@github.com:LucHermitte/lh-style.git
git clone git@github.com:LucHermitte/lh-tags.git
git clone git@github.com:LucHermitte/lh-dev.git
git clone git@github.com:LucHermitte/lh-brackets.git
git clone git@github.com:LucHermitte/searchInRuntime.git
git clone git@github.com:LucHermitte/mu-template.git
git clone git@github.com:tomtom/stakeholders_vim.git
git clone git@github.com:LucHermitte/alternate-lite.git
git clone git@github.com:LucHermitte/lh-cpp.git
  • or with Vundle/NeoBundle (expecting I haven't forgotten anything):
Bundle 'LucHermitte/lh-vim-lib'
Bundle 'LucHermitte/lh-style'
Bundle 'LucHermitte/lh-tags'
Bundle 'LucHermitte/lh-dev'
Bundle 'LucHermitte/lh-brackets'
Bundle 'LucHermitte/searchInRuntime'
Bundle 'LucHermitte/mu-template'
Bundle 'tomtom/stakeholders_vim'
Bundle 'LucHermitte/alternate-lite'
Bundle 'LucHermitte/lh-cpp'


Many people have to be credited:

  • the Vim & VimL gurus ;
  • the people I've stolen scripts and functions from: Stephen Riehm, Michael
    Sharpe, Georgi Slavchev, Johannes Zellner, Saul Lubkin ;
  • the people that gave me many great ideas and even feedback: Gergely Kontra,
    Leif Wickland, Robert Kelly IV [I've also stolen scripts from them] ;
  • Thomas Ribo for his feedback and features-requirements.
  • and many more that I have probably forgotten.


  • Documentation is under CC-BY-SA 3.0
  • lh-cpp is under GPLv3 with exceptions. See acompagning license file, i.e.

    • Plugin, snippets and templates are under GPLv3
    • Most code generated from snippets (for control statements, proto
      -> definition, accessors, ...) are under the License Exception

    detailled in the license file.

    • However, code generated from the following wizards: class,
      singleton, enum (1&2, switch, for), abs-rel -> is under Boost

    Software Licence

See also