Skip to content

LucHermitte/lh-cpp

Repository files navigation

lh-cpp Build Status Project Stats

Features

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

Brackets

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

In mode INSERT VISUAL NORMAL
keys Expands into .. Surrounds the selection with ... 2 Surrounds the current ...
( (<cursor>)«» (<selection>) word
[ [<cursor>]«» 1 1
[ after a [ [[<cursor>]]«» n/a n/a
] before ]] close all ]] n/a n/a
<localleader>[ [<selection>] word
{ {<cursor>}«»3 {<selection>} word
<localleader>{ {\n<selection>\n}«» line
< <<cursor>>«» after #include, or template on the same line
" (1 double quote) "<cursor>"«» 1 1
"" "<selection>" word
' '<cursor>'«» 1 1
'' (2 single quotes) '<selection>' word
; closes all parenthesis after the cursor -- if there is nothing else
Notes:
  • 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 mu-template. 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.

Templates

  • 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 definition.
  • constructors: copy-constructor, default-constructor, destructor, assignment-operator (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

Miscellaneous

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

Installation

ActivateAddons lh-cpp
  • or with vim-flavor which also supports dependencies:
flavor 'LucHermitte/lh-cpp'
  • or you can clone the git repositories (expecting I haven't forgotten anything):
git clone [email protected]:LucHermitte/lh-vim-lib.git
git clone [email protected]:LucHermitte/lh-style.git
git clone [email protected]:LucHermitte/lh-tags.git
git clone [email protected]:LucHermitte/lh-dev.git
git clone [email protected]:LucHermitte/lh-brackets.git
git clone [email protected]:LucHermitte/searchInRuntime.git
git clone [email protected]:LucHermitte/mu-template.git
git clone [email protected]:tomtom/stakeholders_vim.git
git clone [email protected]:LucHermitte/alternate-lite.git
git clone [email protected]: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'

Credits

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.

License

  • 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