Full Code of LucHermitte/lh-cpp for AI

master c0a65da5e8b7 cached
220 files
806.7 KB
243.8k tokens
34 symbols
1 requests
Download .txt
Showing preview only (868K chars total). Download the full file or copy to clipboard to get everything.
Repository: LucHermitte/lh-cpp
Branch: master
Commit: c0a65da5e8b7
Files: 220
Total size: 806.7 KB

Directory structure:
gitextract_f3673ucg/

├── .gitignore
├── .rspec
├── .travis.yml
├── CONTRIBUTORS
├── Gemfile
├── License.md
├── README.md
├── Rakefile
├── VimFlavor
├── addon-info.json
├── after/
│   └── template/
│       ├── c/
│       │   ├── assert.template
│       │   ├── comment.template
│       │   ├── internals/
│       │   │   └── c-header-content.template
│       │   ├── rand_init.template
│       │   └── realloc.template
│       ├── cpp/
│       │   ├── abs-rel.template
│       │   ├── abstract-class.template
│       │   ├── array_size.template
│       │   ├── assignment-operator.template
│       │   ├── auto_ptr-instance.template
│       │   ├── auto_ptr.template
│       │   ├── b-e.template
│       │   ├── base-class-non-virtual.template
│       │   ├── base-class.template
│       │   ├── benchmark.template
│       │   ├── bool-operator.template
│       │   ├── catch.template
│       │   ├── cerr.template
│       │   ├── chrono-how-long.template
│       │   ├── cin.template
│       │   ├── class.template
│       │   ├── clonable-class.template
│       │   ├── copy-and-swap.template
│       │   ├── copy-back_inserter.template
│       │   ├── copy-constructor.template
│       │   ├── copy.template
│       │   ├── cout.template
│       │   ├── default-constructor.template
│       │   ├── destructor.template
│       │   ├── empty-exception-class.template
│       │   ├── ends_with.template
│       │   ├── entity-class.template
│       │   ├── enum.template
│       │   ├── enum2-impl.template
│       │   ├── enum2.template
│       │   ├── erase-remove.template
│       │   ├── exception-class.template
│       │   ├── file.template
│       │   ├── for-enum.template
│       │   ├── for-iterator.template
│       │   ├── for-range.template
│       │   ├── fori.template
│       │   ├── foriN.template
│       │   ├── forward.template
│       │   ├── getter.template
│       │   ├── init-constructor.template
│       │   ├── interface.template
│       │   ├── internals/
│       │   │   ├── abs-rel-shared.template
│       │   │   ├── attribute.template
│       │   │   ├── class-skeleton.template
│       │   │   ├── formatted-comment.template
│       │   │   ├── function-comment.template
│       │   │   ├── function.template
│       │   │   ├── get-b-e.template
│       │   │   ├── get-class-name.template
│       │   │   ├── includes.template
│       │   │   ├── list-constructors.template
│       │   │   ├── namespace-name.template
│       │   │   ├── shall_explicit_defaults.template
│       │   │   ├── stream-common.template
│       │   │   ├── stream-implementation.template
│       │   │   └── stream-signature.template
│       │   ├── iss.template
│       │   ├── list.template
│       │   ├── map.template
│       │   ├── namespace.template
│       │   ├── noncopyable.template
│       │   ├── operator-binary.template
│       │   ├── oss.template
│       │   ├── otb-sug-latex.template
│       │   ├── otb-sug-snippet.template
│       │   ├── path.template
│       │   ├── ptr_vector.template
│       │   ├── ref_setter.template
│       │   ├── scoped_ptr.template
│       │   ├── set.template
│       │   ├── setter.template
│       │   ├── shared_ptr.template
│       │   ├── singleton.template
│       │   ├── sort.template
│       │   ├── starts_with.template
│       │   ├── static_assert.template
│       │   ├── stream-extractor.template
│       │   ├── stream-inserter.template
│       │   ├── string.template
│       │   ├── swap-function.template
│       │   ├── throw.template
│       │   ├── traits.template
│       │   ├── try.template
│       │   ├── typeid.template
│       │   ├── unique_ptr.template
│       │   ├── unordered_map.template
│       │   ├── unordered_set.template
│       │   ├── utf8.template
│       │   ├── value-class.template
│       │   ├── vector.template
│       │   ├── weak_ptr.template
│       │   └── while-getline.template
│       └── dox/
│           ├── author.template
│           ├── code.template
│           ├── em.template
│           ├── file.template
│           ├── function.template
│           ├── group.template
│           ├── html.template
│           ├── ingroup.template
│           ├── since.template
│           └── tt.template
├── autoload/
│   └── lh/
│       ├── cpp/
│       │   ├── AnalysisLib_Class.vim
│       │   ├── AnalysisLib_Function.vim
│       │   ├── GotoFunctionImpl.vim
│       │   ├── UnmatchedFunctions.vim
│       │   ├── abs_rel.vim
│       │   ├── analyse.vim
│       │   ├── constructors.vim
│       │   ├── enum.vim
│       │   ├── ftplugin.vim
│       │   ├── include.vim
│       │   ├── libclang.vim
│       │   ├── macros.vim
│       │   ├── option.vim
│       │   ├── override.vim
│       │   ├── refactor.vim
│       │   ├── scope.vim
│       │   ├── snippets.vim
│       │   ├── style.vim
│       │   ├── tags.vim
│       │   ├── types.vim
│       │   └── understand.vim
│       ├── cpp.vim
│       └── dox.vim
├── doc/
│   ├── API.md
│   ├── Doxygen.md
│   ├── Enums.md
│   ├── TODO.md
│   ├── c.html
│   ├── lh-cpp-readme.txt
│   ├── options.md
│   ├── snippets.md
│   └── types.md
├── ftplugin/
│   ├── c/
│   │   ├── LoadHeaderFile.vim
│   │   ├── c_AddInclude.vim
│   │   ├── c_Doxygen.vim
│   │   ├── c_UnmatchedFunctions.vim
│   │   ├── c_complete_include.vim
│   │   ├── c_doc.vim
│   │   ├── c_gcov.vim
│   │   ├── c_menu.vim
│   │   ├── c_mu-template_api.vim
│   │   ├── c_navigate_functions.vim
│   │   ├── c_pvs-2-qf.vim
│   │   ├── c_set.vim
│   │   ├── c_show_scope.vim
│   │   ├── c_snippets.vim
│   │   ├── c_stl.vim
│   │   ├── c_switch-enum.vim
│   │   ├── flistmaps.vim
│   │   ├── keep_pound_if_path.vim
│   │   ├── previewWord.vim
│   │   └── word.list
│   ├── cpp/
│   │   ├── changelog
│   │   ├── cpp_AddMissingScope.vim
│   │   ├── cpp_BuildTemplates.vim
│   │   ├── cpp_Constructor.vim
│   │   ├── cpp_Enum.vim
│   │   ├── cpp_FindContextClass.vim
│   │   ├── cpp_GotoFunctionImpl.vim
│   │   ├── cpp_InsertAccessors.vim
│   │   ├── cpp_Inspect.vim
│   │   ├── cpp_Override.vim
│   │   ├── cpp_options-commands.vim
│   │   ├── cpp_options.vim
│   │   ├── cpp_refactor.vim
│   │   ├── cpp_set.vim
│   │   └── cpp_snippets.vim
│   └── idl_set.vim
├── mkVba/
│   └── mk-lh-cpp.vim
├── plugin/
│   ├── homeLikeVC++.vim
│   └── omap-param.vim
├── script/
│   └── PVS2qf.xsl
├── spec/
│   ├── abstract-class_spec.rb
│   ├── base-class-NV_spec.rb
│   ├── base-class_spec.rb
│   ├── class-with-attributes_spec.rb
│   ├── clonable-class_spec.rb
│   ├── constructor-command_spec.rb
│   ├── deps_spec.rb
│   ├── empty-exception-class_spec.rb
│   ├── exception-class_spec.rb
│   ├── spe_func_spec.rb
│   ├── spec_helper.rb
│   ├── value-class-with-attributes_spec.rb
│   └── value-class_spec.rb
├── syntax/
│   ├── c-assign-in-condition.vim
│   ├── c-fallthrough-case.vim
│   ├── c.vim
│   ├── cpp-badcatch.vim
│   ├── cpp-c-cast.vim
│   ├── cpp-cxxtest.vim
│   ├── cpp-funcdef.vim
│   ├── cpp-throw-spec.vim
│   └── cpp.vim
└── tests/
    ├── VimFlavor
    └── lh/
        ├── analysis.vim
        ├── cpp-TU-override.cpp
        ├── cpp-TU.cpp
        ├── omap-param.vim
        ├── snippets.vim
        ├── test-flavours.vim
        └── test-types.vim

================================================
FILE CONTENTS
================================================

================================================
FILE: .gitignore
================================================
tags
*.sw*
*~
*.pyc


================================================
FILE: .rspec
================================================
--color
--require spec_helper
--format documentation
-I ~/.vim-flavor/repos/LucHermitte_vim-UT/spec


================================================
FILE: .travis.yml
================================================
dist: xenial
language: ruby
cache: bundler
rvm:
    - 2.1.5
script: bundle exec rake ci
compiler:
    - gcc # for ctags
addons:
    apt:
        packages:
            - vim-gtk
addons:
    apt:
        packages:
            - vim-gtk
before_install:
    - git clone https://github.com/universal-ctags/ctags.git
    - (cd ctags && ./autogen.sh && ./configure --prefix="$HOME" && make -j 4 install)
before_script:
    - "export PATH=$PATH:$HOME/bin"
services:
  - xvfb


================================================
FILE: CONTRIBUTORS
================================================
The following people have contributed to lh-cpp

# Direct contributors
Luc Hermitte, maintainer, 2002(?)-2018
Leif Wickland, original mapping for `GOTOIMPL` (VIM-TIP#335)
Robert KellyIV, first plugin version of `GOTOIMPL`, plus contributions to present code, 2002
Olivier Teuliere, highlight function definitions, 2004 (https://vim.wikia.com/wiki/Highlighting_of_method_names_in_the_definition)
Sven Speckmaier, Apply styles to `GOTOIMPL`, 2016, PR#4
fwSmit, Fix missing dep in doc, 2018, PR#9

Discl. I'm likely to have forgottent old contributors, drop me an email
if you're one of them.

# Plugins imported from other projects:
Charles E. Campbell, Jr., initial flistmaps definition
Georgi Slavchev <goyko at gbg dot bg>, previewWord initial definition, 2002 (https://vim.wikia.com/wiki/Function_signature_previewer)




================================================
FILE: Gemfile
================================================
source 'https://rubygems.org'

gem 'rspec', '~> 3.1.0'
gem 'vimrunner', '~> 0.3.1'
gem 'rake', '~> 10.3.2'
gem 'vim-flavor', '~> 2.1.1'


================================================
FILE: License.md
================================================
Copyright 2001-2015, Luc Hermitte

# Scripts License

All scripts (VimL, templates, bash, perl, etc.) from lh-vim are
distributed under FSF's GPLv3 license.

See http://www.gnu.org/licenses/gpl.txt for more information.


# License exception for generated code

Many lh-vim scripts generate code. Unless specified otherwise, the code generated is under the following license exception.


Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed.

This Exception is an additional permission under section 7 of the GNU General Public License, version 3 ("GPLv3"). It applies to a given file that bears a notice placed by the copyright holder of the file stating that the file is governed by GPLv3 along with this Exception.

The purpose of this Exception is to allow distribution of lh-vim's typical output under terms of the recipient's choice (including proprietary).

## 0. Definitions.
"Covered Code" is the source or object code of a version of lh-vim that is a covered work under this License.

"Normally Copied Code" for a version of lh-vim means all parts of its Covered Code which that version can copy from its code (i.e., not from its input file) into its minimally verbose, non-debugging and non-tracing output.

"Ineligible Code" is Covered Code that is not Normally Copied Code.

## 1. Grant of Additional Permission.
You have permission to propagate output of lh-vim, even if such propagation would otherwise violate the terms of GPLv3. However, if by modifying lh-vim you cause any Ineligible Code of the version you received to become Normally Copied Code of your modified version, then you void this Exception for the resulting covered work. If you convey that resulting covered work, you must remove this Exception in accordance with the second paragraph of Section 7 of GPLv3.

## 2. No Weakening of lh-vim Copyleft.

The availability of this Exception does not imply any general presumption that third-party software is unaffected by the copyleft requirements of the license of lh-vim.

Disclaimer: This lh-vim license exception is directly derived from [AUTOCONF CONFIGURE SCRIPT EXCEPTION](http://www.gnu.org/licenses/autoconf-exception.html) to GPLv3 license.

# License for documentation

The documentation of lh-vim scripts distributed along the scripts, and of the wiki pages here are under the Creative Commons license ([CC by SA 3.0](http://creativecommons.org/licenses/by-sa/3.0/))


================================================
FILE: README.md
================================================
# lh-cpp [![Build Status](https://secure.travis-ci.org/LucHermitte/lh-cpp.png?branch=master)](http://travis-ci.org/LucHermitte/lh-cpp) [![Project Stats](https://www.openhub.net/p/21020/widgets/project_thin_badge.gif)](https://www.openhub.net/p/21020)
## Features

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

It provides the following things:
  * Smart snippets for [brackets pairs](#brackets), [control statements](#code-snippets)
  * a few [templates](#templates)
  * a few [advanced wizards, and high-level features](#wizards-and-other-high-level-features) to Generate classes and singletons, to Generate ready to fill-in function comments for Doxygen, Jump to a function implementation, Search for un-implemented or undeclared functions, _etc._
  * [syntax highlighting](#syntax-highlighting) for identified counter-idioms and bad practices (catch by value, assignments in conditions, throw specifications)
  * an [API](doc/API.md) to build even more complex wizards and advanced features

  An exhaustive [list of all options](doc/options.md) 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](http://github.com/LucHermitte/lh-brackets).

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

##### Notes:
  * <sup>1</sup> Not defined to avoid hijacking default vim key bindings.
  * <sup>2</sup> The visual mode mappings do not surround the current marker/placeholder selected, but trigger the INSERT-mode mappings instead.
  * <sup>3</sup> 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 ...
```C++
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](doc/snippets.md#control-statements) as template-files for
[mu-template](http://github.com/LucHermitte/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](http://github.com/LucHermitte/lh-brackets)), `if` could be expanded into:
```C++
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](http://github.com/LucHermitte/lh-dev#formatting-of-brackets-characters).

#### 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](http://github.com/LucHermitte/lh-dev/#function) -- [see the demo](blob/master/doc/screencast-select-function.gif).

#### Templates
  * All templates, snippets and wizards respect the naming convention set for
    the current project thanks to
    [lh-dev styling feature](http://github.com/LucHermitte/lh-dev#naming-conventions)
    -- see my [project style template](http://github.com/LucHermitte/mu-template/blob/master/after/template/vim/internals/vim-rc-local-cpp-style.template)
    for an idea of what is supported and possible.
  * stream inserters, stream extractor, binary operators.
  * [bool operator](doc/snippets.md#cppbool-operator): almost portable hack to
    provide a boolean operator, strongly inspired by Matthew Wilson's
    _Imperfect C++_.
  * Generation of [enums](doc/Enums.md), and of switch-case statements from enum
    definition.
  * constructors: [`copy-constructor`](doc/snippets.md#cppcopy-constructor),
    [`default-constructor`](doc/snippets.md#cppdefault-constructor),
    [`destructor`](doc/snippets.md#cppdestructor),
    [`assignment-operator`](doc/snippets.md#cppassignment-operator)
    (see `:h :Constructor`).
  * Various [standard types](doc/snippets.md#standard-and-boost-types) and
    [functions](doc/snippets.md#standard-and-boost-functions-and-idioms) (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`](doc/option.md#bgcpp_std_flavour-and-cxxflags) , or
    the analysis of `$CXXFLAGS`, or through the analysis of CMake `CXXFLAGS`
    variables (this will require
    [lh-cmake](http://github.com/LucHermitte/lh-cmake), and the project to be
    configured to CMake.)

I'll try to maintain an up-to-date [documentation](doc/snippets.md) of the
snippets as most of them have options.

#### Wizards and other high-level features
  * [class](doc/snippets.md#cppclass): builds a class skeleton based on the selected (simplified) semantics (value copyable, stack-based non copyable, entity non-copyable, entity clonable)
  * [singleton](doc/snippets.md#cppsingleton): 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](doc/Doxygen.md): analyses a function signature (parameters, return type, throw specification) and provide a default Doxygenized documentation
  * [:GOTOIMPL](doc/GotoImplementation.md), :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](doc/Accessors.md): old facility that helps define const-correct accessors and mutator, will be reworked. [lh-refactor](http://github.com/LucHermitte/vim-refactor) provides more ergonomic mappings for this purpose.
  * [:CppDisplayUnmatchedFunctions](doc/UmatchedFunctions.md), `<c-x>u`: shows the list of functions for which there is neither a declaration, nor a definition
  * [:Override](doc/Override.md): 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?](http://www.gotw.ca/gotw/082.htm)), 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](https://github.com/LucHermitte/VimFold4C),
    which is still experimental.
  * [lh-dev](http://github.com/LucHermitte/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
  * Requirements: Vim 7.+, [lh-vim-lib](https://github.com/LucHermitte/lh-vim-lib), [lh-style](https://github.com/LucHermitte/lh-style), [lh-brackets](https://github.com/LucHermitte/lh-brackets), [mu-template](https://github.com/LucHermitte/mu-template), [lh-dev](https://github.com/LucHermitte/lh-dev), [alternate-lite](https://github.com/LucHermitte/alternate-lite).
  * With [vim-addon-manager](https://github.com/MarcWeber/vim-addon-manager), install lh-cpp. This is the preferred method because of the various dependencies.
```vim
ActivateAddons lh-cpp
```
  * or with [vim-flavor](https://github.com/kana/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 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):
```vim
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](License.md), 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](License.md).
      * However, code generated from the following wizards: `class`,
        `singleton`, `enum` (1&2, switch, for), `abs-rel` -> is under Boost
        Software Licence


## See also
  * [C++ tips on vim.wikia](http://vim.wikia.com/wiki/Category:C%2B%2B)
  * c.vim
  * **Project Management**: [local\_vimrc](https://github.com/LucHermitte/local_vimrc)
  * **Compilation**: [BuildToolsWrappers](http://github.com/LucHermitte/vim-build-tools-wrapper)
  * **Errors Highlighting**: syntastic, [compil-hints](http://github.com/LucHermitte/vim-compil-hints) (a non-dynamic syntastic-lite plugin that'll only highlight errors found after a compilation stage)
  * **CMake Integration**: [lh-cmake](https://github.com/LucHermitte/lh-cmake) + [local\_vimrc](https://github.com/LucHermitte/local_vimrc) + [BuildToolsWrappers](http://github.com/LucHermitte/vim-build-tools-wrapper)
  * **Refactoring**: refactor.vim, [my generic refactoring plugin](http://github.com/LucHermitte/vim-refactor)
  * **Code Completion**: [YouCompleteMe](https://github.com/Valloric/YouCompleteMe), really, check this one!, or [OmniCppComplete](http://www.vim.org/scripts/script.php?script_id=1520), or [clang\_complete](https://github.com/Rip-Rip/clang_complete)
  * **Code Indexing**: [clang\_indexer](https://github.com/LucHermitte/clang_indexer) and [vim-clang](https://github.com/LucHermitte/vim-clang), [lh-tags](http://github.com/LucHermitte/lh-tags)



================================================
FILE: Rakefile
================================================
#!/usr/bin/env rake

require 'rspec/core/rake_task'

RSpec::Core::RakeTask.new(:spec)

task :ci => [:dump, :install, :test]

task :default => :spec

task :dump do
  sh 'vim --version'
end

task :test    => :spec

task :spec do
  # 'spec' is implicitly run as well
  sh 'rspec ~/.vim-flavor/repos/LucHermitte_vim-UT/spec'
end


task :install do
  sh 'cat VimFlavor >> tests/VimFlavor'
  sh 'cd tests && bundle exec vim-flavor install'
end


================================================
FILE: VimFlavor
================================================
flavor 'LucHermitte/lh-vim-lib', '>= 4.1.0'
flavor 'LucHermitte/lh-brackets', '>= 3.1.1'
flavor 'LucHermitte/lh-style'
flavor 'LucHermitte/lh-dev'
flavor 'LucHermitte/mu-template', '>= 4.3.1'
flavor 'LucHermitte/VimFold4C', '>= 3.0.9'
flavor 'LucHermitte/alternate-lite', '>= 0.1.0'


================================================
FILE: addon-info.json
================================================
{
  "name" : "lh-cpp",
  "version" : "dev",
  "author" : "Luc Hermitte <http://github.com/LucHermitte>",
  "maintainer" : "Luc Hermitte <http://github.com/LucHermitte>",
  "repository" : {"type": "git", "url": "git@github.com:LucHermitte/lh-cpp.git"},
  "dependencies" : {
      "lh-vim-lib" : {"type" : "git", "url" : "git@github.com:LucHermitte/lh-vim-lib.git"},
      "lh-brackets" : {"type": "git", "url": "git@github.com:LucHermitte/lh-brackets.git"},
      "lh-dev" : {"type": "git", "git": "git@github.com:LucHermitte/lh-dev.git"},
      "mu-template@lh" : {"type": "git", "url": "git@github.com:LucHermitte/mu-template.git"},
      "alternate-lite" : {"type": "git", "url": "git@github.com:LucHermitte/alternate-lite.git"},
      "VimFold4C" : {"type": "git", "url": "git@github.com:LucHermitte/VimFold4C.git"}
  },
  "description" : "C&C++ ftplugins suite",
  "homepage" : "http://github.com/LucHermitte/lh-cpp"
}



================================================
FILE: after/template/c/assert.template
================================================
VimL:" assert File Template, Luc Hermitte, 24th Sep 2015
VimL:" hint: assert()
VimL: let s:value_start = '¡'
VimL: let s:value_end   = s:value_start
VimL: let s:marker_open  = '<+'
VimL: let s:marker_close = '+>'
VimL: call s:AddPostExpandCallback('lh#dev#import#add(&ft == "cpp" ? "<cassert>" : "<assert.h>")')
assert(¡s:Surround(1, '<+assertion+>')¡);<+s:TerminalPlaceHolder()+>


================================================
FILE: after/template/c/comment.template
================================================
VimL:" comment File Template, Luc Hermitte <hermitte {at} free {dot} fr>, mer. 20 juil. 2016 11:30:01 CEST
VimL:" hint: #if 0 (#else) #endif
VimL: let s:value_start = '¡'
VimL: let s:value_end   = s:value_start
VimL: let s:marker_open  = '<+'
VimL: let s:marker_close = '+>'
VimL: let s:reindent     = 1
MuT:  if s:content.count0 == 0
#if 0
<+s:Surround(1, lh#marker#txt("code;"))+>
#endif
MuT:  else
MuT:  let s:commented_lines = split(s:SurroundRaw(s:content.count0, lh#marker#txt("code;")), "\n")
VimL: " We store the lines into surround1&2 in order to avoid style application as s:Surround disables it
VimL: let s:content.surround1 = join(s:commented_lines[: (s:content.count0-1)], "\n")
VimL: let s:content.surround2 = join(s:commented_lines[(s:content.count0) :], "\n")
#if 1
<+s:Surround(1, lh#marker#txt("code;"))+>
#else
<+s:Surround(2, lh#marker#txt("code;"))+>
#endif
MuT:  endif



================================================
FILE: after/template/c/internals/c-header-content.template
================================================
VimL:" Typical C++ header content, Luc Hermitte, 05th Sep 2019
VimL:" override content for header files for OTK like projects
VimL: let s:default_text = empty(s:Args()) ? "" : (s:Args()[0])
VimL: call s:Include('namespace-name', 'cpp/internals')
MuT:  if !empty(s:namespace)
VimL:   call s:Include('namespace', 'cpp', {'content': s:default_text, 'included': 1})
MuT:  else
<+default_text+>
MuT:  endif
VimL: call s:Include('post-namespace-header-content', 'cpp/internals')


================================================
FILE: after/template/c/rand_init.template
================================================
VimL:" rand_init File Template, Luc Hermitte, 28th Oct 2014
VimL:" hint: srand(time(NULL));
VimL: let s:reindent     = 1
VimL: call s:AddPostExpandCallback('lh#dev#import#add_c_std("time")')
VimL: call s:AddPostExpandCallback('lh#dev#import#add_c_std("stdlib")')
srand(time(NULL));


================================================
FILE: after/template/c/realloc.template
================================================
VimL:" realloc File Template, Luc Hermitte, 20th Aug 2012
VimL:" hint: new_p = realloc(pn size); if (!new_p) {free(p); +reset all 
VimL: let s:marker_open  = '<+'
VimL: let s:marker_close = '+>'
VimL: let s:reindent     = 1
VimL: silent! unlet s:_args
VimL: let s:_args = empty(s:Args()) ? {} : (s:Args()[0])
VimL: if (! has_key(s:_args, "ptr"))     | let s:_args.ptr     = lh#marker#txt("p")    | endif
VimL: if (! has_key(s:_args, "lhs"))     | let s:_args.lhs     = "new_".s:_args.ptr | endif
VimL: if (! has_key(s:_args, "type"))    | let s:_args.type    = lh#marker#txt("T")    | endif
VimL: if (! has_key(s:_args, "count"))   | let s:_args.count   = lh#marker#txt("count")| endif
VimL: if (! has_key(s:_args, "size"))    | let s:_args.size    = s:_args.count." * sizeof(".s:_args.type.")" | endif
VimL: if (! has_key(s:_args, "realloc")) | let s:_args.realloc = "realloc"          | endif
VimL: if (! has_key(s:_args, "free"))    | let s:_args.free    = "free"             | endif
VimL: if (! has_key(s:_args, "macro"))   | let s:_args.macro   = ""                 | endif
VimL: if (! has_key(s:_args, "false"))   | let s:_args.false   = "false"            | endif
<+s:_args.type+> *<+s:_args.lhs+> = (<+s:_args.type+> *) <+s:_args.realloc+>(<+s:_args.ptr+>, <+s:_args.size+>);<+s:_args.macro+>
if (! <+s:_args.lhs+>) {<+s:_args.macro+>
	<+s:_args.free+>(<+s:_args.ptr+>);<+s:_args.macro+>
	<+s:_args.ptr+> = NULL;<+s:_args.macro+>
	<+s:_args.count+> = 0;<+s:_args.macro+>
	<+error_message+>;<+s:_args.macro+>
	return <+s:_args.false+>;<+s:_args.macro+>
}<+s:_args.macro+>
<+s:_args.ptr+> = <+s:_args.lhs+>;


================================================
FILE: after/template/cpp/abs-rel.template
================================================
VimL:" Absolute and relative Classes Template, Luc Hermitte
VimL:" Used to define Date and Duration, Point and Distance, ...
VimL:" hint: Absolute/Relative classes (e.g. point/distance, date/duration, ...)
VimL: let s:value_start = '¡'
VimL: let s:value_end   = '¡'
VimL: let s:reindent = 1
VimL: let s:marker_open  = '<+'
VimL: let s:marker_close = '+>'
VimL: let s:absclsname = inputdialog('Name of the "absolute" class ?')
VimL: let s:relclsname = inputdialog('Name of the "relative" class ?')
VimL: let s:sharedclsname = inputdialog('Name of the "shared" class ? (empty=none)', s:absclsname . lh#naming#param("Impl"))
VimL: let s:issharingimpl = ! empty(s:sharedclsname)
VimL: let s:defaultisenough = lh#ui#confirm( "Are the implicitly generated default constructor, copy-constructor, destructor, and assignement operatror enough?", "&Yes\n&No", 1) == 1
VimL: let s:istemplate = lh#ui#confirm("Are the classes template ?", "&Yes\n&No", 2) == 1
VimL: let s:tmpl_type = lh#marker#txt("T")
VimL: let s:tmpl_decl = lh#ui#if(s:istemplate, "template <".lh#marker#txt("typename")." ".s:tmpl_type."> ", "")
VimL: let s:tmpl = lh#ui#if(s:istemplate, "<".s:tmpl_type.">", "")
VimL: let s:tmpl2_type = lh#marker#txt("U")
VimL: let s:tmpl2_decl = lh#ui#if(s:istemplate, "template <".lh#marker#txt("typename")." ".s:tmpl2_type.">\n", "")
VimL: let s:tmpl2 = lh#ui#if(s:istemplate, "<".s:tmpl2_type.">", "")
VimL: let s:typename = lh#ui#if(s:istemplate, "typename ", "")
VimL: let s:lhs = lh#naming#param("lhs")
VimL: let s:rhs = lh#naming#param("rhs")
VimL: let s:coeff = lh#naming#param("coeff")
VimL:"
VimL:"
<+s:tmpl_decl+>class <+s:absclsname+>;
<+s:tmpl_decl+>class <+s:relclsname+>;
VimL: if s:issharingimpl | call s:Include('abs-rel-shared', 'cpp/internals') | endif
/**
 * <+lh#dox#brief('')+>
 *
 * <+doc+>
 *
 * <+@invariants+>
 *
 * <p><b>Semantics</b><br>
 * <li> Value, mathematical: it's an absolute position
 * <li> <+absolute position+>
 * <+ <li> sem+>
 *
 * @version ¡'$'¡revision$
 * <+lh#dox#author()+>
 */
VimL: let s:super = "DETAILS::".s:sharedclsname.s:tmpl
VimL: let s:inh = lh#ui#if(s:issharingimpl, "\n: ".s:super."(".lh#marker#txt("params").")", "\n".lh#marker#txt(" "))
<+s:tmpl_decl+>class ¡s:absclsname.lh#ui#if(s:issharingimpl, " : protected ".s:super, "")¡
{
public:
    friend class <+s:relclsname+><+s:tmpl+>;
    typedef ¡lh#ui#if(s:issharingimpl, s:typename.s:super."::scalar_type", "<+scalar_type+>")¡ scalar_type;

    /**@name Construction/destruction
     */
    //@{
    /** Initialisation constructor.
     */
    <+s:absclsname+>(<+parameters+>)¡lh#ui#if(s:istemplate, s:inh."{<++>}", ";")¡
    ¡lh#cpp#abs_rel#canonicalortodoxform(s:absclsname, ! s:defaultisenough)¡
    //@}

    /**@name Operators
     */
    //@{
    <+s:absclsname+> & operator+=(¡s:relclsname.s:tmpl¡ const& <+s:rhs+>)¡lh#ui#if(s:issharingimpl, " { this->add(".(s:rhs)."); return *this; }", lh#ui#if(s:istemplate, "<++>", ";"))¡
    <+s:absclsname+> & operator-=(¡s:relclsname.s:tmpl¡ const& <+s:rhs+>)¡lh#ui#if(s:issharingimpl, " { this->dec(".(s:rhs)."); return *this; }", lh#ui#if(s:istemplate, "<++>", ";"))¡

    static <+s:super+> const diff(<+s:absclsname+> const& <+s:lhs+>, <+s:absclsname+> const& <+s:rhs+>)
    {
        <+s:super+> tmp(<+s:lhs+>);
        tmp.dec(<+s:rhs+>);
        return tmp;
    }
    friend bool operator==(<+s:absclsname+> const& <+s:rhs+>, <+s:absclsname+> const& <+s:lhs+>)¡lh#ui#if(s:issharingimpl, "\n{ return ".s:absclsname."::isEqual(".(s:rhs).", ".(s:lhs)."); }", ';')¡
    //@}
};

/**
 * <+lh#dox#brief('')+>
 *
 * <+doc+>
 *
 * <+@invariants+>
 *
 * <p><b>Semantics</b><br>
 * <li> Value, mathematical: it's relative position
 * <li> <+relative position+>
 * <+ <li> sem+>
 *
 * @version ¡'$'¡revision$
 * <+lh#dox#author()+>
 */
<+s:tmpl_decl+>class ¡s:relclsname.lh#ui#if(s:issharingimpl, " : protected ".s:super, "")¡
{
public:
    friend class <+s:absclsname+><+s:tmpl+>;
    typedef ¡lh#ui#if(s:issharingimpl, s:typename.s:super."::scalar_type", "<+scalar_type+>")¡ scalar_type;

    /**@name Construction/destruction
     */
    //@{
    /** Initialisation constructor.
     */
    <+s:relclsname+>(<+parameters+>)¡lh#ui#if(s:istemplate, s:inh."{<++>}", ";")¡
    ¡lh#cpp#abs_rel#canonicalortodoxform(s:relclsname, ! s:defaultisenough)¡
    //@}

    /**@name Operators
     */
    //@{
    <+s:relclsname+> & operator+=(<+s:relclsname+> const& <+s:rhs+>)¡lh#ui#if(s:issharingimpl, " { this->add(".(s:rhs)."); return *this; }", ";")¡
    <+s:relclsname+> & operator-=(<+s:relclsname+> const& <+s:rhs+>)¡lh#ui#if(s:issharingimpl, " { this->dec(".(s:rhs)."); return *this; }", ";")¡
    <+s:relclsname+> & operator*=(scalar_type <+s:coeff+>)¡lh#ui#if(s:issharingimpl, "{ this->mult(".(s:coeff)."); return *this; }", ";")¡
    <+s:relclsname+> & operator/=(scalar_type <+s:coeff+>)¡lh#ui#if(s:issharingimpl, "{ this->div(".(s:coeff)."); return *this; }", ";")¡

    friend bool operator==(<+s:relclsname+> const& <+s:rhs+>, <+s:relclsname+> const& <+s:lhs+>)¡lh#ui#if(s:issharingimpl, "\n{ return ".s:relclsname."::isEqual(".(s:rhs).", ".(s:lhs)."); }", ";")¡

    <+s:tmpl2_decl+>friend ¡s:relclsname.s:tmpl2¡ const operator-(¡s:absclsname.s:tmpl2¡ const& <+s:lhs+>, ¡s:absclsname.s:tmpl2¡ const& <+s:rhs+>);
    //@}

    protected:
    explicit <+s:relclsname+>(<+s:super+> const& <+s:rhs+>) : <+s:super+>(<+s:rhs+>) {}
};

<+s:tmpl_decl+>inline
¡s:relclsname.s:tmpl¡ operator-(
        ¡s:absclsname.s:tmpl¡ const& <+s:lhs+>,
        ¡s:absclsname.s:tmpl¡ const& <+s:rhs+>)
{ return ¡s:relclsname.s:tmpl¡(¡s:absclsname.s:tmpl¡::diff(<+s:lhs+>, <+s:rhs+>)); }

<+s:tmpl_decl+>inline
¡s:absclsname.s:tmpl¡ operator+(
        ¡s:absclsname.s:tmpl¡        <+s:lhs+>,
        ¡s:relclsname.s:tmpl¡ const& <+s:rhs+>)
{ return <+s:lhs+> += <+s:rhs+>; }

<+s:tmpl_decl+>inline
¡s:absclsname.s:tmpl¡ operator+(
        ¡s:relclsname.s:tmpl¡ const& <+s:lhs+>,
        ¡s:absclsname.s:tmpl¡        <+s:rhs+>)
{ return <+s:rhs+> += <+s:lhs+>; }

<+s:tmpl_decl+>inline
¡s:absclsname.s:tmpl¡ operator-(
        ¡s:absclsname.s:tmpl¡        <+s:lhs+>,
        ¡s:relclsname.s:tmpl¡ const& <+s:rhs+>)
{ return <+s:lhs+> -= <+s:rhs+>; }

#if 0
// Makes no sense
<+s:tmpl_decl+>inline
¡s:absclsname.s:tmpl¡ const operator-(
        ¡s:relclsname.s:tmpl¡ const& <+s:lhs+>,
        ¡s:absclsname.s:tmpl¡ const& <+s:rhs+>);
#endif

<+s:tmpl_decl+>inline
¡s:relclsname.s:tmpl¡ operator+(
        ¡s:relclsname.s:tmpl¡        <+s:lhs+>,
        ¡s:relclsname.s:tmpl¡ const& <+s:rhs+>)
{ return <+s:lhs+> += <+s:rhs+>; }

<+s:tmpl_decl+>inline
¡s:relclsname.s:tmpl¡ operator-(
        ¡s:relclsname.s:tmpl¡        <+s:lhs+>,
        ¡s:relclsname.s:tmpl¡ const& <+s:rhs+>)
{ return <+s:lhs+> -= <+s:rhs+>; }

<+s:tmpl_decl+>inline
¡s:relclsname.s:tmpl¡ operator*(
        ¡s:relclsname.s:tmpl¡              <+s:lhs+>,
        ¡s:typename.s:relclsname.s:tmpl¡::scalar_type <+s:rhs+>)
{ return <+s:lhs+> *= <+s:rhs+>; }

<+s:tmpl_decl+>inline
¡s:relclsname.s:tmpl¡ operator*(
        ¡s:typename.s:relclsname.s:tmpl¡::scalar_type <+s:lhs+>,
        ¡s:relclsname.s:tmpl¡              <+s:rhs+>)
{ return <+s:rhs+> *= <+s:lhs+>; }

<+s:tmpl_decl+>inline
¡s:relclsname.s:tmpl¡ operator/(
        ¡s:relclsname.s:tmpl¡              <+s:lhs+>,
        ¡s:typename.s:relclsname.s:tmpl¡::scalar_type <+s:rhs+>)
{ return <+s:lhs+> /= <+s:rhs+>; }

<+s:tmpl_decl+>inline
¡s:relclsname.s:tmpl¡ operator/(
        ¡s:typename.s:relclsname.s:tmpl¡::scalar_type <+s:lhs+>,
        ¡s:relclsname.s:tmpl¡              <+s:rhs+>)
{ return <+s:rhs+> /= <+s:lhs+>; }



================================================
FILE: after/template/cpp/abstract-class.template
================================================
VimL:" abstract-class File Template, Luc Hermitte <hermitte {at} free {dot} fr>, 25th Nov 2015
VimL:" hint: Abstract (base) class to inherit from
MuT:  let s:destructor = s:Param('destructor', {})
VimL: " -- Override any previous setting on visibility and 'how'
VimL: let s:destructor['visibility'] = 'public'
VimL: let s:destructor['how'] = 'pure'
VimL: " --- Defines Doxygen comments
MuT:  let s:parameters = s:Param('cls_parameters', {})
VimL: call lh#dict#add_new(s:parameters, {'comments': {}})
MuT:  let s:cls_comments = s:parameters.comments
VimL: " Don't add "Abstract" if this is an interface
MuT:  if index(get(s:cls_comments, 'semantics', []), 'Interface') < 0
VimL:   let s:cls_comments.semantics = get(s:cls_comments, 'semantics', [])+['Abstract']
MuT:  endif
VimL: " --- Insert the skeleton built
VimL: call s:Include('base-class', 'cpp', {'cls_parameters': s:parameters})


================================================
FILE: after/template/cpp/array_size.template
================================================
VimL:" array_size definition File Template, Luc Hermitte, 25th Apr 2014
VimL:" hint: std::extent<decltype(tab)>::value
VimL: let s:value_start = '¡'
VimL: let s:value_end   = s:value_start
VimL: let s:marker_open  = '<+'
VimL: let s:marker_close = '+>'
MuT:  let s:array_size = lh#ft#option#get('array_size', &ft)
MuT:  if lh#option#is_unset(s:array_size) && lh#cpp#use_cpp17()
MuT:      let s:array_size = {'file': '<iterator>', 'funcname': 'std::size(%1)'}
MuT:  endif
MuT:  if lh#option#is_set(s:array_size)
VimL:     call s:AddPostExpandCallback('lh#dev#import#add(s:array_size.file)')
MuT:      let s:_array_size = s:array_size.funcname
MuT:  elseif lh#cpp#use_cpp11()
VimL:     call s:AddPostExpandCallback('lh#dev#import#add("<type_traits>")')
MuT:      let s:_array_size = 'std::extent<decltype(%1)>::value'
MuT:      let s:restore_style = lh#on#exit().restore('s:content.can_apply_style')
VimL:     let s:content.can_apply_style = 0
// You may want instead to define the missing std::size() in a header file
//   template <typename T, std::size_t N>
//   constexpr std::size_t size(T (&)[N]) noexcept { return N ;}
// And include this file instead.
// In you have such a file ready to be used, please set
//    let b:cpp_array_size = {'file': 'theheader to include', 'funcname': 'std::size(%1)' }
// in your vim project configuration file (_vimrc_local.vim...)
VimL:      call s:restore_style.finalize()
MuT:  else
MuT:      let s:restore_style = lh#on#exit().restore('s:content.can_apply_style')
VimL:     let s:content.can_apply_style = 0
// You may want instead to define the following in a header file
// and include this file instead.
// Then set
//    let b:cpp_array_size = {'file': 'theheader to include', 'funcname': 'array_size(%1)' }
// in your vim project configuration file (_vimrc_local.vim...)
VimL:      call s:restore_style.finalize()
namespace{
    template<typename T, std::size_t N>
        char (&array_size_helper(T (&)[N]))[N];
}// namespace
#define array_size(array) (sizeof ::array_size_helper(array))
MuT:      let s:_array_size = 'array_size(%1)'
MuT:  endif
<+lh#fmt#printf(s:_array_size, s:Surround(1, s:Param("array", lh#marker#txt('array'))))+>


================================================
FILE: after/template/cpp/assignment-operator.template
================================================
VimL:" assignment-operator File Template, Luc Hermitte, 21st Aug 2011
VimL:" hint: T& operator=(T const&);
VimL: "TODO: support noexcept
VimL: let s:marker_open  = "<+"
VimL: let s:marker_close = "+>"
VimL: let s:reindent     = 1
VimL: call s:Include('get-class-name', 'cpp/internals')
VimL: let s:how = get(s:Param("assignment-operator", {}), "how", "")
MuT:  if s:how =~ "deleted\\|defaulted"
<+s:clsname+>& operator=(<+s:clsname+> const&) <+lh#cpp#snippets#{s:how}()+>;
MuT:  else
MuT:    let s:use_copyandswap0 =  s:Param('use_copy_and_swap', lh#option#get('cpp_use_copy_and_swap'))
VimL:   let s:use_copyandswap =  lh#option#is_set(s:use_copyandswap0) ? s:use_copyandswap0 : lh#ui#confirm("Use copy-and-swap idiom?", "Yes\nNo", 1)
MuT:    if 1 == s:use_copyandswap
VimL:     call s:Include("copy-and-swap","cpp", s:clsname)
MuT:    else
VimL:     let s:rhs = lh#naming#param("rhs")
VimL:     let s:fn_comments = { }
VimL:     let s:fn_comments.brief = "Assignment operator"
VimL:     let s:fn_comments.param = [{"dir": "in", "name": (s:rhs), "text": "source data to be copied." } ]
VimL:     let s:fn_comments.throw = {"optional": 1}
VimL:     call s:Include("function-comment", "cpp/internals",s:fn_comments)
MuT:      let s:attributes = s:Param("attributes", lh#option#unset())
MuT:      if lh#option#is_set(s:attributes) && !empty(s:attributes)
MuT:        let s:definition = '{'.join(map(copy(s:attributes), 'lh#naming#member(v:val.name)." = ".lh#cpp#snippets#duplicate_param(s:rhs.".".lh#naming#member(v:val.name), v:val.type).";"'), "\n").'}'
MuT:      else
MuT:        let s:definition = ';'
MuT:      endif
<+s:clsname+>& operator=(<+s:clsname+> const& <+s:rhs+>)<+s:definition+>
MuT:    endif
MuT: endif


================================================
FILE: after/template/cpp/auto_ptr-instance.template
================================================
VimL:" unique_ptr File Template, Luc Hermitte, 22nd May 2014
VimL:" hint: std::auto_ptr<T> ptr(new T(args));
VimL: let s:value_start = '¡'
VimL: let s:value_end   = s:value_start
VimL: let s:marker_open  = '<+'
VimL: let s:marker_close = '+>'
VimL: call s:AddPostExpandCallback('lh#dev#import#add("<memory>")')
std::auto_ptr<¡s:Surround(1, '<+type+>')¡> <+ptr+>(new ¡s:Surround(1, '<+type+>')¡(<+args+>));


================================================
FILE: after/template/cpp/auto_ptr.template
================================================
VimL:" unique_ptr File Template, Luc Hermitte, 22nd May 2014
VimL:" hint: std::auto_ptr<>
VimL: let s:value_start = '¡'
VimL: let s:value_end   = s:value_start
VimL: let s:marker_open  = '<+'
VimL: let s:marker_close = '+>'
VimL: call s:AddPostExpandCallback('lh#dev#import#add("<memory>")')
std::auto_ptr<¡s:Surround(1, '<+type+>')¡><+s:TerminalPlaceHolder()+>


================================================
FILE: after/template/cpp/b-e.template
================================================
VimL:" b-e File Template, Luc Hermitte, 30th Jun 2011
VimL:" hint: <+container+>.begin(), <+container+>.end()
VimL: let s:marker_open  = '<+'
VimL: let s:marker_close = '+>'
VimL: call s:Include('get-b-e', 'cpp/internals')
<+s:begin+>, <+s:end+><++>


================================================
FILE: after/template/cpp/base-class-non-virtual.template
================================================
VimL:" base-class-non-virtual File Template, Luc Hermitte <hermitte {at} free {dot} fr>, 25th Nov 2015
VimL:" hint: Base class to inherit from, but not delete -- Non-copiable entity
VimL: let s:value_start = '¡'
VimL: let s:value_end   = s:value_start
VimL: let s:marker_open  = '<+'
VimL: let s:marker_close = '+>'
VimL: " Set default-constructor to protected if not already set
MuT:  let s:default_constructor = s:Param('default-constructor', {})
VimL: call lh#dict#add_new(s:default_constructor, {'visibility': 'protected'})
VimL: " Force destructor to protected, (and not how)
VimL: let s:destructor = s:Param('destructor', {})
VimL: let s:destructor['visibility'] = 'protected'
VimL: call s:Include('entity-class', 'cpp')


================================================
FILE: after/template/cpp/base-class.template
================================================
VimL:" base-class File Template, Luc Hermitte <hermitte {at} free {dot} fr>, 25th Nov 2015
VimL:" hint: Base class to inherit from -- Not necessarily abstract, Non-copiable entity
VimL: " Set default-consructor to protected if not already set
MuT:  let s:default_constructor = s:Param('default-constructor', {})
VimL: call lh#dict#add_new(s:default_constructor, {'visibility': 'protected'})
VimL: " Set destructor to public, (and no how), if not already set
MuT:  let s:destructor = s:Param('destructor', {})
VimL: call lh#dict#add_new(s:destructor, {'how': ''})
VimL: call lh#dict#add_new(s:destructor, {'visibility': 'public'})
VimL: " Force virtual!
VimL: let s:destructor['virtual'] = 1
VimL: call s:Include('entity-class', 'cpp')


================================================
FILE: after/template/cpp/benchmark.template
================================================
VimL:" google-benchmark File Template, Luc Hermitte, 27th Oct 2015
VimL:" hint: static void BM_<+test+>(benchmark::State & state) {
VimL: let s:value_start = '¡'
VimL: let s:value_end   = s:value_start
VimL: let s:marker_open  = '<+'
VimL: let s:marker_close = '+>'
static void BM_<+bench+>(benchmark::State & state) {
    while (state.KeepRunning()) {
        <++>
    }
}
BENCHMARK(BM_<+bench+>);


================================================
FILE: after/template/cpp/bool-operator.template
================================================
VimL:" bool-operator Template, Luc Hermitte
VimL:" hint: safe bool operator
VimL: let s:reindent     = 1
VimL: let s:marker_open  = '<+'
VimL: let s:marker_close = '+>'
VimL:"
VimL:" @pre must be within a class/struct context
VimL:" @todo propose other approaches (Don Box's, safe_bool, void*, ...)

struct boolean{ int i;};
/** Is the data <+valid+> ?.
 * 
 * Hack to provide a boolean operator that is convertible only to a
 * boolean expression to be used in \c if tests.
 * @see <em>Imperfect C++</em>, Matthew Wilson, Addisson-Welsey, 24.6
 * <+@since +>
 */
operator int boolean ::* () const<+C_nl_before_curlyB()+>{
    return <+isValid()+> ? &boolean::i : 0;
}



================================================
FILE: after/template/cpp/catch.template
================================================
VimL:"{catch(...){...}} Template-File, Luc Hermitte
VimL:" hint: catch(...){...}
VimL: let s:value_start  = '¡'
VimL: let s:value_end    = '¡'
VimL: let s:reindent     = 1 
VimL: let s:marker_open  = '<+'
VimL: let s:marker_close = '+>'
catch(<+...+>){
    ¡s:Surround(1, '<+catch-code+>')¡
}<++>


================================================
FILE: after/template/cpp/cerr.template
================================================
VimL:" cerr File Template, Luc Hermitte, 28th Apr 2014
VimL:" hint: std::cerr
VimL: let s:value_start = '¡'
VimL: let s:value_end   = s:value_start
VimL: let s:marker_open  = '<+'
VimL: let s:marker_close = '+>'
VimL: call s:AddPostExpandCallback('lh#dev#import#add("<iostream>")')
std::cerr << <++>;


================================================
FILE: after/template/cpp/chrono-how-long.template
================================================
VimL:" chrono-how-long File Template, Luc Hermitte <hermitte {at} free {dot} fr>, 24th Apr 2019
VimL:" hint: Compute duration
VimL: let s:value_start = '¡'
VimL: let s:value_end   = s:value_start
VimL: let s:marker_open  = '<+'
VimL: let s:marker_close = '+>'
VimL: let s:reindent     = 1
VimL: call s:AddPostExpandCallback('lh#dev#import#add("<chrono>")')
const auto <+start+> = std::chrono::system_clock::now();
¡s:Surround(1, '<++>')¡
const auto <+end+> = std::chrono::system_clock::now();
const auto elapsed_seconds = std::chrono::duration<double>(<+end+> - <+start+>).count();


================================================
FILE: after/template/cpp/cin.template
================================================
VimL:" cin File Template, Luc Hermitte, 28th Apr 2014
VimL:" hint: std::cin
VimL: let s:value_start = '¡'
VimL: let s:value_end   = s:value_start
VimL: let s:marker_open  = '<+'
VimL: let s:marker_close = '+>'
VimL: call s:AddPostExpandCallback('lh#dev#import#add("<iostream>")')
std::cin >> <++>;


================================================
FILE: after/template/cpp/class.template
================================================
VimL:" C++ Class Template, Luc Hermitte
VimL:" hint: Simplistic class snippet -- unaware of semantics
VimL: let s:value_start = '¡'
VimL: let s:value_end   = '¡'
VimL: let s:reindent = 1
VimL: let s:marker_open  = '<+'
VimL: let s:marker_close = '+>'
MuT:  let s:parameters = s:Param('cls_parameters', {})
VimL: " --- in case the class name is already known, no need to extract it
VimL: call s:Include('get-class-name', 'cpp/internals')
VimL: " --- Defines Doxygen comments
MuT:  let s:cls_comments = lh#dict#add_new(s:parameters, {'comments': {}}).comments
MuT:  let s:cls_comments = s:parameters.comments
VimL: " --- Insert the skeleton built
VimL: call s:Include('class-skeleton', 'cpp/internals', s:parameters)


================================================
FILE: after/template/cpp/clonable-class.template
================================================
VimL:" clonable-class File Template, Luc Hermitte <hermitte {at} free {dot} fr>, 27th Nov 2015
VimL:" hint: Base class with clone function -- duplicable object within a hierarchy
MuT:  "let s:clsname     = s:Param('clsname', lh#marker#txt(lh#naming#type(expand('%:t:r'))))
VimL: call s:Include('get-class-name', 'cpp/internals')
MuT:  let s:functions = s:Param('functions', lh#cpp#snippets#new_function_list())
MuT:  let s:parents     = s:Param('parents', [])
MuT:  let s:pub_parents = filter(copy(s:parents), '!empty(lh#cpp#snippets#_filter_functions(v:val, "public"))')
MuT:  let s:clone_funcname = lh#naming#function('clone')
VimL: " s:clsname in not yet under ctags DB, but fortunately we know the first level parents
MuT:  let s:root_clones = lh#cpp#override#root_function(lh#list#flatten(map(copy(s:pub_parents), 'keys(v:val)')), s:clone_funcname)
VimL: let g:root_clones = s:root_clones
MuT:  if !empty(s:root_clones)
MuT:    let s:override = ' '.lh#cpp#snippets#override()
MuT:    let s:static_type = s:root_clones[-1].class
VimL:   call s:functions.insert({'kind': 'init-constructor', 'parameters': lh#option#unset()})
VimL:   " Remove default-consructor unless already set visible
MuT:    let s:default_constructor = s:Param('default-constructor', {})
VimL:   call lh#dict#add_new(s:default_constructor, {'visibility': 'none'})
MuT:  else
MuT:    let s:override = ''
MuT:    let s:static_type = s:clsname
MuT:  endif
MuT:  let s:ret_type = lh#cpp#snippets#return_ptr_type(s:static_type)
MuT:  let s:copy_constructor = s:Param('copy-constructor', {})
VimL: let s:copy_constructor.visibility = 'protected'
VimL: " TODO "how" will eventually depend on detected non-copyable attributes
VimL: let s:copy_constructor.how        = 'defaulted'
VimL: " TODO: if abstract class => pure virtual clone function
VimL: call s:functions.add([{'signature': 'virtual '.s:ret_type.' '.s:clone_funcname.'() const'.s:override, 'implementation': 'return '.lh#cpp#snippets#make_ptr(s:clsname, s:static_type, '*this').';'}])
VimL: " --- Defines Doxygen comments
MuT:  let s:parameters = s:Param('cls_parameters', {})
VimL: call lh#dict#add_new(s:parameters, {'comments': {}})
MuT:  let s:cls_comments = s:parameters.comments
VimL: let s:cls_comments.semantics = get(s:cls_comments, 'semantics', [])+['Clonable (but not assignable)']
VimL: " --- Insert the skeleton built
VimL: call s:Include('base-class', 'cpp')


================================================
FILE: after/template/cpp/copy-and-swap.template
================================================
VimL:" copy-and-swap File Template, Luc Hermitte, 21st Aug 2011
VimL:" hint: assign op + swap
VimL: " todo: recognize C++11 in order to add the proper nothrow specification
VimL: let s:marker_open  = '<+'
VimL: let s:marker_close = '+>'
VimL: let s:reindent     = 1
VimL: " in case the class name is already known, no need to extract it
VimL: call s:Include('get-class-name', 'cpp/internals')
VimL:"
VimL: let s:rhs = lh#naming#param("rhs")
VimL: let s:fn_comments = lh#dox#new_function("Assignment operator")
VimL: let s:fn_comments.text  = []
VimL: let s:fn_comments.note  = [] " => empty line
VimL: let s:fn_comments.note += ["based on copy-and-swap idiom, with copy-elision exploited"]
VimL: let s:fn_comments.note += ["exception-safe"]
VimL: let s:fn_comments.param = [{"dir": "in", "name": (s:rhs), "text": "source data to be copied." } ]
VimL: let s:fn_comments.throw = {"optional": 1}
VimL: call s:Include("function-comment", "cpp/internals",s:fn_comments)
<+s:clsname+>& operator=(<+s:clsname+> <+s:rhs+>){
    this->swap(<+s:rhs+>);
    return *this;
}
VimL: call s:Include('swap-function', 'cpp')


================================================
FILE: after/template/cpp/copy-back_inserter.template
================================================
VimL:" copy-back_inserter File Template, Luc Hermitte, 23rd May 2014
VimL:" hint: std::copy(orig.begin(), orig.end(), std::back_inserter(dest));
VimL: let s:value_start = '¡'
VimL: let s:value_end   = s:value_start
VimL: let s:marker_open  = '<+'
VimL: let s:marker_close = '+>'
VimL: let s:reindent     = 1
VimL: call s:AddPostExpandCallback('lh#dev#import#add("<algorithm>")')
VimL: call s:AddPostExpandCallback('lh#dev#import#add("<iterator>")')
VimL: let s:orig = s:Surround(1, s:Param('origin', lh#marker#txt('origin')))
VimL: let s:dest = s:Surround(2, s:Param('destination', lh#marker#txt('destination')))
std::copy(<+s:orig+>.begin(),<+s:orig+>.end(), std::back_inserter(<+s:dest+>));
VimL: unlet s:orig
VimL: unlet s:dest


================================================
FILE: after/template/cpp/copy-constructor.template
================================================
VimL:" copy-constructor File Template, Luc Hermitte, 21st Aug 2011
VimL:" hint: T(T const&);
VimL: let s:marker_open  = "<+"
VimL: let s:marker_close = "+>"
VimL: let s:reindent     = 1
VimL: call s:Include('get-class-name', 'cpp/internals')
VimL: let s:how = get(s:Param("copy-constructor", {}), "how", "")
MuT:  if s:how =~ "deleted\\|defaulted"
<+s:clsname+>(<+s:clsname+> const&) <+lh#cpp#snippets#{s:how}()+>;
MuT:  else
VimL:   let s:lead = lh#dox#comment_leading_char()." "
VimL:   let s:param = lh#naming#param("rhs")
VimL:   let s:fn_comments = { }
VimL:   let s:fn_comments.brief = "Copy constructor."
VimL:   let s:fn_comments.throw = {"optional": 1}
VimL:   " let s:fn_comments.text  = []
VimL:   let s:fn_comments.param = [{"dir": "in", "name": (s:param), "text": "source data to be copied." } ]
VimL:   call s:Include("function-comment", "cpp/internals",s:fn_comments)
MuT:    let s:attributes = s:Param("attributes", lh#option#unset())
MuT:    if lh#option#is_set(s:attributes) && !empty(s:attributes)
MuT:      let s:definition = (len(s:attributes)>1?"\n": "").": ".join(map(copy(s:attributes), 'lh#naming#member(v:val.name)."(".lh#cpp#snippets#duplicate_param(s:param.".".lh#naming#member(v:val.name), v:val.type).")"'), "\n, ").'{}'
MuT:    else
MuT:      let s:definition = ';'
MuT:    endif
<+s:clsname+>(<+s:clsname+> const& <+s:param+>)<+s:definition+>
MuT:  endif


================================================
FILE: after/template/cpp/copy.template
================================================
VimL:" std::copy File Template, Luc Hermitte, 04th Nov 2015
VimL:" hint: std::copy(first, last, dest)
VimL: let s:value_start = '¡'
VimL: let s:value_end   = s:value_start
VimL: let s:marker_open  = '<+'
VimL: let s:marker_close = '+>'
VimL: call s:AddPostExpandCallback('lh#dev#import#add("<algorithm>")')
MuT:  let s:container = s:SurroundableParam('container', 1)
std::copy(<+s:container+>.begin(),<+s:container+>.end(), <+dest+>);
VimL: unlet s:container


================================================
FILE: after/template/cpp/cout.template
================================================
VimL:" cout File Template, Luc Hermitte, 28th Apr 2014
VimL:" hint: std::cout
VimL: let s:value_start = '¡'
VimL: let s:value_end   = s:value_start
VimL: let s:marker_open  = '<+'
VimL: let s:marker_close = '+>'
VimL: call s:AddPostExpandCallback('lh#dev#import#add("<iostream>")')
std::cout << <++>;


================================================
FILE: after/template/cpp/default-constructor.template
================================================
VimL:" default-constructor File Template, Luc Hermitte, 21st Aug 2011
VimL:" hint: T();
VimL: let s:marker_open  = "<+"
VimL: let s:marker_close = "+>"
VimL: let s:reindent     = 1
VimL: call s:Include('get-class-name', 'cpp/internals')
VimL: let s:lead = lh#dox#comment_leading_char().' '
VimL: let s:default_constructor = s:Param('default-constructor', {})
VimL: let s:how = get(s:default_constructor, 'how', '')
MuT:  if s:how !~ 'defaulted\|deleted'
MuT:    let s:fn_comments = get(s:default_constructor, 'comments', {})
VimL:   call lh#dict#add_new(s:fn_comments, {'brief': 'Default constructor.'})
VimL:   call lh#dict#add_new(s:fn_comments, {'throw': {'optional': 1}})
VimL:   call s:Include('function-comment', 'cpp/internals',s:fn_comments)
MuT:  else
VimL:   let s:how = ' '.lh#cpp#snippets#{s:how}()
MuT:  endif
<+s:clsname+>()<+s:how+>;


================================================
FILE: after/template/cpp/destructor.template
================================================
VimL:" destructor File Template, Luc Hermitte, 23rd Mar 2012
VimL:" hint: ~T();
VimL: let s:marker_open  = "<+"
VimL: let s:marker_close = "+>"
VimL: let s:reindent     = 1
VimL: call s:Include('get-class-name', 'cpp/internals')
MuT:  let s:destructor = s:Param('destructor', lh#option#unset())
MuT:  if lh#option#is_set(s:destructor)
MuT:      let s:virtual    = get(s:destructor, 'virtual', 0)
MuT:      let s:how        = get(s:destructor, 'how', '')
VimL:     let s:visibility = get(s:destructor, 'visibility', 'public')
VimL:     " Let's suppose s:clsname is set
MuT:  else
MuT:    let s:virtual      = lh#marker#txt('virtual ')
VimL:   let s:how          = ''
VimL:   " TODO: autodetect last visibility
VimL:   let s:visibility   = 'public'
MuT:  endif
MuT:  let s:virtual = type(s:virtual) == type('str') ? s:virtual : ((s:virtual) ? 'virtual ' : '')
MuT:  let s:how = s:how =~ '\vpure|deleted|defaulted' ? ' '.lh#cpp#snippets#{s:how}() : ''
MuT:  let s:fn_comments = get(s:destructor, 'comments', {})
VimL: call lh#dict#add_new(s:fn_comments, {'brief': substitute(s:virtual.'Destructor.', '\v(.)(.*)', '\u\1\L\2', '')})
MuT:  if s:visibility == 'protected'
VimL:     let s:fn_comments.note = ['This class is not meant to be destroyed polymorphically']
MuT:  elseif empty(s:virtual)
VimL:     let s:fn_comments.warning = ['this class is not meant to be publicly inherited']
MuT:  endif
VimL: call lh#dict#add_new(s:fn_comments, {'throw': 'Nothing'})
VimL: " let s:fn_comments.text  = []
VimL: call s:Include('function-comment', 'cpp/internals',s:fn_comments)
<+s:virtual+>~<+s:clsname+>()<+s:how+>;


================================================
FILE: after/template/cpp/empty-exception-class.template
================================================
VimL:" empty-exception-class File Template, Luc Hermitte <hermitte {at} free {dot} fr>, 27th Nov 2015
VimL:" hint: Minimalist exception class
VimL: let s:default_constructor = s:Param("default-constructor", {"visibility": "none"})
VimL: let s:destructor = s:Param("destructor", {})
VimL: let s:destructor.virtual = 1
MuT:  let s:parents = s:Param("parents", [])
MuT:  let s:default_exception = lh#option#get('cpp_root_exception', {"std::runtime_error": {"includes": "<stdexcept>"}})
MuT:  let s:parent_exception = s:Param("root-exception", s:default_exception)
VimL: let s:parents += [s:parent_exception]
VimL: call s:Include('list-constructors', 'cpp/internals')
MuT:  let s:functions = s:Param("functions", lh#cpp#snippets#new_function_list())
MuT:  if lh#cpp#use_cpp11() && empty(s:constructors)
VimL:   call s:functions.insert({"signature": "using ". lh#cpp#snippets#constructor_name(s:parent_exception) })
MuT:  else
VimL:   " override any previous "parameters" argument
VimL:   " TODO: search for new attributes => parameters ; and merge with parent parameters
VimL:   call s:functions.insert({"kind": "init-constructor", 'parameters': lh#option#unset()})
MuT:  endif
VimL: " --- in case the class name is already known, no need to extract it
VimL: call s:Include('get-class-name', 'cpp/internals')
VimL: " --- Defines Doxygen comments
MuT:  let s:parameters = s:Param('cls_parameters', {})
VimL: call lh#dict#add_new(s:parameters, {'comments': {}, 'copyable': 1})
MuT:  let s:cls_comments = s:parameters.comments
VimL: let s:cls_comments.semantics = get(s:cls_comments, 'semantics', [])
VimL: let s:cls_comments.semantics += ['Exception class', 'Copyable']
VimL: " --- Insert the skeleton built
VimL: call s:Include('class-skeleton', 'cpp/internals', s:parameters)


================================================
FILE: after/template/cpp/ends_with.template
================================================
VimL:" ends_with File Template, Luc Hermitte <hermitte at free.fr>, 28th May 2014
VimL:" hint: boost::algorithm::ends_with
VimL: let s:value_start = '¡'
VimL: let s:value_end   = s:value_start
VimL: let s:marker_open  = '<+'
VimL: let s:marker_close = '+>'
VimL: call s:AddPostExpandCallback('lh#dev#import#add("<boost/algorithm/string/predicate.hpp>")')
boost::algorithm::ends_with(<+input+>, <+prefix_searched+>)


================================================
FILE: after/template/cpp/entity-class.template
================================================
VimL:" entity-class File Template, Luc Hermitte <hermitte {at} free {dot} fr>, lun. 19 déc. 2016 17:14:18 CET
VimL:" hint: Entity class -- non copyable
VimL: let s:value_start = '¡'
VimL: let s:value_end   = s:value_start
VimL: let s:marker_open  = '<+'
VimL: let s:marker_close = '+>'
MuT:  let s:parameters = s:Param('cls_parameters', {})
VimL: call lh#dict#add_new(s:parameters, {'noncopyable': 1, 'comments': {}})
VimL: " --- in case the class name is already known, no need to extract it
VimL: call s:Include('get-class-name', 'cpp/internals')
VimL: " --- Defines Doxygen comments
MuT:  let s:cls_comments = s:parameters.comments
VimL: let s:cls_comments.semantics = get(s:cls_comments, 'semantics', [])
MuT:  if match(s:cls_comments.semantics, 'Clonable') < 0
VimL:    let s:cls_comments.semantics += ['Entity','Non-copyable']
MuT:  endif
VimL: " --- Insert the skeleton built
VimL: call s:Include("class-skeleton", "cpp/internals", s:parameters)


================================================
FILE: after/template/cpp/enum.template
================================================
VimL:" Enum definition Template, Luc Hermitte
VimL: let s:value_start = '¡'
VimL:" hint: struct Enum { enum type { ... } };
VimL: let s:value_end   = '¡'
VimL: let s:reindent = 1
VimL: let s:marker_open  = '<+'
VimL: let s:marker_close = '+>'
VimL: let s:enum_name = inputdialog('Name of the enum class ?', lh#marker#txt(expand('%:t:r')))
struct ¡s:enum_name¡ {
    enum type { <+values+>, MAX__ };
    static type next(type e_) {
        assert(e_ < MAX__);
        return type(e_+1);
    }
    static char const* to_string(type e_);
    static type to_enum(std::string const& s_);
};

inline
¡s:enum_name¡::type& operator++(¡s:enum_name¡::type& e_) {
    return e_ = ¡s:enum_name¡::next(e_);
}

inline
¡s:enum_name¡::type operator++(¡s:enum_name¡::type&e_, int) {
    const ¡s:enum_name¡::type tmp = e_;
    e_ = ¡s:enum_name¡::next(e_);
    return tmp;
}


================================================
FILE: after/template/cpp/enum2-impl.template
================================================
VimL:" enum2-impl File Template, Luc Hermitte, 23rd Apr 2014
VimL:" hint: enum2 code that goes into .cpp files
VimL: let s:value_start = '¡'
VimL: let s:value_end   = s:value_start
VimL: let s:marker_open  = '<+'
VimL: let s:marker_close = '+>'
VimL: " let g:args = s:args
MuT:  let s:enum_name   = s:Param('name', lh#marker#txt(lh#naming#type(expand('%:t:r'))))
MuT:  let s:scope       = s:Param('scope', '')
MuT:  let s:values      = map(s:Param('values', [lh#marker#txt('values')]), '"\"".v:val."\""')
MuT:  let s:lhs_        = lh#naming#param("lhs")
MuT:  let s:rhs_        = lh#naming#param("rhs")
MuT:  let s:value_      = lh#naming#param("value")
MuT:  let s:m_value     = lh#naming#member("value")
MuT:  let s:tmp         = lh#naming#local("tmp")
MuT:  let s:range       = s:Param('range', lh#naming#function("range"))
MuT:  let s:RangeType   = s:Param('RangeType', lh#naming#type("range"))
MuT:  let s:iterable    = s:Param("iterable", 0)
MuT:  let s:to_string   = lh#naming#function("to_string")
MuT:  let s:to_internal = lh#naming#function("to_internal")
MuT:  let s:max         = lh#naming#function("max")
MuT:  let s:type        = lh#naming#type("type")
MuT:  let s:str_param   = lh#naming#param("s")
MuT:  let s:k_strings   = lh#naming#constant(s:enum_name.'_strings')
VimL: call s:AddPostExpandCallback('lh#dev#import#add("<algorithm>")')
MuT:  let s:restore_options = lh#on#exit().restore_option('cpp_begin_end_style')
MuT:  if lh#cpp#use_cpp11()
VimL:   call s:AddPostExpandCallback('lh#dev#import#add("<type_traits>")')
VimL:   let b:cpp_begin_end_style = lh#option#get('cpp_begin_end_style', 'std')
MuT:  else
VimL:   let b:cpp_begin_end_style = lh#option#get('cpp_begin_end_style', 'boost')
MuT:  endif
VimL: call s:Include('get-b-e', 'cpp/internals', {'container': '::'.s:k_strings})

namespace  { // Anonymous namespace
    typedef char const* const* strings_iterator;
    static char const* const <+s:k_strings+>[] =
    { <+join(s:values, ', ')+> };
} // Anonymous namespace //  namespaces


<+s:scope+><+s:enum_name+>::<+s:enum_name+>(std::string const& <+s:str_param+>)
{
    strings_iterator const <+s:enum_name+>_it = std::find(<+s:begin+>,<+s:end+>, <+s:str_param+>);
    if (<+s:enum_name+>_it == <+s:end+>) {
VimL: call s:Include('throw', 'cpp', '"Cannot decode '.s:enum_name.' name `"+'.s:str_param.'+"`"')
    }
    <+s:m_value+> = <+s:type+>(std::distance(<+s:begin+>, <+s:enum_name+>_it));
    assert(<+s:m_value+> < MAX__);
}

VimL: call s:Include('array_size', 'cpp')

char const* <+s:scope+><+s:enum_name+>::<+s:to_string+>() const
{
VimL: call s:Include('static_assert', 'cpp', {'condition': 'MAX__ == '.lh#fmt#printf(s:_array_size,'::'.s:k_strings), 'message': '"Array size mismatches number of elements in enum"'})
    assert(<+s:m_value+> != UNDEFINED__); // Yes, I know UNDEFINED__ > MAX__
    assert(<+s:m_value+> < MAX__);
    return <+s:k_strings+>[<+s:m_value+>];
}
MuT:  if s:iterable && lh#cpp#use_cpp11()

/*static*/ <+s:scope+><+s:enum_name+>::<+s:RangeType+> <+s:scope+><+s:enum_name+>::<+s:range+>() { return <+s:RangeType+>(); }
MuT:  endif

VimL: silent! unlet s:values
VimL: call s:restore_options.finalize()


================================================
FILE: after/template/cpp/enum2.template
================================================
VimL:" safe-Enum definition Template, Luc Hermitte
VimL: let s:value_start = '¡'
VimL:" hint: struct Enum { enum type { ... } ; private: type m_value; };
VimL: let s:value_end   = '¡'
VimL: let s:reindent = 1
VimL: let s:marker_open  = '<+'
VimL: let s:marker_close = '+>'
MuT:  let s:enum_args   = s:CmdLineParams([])
MuT:  let s:enum_name   = s:enum_args[0]
MuT:  if empty(s:enum_name)
MuT:    let s:enum_name   = inputdialog('Name of the enum class ?', lh#marker#txt(lh#naming#type(expand('%:t:r'))))
MuT:  endif
MuT:  let s:iterable    = lh#ui#confirm("Shall ".s:enum_name." be iterable ?", "&Yes\n&No", 1) == 1
MuT:  let s:values      = len(s:enum_args) <=1 ? [lh#marker#txt('values')] : s:enum_args[1:]
MuT:  let s:lhs_        = lh#naming#param("lhs")
MuT:  let s:rhs_        = lh#naming#param("rhs")
MuT:  let s:value_      = lh#naming#param("value")
MuT:  let s:m_value     = lh#naming#member("value")
MuT:  let s:tmp         = lh#naming#local("tmp")
MuT:  let s:range       = lh#naming#function("range")
MuT:  let s:RangeType   = lh#naming#type("range")
MuT:  let s:to_string   = lh#naming#function("to_string")
MuT:  let s:to_internal = lh#naming#function("to_internal")
MuT:  let s:max         = lh#naming#function("max")
MuT:  let s:type        = lh#naming#type("type")
VimL: call s:AddPostExpandCallback('lh#dev#import#add("<string>")')
MuT:  if lh#cpp#use_cpp11()
VimL:   call s:AddPostExpandCallback('lh#dev#import#add("<cstdint>")')
MuT:  else
VimL:   call s:AddPostExpandCallback('lh#dev#import#add("<stdint.h>")')
MuT:  endif
VimL: call s:AddPostExpandCallback('lh#dev#import#add("<cassert>")')
VimL: silent! unlet s:doc
MuT:  let s:doc = []
VimL: let s:doc += [{ "tag": "ingroup", "text": "g".lh#ft#option#get('dox_group', &ft, lh#marker#txt('Group')) }]
VimL: let s:doc += [{ "tag": "brief", "text": (s:enum_name)." Safe Enum" }]
VimL: let s:doc += [{ "text": "\n" }]
VimL: let s:doc += [{ "text": "This snippet has been automatically generated with vim plugin mu-template." }]
VimL: let s:doc += [{ "text": "\n" }]
VimL: let s:doc += [{ "text": "<+doc+>" }]
VimL: let s:doc += [{ "text": "\n" }]
VimL: let s:doc += [{ "tag": "invariant"}]
VimL: let s:doc += [{ "text": "\n" }]
VimL: let s:doc += [{ "tag": "version", "text": "$"."revision$"}]
VimL: let s:doc += [{ "tag": "author"}]
VimL: let s:doc += [{ "text": "<b>Licence</b>"}]
VimL: let s:doc += [{ "text": "BSD 3 clauses (http://opensource.org/licenses/BSD-3-Clause)"}]
VimL: let s:doc += [{ "text": "Copyright (c) 2014, Luc Hermitte (snippet author)" }]
VimL: let s:doc += [{ "license": "BSD-3"}]
VimL: call s:Include("formatted-comment", "cpp/internals", s:doc, {'style': 0})
struct <+s:enum_name+>{
    enum <+s:type+>{ <+join(s:values, ', ')+>, MAX__, UNDEFINED__, FIRST__=0 };

MuT:  if lh#cpp#use_cpp11()
    explicit <+s:enum_name+>(std::uint8_t <+s:value_+>)
MuT:  else
    explicit <+s:enum_name+>(uint8_t <+s:value_+>)
MuT:  endif
        : <+s:m_value+>(<+s:type+>(<+s:value_+>))
        {
            if (<+s:value_+> >= MAX__){
VimL: call s:Include('throw', 'cpp', '"Invalid '.s:enum_name.' value"')
            }
        }
    <+s:enum_name+>(<+s:type+> <+s:value_+>)
        : <+s:m_value+>(<+s:type+>(<+s:value_+>)){
            assert(<+s:m_value+> < MAX__);
        }
    <+s:enum_name+>()
        : <+s:m_value+>(UNDEFINED__){}
    <+s:enum_name+>(std::string const& <+lh#naming#param("s")+>);
MuT:  if s:iterable
    <+s:enum_name+>& operator++(){
        assert(<+s:m_value+> < MAX__);
        <+s:m_value+> = <+s:enum_name+>::<+s:type+>(<+s:m_value+>+1);
        return *this;
    }
    <+s:enum_name+> operator++(int){
        <+s:enum_name+> <+s:tmp+> = *this;
        ++*this;
        return <+s:tmp+>;
    }
MuT:  endif

    char const* <+s:to_string+>() const;
MuT:  if lh#cpp#use_cpp11()
    explicit operator int() const{ return <+s:m_value+>; }
MuT:  endif
    <+s:type+> <+s:to_internal+>() const{ return <+s:m_value+>; }
MuT:  if s:iterable
    friend bool operator<=(<+s:enum_name+> <+s:lhs_+>, <+s:enum_name+> <+s:rhs_+>){ return <+s:lhs_+>.<+s:m_value+> <= <+s:rhs_+>.<+s:m_value+>; }
    friend bool operator>=(<+s:enum_name+> <+s:lhs_+>, <+s:enum_name+> <+s:rhs_+>){ return <+s:lhs_+>.<+s:m_value+> >= <+s:rhs_+>.<+s:m_value+>; }
    friend bool operator< (<+s:enum_name+> <+s:lhs_+>, <+s:enum_name+> <+s:rhs_+>){ return <+s:lhs_+>.<+s:m_value+> <  <+s:rhs_+>.<+s:m_value+>; }
    friend bool operator> (<+s:enum_name+> <+s:lhs_+>, <+s:enum_name+> <+s:rhs_+>){ return <+s:lhs_+>.<+s:m_value+> >  <+s:rhs_+>.<+s:m_value+>; }
MuT:  endif
    friend bool operator==(<+s:enum_name+> <+s:lhs_+>, <+s:enum_name+> <+s:rhs_+>){ return <+s:lhs_+>.<+s:m_value+> == <+s:rhs_+>.<+s:m_value+>; }
    friend bool operator!=(<+s:enum_name+> <+s:lhs_+>, <+s:enum_name+> <+s:rhs_+>){ return <+s:lhs_+>.<+s:m_value+> != <+s:rhs_+>.<+s:m_value+>; }

    static <+s:enum_name+> <+s:max+>  (){ return <+s:enum_name+>(build_max()); }
MuT:  if s:iterable
    static <+s:enum_name+> begin(){ return FIRST__; }
    static <+s:enum_name+> end  (){ return <+s:enum_name+>(build_max()); }

MuT:      if lh#cpp#use_cpp11()
          /** Helper class to provide for-range loops on <+s:enum_name+>.
           * @see \c range()
           */
          struct <+s:RangeType+>;
          /** Helper function to provide for-range loops on \c <+s:enum_name+>.
           * e.g.
           * @code
           * for (auto value : <+s:enum_name+>::<+s:range+>())
           *    cout << value.<+s:to_internal+>() << " -> " << value.<+s:to_string+>();
           * @endcode
           */
          static <+s:RangeType+> <+s:range+>();
MuT:      endif
MuT:  endif
private:
    struct build_max{};
    <+s:enum_name+>(build_max) : m_value(MAX__){}

    <+s:type+> <+s:m_value+>;
};
MuT:  if s:iterable && lh#cpp#use_cpp11()

          struct <+s:enum_name+>::<+s:RangeType+>{
              struct iterator{
                iterator(<+s:enum_name+> <+s:value_+>) : <+s:m_value+>(<+s:value_+>){}
                <+s:enum_name+> operator*() const{ return <+s:m_value+>; }
                friend bool operator!=(iterator <+s:lhs_+>, iterator <+s:rhs_+>)
                { return <+s:lhs_+>.<+s:m_value+> != <+s:rhs_+>.<+s:m_value+>;}
                iterator& operator++(){ ++<+s:m_value+>; return *this;}
            private:
                <+s:enum_name+> <+s:m_value+>;
              };
              static iterator begin(){ return <+s:enum_name+>::begin(); }
              static iterator end  (){ return <+s:enum_name+>::end(); }
          };
MuT:  endif
VimL: let b:cpp_last_enum = {'name': s:enum_name, 'type': s:type, 'values': s:values, 'RangeType': s:RangeType, 'range': s:range, 'iterable': s:iterable}
VimL: silent! unlet s:values


================================================
FILE: after/template/cpp/erase-remove.template
================================================
VimL:" erase-remove File Template, Luc Hermitte, 06th Nov 2012
VimL:" hint: erase-remove idiom
VimL: let s:reindent     = 1
VimL: let s:marker_open  = '<+'
VimL: let s:marker_close = '+>'
VimL: call s:AddPostExpandCallback('lh#dev#import#add("<algorithm>")')
MuT:  let s:container = s:SurroundableParam('container', 1)
<+s:container+>.erase(std::remove<+_if+>(<+s:container+>.begin(), <+s:container+>.end(), <+what+>), <+s:container+>.end());
VimL: unlet s:container


================================================
FILE: after/template/cpp/exception-class.template
================================================
VimL:" exception-class File Template, Luc Hermitte <hermitte {at} free {dot} fr>, 25th Nov 2015
VimL:" hint: Value Class ((implicitly) copyable, no hierarchy)
VimL:" NOTE: when we define our own exception types, we do much more than just inherit from a standard exception type
VimL: " There is an init constructor, no need to delete the default constructor.
VimL: let s:default_constructor = s:Param("default-constructor", {"visibility": "none"})
MuT:  let s:functions = s:Param("functions", lh#cpp#snippets#new_function_list())
VimL: call s:functions.add([{"signature": "virtual char const* what() const ".lh#cpp#snippets#noexcept()." ".lh#cpp#snippets#override()}])
VimL: call s:Include("empty-exception-class", "cpp")


================================================
FILE: after/template/cpp/file.template
================================================
VimL:" file File Template, Luc Hermitte, 28th Apr 2014
VimL:" hint: i/ofstream
VimL: let s:value_start = '¡'
VimL: let s:value_end   = s:value_start
VimL: let s:marker_open  = '<+'
VimL: let s:marker_close = '+>'
VimL: call s:AddPostExpandCallback('lh#dev#import#add("<fstream>")')
std::<+i+>fstream f(¡s:Surround(1, '<+filename+>')¡);


================================================
FILE: after/template/cpp/for-enum.template
================================================
VimL:" For loop over Enum definition Template, Luc Hermitte
VimL:" hint: for (Enum::type e=Enum::type(); e!=Enum::MAX__; ++e) { ... }
VimL: let s:value_start = '¡'
VimL: let s:value_end   = '¡'
VimL: let s:reindent = 1
VimL: let s:marker_open  = '<+'
VimL: let s:marker_close = '+>'
VimL: let s:enum_name = inputdialog('Name of the enum class ?', Marker_Txt('EnumType'))
VimL: let s:index = inputdialog('Name of the for index ?', Marker_Txt('e'))
VimL: " todo: automagically detect the type of the real enum, and the MAX__ value
for(¡s:enum_name¡::type ¡s:index¡ = ¡s:enum_name¡::type() ; ¡s:index¡ != ¡s:enum_name¡::MAX__ ; ++¡s:index¡ ){
    ¡s:Surround(1, '<++>')¡
}<+s:TerminalPlaceHolder()+>


================================================
FILE: after/template/cpp/for-iterator.template
================================================
VimL:" C++ for-loop on iterators Template, Luc Hermitte
VimL:" hint: for (T::iterator b=c.begin(), e=c.end(); b!=e; ++b) { ... }
VimL: let s:value_start  = '¡'
VimL: let s:value_end    = '¡'
VimL: let s:reindent     = 1
VimL: let s:marker_open  = '<+'
VimL: let s:marker_close = '+>'
VimL:"
VimL: let s:cont  = lh#ui#input('Container name: ')
VimL: let s:begin = lh#ui#input('Iterator variable: ', 'b')
VimL: let s:end   = lh#ui#input('Iterator end variable: ', 'e')
VimL:"
VimL:" Note: The "const" can be deleted or kept thanks to <Plug>MarkersMark
MuT:  let s:container_type = lh#dev#types#of_var(s:cont, lh#marker#txt('container_type'))
MuT:  let s:const = lh#dev#cpp#types#is_const(s:container_type) ? 'const_' : lh#marker#txt('const_')
VimL: let s:container_type = lh#dev#cpp#types#remove_cv(lh#dev#cpp#types#remove_reference(s:container_type))
for (<+s:container_type+>::<+s:const+>iterator ¡s:begin¡ = ¡s:cont¡.begin(), ¡s:end¡ = ¡s:cont¡.end()
    ; ¡s:begin¡ != ¡s:end¡
    ; ++¡s:begin¡
    )
{
¡s:Surround(1, '<++>')¡
}<+s:TerminalPlaceHolder()+>


================================================
FILE: after/template/cpp/for-range.template
================================================
VimL:" range-based for loop File Template, Luc Hermitte, 07th Jul 2015
VimL:" hint: for(auto&& e : range)
VimL: let s:value_start = '¡'
VimL: let s:value_end   = s:value_start
VimL: let s:marker_open  = '<+'
VimL: let s:marker_close = '+>'
VimL: let s:reindent     = 1
VimL: let s:type = s:Param("type", lh#marker#txt('auto&&'))
VimL: let s:elem = s:Param("elem", lh#marker#txt('e'))
VimL: let s:range = s:Param("range", lh#marker#txt('range'))
for(<+s:type+> <+s:elem+> : <+s:range+>){
    ¡s:Surround(1, '<++>')¡
}<+s:TerminalPlaceHolder()+>
VimL: unlet s:type
VimL: unlet s:elem
VimL: unlet s:range


================================================
FILE: after/template/cpp/fori.template
================================================
VimL:"{for int i=0...} Template-File, Luc Hermitte
VimL:" hint: for (int i=0;i!=N;++i) { action }
VimL: let s:value_start  = '¡'
VimL: let s:value_end    = '¡'
VimL: let s:reindent     = 1
VimL: let s:marker_open  = '<+'
VimL: let s:marker_close = '+>'
for(<+int+> <+i+>=0; <+i+>!=<+MAX+> ; ++<+i+>){
    ¡s:Surround(1, '<+code+>')¡
}<+s:TerminalPlaceHolder()+>


================================================
FILE: after/template/cpp/foriN.template
================================================
VimL:"{for size_t i=0, N= ; i!=N...} Template-File, Luc Hermitte
VimL:" hint: for (std::size_t i=0, N=...;i!=N;++i) { action }
VimL: let s:value_start  = '¡'
VimL: let s:value_end    = '¡'
VimL: let s:reindent     = 1
VimL: let s:marker_open  = '<+'
VimL: let s:marker_close = '+>'
for(<+std::size_t+> <+i+>=0, <+N+>=<+MAX+>; <+i+>!=<+N+> ; ++<+i+>){
    ¡s:Surround(1, '<+code+>')¡
}<+s:TerminalPlaceHolder()+>


================================================
FILE: after/template/cpp/forward.template
================================================
VimL:" forward File Template, Luc Hermitte, mar. 29 mars 2016 17:13:03 CEST
VimL:" hint: std::forward<T>(v)
VimL: let s:value_start = '¡'
VimL: let s:value_end   = s:value_start
VimL: let s:marker_open  = '<+'
VimL: let s:marker_close = '+>'
MuT:  let s:var = s:SurroundableParam('var', 1)
MuT:  let s:type = s:SurroundableParam('type', 2)
VimL: call s:AddPostExpandCallback('lh#dev#import#add("<utility>")')
std::forward<<+s:type+>>(<+s:var+>)<+s:TerminalPlaceHolder()+>


================================================
FILE: after/template/cpp/getter.template
================================================
VimL:" getter File Template, Luc Hermitte <hermitte {at} free {dot} fr>, 02nd Dec 2015
VimL:" hint: T const& getFoo() const
VimL: let s:marker_open  = '<+'
VimL: let s:marker_close = '+>'
VimL: let s:reindent     = 1
VimL: "The interactive mode (w/ dynamic placeholders) won't permit to have "getFoo" and "return m_foo".
MuT:  let s:attribute    = s:Param("attribute", {'type': lh#marker#txt(lh#naming#type('type')), 'name': lh#marker#txt('name')})
MuT:  let s:attrb_name   = s:attribute.name
MuT:  let s:ret_expr = lh#naming#member(s:attrb_name)
MuT:  if lh#dev#cpp#types#is_smart_ptr(s:attribute.type)
MuT:    let s:ret_type = lh#dev#cpp#types#remove_ptr(s:attribute.type)
VimL:   let s:ret_expr = '*'.s:ret_expr
MuT:  else
MuT:    let s:ret_type = s:attribute.type
MuT:  endif
VimL: let s:ret_type = lh#dev#cpp#types#const_correct_type(s:ret_type)
<+s:ret_type+> <+lh#naming#getter(s:attrb_name)+>() const{return <+s:ret_expr+>;}


================================================
FILE: after/template/cpp/init-constructor.template
================================================
VimL:" init-constructor File Template, Luc Hermitte, 30th Nov 2015
VimL:" hint: Constructor(parameters): m_attributes(params){}
VimL: let s:marker_open  = '<+'
VimL: let s:marker_close = '+>'
VimL: let s:reindent     = 1
VimL: " in case the class name is already known, no need to extract it
VimL: call s:Include('get-class-name', 'cpp/internals')
MuT:  let s:parameters = s:Param("parameters", lh#option#unset())
MuT:  let s:fn_comments = lh#dox#new_function("Init constructor.")
VimL: let s:fn_comments.throw = {"optional": 1}
VimL: " let s:fn_comments.text  = []
MuT:  if lh#option#is_set(s:parameters)
MuT:    let s:parameterList = lh#cpp#snippets#build_param_list(s:parameters)
MuT:    let s:definition = (empty(s:parameters)? "" : (len(s:parameters)>1?"\n": "").": ").join(map(copy(s:parameters), 'lh#naming#member(v:val.name)."(".lh#naming#param(v:val.name).")"'), "\n, ").'{}'
VimL:   for param in s:parameters | call s:fn_comments.add_param(param) | unlet param | endfor
MuT:  else
MuT:    let s:parameterList = lh#marker#txt('ctr-parameters')
MuT:    let s:definition = ';'
VimL:   let s:fn_comments.param = [lh#marker#txt('ctr-parameters'). ' ' . lh#marker#txt()]
MuT:  endif
VimL: call s:Include("function-comment", "cpp/internals",s:fn_comments)
<+s:clsname+>(<+s:parameterList+>)<+s:definition+>


================================================
FILE: after/template/cpp/interface.template
================================================
VimL:" interface File Template, Luc Hermitte <hermitte {at} free {dot} fr>, lun. 19 déc. 2016 18:32:45 CET
VimL:" hint: Interface class -- An abstract class actually
VimL: let s:value_start = '¡'
VimL: let s:value_end   = s:value_start
VimL: let s:marker_open  = '<+'
VimL: let s:marker_close = '+>'
VimL: " --- Defines Doxygen comments
MuT:  let s:parameters = s:Param('cls_parameters', {})
VimL: call lh#dict#add_new(s:parameters, {'comments': {}})
MuT:  let s:cls_comments = s:parameters.comments
VimL: let s:cls_comments.semantics = get(s:cls_comments, 'semantics', [])+['Interface']
VimL: " --- Insert the skeleton built
VimL: call s:Include('abstract-class', 'cpp', {'cls_parameters': s:parameters})


================================================
FILE: after/template/cpp/internals/abs-rel-shared.template
================================================
VimL:" Shared definition for Absolute and relative Classes Template, Luc Hermitte
VimL:" Used to define Date and Duration, Point and Distance, ... 
VimL: let s:value_start = '¡'
VimL: let s:value_end   = '¡'
VimL: let s:reindent = 1
VimL: let s:marker_open  = '<+'
VimL: let s:marker_close = '+>'
VimL:"
namespace DETAILS
{
    <+s:tmpl_decl+>class <+s:sharedclsname+>
    {
    public:
	typedef ¡lh#ui#if(s:istemplate, s:tmpl_type, "<+scalar_type+>")¡ scalar_type;
	friend class ¡s:absclsname.s:tmpl¡;
	friend class ¡s:relclsname.s:tmpl¡;
    protected:
	/**@name Construction/destruction
	 */
	//@{
	/** Initialisation constructor.
	 */
	<+s:sharedclsname+>(<+parameters+>)¡lh#ui#if(s:istemplate,"\n<+: +>{<++>}", ";")¡
	/** Protected destructor.
	 */
	~<+s:sharedclsname+>();
	¡lh#cpp#abs_rel#canonicalortodoxform(s:absclsname, ! s:defaultisenough)¡
	//@}

	/**@name Operations
	 */
	//@{
	void add(<+s:sharedclsname+> const& <+s:rhs+>)¡lh#ui#if(s:istemplate,"\n{<++>}", ";")¡
	void dec(<+s:sharedclsname+> const& <+s:rhs+>)¡lh#ui#if(s:istemplate,"\n{<++>}", ";")¡
	void mult(scalar_type <+s:coeff+>)¡lh#ui#if(s:istemplate,"\n{<++>}", ";")¡
	void div(scalar_type <+s:coeff+>)¡lh#ui#if(s:istemplate,"\n{<++>}", ";")¡
	static bool isEqual(
		<+s:sharedclsname+> const& <+s:rhs+>,
		<+s:sharedclsname+> const& <+s:lhs+>)¡lh#ui#if(s:istemplate,"\n{<++>}", ";")¡
	//@}
    private:
	<+representation+>;
    };
}



================================================
FILE: after/template/cpp/internals/attribute.template
================================================
VimL:" attribute File Template, Luc Hermitte <hermitte {at} free {dot} fr>, 02nd Dec 2015
VimL:" hint: Type m_attribute;
VimL: " Parameter: "attribute" (optional)
VimL: "  - "name": string, mandatory
VimL: "  - "type": string, mandatory,
VimL: "  - "type_info": dict, mandatory (comes from lh#cpp#types#get_info())
VimL: "  - "storage": string, optional: "constepxr ", "static ", "thread_local ", ...
VimL: "  - "default": string, optional, C++11+ only: " = value"
VimL: "  - "align": number, optional
VimL: "  - "include": string/list: files to #include
VimL: " @pre "type" is expected to have been processed w/ lh#cpp#type#*()
VimL: let s:marker_open  = '<+'
VimL: let s:marker_close = '+>'
VimL: let s:reindent     = 1
VimL: " TODO: Handle Doxygen/comments as well
MuT:  let s:attribute    = s:Param("attribute", {'type': lh#marker#txt(lh#naming#type('type')), 'name': lh#marker#txt('name')})
VimL: call s:Include('includes', 'cpp/internals', s:attribute)
MuT:  let s:align = repeat(' ', max([0, get(s:attribute, 'align', 0) - lh#encoding#strlen(s:attribute.type)]))
MuT:  if !lh#cpp#use_cpp11()
MuT:    let s:default_attrb_value = ""
MuT:  else
MuT:    let s:default_attrb_value = get(s:attribute, "default", "")
VimL:   let s:default_attrb_value = empty(s:default_attrb_value) ? "" : " = ".s:default_attrb_value
MuT:  endif
MuT:  if lh#option#is_set(s:attribute.type_info)
VimL:    call s:AddPostExpandCallback('lh#dev#import#add_any('.string(get(s:attribute.type_info, "includes", [])).')')
MuT:  endif
<+get(s:attribute, 'storage', '')+><+s:attribute.type+> <+s:align+><+lh#naming#member(s:attribute.name)+><+s:default_attrb_value+>;
VimL: " <+get(s:attribute, 'storage', '')+><+s:Include(s:attribute.type, 'cpp')+> <+s:align+><+lh#naming#member(s:attribute.name)+><+s:default_attrb_value+>;


================================================
FILE: after/template/cpp/internals/class-skeleton.template
================================================
VimL:" class-skeleton File Template, Luc Hermitte <hermitte {at} free {dot} fr>, 25th Nov 2015
VimL:" hint: Routine Skeleton for C++ classes
VimL:" TODO: find a way to order members
VimL:" TODO: find a way to group members
VimL:" TODO: option to disable comments in defaulted functions
VimL:" TODO: C++11 move copy & move assign
VimL:" TODO: Enforce rule of "all or nothing"
VimL:" TODO: Find a way to specify attributes to use in init-ctr and w/ getters/setters when surrounding.
VimL: let s:value_start  = "¡"
VimL: let s:value_end    = s:value_start
VimL: let s:marker_open  = "<+"
VimL: let s:marker_close = "+>"
VimL: let s:reindent     = 1
MuT:  " let s:clsname    = s:Param('clsname', lh#marker#txt(lh#naming#type(expand('%:t:r'))))
VimL: call s:Include('get-class-name', 'cpp/internals')
MuT:  let s:functions  = s:Param('functions', lh#cpp#snippets#new_function_list())
VimL: " =====[ Attributes
VimL: " Fetch attributes from the parameters passed to the class skeleton
MuT:  let s:attributes = s:Param('attributes', [])
VimL: " And also use the surrounded attributes
VimL: let s:attributes += lh#cpp#snippets#_decode_selected_attributes(s:SurroundRaw(1, ''))
VimL: call s:Verbose('attributes: %1', s:attributes)
VimL: " Finally fill the related function with these information
MuT:  let s:attrb_functions = []
MuT:  if !empty(s:attributes)
VimL:   for attr in s:attributes | for fct in get(attr, 'functions', []) | let s:attrb_functions += [{'kind': fct, 'attribute': attr}] | endfor | endfor
VimL:   for attr in s:attributes | let attr.type_info = lh#cpp#types#get_info(attr.type, {'type': attr.type}) | let attr.type = attr.type_info.typename_for_header() |endfor
VimL:   " Set attributes as parameters to init-ctr, unless already set
MuT:    let s:init_constructor = s:functions.get1({'kind' : 'init-constructor'})
VimL:   call s:init_constructor.add_new({'parameters': lh#list#map_on(deepcopy(s:attributes), 'type', 'lh#dev#cpp#types#const_correct_type(v:val)'), 'visibility': 'public'})
VimL:   " Remove default-constructor unless already set visible
MuT:    let s:default_constructor = s:Param('default-constructor', {})
VimL:   call lh#dict#add_new(s:default_constructor, {'visibility': 'none'})
MuT:  endif
VimL: " =====[ Class characteristics
MuT:  let s:is_final = s:Param('final', 0)
MuT:  let s:final_str = s:is_final ? (lh#cpp#use_cpp11() ? ' final' : lh#marker#txt(' final')) : ''
VimL: " =====[ Parents
MuT:  let s:parents = s:Param('parents', [])
MuT:  let s:noncopyable = s:Param('noncopyable', -1) " -1 == maybe
MuT:  let s:copyable    = s:Param('copyable', -1)    " -1 == maybe
MuT:  if s:copyable == 1
VimL:   let s:noncopyable = 0 " clean 'may be'
MuT:  endif
MuT:  if s:noncopyable == 1
VimL:   let s:copyable = 0 " clean 'may be'
MuT:    let s:noncopyable_class = lh#option#get('cpp_noncopyable_class', {'name': 'noncopyable'})
VimL:   " TODO: support auto import of noncopyable file
MuT:    if empty(s:noncopyable_class)
VimL:     call lh#dict#add_new(s:Param('copy-constructor', {}), {'how': 'deleted'})
VimL:     call lh#dict#add_new(s:Param('assignment-operator', {}), {'how': 'deleted'})
MuT:    else
VimL:     " Don't add the noncopyable if there is already a public parent
MuT:      if ! lh#cpp#snippets#_has_a_non_copyable_parent(s:parents)
VimL:       let s:parents += [ lh#cpp#snippets#_merge_include_data(s:noncopyable_class, {'visibility': 'private'})]
MuT:      endif
MuT:      if lh#cpp#snippets#shall_explicit_defaults()
VimL:       call lh#dict#add_new(s:Param('copy-constructor', {}), {'how': 'deleted'})
VimL:       call lh#dict#add_new(s:Param('assignment-operator', {}), {'how': 'deleted'})
MuT:      endif
MuT:    endif
MuT:  endif
VimL: "let g:args=deepcopy(s:args)
MuT:  let s:parents_data = lh#cpp#snippets#parents(s:parents)
VimL: call lh#list#for_each_call(s:parents_data[1], "lh#mut#_add_post_expand_callback(\"lh#dev#import#add(v:val)\")")
VimL: " =====[ Functions
VimL: " --------[ Any Functions
MuT:  "let s:functions = s:Param('functions', [])
VimL: " --------[ Attribute functions (get/set)
VimL: call s:functions.add(s:attrb_functions)
VimL: " --------[ General case
VimL: call s:functions.reverse()
MuT:  let s:pub_functions = s:functions.public()
MuT:  let s:pro_functions = s:functions.protected()
MuT:  let s:pri_functions = s:functions.private()
VimL: " --------[ Special Functions
MuT:  if lh#cpp#snippets#requires_destructor(s:attributes)
MuT:    let s:destructor = s:Param('destructor', {})
VimL:   " Force visible (even private) if not set already
Viml:   call lh#dict#add_new(s:destructor, {'visibility': 'public'})
MuT:  endif
MuT:  if (s:copyable != 0) && lh#cpp#snippets#requires_copy_operations(s:attributes)
MuT:    let s:copy_constructor = s:Param('copy-constructor', {})
VimL:   " Force visible (even protected) if not set already
Viml:   call lh#dict#add_new(s:copy_constructor, {'visibility': 'public'})
MuT:    let s:assignment_operator = s:Param('assignment-operator', {})
VimL:   " Force visible (even protected) if not set already
Viml:   call lh#dict#add_new(s:assignment_operator, {'visibility': 'public'})
MuT:  endif
VimL: call s:Include('shall_explicit_defaults', 'cpp/internals')
VimL: " In reverse order because of how Include() works
MuT:  let s:special_functions = ['destructor', 'assignment-operator', 'copy-constructor', 'default-constructor']
MuT:  let s:spe_func_data = map(copy(s:special_functions), "extend(s:Param(v:val, {}), {'kind': v:val})")
VimL: for spe in s:spe_func_data | call lh#dict#add_new(spe, s:default_explicit) | endfor
MuT:  let s:pub_special_functions = lh#cpp#snippets#_filter_functions(s:spe_func_data, 'public')
MuT:  let s:pro_special_functions = lh#cpp#snippets#_filter_functions(s:spe_func_data, 'protected')
MuT:  let s:pri_special_functions = lh#cpp#snippets#_filter_functions(s:spe_func_data, 'private')
VimL: call extend(s:pub_functions, map(copy(s:pub_special_functions), 'v:val'))
VimL: call extend(s:pro_functions, map(copy(s:pro_special_functions), 'v:val'))
VimL: call extend(s:pri_functions, map(copy(s:pri_special_functions), 'v:val'))
VimL: " =====[ Doxygen
MuT:  let s:cls_comments_default = {}
VimL: let s:cls_comments_default.brief = lh#dox#brief(s:clsname)
VimL: let s:cls_comments_default.ingroup = {}
VimL: let s:cls_comments_default.invariant = lh#marker#txt()
VimL: let s:cls_comments_default.author = lh#dox#author_value(). ', creation'
VimL: let s:cls_comments_default.since = lh#dox#since_value()
MuT:  let s:cls_comments = s:Param('comments', {})
VimL: call extend(s:cls_comments, s:cls_comments_default, 'keep')
VimL: call s:Include('function-comment', 'cpp/internals', s:cls_comments)
VimL: " =====[ The Skeleton
class <+s:clsname+><+s:final_str+><+s:parents_data[0]+>
{
public:

VimL: for fn in s:pub_functions | call s:Include("function", "cpp/internals", {"function": fn}) | endfor
MuT:  if !empty(s:pro_functions)

protected:

VimL:   for fn in s:pro_functions | call s:Include("function", "cpp/internals", {"function": fn}) | endfor
MuT:  endif
MuT:  if !empty(s:pri_functions) || !empty(s:attributes)

private:

VimL:   for fn in s:pri_functions | call s:Include("function", "cpp/internals", {"function": fn}) | endfor
MuT:    let s:longest_type = max(map(copy(s:attributes), 'strlen(v:val.type)'))
VimL:   " calling s:Include() in a loop inserts at the current line => need to reverse
VimL:   for attrb in reverse(s:attributes) | call s:Include('attribute', 'cpp/internals', {"attribute": extend(attrb, {'align':s:longest_type}, 'force')}) | endfor
MuT:  endif
};


================================================
FILE: after/template/cpp/internals/formatted-comment.template
================================================
VimL:" C++ formatted-comment template-routine, Luc Hermitte, 23rd Mar 2012
VimL:" Meant to be used as a function whose parameter is a list of things to print.
VimL:" Default output format=doxygen; override this template for  other formats.
VimL:" hint: /** stuff from the list... */
VimL: let s:reindent     = 1
VimL: function! s:_LoopOverDoxItems(doc)
VimL:    " echomsg "-->".string(a:doc)
VimL:    let lead = lh#dox#comment_leading_char(). " "
VimL:    let lines = []
VimL:    for item in a:doc
VimL:        let text = get(item, 'text', '')
VimL:        if has_key(item,"tag")
VimL:           " try to use the lh#dox#{tag}() function if it exists
VimL:           if (item.tag) == "param"
VimL:               let line = lh#dox#{item.tag}(item)
VimL:           elseif exists("*lh#dox#".(item.tag))
VimL:               let line = lh#dox#{item.tag}(text)
VimL:           else
VimL:               let line = lh#dox#tag(item.tag) . " " . text
VimL:           endif
VimL:        elseif has_key(item, "license")
VimL:            let license = s:GetTemplateLines(item.license, "license/text")
VimL:            let pat_not_text = '\c\(^'.s:Command('').'\|'.s:Special('').'\)'
VimL:            call map(license, "v:val =~ pat_not_text ? (v:val) : lead.v:val")
VimL:            let lines += license
VimL:            continue
VimL:        else
VimL:            let line = text
VimL:        endif
VimL:        " optional entries are completly surrounded by a placeholder
VimL:        if has_key(item,"optional") && item.optional && match(line, lh#marker#txt(".\\{-}"))==-1
VimL:            let line = lh#marker#txt(line)
VimL:        endif
VimL:        " special case: @ingroup is put on the /** line
VimL:        if has_key(item,"tag") && item.tag == "ingroup"
VimL:            let s:content.lines[s:content.crt-1] .= line
VimL:        elseif (line!~'^\s*$') " empty lines produce nothing
VimL:            " Use "\n" as {text} to force an empty line
VimL:            let lines += [line=="\n" ? lead : lead.line]
VimL:        endif
VimL:    endfor
VimL:    "trim trailing whitespaces
VimL:    call map(lines, "substitute(v:val, ' *$', '', '')")
VimL:    call s:Inject(lines)
VimL: endfunction
MuT: if lh#ft#option#get("template_expand_doc", &ft, 1)
MuT:   let s:restore_options = lh#on#exit().restore(s:content, 'can_apply_style')
VimL:  let s:content.can_apply_style = s:Param('style', 0)
/**
VimL:  call s:_LoopOverDoxItems(empty(s:Args()) ? [] : s:Args()[0])
 */
VimL: " let g:lines = deepcopy(s:content.lines)
VimL:  call s:restore_options.finalize()
MuT: endif


================================================
FILE: after/template/cpp/internals/function-comment.template
================================================
VimL:" function-comment File Template, Luc Hermitte, 22nd Aug 2011
VimL:" template to generate function comments, default format=doxygen
VimL: let s:fn_comments=s:Args()[0]
VimL: "
VimL: function! s:_AddItemToDoc(tagname, data)
VimL:   let text = empty(a:data) ? "\n" : a:data
VimL:   if empty(a:tagname)
VimL:      return [{'text': text}]
VimL:   else
VimL:      return [{'tag':(a:tagname), 'text': text}]
VimL:   endif
VimL: endfunction
VimL: "
VimL: function! s:_AddToDoc(tagname, data)
VimL:   " if !has_key(a:data, a:tagname) | return [] | endif
VimL:   let res = []
VimL:   if type(a:data[a:tagname]) == type([])
VimL:     for e in a:data[a:tagname]
VimL:       let e2 = {(a:tagname): e}
VimL:       let res += s:_AddToDoc(a:tagname, e2)
VimL:     endfor
VimL:   elseif type(a:data[a:tagname]) == type({})
VimL:     " special case to handle things like "optional"
VimL:     let data = copy(a:data[a:tagname])
VimL:     let data.tag = a:tagname
VimL:     let res += [data]
VimL:   else
VimL:     let res += s:_AddItemToDoc(a:tagname, a:data[a:tagname])
VimL:   endif
VimL:   return res
VimL: endfunction
VimL: "
VimL: function! s:_GenerateDoc(data)
VimL:   " echomsg "\n-->".string(a:data)
VimL:   " tags ordered => determine the order in which they are displayed
VimL:   let pre_tags_default = [ 'brief', 'ingroup', 'tparam', 'param', 'return', 'throw', 'invariant', 'pre', 'post']
VimL:   let post_tags_default = ['note', 'warning', 'author', 'since', 'version', 'see']
VimL:   let doc = []
VimL:   let tags = lh#ft#option#get('pre_desc_ordered_tags', &ft, pre_tags_default)
VimL:   for tag in filter(copy(tags), 'has_key(a:data, v:val)')
VimL:     let doc +=  s:_AddToDoc(tag, a:data)
VimL:   endfor
VimL:   if has_key(s:fn_comments, 'semantics')
VimL:     let doc += s:_AddItemToDoc('semantics', '')
VimL:     for t in s:fn_comments.semantics
VimL:         let doc += s:_AddItemToDoc('', '- '.t)
VimL:     endfor
VimL:   endif
VimL:   if has_key(s:fn_comments, 'text')
VimL:     if empty(s:fn_comments.text)
VimL:       let doc += s:_AddItemToDoc('', '')
VimL:     else
VimL:       for t in s:fn_comments.text
VimL:         let doc += s:_AddItemToDoc('', t)
VimL:       endfor
VimL:     endif
VimL:   endif
VimL:   let tags = lh#ft#option#get('post_desc_ordered_tags', &ft, post_tags_default)
VimL:   for tag in filter(copy(tags), 'has_key(a:data, v:val)')
VimL:     let doc +=  s:_AddToDoc(tag, a:data)
VimL:   endfor
VimL:   " echomsg string(doc)
VimL:   " and finally, generate!
VimL:   call s:Include('formatted-comment', 'cpp/internals', doc)
VimL: endfunction
MuT:  if lh#ft#option#get('template_expand_doc', &ft, 1)
VimL:   call s:_GenerateDoc(s:fn_comments)
MuT:  endif


================================================
FILE: after/template/cpp/internals/function.template
================================================
VimL:" «function» File Template, Luc Hermitte <hermitte {at} free {dot} fr>, 27th Nov 2015
VimL:" hint: «function-hint»
VimL: let s:marker_open  = '<+'
VimL: let s:marker_close = '+>'
MuT:  let s:function = s:Param('function', {})
MuT:  let s:kind = get(s:function, 'kind', '')
MuT:  if s:kind =~ '\vconstructor|destructor|assignment-operator'
VimL:   call s:Include(s:kind, 'cpp', s:function)
MuT:    " let s:how = get(s:function, 'how', '')
MuT:    " let s:how = s:how =~ "\\vpure|deleted|defaulted" ? " ".lh#cpp#snippets#{s:how}() : ""
MuT:    " let s:clsname = s:Param("clsname", lh#cpp#AnalysisLib_Class#CurrentScope(line("."), "class"))
VimL:   "<+s:clsname+>(<+s:Param("parameters", lh#marker#txt("ctr-parameters"))+>)<+s:how+>;
MuT:  elseif s:kind =~ '\vget|set'
VimL:   call s:Include(s:kind.'ter', 'cpp', {'attribute': s:function.attribute})
MuT:  let s:attrb_name = s:function.attribute.name
MuT:  else
MuT:    let s:signature = get(s:function, 'signature', '')
MuT:    let s:implementation = get(s:function, 'implementation', ';')
VimL:   let s:signature = substitute(s:signature, '<+__clsname__+>', s:clsname, 'g')
MuT:    if s:implementation != ';'
VimL:     let s:implementation = substitute(s:implementation, '<+__clsname__+>', s:clsname, 'g')
VimL:     let s:implementation = '{'.s:implementation.'}'
MuT:    endif
MuT:    let s:fn_comments = get(s:function, 'comments', {})
MuT:    if !empty(s:fn_comments)
VimL:     call s:Include('function-comment', 'cpp/internals', s:fn_comments)
MuT:    endif
<+s:signature+><+s:implementation+>
MuT:  endif
VimL: " TODO: definition in separate file


================================================
FILE: after/template/cpp/internals/get-b-e.template
================================================
VimL:" get-b-e File Template, Luc Hermitte <hermitte {at} free {dot} fr>, jeu. 02 juin 2016 17:02:36 CEST
VimL: " Parameters:
VimL: " - "container"
VimL: " Options:
VimL: " - (bg):cpp_begin_end_style
VimL: " Defines:
VimL: " - s:begin
VimL: " - s:end
VimL: " - s:container
VimL: " And:
VimL: " - include the relevant files according to g:cpp_begin_end_style
VimL: let s:value_start = '¡'
VimL: let s:value_end   = s:value_start
VimL: let s:marker_open  = '<+'
VimL: let s:marker_close = '+>'
MuT:  let s:container = s:SurroundableParam('container', 1)
MuT:  let s:begin = lh#cpp#snippets#_select_begin_end(s:container, 'begin')
MuT:  let s:end   = lh#cpp#snippets#_select_begin_end(s:container, 'end')
MuT:  let s:includes = lh#cpp#snippets#_include_begin_end()
VimL: call lh#list#for_each_call(s:includes, s:getSNR('AddPostExpandCallback("lh#dev#import#add(v:val)")'))


================================================
FILE: after/template/cpp/internals/get-class-name.template
================================================
VimL:" get-class-name routine File Template, Luc Hermitte <hermitte {at} free {dot} fr>, jeu. 17 déc. 2015 18:40:56 CET
VimL:" hint: Internal routine to fetch the class name if already known
VimL: "1- in case the class name is already known, no need to extract it
MuT:  let s:clsname = s:Param("clsname",join(s:CmdLineParams(), ''))
MuT:  if empty(s:clsname)
VimL: "2- otherwise: we try to extract it
MuT:    let s:clsname = lh#cpp#AnalysisLib_Class#CurrentScope(line("."), "class")
MuT:    if empty(s:clsname)
VimL: "3- otherwise, we ask it to the end-user, default = filename minus extensions
MuT:      let s:clsname = lh#ui#input("class name ?", lh#marker#txt(lh#naming#type(expand("%:t:r"))))
MuT:    endif
VimL: "4- reinject the new clsname into the arguments
VimL: "   However, as this template-file is included, arguments will be popped
VimL: "   => clsname will be lost in crt context
VimL: "   => it has to be injected in parent context! (yes, this is quite dirty!)
VimL:   call s:InjectInParentArgs({'clsname': (s:clsname)})
MuT:  endif


================================================
FILE: after/template/cpp/internals/includes.template
================================================
VimL:" includes File Template, Luc Hermitte <hermitte {at} free {dot} fr>, 02nd Dec 2015
VimL:" hint: include skel-routine
VimL: " Parameter: list/string: files to include
MuT:  let s:includes = lh#list#flatten([s:Param("includes", [])])
VimL: for inc in s:includes | call s:AddPostExpandCallback('lh#dev#import#add("'.inc.'")') | endfor


================================================
FILE: after/template/cpp/internals/list-constructors.template
================================================
VimL:" list-constructors File Template, Luc Hermitte <hermitte {at} free {dot} fr>, 27th Nov 2015
VimL:" hint: Routine template-file, returns: s:constructors
VimL: "let g:args = deepcopy(s:args)
MuT:  let s:flat_args     = lh#list#flatten(s:args)
MuT:  let s:constructors  = filter(copy(s:flat_args), 'match(keys(v:val), "constructor") >= 0')
VimL: "let g:constructors0 = deepcopy(s:constructors)
VimL: " Ignore removed (none) constructors
VimL: call filter(s:constructors, "empty(lh#cpp#snippets#_filter_functions(v:val, 'none'))")
VimL: "let g:constructors1 = deepcopy(s:constructors)
VimL: " Ignore defaulted constructors
VimL: call filter(s:constructors, "empty(lh#cpp#snippets#_filter_functions(v:val, 'how', 'defaulted'))")
VimL: "let g:constructors2 = deepcopy(s:constructors)
MuT:  let s:ctr_functions = filter(copy(s:flat_args), 'has_key(v:val,"functions")')
VimL: "let g:ctr_functions = deepcopy(s:ctr_functions)
MuT:  if !empty(s:ctr_functions)
VimL:   let s:ctr_functions2 = lh#list#accumulate2(s:ctr_functions, {}, 'extend(v:1_, v:2_)')
VimL:   "let s:ctr_functions3 = filter(copy(s:ctr_functions2['functions']), 'get(v:val, "kind", "") == "constructor"')
VimL:   let s:ctr_functions3 = s:ctr_functions2.functions.filter({'kind': 'constructor'})
VimL:   call extend(s:constructors, s:ctr_functions3)
MuT:  endif
VimL: "let g:constructors3 = deepcopy(s:constructors)


================================================
FILE: after/template/cpp/internals/namespace-name.template
================================================
VimL:" Factorize namespace name "computation"
MuT:  let s:namespace = s:Param('namespace', '###')
MuT:  if (type(s:namespace) == type('')) && (s:namespace == '###')
MuT:     let s:namespace0 = lh#ft#option#get('project_namespace', &ft, lh#marker#txt('ns'))
MuT:     let s:namespace = type(s:namespace0) == type([]) ? join(s:namespace0, "::") : s:namespace0
VimL:    let s:namespace = lh#ui#input('Namespace name: ', s:namespace)
MuT:  endif


================================================
FILE: after/template/cpp/internals/shall_explicit_defaults.template
================================================
VimL:" shall_explicit_defaults File Template, Luc Hermitte <hermitte {at} free {dot} fr>, 26th Nov 2015
VimL:" hint: wraps call to lh#cpp#snippets#shall_explicit_defaults()
VimL: let s:value_start = '¡'
VimL: let s:value_end   = s:value_start
VimL: let s:marker_open  = '<+'
VimL: let s:marker_close = '+>'
MuT:  if lh#cpp#snippets#shall_explicit_defaults()
MuT:    let default_explicit = {"visibility": "public", "how": "defaulted"}
MuT:  else
MuT:    let default_explicit = {"visibility": "none"}
MuT:  endif


================================================
FILE: after/template/cpp/internals/stream-common.template
================================================
VimL:" «stream-common» File Template, Luc Hermitte
VimL: let s:reindent     = 1
VimL: let s:marker_open  = '<+'
VimL: let s:marker_close = '+>'
VimL: let s:type = 'std::'.s:direction.'stream'
VimL: let s:op = lh#ui#if(s:direction=='o', '<<', '>>')
VimL: let s:const = lh#ui#if(s:direction=='o', 'const ', ' ')
VimL: let s:clsname0 = Cpp_SearchClassDefinition(line('.'))
VimL: let s:friend = lh#ui#if(strlen(s:clsname0), 'friend ', ' ')
VimL: let s:clsname  = lh#ui#input("Template\noperator".s:op." for the class:", s:clsname0)
VimL: call s:Include('stream-signature', 'cpp/internals')
VimL: call s:Include('stream-implementation', 'cpp/internals')
<++>
VimL: " Todo: check for context-namespaces and trim them from s:clsname
VimL: " Todo: check for the previous class if s:clsname0 isempty
VimL: " Todo: options for inline or not ; -> g:implPlace, ...
VimL: " Todo: ask for simple or complex (Langer/Roguewave) inserter
VimL: " Todo: Try to detect The attributes of the objet in order to generate the instruction. ; option: separator


================================================
FILE: after/template/cpp/internals/stream-implementation.template
================================================
VimL:" «stream-implementation» File Template, Luc Hermitte
VimL: call s:AddPostExpandCallback('lh#dev#import#add("<'.s:direction.'stream>")')
{
VimL: " The space for the second argument is madatory at the moment.
    return ¡s:stream_param.' '.s:op¡ <+fields+>;
}


================================================
FILE: after/template/cpp/internals/stream-signature.template
================================================
VimL:" «stream-signature» File Template, Luc Hermitte, 04th Jun 2004
VimL: let s:stream_param = lh#naming#param(s:direction."s")
<+s:friend.s:type+> & operator<+s:op+>(¡s:type.' & '.s:stream_param¡, <+s:const.s:clsname+> & <+lh#naming#param("v")+>)


================================================
FILE: after/template/cpp/iss.template
================================================
VimL:" {istringstream iss(str); iss >>..} File Template, Luc Hermitte, 06th Dec 2010
VimL:" hint: std::istringstream iss(str); if (iss >> ...) { ... }
VimL: let s:value_start = '¡'
VimL: let s:value_start = '¡'
VimL: let s:value_end   = s:value_start
VimL: let s:marker_open  = '<+'
VimL: let s:marker_close = '+>'
VimL: call s:AddPostExpandCallback('lh#dev#import#add("<sstream>")')
std::istringstream iss(<++>);
if (iss >> <++>) {
    <++>
}<++>


================================================
FILE: after/template/cpp/list.template
================================================
VimL:" list File Template, Luc Hermitte, 28th Apr 2014
VimL:" hint: std::list<>
VimL: let s:value_start = '¡'
VimL: let s:value_end   = s:value_start
VimL: let s:marker_open  = '<+'
VimL: let s:marker_close = '+>'
VimL: call s:AddPostExpandCallback('lh#dev#import#add("<list>")')
std::list<¡s:Surround(1, '<+type+>')¡> <++>


================================================
FILE: after/template/cpp/map.template
================================================
VimL:" map File Template, Luc Hermitte, 28th Apr 2014
VimL:" hint: std::map<>
VimL: let s:value_start = '¡'
VimL: let s:value_end   = s:value_start
VimL: let s:marker_open  = '<+'
VimL: let s:marker_close = '+>'
VimL: call s:AddPostExpandCallback('lh#dev#import#add("<map>")')
std::map<¡s:Surround(1, '<+key+>')¡, ¡s:Surround(2, '<+value+>')¡><+s:TerminalPlaceHolder()+>


================================================
FILE: after/template/cpp/namespace.template
================================================
VimL:" C++ namespace Template, Luc Hermitte
VimL:" hint: namespace ns { ... } // ns
VimL:" Options:
VimL:" - snippet parameter: {'namespace' : xxx}
VimL:" - (bg):[cpp_]project_namespace
VimL:" - (bg):cpp_use_nested_namespace (bool) when [bg]:cpp_std_flavour=/CXXFLAGS/CMake match C++17
VimL:" - lh#style options
VimL: let s:value_start  = '¡'
VimL: let s:value_end    = '¡'
VimL: let s:reindent     = 1
VimL: let s:marker_open  = '<+'
VimL: let s:marker_close = '+>'
VimL:"
MuT:  if ! exists('s:namespace')
VimL: call s:Include('namespace-name', 'cpp/internals')
MuT:  endif
MuT:  let s:ns_join = lh#cpp#option#multiple_namespaces_on_same_line()
MuT:  if lh#cpp#use_cpp17() && lh#option#get('cpp_use_nested_namespaces', 1)
MuT:    let s:namespaces = type(s:namespace) == type([]) ? s:namespace : [s:namespace]
MuT:  else
MuT:    let s:namespaces = type(s:namespace) == type([]) ? s:namespace : split(s:namespace, "::")
MuT:  endif
VimL: " let s:ns_open   = s:namespace =~ '^\s*$' ? ["namespace{// Anonymous namespace"] : map(copy(s:namespaces), '"namespace ".v:val."{"')
VimL: " let s:ns_close  = s:namespace =~ '^\s*$' ? ["}// Anonymous namespace"] : map(copy(s:namespaces), '"}".(s:ns_join ? "" : " // ".v:val." namespace")')
VimL: let s:ns_open   = empty(s:namespaces) ? ["namespace{// Anonymous namespace"] : map(copy(s:namespaces), '"namespace ".v:val."{"')
VimL: let s:ns_close  = empty(s:namespaces) ? ["}// Anonymous namespace"] : map(copy(s:namespaces), '"}".(s:ns_join ? "" : "// ".v:val." namespace")')
VimL: let s:ns_join_s = s:ns_join ? " " : "\n"
<+join(s:ns_open, s:ns_join_s)+>
MuT:  let s:def_content = s:Param('content', lh#marker#txt())
¡s:Surround(1, s:def_content)¡
MuT:  let s:ns_comment = s:ns_join && !empty(s:namespaces) ? ("// ".join(s:namespaces, "::") . " namespace".(len(s:namespaces)>1 ? "s": "")) : ""
<+join(s:ns_close, s:ns_join_s)+><+s:ns_comment+>
MuT:  if ! s:Param('included', 0)
<+s:TerminalPlaceHolder()+>
MuT:  endif
VimL: "<+join(s:ns_close, s:ns_join_s)+><+s:ns_join && s:namespace !~ '^\s*$'? (" // ".s:namespace . " namespace".(len(s:namespaces)>1 ? "s": "")) : ""+>


================================================
FILE: after/template/cpp/noncopyable.template
================================================
VimL:" noncopyable File Template, Luc Hermitte <hermitte at free.fr>, 28th May 2014
VimL:" hint: boost::noncopyable
VimL: let s:value_start = '¡'
VimL: let s:value_end   = s:value_start
VimL: let s:marker_open  = '<+'
VimL: let s:marker_close = '+>'
VimL: call s:AddPostExpandCallback('lh#dev#import#add("<boost/noncopyable.hpp>")')
boost::noncopyable


================================================
FILE: after/template/cpp/operator-binary.template
================================================
VimL:" C++ binary operator snippet, Luc Hermitte, 30th Sep 2013
VimL:" hint: operatorX(T lhs, T const& rhs) { return lhs X= rhs; }
VimL: let s:marker_open  = '<+'
VimL: let s:marker_close = '+>'
VimL: let s:reindent     = 1
VimL:"
VimL: "1- snippet parameters
VimL: "1.1- classname
VimL: "1.1.1- in case the class name is already known, no need to extract it
MuT:  let s:clsname = s:Param("clsname",join(s:CmdLineParams(), ''))
MuT:  if empty(s:clsname)
VimL: "1.1.2- otherwise: we try to extract it
MuT:    let s:clsname = lh#cpp#AnalysisLib_Class#CurrentScope(line("."), "class")
MuT:    if empty(s:clsname)
VimL: "1.1.3- otherwise, we try to get the name of the last class found
MuT:      let s:clsname = lh#cpp#AnalysisLib_Class#search_closest_class(line('.'))
VimL: "1.1.4- otherwise, we ask it to the end-user, default = filename minus extensions
MuT:      if empty(s:clsname)
MuT:        let s:clsname = lh#ui#input("class name ?", lh#marker#txt(lh#naming#type(expand("%:t:r"))))
MuT:      endif
MuT:      let s:_friend = ''
MuT:    else
MuT:      let s:_friend = 'friend '
MuT:    endif
MuT:  else
MuT:    let s:_friend = lh#marker#txt('friend ')
MuT:  endif
VimL: "1.2- the operator
MuT:  let s:_op      = s:Param('operator', lh#marker#txt('X'))
VimL: "1.3- operator parameters
MuT:  let s:_lhs     = lh#naming#param('lhs')
MuT:  let s:_rhs     = lh#naming#param('rhs')
VimL: "
VimL:" 2- the code
<+s:_friend+><+s:clsname+> operator<+s:_op+>(<+s:clsname+> <+s:_lhs+>, <+s:clsname+> const& <+s:_rhs+>){ return <+s:_lhs+> <+s:_op+>= <+s:_rhs+>; }


================================================
FILE: after/template/cpp/oss.template
================================================
VimL:"{std::ostringstream oss; oss << } Template-File, Luc Hermitte
VimL:" hint: std::ostringstream oss; oss << ...
VimL: let s:value_start  = '¡'
VimL: let s:value_end    = '¡'
VimL: let s:reindent     = 1 
VimL: let s:marker_open  = '<+'
VimL: let s:marker_close = '+>'
VimL: call s:AddPostExpandCallback('lh#dev#import#add("<sstream>")')
std::ostringstream oss;
oss << <++>;
<++>


================================================
FILE: after/template/cpp/otb-sug-latex.template
================================================
VimL:" $Id$
VimL:" otb-sug-latex File Template, Luc Hermitte, 21st May 2012
VimL:" hint: Software Guide : BeginLatex
VimL: let s:marker_open  = '<+'
VimL: let s:marker_close = '+>'
// Software Guide : BeginLatex
//
¡s:Surround(1, '//  <+doc+>')¡
//
// Software Guide : EndLatex


================================================
FILE: after/template/cpp/otb-sug-snippet.template
================================================
VimL:" $Id$
VimL:" otb-sug-snippet File Template, Luc Hermitte, 21st May 2012
VimL:" hint: Software Guide : BeginCodeSnippet
VimL: let s:marker_open  = '<+'
VimL: let s:marker_close = '+>'
// Software Guide : BeginCodeSnippet
¡s:Surround(1, '<+code+>')¡
// Software Guide : EndCodeSnippet


================================================
FILE: after/template/cpp/path.template
================================================
VimL:" boost-path File Template, Luc Hermitte, 29th Apr 2014
VimL:" hint: boost::filesystem::path
VimL: let s:value_start = '¡'
VimL: let s:value_end   = s:value_start
VimL: let s:marker_open  = '<+'
VimL: let s:marker_close = '+>'
VimL: call s:AddPostExpandCallback('lh#dev#import#add("<boost/filesystem.hpp>")')
boost::filesystem::path<++>


================================================
FILE: after/template/cpp/ptr_vector.template
================================================
VimL:" ptr_vector File Template, Luc Hermitte <hermitte at free.fr>, 22nd May 2014
VimL:" hint: boost::ptr_vector<>
VimL:" hint: std::vector<>
VimL: let s:value_start = '¡'
VimL: let s:value_end   = s:value_start
VimL: let s:marker_open  = '<+'
VimL: let s:marker_close = '+>'
VimL: call s:AddPostExpandCallback('lh#dev#import#add("<boost/ptr_container/ptr_vector.hpp>")')
boost::ptr_vector<¡s:Surround(1, '<+type+>')¡> <++>


================================================
FILE: after/template/cpp/ref_setter.template
================================================
VimL:" setter File Template, Luc Hermitte <hermitte {at} free {dot} fr>, 02nd Dec 2015
VimL:" hint: void setFoo(T const& foo) { *m_foo = foo; } // for ptr attributes
VimL: let s:marker_open  = '<+'
VimL: let s:marker_close = '+>'
VimL: let s:reindent     = 1
VimL: "The interactive mode (w/ dynamic placeholders) won't permit to have "setFoo" and "return m_foo".
MuT:  let s:attribute    = s:Param("attribute", {'type': lh#marker#txt(lh#naming#type('type')), 'name': lh#marker#txt('name')})
MuT:  let s:attrb_name   = s:attribute.name
MuT:  let s:attrb_param  = lh#naming#param(s:attrb_name)
MuT:  if !lh#dev#cpp#types#IsPointer(s:attribute.type)
VimL:   throw "ref_setter snippet: ".s:attribute.type." is not recognized as a pointer type"
MuT:  else
MuT:    let s:in_type = lh#dev#cpp#types#remove_ptr(s:attribute.type)
VimL:   let s:in_type = lh#dev#cpp#types#const_correct_type(s:in_type)
void <+lh#naming#setter(s:attrb_name)+>(<+s:in_type+> <+s:attrb_param+>){*<+lh#naming#member(s:attrb_name)+> = <+s:attrb_param+>;}
MuT:  endif


================================================
FILE: after/template/cpp/scoped_ptr.template
================================================
VimL:" scoped_ptr File Template, Luc Hermitte <hermitte {at} free {dot} fr>, jeu. 23 juin 2016 17:28:07 CEST
VimL:" hint: boost::scoped_ptr<>
VimL: let s:value_start = '¡'
VimL: let s:value_end   = s:value_start
VimL: let s:marker_open  = '<+'
VimL: let s:marker_close = '+>'
VimL: call s:AddPostExpandCallback('lh#dev#import#add("<boost/scoped_ptr.hpp>")')
boost::scoped_ptr<¡s:Surround(1, '<+type+>')¡><+s:TerminalPlaceHolder()+>


================================================
FILE: after/template/cpp/set.template
================================================
VimL:" set File Template, Luc Hermitte, 28th Apr 2014
VimL:" hint: std::set<>
VimL: let s:value_start = '¡'
VimL: let s:value_end   = s:value_start
VimL: let s:marker_open  = '<+'
VimL: let s:marker_close = '+>'
VimL: call s:AddPostExpandCallback('lh#dev#import#add("<set>")')
std::set<¡s:Surround(1, '<+type+>')¡><+s:TerminalPlaceHolder()+>


================================================
FILE: after/template/cpp/setter.template
================================================
VimL:" setter File Template, Luc Hermitte <hermitte {at} free {dot} fr>, 02nd Dec 2015
VimL:" hint: void setFoo(T const& foo) { m_foo = foo; }
VimL: let s:marker_open  = '<+'
VimL: let s:marker_close = '+>'
VimL: let s:reindent     = 1
VimL: "The interactive mode (w/ dynamic placeholders) won't permit to have "setFoo" and "return m_foo".
MuT:  let s:attribute    = s:Param("attribute", {'type': lh#marker#txt(lh#naming#type('type')), 'name': lh#marker#txt('name')})
MuT:  let s:attrb_name   = s:attribute.name
MuT:  let s:attrb_param  = lh#naming#param(s:attrb_name)
void <+lh#naming#setter(s:attrb_name)+>(<+lh#dev#cpp#types#const_correct_type(s:attribute.type)+> <+s:attrb_param+>){<+lh#naming#member(s:attrb_name)+> = <+s:attrb_param+>;}


================================================
FILE: after/template/cpp/shared_ptr.template
================================================
VimL:" shared_ptr File Template, Luc Hermitte, 28th Apr 2014
VimL:" hint: std/boost::shared_ptr<>
VimL: let s:value_start = '¡'
VimL: let s:value_end   = s:value_start
VimL: let s:marker_open  = '<+'
VimL: let s:marker_close = '+>'
MuT:  if lh#cpp#use_cpp11()
VimL:    call s:AddPostExpandCallback('lh#dev#import#add("<memory>")')
std::shared_ptr<¡s:Surround(1, '<+type+>')¡> <++>
MuT:  else
VimL:    call s:AddPostExpandCallback('lh#dev#import#add("<boost/shared_ptr.hpp>")')
boost::shared_ptr<¡s:Surround(1, '<+type+>')¡> <++>
MuT:  endif


================================================
FILE: after/template/cpp/singleton.template
================================================
VimL:" C++ Singleton-Class Template, Luc Hermitte
VimL:" «Meyers singleton», cf. More Effective C++ Item 26
VimL:" For a more precise definition, cf. A. Alexandrescu's Modern C++ Design
VimL:" hint: Singleton class Wizard
VimL: let s:value_start  = '¡'
VimL: let s:value_end   = s:value_start
VimL: let s:reindent     = 1
VimL: let s:marker_open  = '<+'
VimL: let s:marker_close = '+>'
MuT:  let s:parameters = s:Param('cls_parameters', {})
VimL: call lh#dict#add_new(s:parameters, {'noncopyable': 1, 'final': 1, 'comments': {}})
MuT:  let s:functions = s:Param('functions', lh#cpp#snippets#new_function_list())
VimL: " in case the class name is already known, no need to extract it
VimL: call s:Include('get-class-name', 'cpp/internals')
VimL: " Defines Doxygen comments
MuT:  let s:cls_comments = s:parameters.comments
VimL: let s:cls_comments.brief = lh#dox#brief(s:clsname.' singleton.')
VimL: " Ask which kind
MuT:  let s:type = confirm('Of what type of the singleton should be?', "&Meyers' (local-static, MT-safe (in C++11), default ctr)\n" .'&Explicit Initialisation (MT-safe)', 2 - lh#cpp#use_cpp11())
MuT:  if s:type == 1
VimL: " ----> Meyers' singleton
VimL:    " --- instance()
MuT:     let s:instance = {'signature': 'static <+__clsname__+> & instance() '.lh#cpp#snippets#noexcept()}
VimL:    let s:instance.implementation = "static <+__clsname__+> s_instance;\nreturn s_instance;"
VimL:    let s:instance.comments = {'brief': 'Singleton Accessor.', 'throw': 'None'}
VimL:    call s:functions.insert(s:instance)
VimL:    " --- Force default-constructor and destructor to private
VimL:    " And set how to defaulted, in not already set
MuT:     let s:default_constructor = s:Param('default-constructor', {})
VimL:    let s:default_constructor.visibility = 'private'
VimL:    let s:default_constructor.comments = {'text': ['Hidden constructor.'], 'see': '`instance()`'}
VimL:    call lh#dict#add_new(s:default_constructor, {'how': 'defaulted'})
MuT:     let s:destructor = s:Param('destructor', {})
VimL:    let s:destructor['visibility'] = 'private'
VimL:    call lh#dict#add_new(s:destructor, {'how': 'defaulted'})
VimL:    " --- Complete Doxygen comments
VimL:    let s:cls_comments.semantics = ['Implicitly initialized with a default constructor', 'MT-safe', 'Non-copyable']
VimL:    " --- Insert the skeleton built
VimL:    call s:Include('class-skeleton', 'cpp/internals', s:parameters)
MuT:  elseif s:type == 2
VimL: " ----> Explicit' singleton
VimL:    call s:AddPostExpandCallback('lh#dev#import#add("<cassert>")')
VimL:    " --- instance()
MuT:     let s:instance = {}
VimL:    let s:instance.comments = {'brief': 'Singleton Accessor.', 'throw': 'None', 'pre': '`ms_instance != nullptr`'}
VimL:    let s:instance.signature = 'static <+__clsname__+> & instance() '.lh#cpp#snippets#noexcept()
VimL:    let s:instance.implementation = 'assert(ms_instance && "Singleton not initialized.");'
VimL:    let s:instance.implementation .= "\nreturn *ms_instance;"
VimL:    call s:functions.insert(s:instance)
VimL:    " --- create()
MuT:     let s:create = {}
VimL:    let s:create.comments = {'brief': 'Singleton Construction.', 'throw': lh#marker#txt('std::exception'), 'pre': ' `ms_instance == nullptr`', 'post': '`ms_instance != nullptr`'}
VimL:    let s:create.signature = 'static void create('.lh#marker#txt('Parameters').')'
VimL:    let s:create.implementation = 'assert(!ms_instance && "Singleton already initialized.");'
VimL:    let s:create.implementation .= "\nms_instance = new <+__clsname__+>(".lh#marker#txt('parameters').');'
VimL:    call s:functions.insert(s:create)
VimL:    " --- release()
MuT:     let s:release = {}
VimL:    let s:release.comments = {'brief': 'Singleton Destruction.', 'throw': 'None', 'pre': ' `ms_instance != nullptr`', 'post': '`ms_instance == nullptr`'}
VimL:    let s:release.signature = 'static void release() '.lh#cpp#snippets#noexcept()
VimL:    let s:release.implementation = 'assert(ms_instance && "Singleton not initialized.");'
VimL:    let s:release.implementation .= "\nms_instance = ".lh#cpp#snippets#nullptr().";"
VimL:    call s:functions.insert(s:release)
VimL:    " --- Define an init-constructor
MuT:     let s:init_constructor = s:functions.get1({'kind' : 'init-constructor'})
VimL:    let s:init_constructor.visibility = 'private'
VimL:    " call s:functions.insert(s:init_constructor)
VimL:    " --- Set destructor to private, set how to defaulted, in not already set
MuT:     let s:destructor = s:Param('destructor', {})
VimL:    let s:destructor['visibility'] = 'private'
VimL:    call lh#dict#add_new(s:destructor, {'how': 'defaulted'})
VimL:    " --- Complete Doxygen comments
VimL:    let s:cls_comments.semantics = ['Explicitly initialized', 'MT-safe', 'Non-copyable']
VimL:    " --- Insert the skeleton built
VimL:    call s:Include('class-skeleton', 'cpp/internals', s:parameters)
// don't forget to move the following definition to <+expand('%:t:r')+>.cpp
<+s:clsname+> *<+s:clsname+>::ms_instance = <+lh#cpp#snippets#nullptr()+>;
MuT:  endif


================================================
FILE: after/template/cpp/sort.template
================================================
VimL:" std::sort File Template, Luc Hermitte, 28th May 2015
VimL:" hint: std::sort(range.begin(), range.end());
VimL:" todo: support for std::begin() and std::end()
VimL: let s:value_start = '¡'
VimL: let s:value_end   = s:value_start
VimL: let s:marker_open  = '<+'
VimL: let s:marker_close = '+>'
VimL: let s:reindent     = 1
VimL: call s:AddPostExpandCallback('lh#dev#import#add("<algorithm>")')
VimL: let s:range = s:Surround(1, s:Param('range', lh#marker#txt('range')))
std::sort(<+s:range+>.begin(),<+s:range+>.end());
VimL: unlet s:range


================================================
FILE: after/template/cpp/starts_with.template
================================================
VimL:" starts_with File Template, Luc Hermitte <hermitte at free.fr>, 28th May 2014
VimL:" hint: boost::algorithm::starts_with
VimL: let s:value_start = '¡'
VimL: let s:value_end   = s:value_start
VimL: let s:marker_open  = '<+'
VimL: let s:marker_close = '+>'
VimL: call s:AddPostExpandCallback('lh#dev#import#add("<boost/algorithm/string/predicate.hpp>")')
boost::algorithm::starts_with(<+input+>, <+prefix_searched+>)


================================================
FILE: after/template/cpp/static_assert.template
================================================
VimL:" static_assert File Template, Luc Hermitte, 23rd Apr 2014
VimL:" hint: static_assert(cond, msg)/BOOST_STATIC_ASSERT(cond)
VimL: let s:marker_open  = '<+'
VimL: let s:marker_close = '+>'
VimL: let s:reindent     = 1
VimL: let s:_condition = s:Param('condition', lh#marker#txt("condition"))
VimL: let s:_message   = s:Param('message', lh#marker#txt("message"))
MuT:  if lh#cpp#use_cpp11()
static_assert(<+s:_condition+>, <+s:_message+>);
MuT:  else
BOOST_STATIC_ASSERT(<+s:_condition+>);
VimL: call s:AddPostExpandCallback(lh#dev#import#add("<boost/static_assert.hpp>"))
MuT:  endif


================================================
FILE: after/template/cpp/stream-extractor.template
================================================
VimL:" C++ stream-extractor (operator>>) Template, Luc Hermitte, 04th Jun 2004
VimL:" hint: istream& operator>>(istream &, class-type)
VimL: let s:value_start = '¡'
VimL: let s:value_end   = s:value_start
VimL: let s:direction   = 'i'
VimL: call s:Include('stream-common', 'cpp/internals')


================================================
FILE: after/template/cpp/stream-inserter.template
================================================
VimL:" C++ stream-inserter (operator<<) Template, Luc Hermitte, 04th Jun 2004
VimL:" hint: ostream& operator<<(ostream &, class-type)
VimL: let s:value_start = '¡'
VimL: let s:value_end   = s:value_start
VimL: let s:direction   = 'o'
VimL: call s:Include('stream-common', 'cpp/internals')


================================================
FILE: after/template/cpp/string.template
================================================
VimL:" string File Template, Luc Hermitte, 28th Apr 2014
VimL:" hint: std::string
VimL: let s:marker_open  = '<+'
VimL: let s:marker_close = '+>'
VimL: call s:AddPostExpandCallback('lh#dev#import#add("<string>")')
std::string<+s:TerminalPlaceHolder()+>


================================================
FILE: after/template/cpp/swap-function.template
================================================
VimL:" swap-function File Template, Luc Hermitte <hermitte {at} free {dot} fr>, mar. 22 déc. 2015 11:34:40 CET
VimL:" hint: void swap(T & other)
VimL: let s:marker_open  = '<+'
VimL: let s:marker_close = '+>'
VimL: call s:Include('get-class-name', 'cpp/internals')
MuT:  let s:param_name = lh#naming#param("other")
VimL: let s:fn_comments = lh#dox#new_function("Swap operation.")
VimL: let s:fn_comments.throw = ["None"]
VimL: let s:fn_comments.param = [{'name': s:param_name, 'text': "data with which content is swapped", 'dir': 'in,out'}]
VimL: call s:Include("function-comment", "cpp/internals",s:fn_comments)
VimL: " If parameters are known => swap them!
MuT:  let s:attributes = s:Param("attributes", lh#option#unset())
MuT:  if lh#option#is_set(s:attributes) && !empty(s:attributes)
MuT:    let s:definition = "{using std::swap;\n"
VimL:   let s:definition .= join(map(copy(s:attributes), '"swap(".lh#naming#member(v:val.name).", ".s:param_name.".".lh#naming#member(v:val.name).");"'), "\n")
VimL:   let s:definition .= '}'
MuT:  else
MuT:    let s:definition = ';'
MuT:  endif
void swap(<+s:clsname+> & <+s:param_name+>) <+lh#cpp#snippets#noexcept()+><+s:definition+>


================================================
FILE: after/template/cpp/throw.template
================================================
VimL:"{throw default exceptions for project} Template-File, Luc Hermitte
VimL:" hint: throw std::runtime_error/@throw (depending on context)
VimL:"
VimL:" This snippet supports options:
VimL:" - b:exception_type in the form of a string
VimL:" - b:exception_args in the form of lh#function:
VimL:"   e.g.: let b:exception_args = 'v:1_.lh#marker#txt(", ".b:cpp_project_namespace."::ExitCode::")'
VimL:"   This functor takes a parameter that will get injected in place of v:1_
VimL:"   e.g. VimL: call s:Include('throw', 'cpp', '"Cannot decode'.s:enum_name.'"')
VimL:"   Note: If you want to dynamically adapt to the current marcher
VimL:"   characters, or the current b:cpp_project_namespace option, don't use `string()`
VimL:"   in expressions like:
VimL:"   :let b:exception_args = 'v:1_.'.string(lh#marker#txt(', '.b:cpp_project_namespace.'::ExitCode::'))
VimL:"
VimL: let s:reindent     = 1
VimL: let s:marker_open  = '<+'
VimL: let s:marker_close = '+>'
MuT:  let s:_exception_type = lh#ft#option#get('exception_type', &ft, 'std::runtime_error')
MuT:  let s:_exception_txt  = empty(s:CmdLineParams()) ? lh#marker#txt('text') : (s:CmdLineParams()[0])
MuT:  let s:_exception_args = lh#function#bind(lh#ft#option#get('exception_args', &ft, 'v:1_'))
MuT:  if synIDattr(synID(line('.'),col('.')-1,1),'name') =~ 'doxygen\|comment'
<+lh#dox#throw(lh#marker#txt(s:_exception_type))+><++>
MuT:  else
MuT:    if s:_exception_type =~ 'std::.*'
VimL:     call s:AddPostExpandCallback('lh#dev#import#add("<stdexcept>")')
MuT:    endif
throw <+s:_exception_type+>(<+lh#function#execute(s:_exception_args, s:_exception_txt)+>);<++>
MuT:  endif
VimL: unlet s:_exception_type
VimL: unlet s:_exception_txt
VimL: unlet s:_exception_args


================================================
FILE: after/template/cpp/traits.template
================================================
VimL:" traits-class File Template, Luc Hermitte, 20th Jan 2011
VimL:" hint: traits-class
VimL: let s:value_start = '¡'
VimL: let s:value_start = '¡'
VimL: let s:value_end   = s:value_start
VimL: let s:marker_open  = '<+'
VimL: let s:marker_close = '+>'
/** <+name+> traits class.
 */
template <typename <+T+>> struct <+name+>_traits
{
    <++>
};

/** <+name+> traits class specialization for \c <+spe+>.
 */
VimL: " todo: auto deduce the overridable traits
template <> struct <+name+>_traits<<+spe+>>
{
    <++>
};


================================================
FILE: after/template/cpp/try.template
================================================
VimL:"{try{...}catch(){...}} Template-File, Luc Hermitte
VimL:" hint: try { ... } catch(...) { ... }
VimL: let s:value_start  = '¡'
VimL: let s:value_end    = '¡'
VimL: let s:reindent     = 1
VimL: let s:marker_open  = '<+'
VimL: let s:marker_close = '+>'
try{
    ¡s:Surround(1, '<+code+>')¡
}catch(<+std::exception const& e+>){
    ¡s:Surround(2, '<+catch-code+>')¡
} <+s:TerminalPlaceHolder()+>


================================================
FILE: after/template/cpp/typeid.template
================================================
VimL:" typeid File Template, Luc Hermitte <hermitte {at} free {dot} fr>, jeu. 31 mars 2016 11:38:16 CEST
VimL:" hint: typeid(<++>).name()
VimL: let s:value_start = '¡'
VimL: let s:value_end   = s:value_start
VimL: let s:marker_open  = '<+'
VimL: let s:marker_close = '+>'
VimL: call s:AddPostExpandCallback('lh#dev#import#add("<typeinfo>")')
typeid(<+s:SurroundableParam("type", 1)+>).name()<+s:TerminalPlaceHolder()+>


================================================
FILE: after/template/cpp/unique_ptr.template
================================================
VimL:" unique_ptr File Template, Luc Hermitte, 28th Apr 2014
VimL:" hint: std::unique_ptr<>
VimL: let s:value_start = '¡'
VimL: let s:value_end   = s:value_start
VimL: let s:marker_open  = '<+'
VimL: let s:marker_close = '+>'
VimL: call s:AddPostExpandCallback('lh#dev#import#add("<memory>")')
std::unique_ptr<¡s:Surround(1, '<+type+>')¡> <++>


================================================
FILE: after/template/cpp/unordered_map.template
================================================
VimL:" unordered_map File Template, Luc Hermitte, 07th Oct 2017
VimL:" hint: std::unordered_map
VimL: let s:value_start = '¡'
VimL: let s:value_end   = s:value_start
VimL: let s:marker_open  = '<+'
VimL: let s:marker_close = '+>'
VimL: call s:AddPostExpandCallback('lh#dev#import#add("<unordered_map>")')
std::unordered_map<¡s:Surround(1, '<+key+>')¡, ¡s:Surround(2, '<+value+>')¡><+s:TerminalPlaceHolder()+>


================================================
FILE: after/template/cpp/unordered_set.template
================================================
VimL:" unordered_set File Template, Luc Hermitte, 07th Oct 2017
VimL:" hint: std::unordered_map
VimL: let s:value_start = '¡'
VimL: let s:value_end   = s:value_start
VimL: let s:marker_open  = '<+'
VimL: let s:marker_close = '+>'
VimL: call s:AddPostExpandCallback('lh#dev#import#add("<unordered_set>")')
std::unordered_set<¡s:Surround(1, '<+type+>')¡><+s:TerminalPlaceHolder()+>


================================================
FILE: after/template/cpp/utf8.template
================================================
let s:value_start  = '¡'
 


================================================
FILE: after/template/cpp/value-class.template
================================================
VimL:" value-class File Template, Luc Hermitte <hermitte {at} free {dot} fr>, 25th Nov 2015
VimL:" hint: Value Class ((implicitly) copyable, no hierarchy)
MuT:  let s:destructor = s:Param("destructor", {})
VimL: if get(s:destructor, 'virtual', 0) | throw "Value classes aren't expected to belong to polymorphic hierarchies" | endif
VimL: " --- in case the class name is already known, no need to extract it
VimL: call s:Include('get-class-name', 'cpp/internals')
VimL: " --- Defines Doxygen comments
MuT:  let s:parameters = s:Param('cls_parameters', {})
VimL: call lh#dict#add_new(s:parameters, {'comments': {}, 'copyable': 1})
MuT:  let s:cls_comments = s:parameters.comments
VimL: let s:cls_comments.semantics = get(s:cls_comments, 'semantics', [])
VimL: let s:cls_comments.semantics += ['Value object',lh#marker#txt('Regular object'),lh#marker#txt('Comparable')]
VimL: " --- Force special functions
VimL: " TODO: detect when the class has no declared attribute. Propose to force the generation of empty shells for the special functions in case the object will contain non-copyable attributes
VimL: " --- Insert the skeleton built
VimL: call s:Include('class-skeleton', 'cpp/internals', s:parameters)


================================================
FILE: after/template/cpp/vector.template
================================================
VimL:" vector File Template, Luc Hermitte, 28th Apr 2014
VimL:" hint: std::vector<>
VimL: let s:marker_open  = '<+'
VimL: let s:marker_close = '+>'
VimL: call s:AddPostExpandCallback('lh#dev#import#add("<vector>")')
MuT:  let s:type = s:SurroundableParam('type', 1)
std::vector<<+s:type+>> <+s:TerminalPlaceHolder()+>


================================================
FILE: after/template/cpp/weak_ptr.template
================================================
VimL:" weak_ptr File Template, Luc Hermitte, 28th Apr 2014
VimL:" hint: std/boost::weak_ptr<>
VimL: let s:value_start = '¡'
VimL: let s:value_end   = s:value_start
VimL: let s:marker_open  = '<+'
VimL: let s:marker_close = '+>'
MuT:  if lh#cpp#use_cpp11()
VimL:    call s:AddPostExpandCallback('lh#dev#import#add("<memory>")')
std::weak_ptr<¡s:Surround(1, '<+type+>')¡> <++>
MuT:  else
VimL:    call s:AddPostExpandCallback('lh#dev#import#add("<boost/shared_ptr.hpp>")')
boost::weak_ptr<¡s:Surround(1, '<+type+>')¡> <++>
MuT:  endif


================================================
FILE: after/template/cpp/while-getline.template
================================================
VimL:" while-getline File Template, Luc Hermitte, 06th Sep 2012
VimL:" hint: while(std::getline(stream,line)) { action; }
VimL: let s:value_start = '¡'
VimL: let s:value_end   = s:value_start
VimL: let s:marker_open  = '<+'
VimL: let s:marker_close = '+>'
VimL: let s:reindent     = 1
VimL: call s:AddPostExpandCallback('lh#dev#import#add("<string>")')
while(std::getline(<+stream+>, <+line+>)){
    ¡s:Surround(1, '<+code+>')¡
}<+s:TerminalPlaceHolder()+>


================================================
FILE: after/template/dox/author.template
================================================
VimL:" C++ Doxygen snippet for authors, Luc Hermitte
VimL:" hint: @author
VimL: let s:marker_open  = '<+'
VimL: let s:marker_close = '+>'
VimL: let s:reindent = 1
<+lh#dox#author()+>


================================================
FILE: after/template/dox/code.template
================================================
VimL:" doxygen <code/> File Template, Luc Hermitte, 11th Apr 2012
VimL:" hint: <code>|</code>
VimL: let s:marker_open  = '<+'
VimL: let s:marker_close = '+>'
VimL: let s:reindent     = 1
VimL: let s:code = s:Param("code", lh#marker#txt())
VimL: let s:text = s:Surround(1, s:code)
<+lh#dox#tag("code")+>
VimL: unlet s:code
VimL: unlet s:text


================================================
FILE: after/template/dox/em.template
================================================
VimL:" doxygen <em/> snippet, Luc Hermitte, 11th Apr 2012
VimL:" hint: <em>|</em>
VimL: let s:text = s:Surround(1, lh#marker#txt())
<em><+s:text+></em><+s:TerminalPlaceHolder()+>


================================================
FILE: after/template/dox/file.template
================================================
VimL:" dox/file Template, Luc Hermitte
VimL:" hint: /** @file ... */
VimL: let s:value_start  = '¡'
VimL: let s:value_end    = '¡'
VimL: let s:reindent     = 1
VimL: let s:marker_open  = '<+'
VimL: let s:marker_close = '+>'
VimL:"
/**<+lh#dox#tag("ingroup")+> g¡lh#option#get('dox_group', '<+Projet+>')¡
 * <+lh#dox#tag("file")+>    ¡expand('%:t')¡
 * <+lh#dox#author()+>
 * <+lh#dox#tag("version")+> ¡'$'¡Revision$
 * <+lh#dox#since()+>
 * ¡'$'¡Id$
 */



================================================
FILE: after/template/dox/function.template
================================================
VimL:" C++ Doxygen snippet for functions, Luc Hermitte
VimL:" Meant to be used through the command :DOX
VimL:" hint: /** @ingroup, @params, @exceptions, ... */
VimL:" TODO: rewrite to rely on function-comment.template
VimL: let s:value_start  = '¡'
VimL: let s:value_end    = '¡'
VimL: let s:reindent     = 1
VimL: let s:marker_open  = '<+'
VimL: let s:marker_close = '+>'
/**¡CppDox_snippet('ingroup', '')¡
 ¡CppDox_snippet('brief', '* ')¡
 * <+details+>
 ¡CppDox_snippet('Params', '* ')¡
 *
 ¡CppDox_snippet('return', '* ')¡
 ¡CppDox_snippet('exceptions', '* ')¡
 ¡CppDox_snippet('preconditions', '* ')¡
 */


================================================
FILE: after/template/dox/group.template
================================================
VimL:" Doxygen local group File-Template, Luc Hermitte, 26th Jan 2011
VimL:" hint: Doxygen local group
VimL: let s:marker_open  = '<+'
VimL: let s:marker_close = '+>'
VimL: let s:reindent     = 1
/**<+lh#dox#tag("name ")+><+group-name+> */
MuT:  let s:text = s:Surround(1, "<++>")
VimL: let s:text = s:text != "<++>" ? ("\n".s:text) : lh#marker#txt()
//@{<+s:text+>
//@}<+s:TerminalPlaceHolder()+>


================================================
FILE: after/template/dox/html.template
================================================
VimL:" doxygen <+html+> snippets, Luc Hermitte, 11th Apr 2012
VimL:" hint: <html-tag>|</html-tag>
VimL: let s:marker_open  = '<+'
VimL: let s:marker_close = '+>'
MuT: let s:text = s:Surround(1, lh#marker#txt())
MuT: let s:tag = s:Surround(2, lh#marker#txt("html"))
<<+s:tag+>><+s:text+></<+s:tag+>><+s:TerminalPlaceHolder()+>


================================================
FILE: after/template/dox/ingroup.template
================================================
VimL:" $Id$
VimL:" dox/ingroup File Template, Luc Hermitte, 23rd Dec 2013
VimL:" hint: /**@ingroup ... */
VimL: let s:value_start = '¡'
VimL: let s:value_end   = s:value_start
VimL: let s:marker_open  = '<+'
VimL: let s:marker_close = '+>'
VimL: let s:reindent     = 1
VimL:"
/**<+lh#dox#tag("ingroup")+> g¡lh#option#get('dox_group', '<+Projet+>')¡
 */<++>


================================================
FILE: after/template/dox/since.template
================================================
VimL:" C++ Doxygen snippet for since tag, Luc Hermitte
VimL:" hint: @since Version
VimL: let s:value_start = '¡'
VimL: let s:value_end   = s:value_start
VimL: let s:marker_open  = '<+'
VimL: let s:marker_close = '+>'
<+lh#dox#since()+>


================================================
FILE: after/template/dox/tt.template
================================================
VimL:" doxygen <tt/> File Template, Luc Hermitte, 11th Apr 2012
VimL:" hint: <tt>|</tt>
MuT:  let s:text = s:Surround(1, lh#marker#txt())
<tt><+s:text+></tt><+s:TerminalPlaceHolder()+>


================================================
FILE: autoload/lh/cpp/AnalysisLib_Class.vim
================================================
" ========================================================================
" File:         autoload/lh/cpp/AnalysisLib_Class.vim                 {{{1
" Author:       Luc Hermitte <EMAIL:hermitte {at} free {dot} fr>
"               <URL:http://github.com/LucHermitte/lh-cpp>
" License:      GPLv3 with exceptions
"               <URL:http://github.com/LucHermitte/lh-cpp/tree/master/License.md>
let s:k_version = 220
" Version:      2.2.0
" Last Update:  31st Aug 2018
"------------------------------------------------------------------------
" Description:
"       Library C++ ftplugin.
"       It provides functions used by other C++ ftplugins.
"       The theme of this library is the analysis of C++ scopes.
"
" Defines: {{{2
" (*) Function: lh#cpp#AnalysisLib_Class#CurrentScope(lineNo, scope_type)
"     Returns the scope (class name or namespace name) at line lineNo.
"     scope_type can value: "any", "class" or "namespace".
" (*) Function: lh#cpp#AnalysisLib_Class#SearchClassDefinition(lineNo)
"     Returns the class name of any member at line lineNo -- could be of the
"     form: "A::B::C" for nested classes.
"     Note: Outside class-scope, an empty string is returned
"     Note: Classes must be correctly defined: don't forget the ';' after the
"     '}'
" (*) Function lh#cpp#AnalysisLib_Class#BaseClasses(lineNo)
"     Return the list of the direct base classes of the class around lineNo.
"     form: "+a_public_class, #a_protected_class, -a_private_class"
" }}}2
"------------------------------------------------------------------------
" Installation: See |lh-cpp-readme.txt|
" Dependencies: VIM 7.0+

" History:      {{{2
"       06th Dec 2016
"       (*) Fix scope searching to ignore non-namespace/enum/class scopes
"       17th Feb 2015
"       (*) + list available namespaces
"       (*) + simplfy_id()
"       31st May 2012
"       (*) v2.0.0 , License GPLv3 w/ extension
"       26th Aug 2011
"       (*) list of imported namespaces lh#cpp#AnalysisLib_Class#used_namespaces
"       31st May 2010
"       (*) many generic functions move to lh#dev#class#
"       23rd Apr 2008
"       (*) #Ancestors() return the list of base classes (topologicaly sorted)
"       13th Feb 2008
"       (*) new option [bg]:cpp_defines_to_ignore
"       12th Sep 2007
"       (*) support "namespace NS1 { namespace NS2 {" on a same line
"
"       07th Oct 2006
"       (*) Renamed from ftplugin/cpp/cpp_FindContextClass.vim to
"       autoload/lh/cpp/AnalysisLib_Class.vim
"
"       16th May 2006
"       (*) Bug fix: "using namespace" was misdirecting lh#cpp#AnalysisLib_Class#CurrentScope(), and
"           :GOTOIMPL as a consequence.
"       29th Apr 2005
"       (*) Not misdriven anymore by:
"           - forward declaration in namespaces
"             -> "namespace N {class foo;} namespace M{ class bar{}; }"
"       09th Feb 2005
"       (*) class_token += enum\|union
"       (*) Not misdriven anymore by:
"           - consecutive classes
"             -> "namespace N {class foo {}; class bar{};}"
"           - comments
"       16th dec 2002
"       (*) Bug fixed regarding forwarded classes.
"       16th oct 2002
"       (*) Able to handle C-definitions like
"           "typedef struct foo{...} *PFoo,Foo;"
"       (*) An inversion problem, with nested classes, fixed.
"       (*) Cpp_SearchClassDefinition becomes obsolete. Instead, use
"           lh#cpp#AnalysisLib_Class#CurrentScope(lineNo, scope_type) to search for a
"           namespace::class scope.
"       11th oct 2002
"       (*) Cpp_SearchClassDefinition supports:
"           - inheritance -> 'class A : xx B, xx C ... {'
"           - and declaration on several lines of the previous inheritance
"           text.
"       (*) Functions that will return the list of the direct base classes of
"           the current class.
"
" TODO: {{{2
" (*) Support templates -> A<T>::B, etc
" (*) Must we differentiate anonymous namespaces from the global namespace ?
" (*) reinject implicit context in #Ancestors
" }}}1
" ==========================================================================
let s:cpo_save = &cpo
set cpo&vim
" ==========================================================================
" Internal constant regexes {{{1
" Note: this regex can be tricked with nasty comments
let s:id              = '\(\<\I\i*\>\)'
let s:class_token     = '\<\(class\|struct\|enum\|union\)\>'
let s:class_part      = s:class_token  . '\_s\+' . s:id
let s:namespace_token = '\<\(namespace\)\>\_s\+'
let s:namespace_part  = s:namespace_token . s:id

let s:both_token     = '\<\(struct\|enum\(\s\+class\)\=\|\(enum\s\+\)\@<!class\|union\|namespace\)\>'
let s:both_part      = s:both_token  . '\_s\+' . s:id
" let s:namespace_part = '\<\(namespace\)\>\_s\+' . s:id . '\='
" Use '\=' for anonymous namespaces

" let s:class_open      = '\_.\{-}{'
" '.' -> '[^;]' in order to avoid forward declarations.
let s:class_open00    = '\_[^;]\{-}{'
let s:class_open      = '\_[^;]\{-}'
let s:class_close     = '}\%(\_s\+\|\*\=\s*\<\I\i*\>,\=\)*;'
  "Note: '\%(\_s*\|\*=\s*\<\I\i*\>,\=\)*' is used to accept C typedef like :
  "  typedef struct foo {...} *PFoo, Foo;
let s:namespace_open00= '\_s*{'
let s:namespace_open  = '\_s*'
let s:namespace_close = '}'
" }}}1
" ==========================================================================
" Debug oriented command {{{1
if exists('g:force_load_cpp_FindContextClass')
  command! -nargs=1 CppCACEcho :echo s:<arg>
endi

" # Version {{{2
function! lh#cpp#AnalysisLib_Class#version()
  return s:k_version
endfunction

" # Debug   {{{2
let s:verbose = get(s:, 'verbose', 0)
function! lh#cpp#AnalysisLib_Class#verbose(...)
  if a:0 > 0 | let s:verbose = a:1 | endif
  return s:verbose
endfunction

function! s:Log(expr, ...)
  call call('lh#log#this',[a:expr]+a:000)
endfunction

function! s:Verbose(expr, ...)
  if s:verbose
    call call('s:Log',[a:expr]+a:000)
  endif
endfunction

function! lh#cpp#AnalysisLib_Class#debug(expr) abort
  return eval(a:expr)
endfunction

" }}}1
" ==========================================================================
" Search for current and most nested namespace/class <internal> {{{

let s:skip_comments = 'synIDattr(synID(line("."), col("."), 0), "name") =~?'
      \ . '"string\\|comment\\|doxygen"'

function! s:SearchBracket() abort
  let flag = 'bW'
  let res = searchpair('{', '', '}', flag, s:skip_comments)
  call s:Verbose('|   +-> s:SearchBracket("{", "", "}", "bW" -- from=%1) --> %2', getpos('.'), res)
  return res
endfunction

let s:k_skip_comments = '(synIDattr(synID(line("."), col("."), 0), "name") '
      \ . '!~? "c\\%(pp\\)\\=Structure")'
let s:k_skip_using_ns = '(getline(".") =~ "using\s*namespace")'
function! s:CurrentScope(bMove, scope_type) abort
  call s:Verbose('+-> s:CurrentScope(%1) at %2', a:, getpos('.'))
  let flag = a:bMove ? 'bW' : 'bnW'
  let pos = 'call cursor(' . line('.') . ',' . col('.') . ')'
  let result = line('.')
  try
    while 1
      " First, search for current block start
      let result = s:SearchBracket()
      if result <= 0 | return result | endif

      " Then, check whether this is the kind of scoping block we are looking for
      let start = substitute(s:both_part, '(', '%(', 'g'). s:{a:scope_type}_open
      let last_pos = lh#position#getcur()
      let result = searchpair(
            \ start, '', '{', 'bW',
            \ s:k_skip_comments.'&&'.s:k_skip_using_ns)
      call s:Verbose('|   +-> searchpair(%1, "", "{", %2, skip comments & using) -> %3', start, flag, result)
      if result > 0
        " Be sure this is the exact token searched (s:both_path searches
        " everything)
        call s:Verbose("|   +-> %3: '%1' =~ '%2'", getline(result), '.*'.s:{a:scope_type}_token.'.*', getline(result) =~ '.*'.s:{a:scope_type}_token.'.*' ? 'True': 'False')
        if getline(result) !~ '.*'.s:{a:scope_type}_token.'.*'
          let result = 0 " needed by finally
          return result
        endif
        " Check that if we search this last thing in the other direction then
        " we go to the last_pos
        let r2 = searchpairpos(start, '', '{', 'Wn',
              \ s:k_skip_comments.'&&'.s:k_skip_using_ns)
        call lh#assert#value(r2[0]).is_gt(0)
        if r2 == last_pos[1:2]
          " This was a searched scope
          call s:Verbose('|  +-> This was searched scope => return %1', result)
          return result
        endif
        call s:Verbose('|   +-> The previous scope start (%1) is not compatible with the current scope found (%2)', lh#position#getcur(), last_pos)
        call setpos('.', last_pos) " go back and search again
      endif
    endwhile
    return result
  finally
    if result <= 0
      exe pos
    endif
  endtry
endfunction


" obsolete
function! s:CurrentScope000(bMove,scope_type) abort
  let flag = a:bMove ? 'bW' : 'bnW'
  return searchpair(
        \ substitute(s:{a:scope_type}_part, '(', '%(', 'g')
        \ . s:{a:scope_type}_open00, '', s:{a:scope_type}_close00, flag,
        \ s:skip_comments)
  "Note: '\(..\)' must be changed into '\%(...\)' with search() and
  "searchpair().
endfunction
" }}}
" ==========================================================================
" Search for a class definition (not forwarded definition) {{{
" Checks whether lineNo is in between the '{' at line classStart and its
" '}' counterpart ; in that case, returns "::".className
function! s:SearchClassOrNamespaceDefinition(class_or_ns) abort
  call s:Verbose('s:SearchClassOrNamespaceDefinition(%1)', a:)
  let pos = 1
  let scope = ''
  let defines = lh#option#get('cpp_defines_to_ignore', '')
  while pos > 0
    let pos = s:CurrentScope(1, a:class_or_ns)
    if pos > 0
      " in case of "ns NS1 { ns NS2 {", filter from cursor to EOL
      let line = getline(pos)[col('.')-1:]
      if strlen(defines) > 0
        let line = substitute(line, defines, '', 'g')
      endif
      let current_scope = substitute(line,
            \ '^.\{-}'.s:{a:class_or_ns}_part.'.*$', '\2', '')
      let scope = '::' . current_scope . scope
    endif
  endwhile
  return substitute (scope, '^:\+', '', 'g')
endfunction
" }}}
" ==========================================================================
" Search for a class definition (not forwarded definition) {{{
" Function: Cpp_SearchClassDefinition(lineNo [, bNamespaces])
" Checks whether lineNo is in between the '{' at line classStart and its
" '}' counterpart ; in that case, returns "::".className
function! lh#cpp#AnalysisLib_Class#SearchClassDefinition(lineNo,...) abort
  " let pos = a:lineNo
  exe a:lineNo
  let scope = s:SearchClassOrNamespaceDefinition('class')
  if (a:0 > 0) && (a:1 == 1)
    let ns = s:SearchClassOrNamespaceDefinition('namespace')
    let scope = ns . (((""!=scope) && (""!=ns)) ? '::' : '') . scope
  endif
  exe a:lineNo
  return scope
endfunction

" Possible Values:
"  - 'class'
"  - 'namespace'
"  - 'any'
function! lh#cpp#AnalysisLib_Class#CurrentScope(lineNo, scope_type) abort
  exe a:lineNo
  if a:scope_type =~ 'any\|##'
    let scope = s:SearchClassOrNamespaceDefinition('class')
    let ns = s:SearchClassOrNamespaceDefinition('namespace')
    let scope = ns . (((""!=scope) && (""!=ns))
          \ ? ((a:scope_type == '##') ? '#::#' : '::')
          \ : '') . scope
  elseif a:scope_type =~ 'class\|namespace'
    let scope = s:SearchClassOrNamespaceDefinition(a:scope_type)
  else
    echoerr 'lh#cpp#AnalysisLib_Class#CurrentScope(): the only ' .
          \ 'scope-types accepted are {class}, {namespace} and {any}!'
    return ''
  endif
  exe a:lineNo
  return scope
endfunction
" }}}
" ==========================================================================
" Function: lh#cpp#AnalysisLib_Class#search_closest_class(line) {{{
function! lh#cpp#AnalysisLib_Class#search_closest_class(line) abort
  " We can't use search('class|struct', b') as it will not distinguish
  " "class foo" from "template <class Foo> void f()"
  " So, we'll use ctags for now, and libclang in the future
  try
    let session = lh#tags#session#get()
    let tags = session.tags
    " tags generated by lh#tags#session#get() have a line field
    let tags = filter(copy(tags), 'v:val.kind=~"[sc]" && v:val.line < a:line')
    " and they are sorted by lines numbers...
    if empty(tags)
      call lh#common#error_msg("No class definition upstream")
      return ''
    else
      return tags[-1].name
    endif
  finally
    call session.finalize()
  endtry
endfunction
" }}}
" ==========================================================================
" Search for templates specs <internal> {{{
function! s:TemplateSpecs() abort
endfunction
" }}}
" ==========================================================================
" Search for the direct base classes <internal> <deprecated> {{{
function! s:BaseClasses0(pos) abort
  " a- Retrieve the declaration: 'class xxx : yyy {' zone limits {{{
  let pos = a:pos
  let end_pos = line('$')
  let decl = ''
  while pos < end_pos
    " Concat lines and strip comments on the way to the '{'.
    let text = substitute(getline(pos), '/\*.\{-}\*/\|//.*$', '', 'g')
    let decl = decl . ' ' . text
    if text =~ '{' | break | endif
    let pos = pos + 1
  endwhile
  " }}}
  " b- Get the base classes only {{{
  let base = substitute(decl, '^.*'.s:class_part.'[^:]*:\([^{]*\){.*$', '\3','')
  let base = substitute(base, 'public',    '+', 'g')
  let base = substitute(base, 'protected', '#', 'g')
  let base = substitute(base, 'private',   '-', 'g')
  let base = substitute(base, '\s*', '', 'g')
  let base = substitute(base, ',', ', ', 'g')
  " }}}
  return base
endfunction
function! lh#cpp#AnalysisLib_Class#BaseClasses0(lineNo) abort
  exe a:lineNo
  let pos = s:CurrentScope(1, 'class')
  exe a:lineNo
  return (pos > 0) ? s:BaseClasses0(pos) : ''
endfunction
" }}}
" ==========================================================================
" Search for the base classes {{{
" @todo determine the access rigths
" @todo get children
" @todo get all public functions
" @todo get available functions
" @todo get overidable functions
" @todo follow typedefs

function! lh#cpp#AnalysisLib_Class#GetClassTag(id) abort
  call lh#common#error_msg("lh#cpp#AnalysisLib_Class#GetClassTag is deprecated, use lh#dev#class#get_class_tag() instead")
  return lh#dev#option#call('class#get_class_tag', &ft, a:id)
endfunction


function! lh#cpp#AnalysisLib_Class#FetchDirectParents(id) abort
  call lh#common#error_msg("lh#cpp#AnalysisLib_Class#FetchDirectParents is deprecated, use lh#dev#class#fetch_direct_parents() instead")
  return lh#dev#option#call('class#fetch_direct_parents', &ft, a:id)
endfunction

function! lh#cpp#AnalysisLib_Class#Ancestors(id) abort
  call lh#common#error_msg("lh#cpp#AnalysisLib_Class#Ancestors is deprecated, use lh#dev#class#ancestors() instead")
  return lh#dev#option#call('class#ancestors', &ft, a:id)
endfunction

" }}}
" ==========================================================================
" Search for the child classes {{{1
" a:namespace_where_to_search is a hack because listing all element to extract
" classes is very slow!
" lh#cpp#AnalysisLib_Class#FetchDirectChildren(id, namespace_where_to_search [, recheck_namespace])
function! lh#cpp#AnalysisLib_Class#FetchDirectChildren(id, namespace_where_to_search, ...) abort
  call lh#common#error_msg("lh#cpp#AnalysisLib_Class#FetchDirectChildren is deprecated, use lh#dev#class#fetch_direct_children() instead")
  return lh#dev#option#call('class#fetch_direct_children', &ft, a:id)
endfunction

" }}}1
" ==========================================================================
" List of imported namespaces {{{1
" Function: lh#cpp#AnalysisLib_Class#used_namespaces([up_to]) {{{3
" @return list of imported namespaces
" @todo take the "namespace xx {" scop into account
function! lh#cpp#AnalysisLib_Class#used_namespaces(...) abort
  let up_to_line = (a:0>0) ? (a:1) : line('$')
  let imported_ns = map(
        \filter(
        \    getline(1,up_to_line),
        \    'v:val =~ "^\\s*using\\s\\+namespace"'),
        \ 'matchstr(v:val, "^\\s*using\\s\\+namespace\\s\\+\\zs.\\{-}\\ze\\s*;")'
        \ )
  return imported_ns
endfunction

" ==========================================================================
" List of available namespaces {{{1
" Function: lh#cpp#AnalysisLib_Class#available_namespaces(up_to) {{{3
" @return list of available namespaces (imported + current)
function! lh#cpp#AnalysisLib_Class#available_namespaces(up_to_line) abort
  let current_ns = lh#cpp#AnalysisLib_Class#CurrentScope(a:up_to_line, 'namespace')
  let imported_ns = lh#cpp#AnalysisLib_Class#used_namespaces(a:up_to_line)
  let ns_list = imported_ns + [current_ns]
  return ns_list
endfunction

" ==========================================================================
" Simplify id {{{1
" Function: lh#cpp#AnalysisLib_Class#simplify_id(id, available_scopes [, return_ns_found]) {{{3
" Strips the best scope that matches the {id}. If
" {return_ns_found} is set, return the matching scope as well.
" @see tests/lh/analysis.vim
function! lh#cpp#AnalysisLib_Class#simplify_id(id, available_scopes, ...) abort
  let return_ns_found = a:0==0 ? 0 : a:1
  let scopes = reverse(sort(a:available_scopes))
  let re = join(
        \ map(scopes, 'substitute(v:val, "^\\(.\\{-}\\)\\(::\\)\\=$", "^\\1\\\\(::\\\\)\\\\=", "")'),
        \'\|')
  let g:re = re
  if !return_ns_found
    return substitute(a:id, re, '', '')
  else
    let match = substitute(a:id, re, '&#', '')
    if stridx(match, '#') == -1
      let match = '#'.match
    endif
    return split(match, '#', 1)
  endif
endfunction

" ==========================================================================
" Fetch Attributes {{{1
function! lh#cpp#AnalysisLib_Class#attributes(id) abort
  call lh#common#error_msg("lh#cpp#AnalysisLib_Class#attributes is deprecated, use lh#dev#class#attributes() instead")
  return lh#dev#option#call('class#attributes', &ft, a:id)
endfunction
" }}}1
" ==========================================================================
let &cpo = s:cpo_save
" ========================================================================
" vim60: set fdm=marker:


================================================
FILE: autoload/lh/cpp/AnalysisLib_Function.vim
================================================
"=============================================================================
" File:         autoload/lh/cpp/AnalysisLib_Function.vim                  {{{1
" Author:       Luc Hermitte <EMAIL:hermitte {at} free {dot} fr>
"               <URL:http://github.com/LucHermitte/lh-cpp>
" License:      GPLv3 with exceptions
"               <URL:http://github.com/LucHermitte/lh-cpp/tree/master/License.md>
" Version:      2.2.0
" Created:      05th Oct 2006
" Last Update:  26th Nov 2019
"------------------------------------------------------------------------
" Description:
"       This plugin defines VimL functions specialized in the analysis of C++
"       code.
"       It can be seen as a library plugin.
"
" Functions Defined:
"       Scope: lh#cpp#AnalysisLib_Function#
"
"       GetFunctionPrototype(lineno, onlyDeclaration)
"               @param lineno           Number of the line where the prototype is fetched
"               @param onlyDeclaration  Restrict to function declarations (1), or
"                                      definition are accepted (0)
"               @return The exact prototype found at the given line
"
"       GetListOfParams(prototype)
"               @param prototype        Prototype to analyse
"               @return a list of [ {type}, {name}, {default value} ], one
"                       for each parameter specified in the prototype
"
"       AnalysePrototype(prototype)
"               @param prototype        Prototype to analyse
"               @return a |dictionary| made of the following fields:
"                       - qualifier: "" / "virtual" / "static" / "explicit"
"                       - return: type of the value returned by the function
"                       - name: list of the scopes + the name of the function
"                       - parameters: @see GetListOfParams
"                       - const: 0/1 whether the function is a const-member "                   function
"                       - throw: list of exception specified in the signature
"
"------------------------------------------------------------------------
" Installation:
"       Drop it into: {rtp}/autoload
"       Requirements: Vim7
" History:
"       v2.2.0
"       (*) Add detection of final, override, constexpr, noexept, volatile,
"          =default, =delete
"       (*) Fix regex building for operator()
"       (*) Support `decltype(auto)`
"       (*) Support `->` return type specification
"       v2.0.0
"       (*) GPLv3 w/ exception
"       (*) AnalysePrototype() accepts spaces between functionname and (
"       (*) Fix :GOTOIMPL to support operators like +=
"       v1.1.1
"       (*) lh#cpp#AnalysisLib_Function#GetListOfParams() is not messed up by
"       throw-spec
"       v1.0.1:
"       (*) Remembers the parameter is on a new line
"       v1.0.0: First version
"               Code extracted from cpp_GotoFunctionImpl
" TODO:
"       (*) Support template, function types, friends
" }}}1
"=============================================================================


"=============================================================================
let s:cpo_save=&cpo
set cpo&vim
"------------------------------------------------------------------------
" ## Functions {{{1
" # Debug {{{2
let s:verbose = get(s:, 'verbose', 0)
function! lh#cpp#AnalysisLib_Function#verbose(...)
  if a:0 > 0 | let s:verbose = a:1 | endif
  return s:verbose
endfunction

function! s:Log(...)
  call call('lh#log#this', a:000)
endfunction

function! s:Verbose(...)
  if s:verbose
    call call('s:Log', a:000)
  endif
endfunction

function! lh#cpp#AnalysisLib_Function#debug(expr)
  return eval(a:expr)
endfunction

"------------------------------------------------------------------------
" # Public {{{2
let s:k_not_available = lh#option#unset('libclang cannot tell')

" " Function: lh#cpp#AnalysisLib_Function#get_function_info(lineno, onlyDeclaration) {{{3
function! lh#cpp#AnalysisLib_Function#get_function_info(lineno, onlyDeclaration) abort
  try
    if lh#has#plugin('autoload/clang.vim') && clang#can_plugin_be_used()
      " TODO move cursor to function name
      let py_info = clang#get_symbol()
      if py_info.is_definition && a:onlyDeclaration
        return {}
      endif

      let [sNoexceptSpec, idx_s, idx_e] = lh#string#matchstrpos(py_info.type.spelling, s:re_noexcept_spec)
      call s:Verbose("sNoexceptSpec: %1 ∈ [%2, %3]", sNoexceptSpec, idx_s, idx_e)

      let info = {}
      let info.qualifier
            \ = py_info.static   ? 'static'
            \ : py_info.virtual  ? 'virtual'
            \ : ''
            " \ : py_info.explicit ? 'explicit'
            " As of 9, libclang still cannot tell whether a constructor is
            " declared explicit
      let info.return     = py_info.true_kind =~ '\vCONSTRUCTOR|DESTRUCTOR'
            \ ? ''
            \ : py_info.result_type.spelling
      let info.name       = py_info.spelling
      let info.constexpr  = s:k_not_available
      let info.const      = py_info.const
      let info.volatile   = py_info.type.spelling =~ '\v<volatile>'
      let info.pure       = py_info.pure
      let info.special_definition
            \ = py_info.is_default_method ? '= default'
            \ : ''
            " \ : py_info.deleted   ? '= delete'
            " As of 9, libclang still cannot tell whether a function is
            " deleted...
      let info.throw      = [] " Let's forget about this
      let info.noexcept   = sNoexceptSpec
      let info.final      = ! empty(get(py_info.children, 'CursorKind.CXX_FINAL_ATTR', {}))
      let info.overriden  = ! empty(get(py_info.children, 'CursorKind.CXX_OVERRIDE_ATTR', {}))
      let info.parameters = []
      for py_param in get(py_info.children, 'CursorKind.PARM_DECL', [])
        let param = {
              \ 'name'   : py_param.spelling
              \,'type'   : py_param.type.spelling
              \,'default': s:k_not_available
              \,'nl'     : s:k_not_available
              \ }
        let info.parameters += [param]
      endfor
      let info.tparams    = []
      for py_param in get(py_info.children, 'CursorKind.TEMPLATE_TYPE_PARAMETER', [])
            \ + get(py_info.children, 'CursorKind.TEMPLATE_NON_TYPE_PARAMETER', [])
        let param = {
              \ 'name'   : py_param.spelling
              \,'default': s:k_not_available
              \,'nl'     : s:k_not_available
              \ }
        let info.tparams += [param]
      endfor
      let info.start = py_info.extent.start
      let info.end   = py_info.extent.end
      return info
    endif
  catch /.*/
    call lh#common#warning_msg("We cannot use vim-clang+libclang to decode function prototype, falling back to pure vimscript analysis. ".v:exception)
  endtry

  " If vim-clang + libclang could not be used....
  let proto = lh#dev#c#function#get_prototype(a:lineno, a:onlyDeclaration)
  let info  = lh#cpp#AnalysisLib_Function#AnalysePrototype(proto)
  return info
endfunction

" Function: lh#cpp#AnalysisLib_Function#GetFunctionPrototype " {{{3
" Todo:
" * Retrieve the type even when it is not on the same line as the function
"   identifier.
" * Retrieve the const modifier even when it is not on the same line as the
"   ')'.
function! lh#cpp#AnalysisLib_Function#GetFunctionPrototype(lineno, onlyDeclaration) abort
  " deprecated
  return lh#dev#c#function#get_prototype(a:lineno, a:onlyDeclaration)
endfunction

" Function: lh#cpp#AnalysisLib_Function#get_prototype(pos, onlyDeclaration) {{{3
" @WARNING: never tested/used function
function! lh#cpp#AnalysisLib_Function#get_prototype(pos, onlyDeclaration) abort
  if type(a:pos) == type(0)
    let lineno = a:pos
    return lh#dev#c#function#get_prototype(lineno, a:onlyDeclaration)
  elseif type(a:pos) == type({}) " this is a tag definition
    " TODO: extract this position rollback code to its own function
    let cleanup = lh#on#exit()
    let filename = a:pos.filename
    let nb_windows = winnr('$')
    let crt_win = winnr()
    call lh#buffer#jump(filename, 'sp')
    if winnr('$') != nb_windows
      call cleanup.register(':q')
    elseif crt_win != winnr()
      call cleanup.register(':'.crt_win.'wincmd w')
    endif
    try
      if a:pos.cmd == '^/'
        let lineno = search(cmd, 'n')
      elseif a:pos.cmd == ':'
        let lineno = eval(a:pos.cmd[1:])
      endif
      if 0 == lineno
        throw "lh-cpp: Impossible to find where prototype for ".(a:pos.name). " is"
      endif
      return lh#dev#c#function#get_prototype(lineno, a:onlyDeclaration)
    finally
      call cleanup.finalize()
    endtry
  endif
endfunction
" }}}3

"------------------------------------------------------------------------
" Function: s:SplitTypeParam(typed_param) {{{3
" @return 4-uple -> [parameter-type, parameter-name, default-value, new-line-before]
" @under deprecation...
function! s:SplitTypeParam(typed_param) abort
  let pa = lh#dev#option#call('function#_analyse_parameter', &ft, a:typed_param)
  return [pa.type, pa.name, pa.default, pa.nl]
endfunction
" }}}3
"------------------------------------------------------------------------
" Function: lh#cpp#AnalysisLib_Function#GetListOfParams(prototype, mustCleanSpace) {{{3
" todo: beware of exception specifications
" todo: check about of functions types ; to be done with templates... ?
" todo: Arrays of pointers       : "T (*p)[n]"
function! lh#cpp#AnalysisLib_Function#GetListOfParams(prototype, mustCleanSpace) abort
  " 1- Strip comments and parenthesis
  let prototype = a:prototype
  let prototype = substitute(prototype, '//.\{-}\n', '', 'g')
  let prototype = substitute(prototype, '/\*\_.\{-}\*/', '', 'g')
  " 2- Strip throw spec
  let prototype = substitute(prototype, ')\zs\_s*throw(.*', '', '')

  " 3- convert the string into a list, the separation being done on commas
  let res_params = lh#dev#option#call('function#_signature_to_parameters', &ft, prototype, a:mustCleanSpace)

  return res_params
endfunction
" }}}3

" Function: lh#cpp#AnalysisLib_Function#AnalysePrototype(prototype) {{{3
" @return: {qualifier, return-type, function-name, parameters, throw-spec, const}
" @todo support friends.
" @todo support function types
" @todo support templates
" Constants {{{4
let s:re_qualifiers                 = '\<\%(static\|explicit\|virtual\)\>'

let s:re_qualified_name1            = '\%(::\s*\)\=\<\I\i*\>'
let s:re_qualified_name2            = '\s*::\s*\<\I\i*\>'
let s:re_qualified_name             = s:re_qualified_name1.'\%('.s:re_qualified_name2.'\)*'

let s:re_operators                  = '\<operator\%([=~%+-\*/^&|]\|[]\|()\|&&\|||\|->\|<<\|>>\|==\| \)'
"   What looks like to a "space" operator is actually used in next regex to
"   match convertion operators
let s:re_qualified_oper             = '\%('.s:re_qualified_name . '\s*::\s*\)\=' . s:re_operators . '.\{-}\ze('

let s:re_const_member_fn            = ')\s*\zs\<const\>'
let s:re_volatile_member_fn         = ')\s*\zs\<volatile\>'
let s:re_throw_spec                 = ')\s*\%(\%(\<const\>\|\<volatile\>\)\s\+\)\=\<throw\>(\(\zs.*\ze\))'
" let s:re_noexcept_spec              = ')\s*\%(\%(\<const\>\|\<volatile\>\)\s\+\)\=\<noexcept\>\((\zs.*\ze)\)\='
let s:re_noexcept_spec              = '\<noexcept\>\%((\zs.*\ze)\)\='
let s:re_defined_by_compiler_prefix = ')\s*\%(\%(\<const\>\|\<volatile\>\)\s*\)\=\%(\<noexcept\>\%((.*)\)\=\s*\)\==\s*'
let s:re_pure_virtual               = s:re_defined_by_compiler_prefix . '0\s*[;{]'
let s:re_special_definition         = s:re_defined_by_compiler_prefix . '\zs\<\(default\|delete\)\>\ze\s*[;{]'

let s:re_constexpr                  = '\<constexpr\>'
let s:re_final                      = '\<final\>'
let s:re_override                   = '\<override\>'

" Implementation {{{4
function! lh#cpp#AnalysisLib_Function#AnalysePrototype(prototype) abort
  " 0- strip comments                            {{{5
  let prototype = substitute(a:prototype, "\\(\\s\\|\n\\)\\+", ' ', 'g')
  let prototype = substitute(prototype, '/\*.\{-}\*/\|//.*$', '', 'g')

  " let prototype = s:StripComments(a:prototype)

  " 1- Qualifier (only one possible in C++)      {{{5
  "   -> virtual / explicit / static
  let qualifier = matchstr  (prototype, s:re_qualifiers)
  let prototype = substitute(prototype, '\s*'.qualifier.'\s*', '', '')

  " 2- Function name                             {{{5
  "   Not supposed to have a scoped qualification
  "   Operators need a special care
  let iName = match(prototype, s:re_qualified_oper)
  "   '.\{-}\ze(' is to match anything till the firt '(' -> convertion
  "   operators
  if iName == -1
    " if not an operator -> just a function

    " First: special case of `decltype(auto)`
    let iName = match   (prototype, 'decltype(auto)\s*\zs'.s:re_qualified_name . '\ze\s*(')
    if  iName >= 0
      let sName = matchstr(prototype, 'decltype(auto)\s*\zs'.s:re_qualified_name . '\ze\s*(')
    else
      " "\s*(" -> parenthesis may be aligned and not sticking to the function
      " name
      let iName = match   (prototype, s:re_qualified_name . '\ze\s*(')
      let sName = matchstr(prototype, s:re_qualified_name . '\ze\s*(')
    endif
  else
    " echo "operator"
    let sName = matchstr(prototype, s:re_qualified_oper)
  endif
  let sName = matchstr(sName, '^\s*\zs.\{-}\ze\s*$')
  let lName = split(sName, '::')

  " 3- Return type                               {{{5
  let retType = strpart(prototype, 0, iName)
  let retType = matchstr(retType, '^\s*\zs.\{-}\ze\s*$')
  if retType =~ '\~$'  " destructor
    let sName   = retType.sName
    let sName   = matchstr(sName, '^\s*\zs.\{-}\ze\s*$')
    let lName   = split(sName, '::')
    let retType = ''
  endif
  let retType = substitute(retType, s:re_constexpr.'\s*', '', '')
  if retType =~ '\v^$|auto' && prototype =~ '->'
    " New C++11 syntax for return type specification
    let retType = matchstr(prototype, '\v-\>\s*\zs.{-}\ze\s*[{;]\s*$')
    let prototype = matchstr(prototype, '\v^.{-}\ze\s*-\>')
  endif

  " 4- Throw specification                       {{{5
  let sThrowSpec = matchstr(prototype, s:re_throw_spec)
  let lThrowSpec = split(sThrowSpec, '\s*,\s*')
  if len(lThrowSpec) == 0 && match(prototype, s:re_throw_spec) > 0
    let lThrowSpec = [ '' ]
  endif
  let [sNoexceptSpec, idx_s, idx_e] = lh#string#matchstrpos(prototype, s:re_noexcept_spec)
  call s:Verbose("sNoexceptSpec: %1 ∈ [%2, %3]", sNoexceptSpec, idx_s, idx_e)
  if !empty(sNoexceptSpec)
    " call s:Verbose("Prototype before trimming noexcept(): %1", prototype)
    let prototype = prototype[:idx_s-2].prototype[idx_e+1:]
    " +2: to remove () that'll mess param extraction
    call s:Verbose("Prototype after trimming noexcept(): %1", prototype)
  endif

  " 5- Parameters                                {{{5
  let sParams = strpart(prototype, iName+len(sName))
  let params = lh#cpp#AnalysisLib_Function#GetListOfParams(sParams, 0)

  " 6- Const member function ?                   {{{5
  let isConst    = match(prototype, s:re_const_member_fn) != -1
  let isVolatile = match(prototype, s:re_volatile_member_fn) != -1

  " 7- Pure member function ?                    {{{5
  let isPure =  prototype =~ s:re_pure_virtual

  " 8- =default/=delete ?                        {{{5
  let special_definition =  matchstr(prototype, s:re_special_definition)

  " 9- final/override ?                          {{{5
  let isFinal     = prototype =~ s:re_final
  let isOverriden = prototype =~ s:re_override

  " 10- constexpr ?                              {{{5
  let isConstexpr = prototype =~ s:re_constexpr

  " *- Result                                    {{{5
  " let result = [ qualifier, retType, lName, params]
  let result =
        \ { "qualifier"          : qualifier
        \ , "return"             : retType
        \ , "name"               : lName
        \ , "parameters"         : params
        \ , "constexpr"          : isConstexpr
        \ , "const"              : isConst
        \ , "volatile"           : isVolatile
        \ , "pure"               : isPure
        \ , "special_definition" : special_definition
        \ , "throw"              : lThrowSpec
        \ , "noexcept"           : sNoexceptSpec
        \ , "final"              : isFinal
        \ , "overriden"          : isOverriden
        \ }
  return result
endfunction
" }}}3
"------------------------------------------------------------------------
" Function: lh#cpp#AnalysisLib_Function#HaveSameSignature(sig1, sig2) {{{3
" @param[in] sig1 Signature 1 (GetListOfParams() format)
" @param[in] sig2 Signature 2 (GetListOfParams() format)
" @return whether the two signatures are similar (parameters names, default
" parameters and other comment are ignored)
function! lh#cpp#AnalysisLib_Function#HaveSameSignature(sig1, sig2) abort
  return a:sig1 == a:sig2

  if len(a:sig1) != len(a:sig2) | return 0 | endif
  let i = 0
  while i != len(a:sig1)
    if a:sig1[i] != a:sig2[i] | return 0 | endif
    let i += 1
  endwhile
  return 1
endfunction
" }}}3
"------------------------------------------------------------------------
" Function: lh#cpp#AnalysisLib_Function#SignatureToString(fn) {{{3
function! s:ParamToString(param) abort
  " 0:Type + 1:param name
  let p = (a:param.type) . ' ' .(a:param.name)
  return p
endfunction

function! lh#cpp#AnalysisLib_Function#BuildSignatureAsString(fn) abort
  let params = []
  for param in a:fn.parameters
    call add(params, s:ParamToString(param))
  endfor
  let sig = a:fn.name.'(' . join(params, ', ') .')'
  if a:fn.const
    let sig .= ' const'
  endif
  return sig
endfunction
" }}}3
"------------------------------------------------------------------------
" Function: lh#cpp#AnalysisLib_Function#SignatureToString(fn) {{{3
" function! lh#cpp#AnalysisLib_Function#IsSame(def, decl)
  " return a:def.name == a:decl[0].name
        " \ && lh#cpp#AnalysisLib_Function#HaveSameSignature(a:def.parameters, a:decl[0].parameters)
" endfunction
function! lh#cpp#AnalysisLib_Function#IsSame(def, decl) abort
  let res = a:def.name == a:decl.name
        \ && lh#cpp#AnalysisLib_Function#HaveSameSignature(a:def.parameters, a:decl.parameters)
  " if a:def.name == a:decl.name
    " echomsg res ."[".(a:def.name)."] <- " . string(a:def.parameters) . ' <--> ' . string(a:decl.parameters)
  " endif
  return res
endfunction
" }}}3
"------------------------------------------------------------------------
" Function: lh#cpp#AnalysisLib_Function#LoadTags(id) {{{3
function! s:ConvertTag(t) abort
  let fn_data = {
        \ 'name'          : a:t.name,
        \ 'signature'     : a:t.signature,
        \ 'parameters'    : lh#cpp#AnalysisLib_Function#GetListOfParams(a:t.signature, 1),
        \ 'const'         : match(a:t.signature, s:re_const_member_fn) != -1,
        \ 'filename'      : a:t.filename,
        \ 'implementation': get(a:t, 'implementation', ''),
        \ 'class'         : get(a:t, 'class', ''),
        \ 'cmd'           : a:t.cmd }
  if has_key(a:t, 'access')
    let fn_data['access'] = a:t.access
  endif
  return fn_data
endfunction

function! lh#cpp#AnalysisLib_Function#LoadTags(id) abort
  let tags = taglist(a:id)
  call s:Verbose('%1 functions definitions & declarations matching %2 found', len(tags), a:id)

  " # Definitions (f)
  let f_tags = filter(copy(tags), 'v:val.kind == "f"')
  let definitions = map(copy(f_tags), 's:ConvertTag(v:val)')
  call s:Verbose('%1 functions definitions found', len(definitions))
  " Remove inline definitions
  " -> a definition with an access specifier is an inline definition
  call filter(definitions, '! has_key(v:val, "access")')
  " -> We can also use universal ctags {c++.properties} field option
  call filter(definitions, 'get(v:val, "properties","") =~ "inline"')
  call s:Verbose('%1 functions definitions kept (class-inline definitions removed)', len(definitions))

  " # Declarations (p)
  let p_tags = filter(copy(tags), 'v:val.kind == "p"')
  let declarations = map(copy(p_tags), 's:ConvertTag(v:val)')
  call s:Verbose('%1 functions declarations found', len(declarations))

  " Remove "= 0"
  call filter(declarations, 'v:val.implementation !~ "pure"')
  call s:Verbose('%1 functions declarations kept (pure virtual function removed)', len(declarations))
  " Remove "= default" & "= delete"
  " -> not present in the signature.
  " -> at best, it may be in the command
  call filter(declarations, 'v:val.cmd !~ "=\\v\\s*(default|delete)"')
  " -> We can also use universal ctags {c++.properties} field option
  call filter(declarations, 'get(v:val, "properties","") =~ "default\\|delete"')
  call s:Verbose('%1 functions declarations found and kept (defaulted/deleted function removed)', len(declarations))

  let result = { 'definitions':definitions, 'declarations': declarations }
  return result
endfunction
" }}}3
"------------------------------------------------------------------------
" Function: lh#cpp#AnalysisLib_Function#SearchUnmatched(fn) {{{3
function! s:CmpSig(lhs, rhs) abort
  if     len(a:lhs) < len(a:rhs) | return -1
  elseif len(a:lhs) > len(a:rhs) | return  1
  else
    let i = 0
    while i != len(a:rhs)
      if     a:lhs[i] < a:rhs[i] | return -1
      elseif a:lhs[i] > a:rhs[i] | return  1
      endif
      let i += 1
    endwhile
    return 0
  endif
endfunction

function! lh#cpp#AnalysisLib_Function#_ByNameAndSig(lhs, rhs) abort
  let res = a:lhs.name <  a:rhs.name ? -1
        \ : a:lhs.name == a:rhs.name ? s:CmpSig(lh#list#get(a:lhs.parameters,'type'), lh#list#get(a:rhs.parameters, 'type'))
        \ :                             1
  return res
endfunction

function! s:SearchUnmatched(functions) abort
  let decls = sort(a:functions.declarations, function('lh#cpp#AnalysisLib_Function#_ByNameAndSig'))
  call s:Verbose('%1 function declarations sorted', len(a:functions.declarations))
  let defs  = sort(a:functions.definitions,  function('lh#cpp#AnalysisLib_Function#_ByNameAndSig'))
  call s:Verbose('%1 function definitions sorted', len(a:functions.definitions))

  let unmatched_decl = []
  let unmatched_def  = []
  call lh#list#concurrent_for(a:functions.declarations, a:functions.definitions,
        \ unmatched_decl, unmatched_def, [],
        \ function('lh#cpp#AnalysisLib_Function#_ByNameAndSig'))
  let unmatched = { 'definitions':unmatched_def, 'declarations':unmatched_decl }
  call s:Verbose('Symetric difference between function definitions and declarions done')
  return unmatched
endfunction

function! lh#cpp#AnalysisLib_Function#SearchUnmatched(what) abort
  if     type(a:what) == type('string')
    let functions = lh#cpp#AnalysisLib_Function#LoadTags(a:what)
    return s:SearchUnmatched(functions)
  elseif type(a:what) == type({})
    return s:SearchUnmatched(a:what)
  else
    throw "lh#cpp#AnalysisLib_Function#SearchUnmatched: Invalid argument type"
    " We only accept id to fetch with taglist, or list of functions
  endif
endfunction

"------------------------------------------------------------------------
" Function: lh#cpp#AnalysisLib_Function#SearchAllDeclarations(fn) {{{3
" inline member function are seen as "p" (instead of "f") by ctags, hence this
" function
function! lh#cpp#AnalysisLib_Function#SearchAllDeclarations(functions) abort
  let declarations = deepcopy(a:functions.declarations)
  let unmatched_def = copy(a:functions.definitions)

  for f in declarations
    let idx = lh#list#Find_if(unmatched_def, 'lh#cpp#AnalysisLib_Function#IsSame(v:val,v:1_)', [f], 0)
    if idx != -1
      call remove(unmatched_def, idx)
    endif
  endfor

  " That is not a very good way to identify inline functions, at least all
  " inline function are still kept
  call extend(declarations, unmatched_def)
  return declarations
endfunction
"------------------------------------------------------------------------
" }}}3
"------------------------------------------------------------------------
" Function! lh#cpp#AnalysisLib_Function#SignatureToSearchRegex2(signature,className) {{{3
" todo:
" - ignore default arguments
" - template types like std::auto_ptr<foo::bar>
function! s:Type2Regex(type, param) abort
  let type = a:type
  "
  " let id = (""!=ptr) ? ' ( \* \%(\<\I\i*\>\)\= ) ' : ' \%(\<\I\i*\>\)\= '
  let id =  strlen(a:param) ? ' \%(\<\I\i*\>\)\= ' : ''
  " arrays
  let array = matchstr(a:param, '\[.*\]')

  " escape arrays and pointers characters
  let type = substitute(type, '\s*\([[\]*]\)\s*', ' \\\1 ', 'g')
  let type = substitute(type, '\s*&\s*', ' \0 ', 'g')
  let array = substitute(array, '\s*\([[\]*]\)\s*', ' \\\1 ', 'g')
  " echomsg a:param . ' -> ' . type
  let re_param = type . ' ' . id . ' ' . array
  return re_param
endfunction

function! lh#cpp#AnalysisLib_Function#SignatureToSearchRegex2(signature,className) abort
  let function_data = lh#cpp#AnalysisLib_Function#AnalysePrototype(a:signature)

  " Return type {{{4
  let impl2search = ''
  if strlen(function_data.return) > 0
  let impl2search .= s:Type2Regex(function_data.return, '') . ' '
  endif

  " Class::functionname {{{4
  let className = a:className . (""!=a:className ? '::' : '')
  if className =~ '#::#'
    let ns = matchstr(className, '^.*\ze#::#') . '::'
    let b = substitute(ns, '[^:]', '', 'g')
    let b = substitute(b, '::', '\\%(', 'g')
    let ns_re = b.substitute(ns, '\<\I\i*\>::', '\0\\)\\=', 'g')
    let cl_re = matchstr(className, '#::#\zs.*$')
    let className = ns_re.cl_re
  endif
  let className   = substitute(className, '\s*::\s*', ' :: ', 'g')
  let name = className . join(function_data.name, ' :: ')
  let impl2search .= escape(name, '~')

  " Parameters {{{4
  let params = []
  for param in function_data.parameters
    call add(params, s:Type2Regex(param[0], param[1]))
  endfor
  let impl2search .= ' ( ' . join(params, ' , ').' )'

  let impl2search .= function_data.const ? ' const' : ''


  " Spaces & comments -> '\(\_s\|/\*.\{-}\*/\|//.*$\)*' and \i {{{4
  let impl2search = substitute(impl2search, '\s\{2,}', ' ', 'g')
  let g:impl2search2 = impl2search

  let impl2search = substitute(' \zs'.impl2search, ' ',
        \ '\\%(\\_s\\|/\\*.\\{-}\\*/\\|//.*$\\)*', 'g')
  " Note: \%(\) is like \(\) but the subexpressions are not counted.
  " Note: ' \zs' inserted at the start of the regex helps ignore any comments
  " before the signature of the function.
  " Return the regex built {{{4
  "
  " Check pure virtual functions: {{{4
  let isPure =  function_data.pure

  " Check =delete/=default functions: {{{4
  let isWithoutDefinition = !empty(function_data.special_definition)

  let res = {'regex':impl2search, 'ispure':isPure, 'isWithoutDefinition': isWithoutDefinition}
  return res
endfunction

" Function! lh#cpp#AnalysisLib_Function#SignatureToSearchRegex(signature,className) {{{3
function! lh#cpp#AnalysisLib_Function#SignatureToSearchRegex(signature,className) abort
  let g:signature = a:signature
  let g:className = a:className
  " trim spaces {{{4
  let impl2search = substitute(a:signature, "\\(\\s\\|\n\\)\\+", ' ', 'g')
  " trim comments {{{4
  let impl2search = substitute(impl2search, '/\*.\{-}\*/\|//.*$', '', 'g')
  " destructor ? {{{4
  let impl2search = substitute(impl2search, '\~', '\\\0', 'g')
  " '[,' '],' pointers {{{4
    " let impl2search = substitute(impl2search, '\s*\([[\]*]\)\s*', ' \\\1 ', 'g')
    " Note: these characters will be backspaced into s:TrimParametersNames
  " echo impl2search
  let impl2search = substitute(impl2search, '\s*\([[\]*]\)\s*', ' \1 ', 'g')
    " However returned pointers must be backspaced
    let retTypePos = matchend(impl2search, '.\{-}\s\+\ze\i\{-}\s*(\|\ze\<operator\>')
    let retType       = strpart(impl2search, 0, retTypePos)
    let func_n_params = strpart(impl2search, retTypePos)
    let retType = substitute(retType, '\s*\([[\]*]\)\s*', ' \\\1 ', 'g')
    let impl2search = retType . func_n_params
  " operator* {{{4
  let impl2search = substitute(impl2search, 'operator\s*\*', 'operator \\*', '')
  "  <, >, =, (, ), ',' and references {{{4
  let impl2search = substitute(impl2search, '\s*\([-+*/%^=<>!]=\|&&\|||\|[<>=(),&]\)\s*', ' \1 ', 'g')
  " Check pure virtual functions: {{{4
  let isPure =  impl2search =~ '=\s*0\s*;\s*$'
  " Check =delete/=default functions: {{{4
  let isWithoutDefinition = impl2search =~ '=\s*\<\(default\|delete\)\>\s*;\s*$'
  " Start and end {{{4
  let impl2search = substitute(impl2search, '^\s*\|\s*;\s*$', '', 'g')
  " Default parameters -> comment => ignored along with spaces {{{4
  " -> recognize "=" to strip what follows when not operator[-+*/=!^]=
  let impl2search = substitute(impl2search, '\%(\<operator\>\s*\([-+*/=!^%]\s*\)\=\)\@<!=[^,)]\+', '', 'g')
  " virtual, static and explicit -> comment => ignored along with spaces {{{4
  let impl2search = substitute(impl2search,
        \ '\_s*\<\%(virtual\|static\|explicit\)\>\_s*', '', 'g')
  " Extract throw specs {{{4
  let throw_specs = matchstr(impl2search, '\v\)\s*\zs(throw|noexcept).*$')
  " Trim the variables names {{{4
  " Todo: \(un\)signed \(short\|long\) \(int\|float\|double\)
  "       const, *
  "       First non spaced type + exceptions like: scope\s*::\s*type ,
  "       class<xxx,yyy> (scope or type)
  let impl2search = lh#cpp#AnalysisLib_Function#TrimParametersNames(impl2search)
  " class name {{{4
  let className = a:className . (""!=a:className ? '::' : '')
  if className =~ '#::#'
    let ns = matchstr(className, '^.*\ze#::#') . '::'
    let b = substitute(ns, '[^:]', '', 'g')
    let b = substitute(b, '::', '\\%(', 'g')
    let ns_re = b.substitute(ns, '\<\I\i*\>::', '\0\\)\\=', 'g')
    let cl_re = matchstr(className, '#::#\zs.*$')
    let className = ns_re.cl_re
  endif
  let className   = substitute(className, '\s*::\s*', ' :: ', 'g')
  " let g:className = className
  " and finally inject the class name patten in the search pattern
  " NB: operators have a special treatment
  let impl2search = substitute(impl2search,
        \ '\%(\\\~\)\=\<\I\i*\>\_s*(\|\<operator\>',
        \ escape(className, '\' ) .'\0', '')
  " echo impl2search
  let g:impl2search1 = impl2search

  " Reinject throw specs {{{4
  let impl2search .= ' '.throw_specs
  " Spaces & comments -> '\(\_s\|/\*.\{-}\*/\|//.*$\)*' and \i {{{4
  " let impl2search = substitute(' \zs'.impl2search, ' ',
  let impl2search = substitute(impl2search, ' ',
        \ '\\%(\\_s\\|/\\*.\\{-}\\*/\\|//.*$\\)*', 'g')
  " Note: \%(\) is like \(\) but the subexpressions are not counted.
  " Note: ' \zs' inserted at the start of the regex helps ignore any comments
  " before the signature of the function.
  " Return the regex built {{{4
  "
  let res = {'regex':impl2search, 'ispure':isPure, 'isWithoutDefinition': isWithoutDefinition}
  return res
endfunction "}}}4
"------------------------------------------------------------------------
" Function: s:TrimParametersNames(str) {{{3
" Some constant regexes {{{4
let s:type_sign = 'unsigned\|signed'
let s:type_size = 'short\|long'
let s:type_main = 'void\|char\|int\|float'
let s:type_simple = s:type_sign.'\|'.s:type_size.'\|'.s:type_main
let s:type_scope1 = '\%(::\s*\)\=\<\I\i*\>'
let s:type_scope2 = '\s*::\s*\<\I\i*\>'
let s:type_scope  = s:type_scope1.'\%('.s:type_scope2.'\)*'
let s:re = '^\s*\%(\<const\>\s*\)\='.
      \ '\%(\%('.s:type_simple.'\|\s\+\)\+\|'.s:type_scope.'\)'.
      \ '\%(\<const\>\|\*\|&\|\s\+\)*'
" }}}4
function! lh#cpp#AnalysisLib_Function#TrimParametersNames(str) abort
  " Stuff Supported: {{{4
  " - Simple parameters          : "T p"
  " - Arrays                     : "T p[][n]"
  " - Arrays of pointers         : "T (*p)[n]"
  " - Scopes within complex types: "T1::T2"
    " Todo: support templates like "A<B,C>"
    " Todo: support functions like "T (*NameF)(P1, P2, ...)" ,
    "                              "T (CL::* pmf)(params)"
  " }}}4
  " Cut the signature in order to concentrate on the most outer parenthesis
  let head_end = matchend(a:str, '^\([^(]\{-}\<operator\>\s*(\s*)\s*\|[^(]*\)(') " take operator() into account
  let head = a:str[ : head_end]
  let tail = matchstr(a:str, ')[^)]*$', head_end-1)
  let params = matchstr(a:str, '^[^(]*(\zs.*\ze)[^)]*$', head_end-1)
  let params_types = ''
  " Loop on the parameters
  while '' != params
    " Get the parameter field
    let field  = matchstr(params, '^[^,]*')
    let params = matchstr(params, ',\zs.*$')

    " Handle case of arrays {{{5
    let p = 0
    let array = ''
    while -1 != p
      let p = match(field, '\[.\{-}\]', p)
      if -1 == p | break | endif
      let array = array . escape(matchstr(field, '\[.\{-}\]', p), '[]')
      let p = p + 1
    endwhile " }}}4
    " Extract the type of the parameter and only the type
    let type = matchstr(field, s:re)
    " let type = matchstr(field, '^\s*\(\<const\>\s*\)\='.
          " \ '\(\('.s:type_simple.'\|\s\+\)\+\|\<\I\i*\>\)'.
          " \ '\(\<const\>\|\*\|&\|\s\+\)*')
    " Check for special pointers stuff "T (*p_id)"
    let ptr = matchstr(field, '(\s*\*\s*\(\<\I\i*\>\)\=\s*)')
    let id = (""!=ptr) ? ' ( \* \%(\<\I\i*\>\)\= ) ' : ' \%(\<\I\i*\>\)\= '
    " Build the regex containing the parameter type, spaces, etc
    let params_types = params_types.','.
          \ escape(type, '*')
          \ . id
          \ . array
          " \ type.'\%(\<\I\i*\>\)\= '
  endwhile

  " Return the final regex to search.
  return substitute(head . strpart(params_types,1) . tail, '\s\s\+', ' ', 'g')
endfunction
" }}}3
"------------------------------------------------------------------------
" }}}2

" Functions }}}1
"------------------------------------------------------------------------
let &cpo=s:cpo_save
"=============================================================================
" vim600: set fdm=marker:


================================================
FILE: autoload/lh/cpp/GotoFunctionImpl.vim
================================================
"=============================================================================
" File:         autoload/lh/cpp/GotoFunctionImpl.vim                      {{{1
" Author:       Luc Hermitte <EMAIL:hermitte {at} free {dot} fr>
"               <URL:http://github.com/LucHermitte/lh-cpp>
" License:      GPLv3 with exceptions
"               <URL:http://github.com/LucHermitte/lh-cpp/tree/master/License.md>
" Version:      2.2.1
let s:k_version = '221'
" Created:      07th Oct 2006
" Last Update:  04th Apr 2019
"------------------------------------------------------------------------
" Description:
"       Implementation functions for ftplugin/cpp/cpp_GotoImpl
"
"------------------------------------------------------------------------
" Installation:
"       Drop this file into {rtp}/autoload/lh/cpp/
"       Use Vim 7+
" History:
"       12th Sep 2007:
"       (*) Accepts spaces between "~" and class name (destructors)
"       v1.0.0:
"       (*) Code moved from ftplugin/cpp/cpp_GotoFunctionImpl.vim
"       (*) Fixes issues with g:alternateSearchPath in order to open the .cpp
"       in the correct subdirectory
"       (*) Don't escape '&' (from parameter's type) to build search regex
"       (*) Preserve line breaks between parameters
"       (*) A message is displayed if the position of the function definition
"           cannot be found.
"       v1.1.0
"       (*) two functions moved to autoload/lh/cpp/AnalysisLib_Function
"       v1.1.1
"       (*) Support jump to existing destructor
"       (*) Support jump to constructor with a initialization-list
"       (*) Support "using namespace"
"       (*) Don't expect the searched regex to start the line (as the return
"           type may need to be fully-qualified is the function definition)
"       v2.0.0
"       (*) GPLv3 with exception
"       (*) parameter for the new implementation file ex
Download .txt
gitextract_f3673ucg/

├── .gitignore
├── .rspec
├── .travis.yml
├── CONTRIBUTORS
├── Gemfile
├── License.md
├── README.md
├── Rakefile
├── VimFlavor
├── addon-info.json
├── after/
│   └── template/
│       ├── c/
│       │   ├── assert.template
│       │   ├── comment.template
│       │   ├── internals/
│       │   │   └── c-header-content.template
│       │   ├── rand_init.template
│       │   └── realloc.template
│       ├── cpp/
│       │   ├── abs-rel.template
│       │   ├── abstract-class.template
│       │   ├── array_size.template
│       │   ├── assignment-operator.template
│       │   ├── auto_ptr-instance.template
│       │   ├── auto_ptr.template
│       │   ├── b-e.template
│       │   ├── base-class-non-virtual.template
│       │   ├── base-class.template
│       │   ├── benchmark.template
│       │   ├── bool-operator.template
│       │   ├── catch.template
│       │   ├── cerr.template
│       │   ├── chrono-how-long.template
│       │   ├── cin.template
│       │   ├── class.template
│       │   ├── clonable-class.template
│       │   ├── copy-and-swap.template
│       │   ├── copy-back_inserter.template
│       │   ├── copy-constructor.template
│       │   ├── copy.template
│       │   ├── cout.template
│       │   ├── default-constructor.template
│       │   ├── destructor.template
│       │   ├── empty-exception-class.template
│       │   ├── ends_with.template
│       │   ├── entity-class.template
│       │   ├── enum.template
│       │   ├── enum2-impl.template
│       │   ├── enum2.template
│       │   ├── erase-remove.template
│       │   ├── exception-class.template
│       │   ├── file.template
│       │   ├── for-enum.template
│       │   ├── for-iterator.template
│       │   ├── for-range.template
│       │   ├── fori.template
│       │   ├── foriN.template
│       │   ├── forward.template
│       │   ├── getter.template
│       │   ├── init-constructor.template
│       │   ├── interface.template
│       │   ├── internals/
│       │   │   ├── abs-rel-shared.template
│       │   │   ├── attribute.template
│       │   │   ├── class-skeleton.template
│       │   │   ├── formatted-comment.template
│       │   │   ├── function-comment.template
│       │   │   ├── function.template
│       │   │   ├── get-b-e.template
│       │   │   ├── get-class-name.template
│       │   │   ├── includes.template
│       │   │   ├── list-constructors.template
│       │   │   ├── namespace-name.template
│       │   │   ├── shall_explicit_defaults.template
│       │   │   ├── stream-common.template
│       │   │   ├── stream-implementation.template
│       │   │   └── stream-signature.template
│       │   ├── iss.template
│       │   ├── list.template
│       │   ├── map.template
│       │   ├── namespace.template
│       │   ├── noncopyable.template
│       │   ├── operator-binary.template
│       │   ├── oss.template
│       │   ├── otb-sug-latex.template
│       │   ├── otb-sug-snippet.template
│       │   ├── path.template
│       │   ├── ptr_vector.template
│       │   ├── ref_setter.template
│       │   ├── scoped_ptr.template
│       │   ├── set.template
│       │   ├── setter.template
│       │   ├── shared_ptr.template
│       │   ├── singleton.template
│       │   ├── sort.template
│       │   ├── starts_with.template
│       │   ├── static_assert.template
│       │   ├── stream-extractor.template
│       │   ├── stream-inserter.template
│       │   ├── string.template
│       │   ├── swap-function.template
│       │   ├── throw.template
│       │   ├── traits.template
│       │   ├── try.template
│       │   ├── typeid.template
│       │   ├── unique_ptr.template
│       │   ├── unordered_map.template
│       │   ├── unordered_set.template
│       │   ├── utf8.template
│       │   ├── value-class.template
│       │   ├── vector.template
│       │   ├── weak_ptr.template
│       │   └── while-getline.template
│       └── dox/
│           ├── author.template
│           ├── code.template
│           ├── em.template
│           ├── file.template
│           ├── function.template
│           ├── group.template
│           ├── html.template
│           ├── ingroup.template
│           ├── since.template
│           └── tt.template
├── autoload/
│   └── lh/
│       ├── cpp/
│       │   ├── AnalysisLib_Class.vim
│       │   ├── AnalysisLib_Function.vim
│       │   ├── GotoFunctionImpl.vim
│       │   ├── UnmatchedFunctions.vim
│       │   ├── abs_rel.vim
│       │   ├── analyse.vim
│       │   ├── constructors.vim
│       │   ├── enum.vim
│       │   ├── ftplugin.vim
│       │   ├── include.vim
│       │   ├── libclang.vim
│       │   ├── macros.vim
│       │   ├── option.vim
│       │   ├── override.vim
│       │   ├── refactor.vim
│       │   ├── scope.vim
│       │   ├── snippets.vim
│       │   ├── style.vim
│       │   ├── tags.vim
│       │   ├── types.vim
│       │   └── understand.vim
│       ├── cpp.vim
│       └── dox.vim
├── doc/
│   ├── API.md
│   ├── Doxygen.md
│   ├── Enums.md
│   ├── TODO.md
│   ├── c.html
│   ├── lh-cpp-readme.txt
│   ├── options.md
│   ├── snippets.md
│   └── types.md
├── ftplugin/
│   ├── c/
│   │   ├── LoadHeaderFile.vim
│   │   ├── c_AddInclude.vim
│   │   ├── c_Doxygen.vim
│   │   ├── c_UnmatchedFunctions.vim
│   │   ├── c_complete_include.vim
│   │   ├── c_doc.vim
│   │   ├── c_gcov.vim
│   │   ├── c_menu.vim
│   │   ├── c_mu-template_api.vim
│   │   ├── c_navigate_functions.vim
│   │   ├── c_pvs-2-qf.vim
│   │   ├── c_set.vim
│   │   ├── c_show_scope.vim
│   │   ├── c_snippets.vim
│   │   ├── c_stl.vim
│   │   ├── c_switch-enum.vim
│   │   ├── flistmaps.vim
│   │   ├── keep_pound_if_path.vim
│   │   ├── previewWord.vim
│   │   └── word.list
│   ├── cpp/
│   │   ├── changelog
│   │   ├── cpp_AddMissingScope.vim
│   │   ├── cpp_BuildTemplates.vim
│   │   ├── cpp_Constructor.vim
│   │   ├── cpp_Enum.vim
│   │   ├── cpp_FindContextClass.vim
│   │   ├── cpp_GotoFunctionImpl.vim
│   │   ├── cpp_InsertAccessors.vim
│   │   ├── cpp_Inspect.vim
│   │   ├── cpp_Override.vim
│   │   ├── cpp_options-commands.vim
│   │   ├── cpp_options.vim
│   │   ├── cpp_refactor.vim
│   │   ├── cpp_set.vim
│   │   └── cpp_snippets.vim
│   └── idl_set.vim
├── mkVba/
│   └── mk-lh-cpp.vim
├── plugin/
│   ├── homeLikeVC++.vim
│   └── omap-param.vim
├── script/
│   └── PVS2qf.xsl
├── spec/
│   ├── abstract-class_spec.rb
│   ├── base-class-NV_spec.rb
│   ├── base-class_spec.rb
│   ├── class-with-attributes_spec.rb
│   ├── clonable-class_spec.rb
│   ├── constructor-command_spec.rb
│   ├── deps_spec.rb
│   ├── empty-exception-class_spec.rb
│   ├── exception-class_spec.rb
│   ├── spe_func_spec.rb
│   ├── spec_helper.rb
│   ├── value-class-with-attributes_spec.rb
│   └── value-class_spec.rb
├── syntax/
│   ├── c-assign-in-condition.vim
│   ├── c-fallthrough-case.vim
│   ├── c.vim
│   ├── cpp-badcatch.vim
│   ├── cpp-c-cast.vim
│   ├── cpp-cxxtest.vim
│   ├── cpp-funcdef.vim
│   ├── cpp-throw-spec.vim
│   └── cpp.vim
└── tests/
    ├── VimFlavor
    └── lh/
        ├── analysis.vim
        ├── cpp-TU-override.cpp
        ├── cpp-TU.cpp
        ├── omap-param.vim
        ├── snippets.vim
        ├── test-flavours.vim
        └── test-types.vim
Download .txt
SYMBOL INDEX (34 symbols across 3 files)

FILE: spec/spec_helper.rb
  type Vimrunner (line 11) | module Vimrunner
    class Client (line 12) | class Client
      method runtime (line 13) | def runtime(script)
  function write_file (line 91) | def write_file(filename, contents)

FILE: tests/lh/cpp-TU-override.cpp
  type nZ (line 3) | namespace nZ {
    class B (line 4) | class B {}
  class A0 (line 9) | class A0
  class A1 (line 15) | class A1
    method f2 (line 19) | virtual void f2() { f1("foo"); }
  class A3 (line 34) | class A3 : virtual A0
    class C1 (line 41) | class C1 : A1, A2
    class D (line 49) | class D : C1, virtual A0
    class B (line 55) | class B : A0{}
  type V (line 60) | struct V {}
  type Z (line 61) | struct Z {}
  type C1 (line 62) | struct C1 : virtual V {}
  type C2 (line 63) | struct C2 : virtual V, Z {}
  type C3 (line 64) | struct C3 : C2{}
  type D (line 65) | struct D : C1, C3, B {}

FILE: tests/lh/cpp-TU.cpp
  type Ee (line 4) | enum Ee { E_a, E_b}
  type Ec (line 5) | enum class Ec {a, c}
  function f (line 8) | void f(int z) {
  type MyEnum (line 19) | struct MyEnum {
    type type (line 20) | enum type { E1, E2, MAX__}
  function f (line 23) | void f(int)
  class Toto (line 27) | class Toto
  type NS1 (line 59) | namespace NS1 { namespace NS2 {
    type NS2 (line 59) | namespace NS2 {
      class Bar (line 61) | class Bar {
  function Toto (line 81) | Toto* Toto::operator*(Toto const& rhs)
  function Titi (line 85) | Titi & Toto::g()
  function Titi (line 89) | Titi * Toto::f()
  function Toto (line 93) | Toto& Toto::operator=(Toto const& rhs)
  class Titi (line 106) | class Titi
Condensed preview — 220 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (878K chars).
[
  {
    "path": ".gitignore",
    "chars": 20,
    "preview": "tags\n*.sw*\n*~\n*.pyc\n"
  },
  {
    "path": ".rspec",
    "chars": 100,
    "preview": "--color\n--require spec_helper\n--format documentation\n-I ~/.vim-flavor/repos/LucHermitte_vim-UT/spec\n"
  },
  {
    "path": ".travis.yml",
    "chars": 467,
    "preview": "dist: xenial\nlanguage: ruby\ncache: bundler\nrvm:\n    - 2.1.5\nscript: bundle exec rake ci\ncompiler:\n    - gcc # for ctags\n"
  },
  {
    "path": "CONTRIBUTORS",
    "chars": 822,
    "preview": "The following people have contributed to lh-cpp\n\n# Direct contributors\nLuc Hermitte, maintainer, 2002(?)-2018\nLeif Wickl"
  },
  {
    "path": "Gemfile",
    "chars": 136,
    "preview": "source 'https://rubygems.org'\n\ngem 'rspec', '~> 3.1.0'\ngem 'vimrunner', '~> 0.3.1'\ngem 'rake', '~> 10.3.2'\ngem 'vim-flav"
  },
  {
    "path": "License.md",
    "chars": 2471,
    "preview": "Copyright 2001-2015, Luc Hermitte\n\n# Scripts License\n\nAll scripts (VimL, templates, bash, perl, etc.) from lh-vim are\ndi"
  },
  {
    "path": "README.md",
    "chars": 18539,
    "preview": "# lh-cpp [![Build Status](https://secure.travis-ci.org/LucHermitte/lh-cpp.png?branch=master)](http://travis-ci.org/LucHe"
  },
  {
    "path": "Rakefile",
    "chars": 438,
    "preview": "#!/usr/bin/env rake\n\nrequire 'rspec/core/rake_task'\n\nRSpec::Core::RakeTask.new(:spec)\n\ntask :ci => [:dump, :install, :te"
  },
  {
    "path": "VimFlavor",
    "chars": 283,
    "preview": "flavor 'LucHermitte/lh-vim-lib', '>= 4.1.0'\nflavor 'LucHermitte/lh-brackets', '>= 3.1.1'\nflavor 'LucHermitte/lh-style'\nf"
  },
  {
    "path": "addon-info.json",
    "chars": 924,
    "preview": "{\n  \"name\" : \"lh-cpp\",\n  \"version\" : \"dev\",\n  \"author\" : \"Luc Hermitte <http://github.com/LucHermitte>\",\n  \"maintainer\" "
  },
  {
    "path": "after/template/c/assert.template",
    "chars": 381,
    "preview": "VimL:\" assert File Template, Luc Hermitte, 24th Sep 2015\nVimL:\" hint: assert()\nVimL: let s:value_start = '¡'\nVimL: let s"
  },
  {
    "path": "after/template/c/comment.template",
    "chars": 892,
    "preview": "VimL:\" comment File Template, Luc Hermitte <hermitte {at} free {dot} fr>, mer. 20 juil. 2016 11:30:01 CEST\nVimL:\" hint: "
  },
  {
    "path": "after/template/c/internals/c-header-content.template",
    "chars": 473,
    "preview": "VimL:\" Typical C++ header content, Luc Hermitte, 05th Sep 2019\nVimL:\" override content for header files for OTK like pro"
  },
  {
    "path": "after/template/c/rand_init.template",
    "chars": 282,
    "preview": "VimL:\" rand_init File Template, Luc Hermitte, 28th Oct 2014\nVimL:\" hint: srand(time(NULL));\nVimL: let s:reindent     = 1"
  },
  {
    "path": "after/template/c/realloc.template",
    "chars": 1614,
    "preview": "VimL:\" realloc File Template, Luc Hermitte, 20th Aug 2012\nVimL:\" hint: new_p = realloc(pn size); if (!new_p) {free(p); +"
  },
  {
    "path": "after/template/cpp/abs-rel.template",
    "chars": 7585,
    "preview": "VimL:\" Absolute and relative Classes Template, Luc Hermitte\nVimL:\" Used to define Date and Duration, Point and Distance,"
  },
  {
    "path": "after/template/cpp/abstract-class.template",
    "chars": 887,
    "preview": "VimL:\" abstract-class File Template, Luc Hermitte <hermitte {at} free {dot} fr>, 25th Nov 2015\nVimL:\" hint: Abstract (ba"
  },
  {
    "path": "after/template/cpp/array_size.template",
    "chars": 2186,
    "preview": "VimL:\" array_size definition File Template, Luc Hermitte, 25th Apr 2014\nVimL:\" hint: std::extent<decltype(tab)>::value\nV"
  },
  {
    "path": "after/template/cpp/assignment-operator.template",
    "chars": 1718,
    "preview": "VimL:\" assignment-operator File Template, Luc Hermitte, 21st Aug 2011\nVimL:\" hint: T& operator=(T const&);\nVimL: \"TODO: "
  },
  {
    "path": "after/template/cpp/auto_ptr-instance.template",
    "chars": 406,
    "preview": "VimL:\" unique_ptr File Template, Luc Hermitte, 22nd May 2014\nVimL:\" hint: std::auto_ptr<T> ptr(new T(args));\nVimL: let s"
  },
  {
    "path": "after/template/cpp/auto_ptr.template",
    "chars": 362,
    "preview": "VimL:\" unique_ptr File Template, Luc Hermitte, 22nd May 2014\nVimL:\" hint: std::auto_ptr<>\nVimL: let s:value_start = '¡'\n"
  },
  {
    "path": "after/template/cpp/b-e.template",
    "chars": 250,
    "preview": "VimL:\" b-e File Template, Luc Hermitte, 30th Jun 2011\nVimL:\" hint: <+container+>.begin(), <+container+>.end()\nVimL: let "
  },
  {
    "path": "after/template/cpp/base-class-non-virtual.template",
    "chars": 727,
    "preview": "VimL:\" base-class-non-virtual File Template, Luc Hermitte <hermitte {at} free {dot} fr>, 25th Nov 2015\nVimL:\" hint: Base"
  },
  {
    "path": "after/template/cpp/base-class.template",
    "chars": 735,
    "preview": "VimL:\" base-class File Template, Luc Hermitte <hermitte {at} free {dot} fr>, 25th Nov 2015\nVimL:\" hint: Base class to in"
  },
  {
    "path": "after/template/cpp/benchmark.template",
    "chars": 399,
    "preview": "VimL:\" google-benchmark File Template, Luc Hermitte, 27th Oct 2015\nVimL:\" hint: static void BM_<+test+>(benchmark::State"
  },
  {
    "path": "after/template/cpp/bool-operator.template",
    "chars": 670,
    "preview": "VimL:\" bool-operator Template, Luc Hermitte\nVimL:\" hint: safe bool operator\nVimL: let s:reindent     = 1\nVimL: let s:mar"
  },
  {
    "path": "after/template/cpp/catch.template",
    "chars": 297,
    "preview": "VimL:\"{catch(...){...}} Template-File, Luc Hermitte\nVimL:\" hint: catch(...){...}\nVimL: let s:value_start  = '¡'\nVimL: le"
  },
  {
    "path": "after/template/cpp/cerr.template",
    "chars": 301,
    "preview": "VimL:\" cerr File Template, Luc Hermitte, 28th Apr 2014\nVimL:\" hint: std::cerr\nVimL: let s:value_start = '¡'\nVimL: let s:"
  },
  {
    "path": "after/template/cpp/chrono-how-long.template",
    "chars": 582,
    "preview": "VimL:\" chrono-how-long File Template, Luc Hermitte <hermitte {at} free {dot} fr>, 24th Apr 2019\nVimL:\" hint: Compute dur"
  },
  {
    "path": "after/template/cpp/cin.template",
    "chars": 298,
    "preview": "VimL:\" cin File Template, Luc Hermitte, 28th Apr 2014\nVimL:\" hint: std::cin\nVimL: let s:value_start = '¡'\nVimL: let s:va"
  },
  {
    "path": "after/template/cpp/class.template",
    "chars": 715,
    "preview": "VimL:\" C++ Class Template, Luc Hermitte\nVimL:\" hint: Simplistic class snippet -- unaware of semantics\nVimL: let s:value_"
  },
  {
    "path": "after/template/cpp/clonable-class.template",
    "chars": 2400,
    "preview": "VimL:\" clonable-class File Template, Luc Hermitte <hermitte {at} free {dot} fr>, 27th Nov 2015\nVimL:\" hint: Base class w"
  },
  {
    "path": "after/template/cpp/copy-and-swap.template",
    "chars": 1108,
    "preview": "VimL:\" copy-and-swap File Template, Luc Hermitte, 21st Aug 2011\nVimL:\" hint: assign op + swap\nVimL: \" todo: recognize C+"
  },
  {
    "path": "after/template/cpp/copy-back_inserter.template",
    "chars": 731,
    "preview": "VimL:\" copy-back_inserter File Template, Luc Hermitte, 23rd May 2014\nVimL:\" hint: std::copy(orig.begin(), orig.end(), st"
  },
  {
    "path": "after/template/cpp/copy-constructor.template",
    "chars": 1387,
    "preview": "VimL:\" copy-constructor File Template, Luc Hermitte, 21st Aug 2011\nVimL:\" hint: T(T const&);\nVimL: let s:marker_open  = "
  },
  {
    "path": "after/template/cpp/copy.template",
    "chars": 459,
    "preview": "VimL:\" std::copy File Template, Luc Hermitte, 04th Nov 2015\nVimL:\" hint: std::copy(first, last, dest)\nVimL: let s:value_"
  },
  {
    "path": "after/template/cpp/cout.template",
    "chars": 301,
    "preview": "VimL:\" cout File Template, Luc Hermitte, 28th Apr 2014\nVimL:\" hint: std::cout\nVimL: let s:value_start = '¡'\nVimL: let s:"
  },
  {
    "path": "after/template/cpp/default-constructor.template",
    "chars": 849,
    "preview": "VimL:\" default-constructor File Template, Luc Hermitte, 21st Aug 2011\nVimL:\" hint: T();\nVimL: let s:marker_open  = \"<+\"\n"
  },
  {
    "path": "after/template/cpp/destructor.template",
    "chars": 1606,
    "preview": "VimL:\" destructor File Template, Luc Hermitte, 23rd Mar 2012\nVimL:\" hint: ~T();\nVimL: let s:marker_open  = \"<+\"\nVimL: le"
  },
  {
    "path": "after/template/cpp/empty-exception-class.template",
    "chars": 1772,
    "preview": "VimL:\" empty-exception-class File Template, Luc Hermitte <hermitte {at} free {dot} fr>, 27th Nov 2015\nVimL:\" hint: Minim"
  },
  {
    "path": "after/template/cpp/ends_with.template",
    "chars": 415,
    "preview": "VimL:\" ends_with File Template, Luc Hermitte <hermitte at free.fr>, 28th May 2014\nVimL:\" hint: boost::algorithm::ends_wi"
  },
  {
    "path": "after/template/cpp/entity-class.template",
    "chars": 953,
    "preview": "VimL:\" entity-class File Template, Luc Hermitte <hermitte {at} free {dot} fr>, lun. 19 déc. 2016 17:14:18 CET\nVimL:\" hin"
  },
  {
    "path": "after/template/cpp/enum.template",
    "chars": 858,
    "preview": "VimL:\" Enum definition Template, Luc Hermitte\nVimL: let s:value_start = '¡'\nVimL:\" hint: struct Enum { enum type { ... }"
  },
  {
    "path": "after/template/cpp/enum2-impl.template",
    "chars": 3165,
    "preview": "VimL:\" enum2-impl File Template, Luc Hermitte, 23rd Apr 2014\nVimL:\" hint: enum2 code that goes into .cpp files\nVimL: let"
  },
  {
    "path": "after/template/cpp/enum2.template",
    "chars": 6715,
    "preview": "VimL:\" safe-Enum definition Template, Luc Hermitte\nVimL: let s:value_start = '¡'\nVimL:\" hint: struct Enum { enum type { "
  },
  {
    "path": "after/template/cpp/erase-remove.template",
    "chars": 467,
    "preview": "VimL:\" erase-remove File Template, Luc Hermitte, 06th Nov 2012\nVimL:\" hint: erase-remove idiom\nVimL: let s:reindent     "
  },
  {
    "path": "after/template/cpp/exception-class.template",
    "chars": 721,
    "preview": "VimL:\" exception-class File Template, Luc Hermitte <hermitte {at} free {dot} fr>, 25th Nov 2015\nVimL:\" hint: Value Class"
  },
  {
    "path": "after/template/cpp/file.template",
    "chars": 336,
    "preview": "VimL:\" file File Template, Luc Hermitte, 28th Apr 2014\nVimL:\" hint: i/ofstream\nVimL: let s:value_start = '¡'\nVimL: let s"
  },
  {
    "path": "after/template/cpp/for-enum.template",
    "chars": 697,
    "preview": "VimL:\" For loop over Enum definition Template, Luc Hermitte\nVimL:\" hint: for (Enum::type e=Enum::type(); e!=Enum::MAX__;"
  },
  {
    "path": "after/template/cpp/for-iterator.template",
    "chars": 1058,
    "preview": "VimL:\" C++ for-loop on iterators Template, Luc Hermitte\nVimL:\" hint: for (T::iterator b=c.begin(), e=c.end(); b!=e; ++b)"
  },
  {
    "path": "after/template/cpp/for-range.template",
    "chars": 602,
    "preview": "VimL:\" range-based for loop File Template, Luc Hermitte, 07th Jul 2015\nVimL:\" hint: for(auto&& e : range)\nVimL: let s:va"
  },
  {
    "path": "after/template/cpp/fori.template",
    "chars": 362,
    "preview": "VimL:\"{for int i=0...} Template-File, Luc Hermitte\nVimL:\" hint: for (int i=0;i!=N;++i) { action }\nVimL: let s:value_star"
  },
  {
    "path": "after/template/cpp/foriN.template",
    "chars": 412,
    "preview": "VimL:\"{for size_t i=0, N= ; i!=N...} Template-File, Luc Hermitte\nVimL:\" hint: for (std::size_t i=0, N=...;i!=N;++i) { ac"
  },
  {
    "path": "after/template/cpp/forward.template",
    "chars": 472,
    "preview": "VimL:\" forward File Template, Luc Hermitte, mar. 29 mars 2016 17:13:03 CEST\nVimL:\" hint: std::forward<T>(v)\nVimL: let s:"
  },
  {
    "path": "after/template/cpp/getter.template",
    "chars": 933,
    "preview": "VimL:\" getter File Template, Luc Hermitte <hermitte {at} free {dot} fr>, 02nd Dec 2015\nVimL:\" hint: T const& getFoo() co"
  },
  {
    "path": "after/template/cpp/init-constructor.template",
    "chars": 1310,
    "preview": "VimL:\" init-constructor File Template, Luc Hermitte, 30th Nov 2015\nVimL:\" hint: Constructor(parameters): m_attributes(pa"
  },
  {
    "path": "after/template/cpp/interface.template",
    "chars": 706,
    "preview": "VimL:\" interface File Template, Luc Hermitte <hermitte {at} free {dot} fr>, lun. 19 déc. 2016 18:32:45 CET\nVimL:\" hint: "
  },
  {
    "path": "after/template/cpp/internals/abs-rel-shared.template",
    "chars": 1411,
    "preview": "VimL:\" Shared definition for Absolute and relative Classes Template, Luc Hermitte\nVimL:\" Used to define Date and Duratio"
  },
  {
    "path": "after/template/cpp/internals/attribute.template",
    "chars": 1799,
    "preview": "VimL:\" attribute File Template, Luc Hermitte <hermitte {at} free {dot} fr>, 02nd Dec 2015\nVimL:\" hint: Type m_attribute;"
  },
  {
    "path": "after/template/cpp/internals/class-skeleton.template",
    "chars": 7525,
    "preview": "VimL:\" class-skeleton File Template, Luc Hermitte <hermitte {at} free {dot} fr>, 25th Nov 2015\nVimL:\" hint: Routine Skel"
  },
  {
    "path": "after/template/cpp/internals/formatted-comment.template",
    "chars": 2555,
    "preview": "VimL:\" C++ formatted-comment template-routine, Luc Hermitte, 23rd Mar 2012\nVimL:\" Meant to be used as a function whose p"
  },
  {
    "path": "after/template/cpp/internals/function-comment.template",
    "chars": 2687,
    "preview": "VimL:\" function-comment File Template, Luc Hermitte, 22nd Aug 2011\nVimL:\" template to generate function comments, defaul"
  },
  {
    "path": "after/template/cpp/internals/function.template",
    "chars": 1606,
    "preview": "VimL:\" «function» File Template, Luc Hermitte <hermitte {at} free {dot} fr>, 27th Nov 2015\nVimL:\" hint: «function-hint»\n"
  },
  {
    "path": "after/template/cpp/internals/get-b-e.template",
    "chars": 870,
    "preview": "VimL:\" get-b-e File Template, Luc Hermitte <hermitte {at} free {dot} fr>, jeu. 02 juin 2016 17:02:36 CEST\nVimL: \" Parame"
  },
  {
    "path": "after/template/cpp/internals/get-class-name.template",
    "chars": 1047,
    "preview": "VimL:\" get-class-name routine File Template, Luc Hermitte <hermitte {at} free {dot} fr>, jeu. 17 déc. 2015 18:40:56 CET\n"
  },
  {
    "path": "after/template/cpp/internals/includes.template",
    "chars": 338,
    "preview": "VimL:\" includes File Template, Luc Hermitte <hermitte {at} free {dot} fr>, 02nd Dec 2015\nVimL:\" hint: include skel-routi"
  },
  {
    "path": "after/template/cpp/internals/list-constructors.template",
    "chars": 1379,
    "preview": "VimL:\" list-constructors File Template, Luc Hermitte <hermitte {at} free {dot} fr>, 27th Nov 2015\nVimL:\" hint: Routine t"
  },
  {
    "path": "after/template/cpp/internals/namespace-name.template",
    "chars": 441,
    "preview": "VimL:\" Factorize namespace name \"computation\"\nMuT:  let s:namespace = s:Param('namespace', '###')\nMuT:  if (type(s:names"
  },
  {
    "path": "after/template/cpp/internals/shall_explicit_defaults.template",
    "chars": 511,
    "preview": "VimL:\" shall_explicit_defaults File Template, Luc Hermitte <hermitte {at} free {dot} fr>, 26th Nov 2015\nVimL:\" hint: wra"
  },
  {
    "path": "after/template/cpp/internals/stream-common.template",
    "chars": 1035,
    "preview": "VimL:\" «stream-common» File Template, Luc Hermitte\nVimL: let s:reindent     = 1\nVimL: let s:marker_open  = '<+'\nVimL: le"
  },
  {
    "path": "after/template/cpp/internals/stream-implementation.template",
    "chars": 264,
    "preview": "VimL:\" «stream-implementation» File Template, Luc Hermitte\nVimL: call s:AddPostExpandCallback('lh#dev#import#add(\"<'.s:d"
  },
  {
    "path": "after/template/cpp/internals/stream-signature.template",
    "chars": 249,
    "preview": "VimL:\" «stream-signature» File Template, Luc Hermitte, 04th Jun 2004\nVimL: let s:stream_param = lh#naming#param(s:direct"
  },
  {
    "path": "after/template/cpp/iss.template",
    "chars": 448,
    "preview": "VimL:\" {istringstream iss(str); iss >>..} File Template, Luc Hermitte, 06th Dec 2010\nVimL:\" hint: std::istringstream iss"
  },
  {
    "path": "after/template/cpp/list.template",
    "chars": 324,
    "preview": "VimL:\" list File Template, Luc Hermitte, 28th Apr 2014\nVimL:\" hint: std::list<>\nVimL: let s:value_start = '¡'\nVimL: let "
  },
  {
    "path": "after/template/cpp/map.template",
    "chars": 371,
    "preview": "VimL:\" map File Template, Luc Hermitte, 28th Apr 2014\nVimL:\" hint: std::map<>\nVimL: let s:value_start = '¡'\nVimL: let s:"
  },
  {
    "path": "after/template/cpp/namespace.template",
    "chars": 2111,
    "preview": "VimL:\" C++ namespace Template, Luc Hermitte\nVimL:\" hint: namespace ns { ... } // ns\nVimL:\" Options:\nVimL:\" - snippet par"
  },
  {
    "path": "after/template/cpp/noncopyable.template",
    "chars": 352,
    "preview": "VimL:\" noncopyable File Template, Luc Hermitte <hermitte at free.fr>, 28th May 2014\nVimL:\" hint: boost::noncopyable\nVimL"
  },
  {
    "path": "after/template/cpp/operator-binary.template",
    "chars": 1589,
    "preview": "VimL:\" C++ binary operator snippet, Luc Hermitte, 30th Sep 2013\r\nVimL:\" hint: operatorX(T lhs, T const& rhs) { return lh"
  },
  {
    "path": "after/template/cpp/oss.template",
    "chars": 383,
    "preview": "VimL:\"{std::ostringstream oss; oss << } Template-File, Luc Hermitte\nVimL:\" hint: std::ostringstream oss; oss << ...\nVimL"
  },
  {
    "path": "after/template/cpp/otb-sug-latex.template",
    "chars": 278,
    "preview": "VimL:\" $Id$\nVimL:\" otb-sug-latex File Template, Luc Hermitte, 21st May 2012\nVimL:\" hint: Software Guide : BeginLatex\nVim"
  },
  {
    "path": "after/template/cpp/otb-sug-snippet.template",
    "chars": 289,
    "preview": "VimL:\" $Id$\nVimL:\" otb-sug-snippet File Template, Luc Hermitte, 21st May 2012\nVimL:\" hint: Software Guide : BeginCodeSni"
  },
  {
    "path": "after/template/cpp/path.template",
    "chars": 342,
    "preview": "VimL:\" boost-path File Template, Luc Hermitte, 29th Apr 2014\nVimL:\" hint: boost::filesystem::path\nVimL: let s:value_star"
  },
  {
    "path": "after/template/cpp/ptr_vector.template",
    "chars": 425,
    "preview": "VimL:\" ptr_vector File Template, Luc Hermitte <hermitte at free.fr>, 22nd May 2014\nVimL:\" hint: boost::ptr_vector<>\nVimL"
  },
  {
    "path": "after/template/cpp/ref_setter.template",
    "chars": 1035,
    "preview": "VimL:\" setter File Template, Luc Hermitte <hermitte {at} free {dot} fr>, 02nd Dec 2015\nVimL:\" hint: void setFoo(T const&"
  },
  {
    "path": "after/template/cpp/scoped_ptr.template",
    "chars": 432,
    "preview": "VimL:\" scoped_ptr File Template, Luc Hermitte <hermitte {at} free {dot} fr>, jeu. 23 juin 2016 17:28:07 CEST\nVimL:\" hint"
  },
  {
    "path": "after/template/cpp/set.template",
    "chars": 342,
    "preview": "VimL:\" set File Template, Luc Hermitte, 28th Apr 2014\nVimL:\" hint: std::set<>\nVimL: let s:value_start = '¡'\nVimL: let s:"
  },
  {
    "path": "after/template/cpp/setter.template",
    "chars": 743,
    "preview": "VimL:\" setter File Template, Luc Hermitte <hermitte {at} free {dot} fr>, 02nd Dec 2015\nVimL:\" hint: void setFoo(T const&"
  },
  {
    "path": "after/template/cpp/shared_ptr.template",
    "chars": 541,
    "preview": "VimL:\" shared_ptr File Template, Luc Hermitte, 28th Apr 2014\nVimL:\" hint: std/boost::shared_ptr<>\nVimL: let s:value_star"
  },
  {
    "path": "after/template/cpp/singleton.template",
    "chars": 5025,
    "preview": "VimL:\" C++ Singleton-Class Template, Luc Hermitte\nVimL:\" «Meyers singleton», cf. More Effective C++ Item 26\nVimL:\" For a"
  },
  {
    "path": "after/template/cpp/sort.template",
    "chars": 545,
    "preview": "VimL:\" std::sort File Template, Luc Hermitte, 28th May 2015\nVimL:\" hint: std::sort(range.begin(), range.end());\nVimL:\" t"
  },
  {
    "path": "after/template/cpp/starts_with.template",
    "chars": 421,
    "preview": "VimL:\" starts_with File Template, Luc Hermitte <hermitte at free.fr>, 28th May 2014\nVimL:\" hint: boost::algorithm::start"
  },
  {
    "path": "after/template/cpp/static_assert.template",
    "chars": 587,
    "preview": "VimL:\" static_assert File Template, Luc Hermitte, 23rd Apr 2014\nVimL:\" hint: static_assert(cond, msg)/BOOST_STATIC_ASSER"
  },
  {
    "path": "after/template/cpp/stream-extractor.template",
    "chars": 290,
    "preview": "VimL:\" C++ stream-extractor (operator>>) Template, Luc Hermitte, 04th Jun 2004\nVimL:\" hint: istream& operator>>(istream "
  },
  {
    "path": "after/template/cpp/stream-inserter.template",
    "chars": 289,
    "preview": "VimL:\" C++ stream-inserter (operator<<) Template, Luc Hermitte, 04th Jun 2004\nVimL:\" hint: ostream& operator<<(ostream &"
  },
  {
    "path": "after/template/cpp/string.template",
    "chars": 253,
    "preview": "VimL:\" string File Template, Luc Hermitte, 28th Apr 2014\nVimL:\" hint: std::string\nVimL: let s:marker_open  = '<+'\nVimL: "
  },
  {
    "path": "after/template/cpp/swap-function.template",
    "chars": 1175,
    "preview": "VimL:\" swap-function File Template, Luc Hermitte <hermitte {at} free {dot} fr>, mar. 22 déc. 2015 11:34:40 CET\nVimL:\" hi"
  },
  {
    "path": "after/template/cpp/throw.template",
    "chars": 1721,
    "preview": "VimL:\"{throw default exceptions for project} Template-File, Luc Hermitte\nVimL:\" hint: throw std::runtime_error/@throw (d"
  },
  {
    "path": "after/template/cpp/traits.template",
    "chars": 516,
    "preview": "VimL:\" traits-class File Template, Luc Hermitte, 20th Jan 2011\nVimL:\" hint: traits-class\nVimL: let s:value_start = '¡'\nV"
  },
  {
    "path": "after/template/cpp/try.template",
    "chars": 398,
    "preview": "VimL:\"{try{...}catch(){...}} Template-File, Luc Hermitte\nVimL:\" hint: try { ... } catch(...) { ... }\nVimL: let s:value_s"
  },
  {
    "path": "after/template/cpp/typeid.template",
    "chars": 419,
    "preview": "VimL:\" typeid File Template, Luc Hermitte <hermitte {at} free {dot} fr>, jeu. 31 mars 2016 11:38:16 CEST\nVimL:\" hint: ty"
  },
  {
    "path": "after/template/cpp/unique_ptr.template",
    "chars": 344,
    "preview": "VimL:\" unique_ptr File Template, Luc Hermitte, 28th Apr 2014\nVimL:\" hint: std::unique_ptr<>\nVimL: let s:value_start = '¡"
  },
  {
    "path": "after/template/cpp/unordered_map.template",
    "chars": 409,
    "preview": "VimL:\" unordered_map File Template, Luc Hermitte, 07th Oct 2017\nVimL:\" hint: std::unordered_map\nVimL: let s:value_start "
  },
  {
    "path": "after/template/cpp/unordered_set.template",
    "chars": 380,
    "preview": "VimL:\" unordered_set File Template, Luc Hermitte, 07th Oct 2017\nVimL:\" hint: std::unordered_map\nVimL: let s:value_start "
  },
  {
    "path": "after/template/cpp/utf8.template",
    "chars": 27,
    "preview": "let s:value_start  = '¡'\n \n"
  },
  {
    "path": "after/template/cpp/value-class.template",
    "chars": 1204,
    "preview": "VimL:\" value-class File Template, Luc Hermitte <hermitte {at} free {dot} fr>, 25th Nov 2015\nVimL:\" hint: Value Class ((i"
  },
  {
    "path": "after/template/cpp/vector.template",
    "chars": 318,
    "preview": "VimL:\" vector File Template, Luc Hermitte, 28th Apr 2014\nVimL:\" hint: std::vector<>\nVimL: let s:marker_open  = '<+'\nVimL"
  },
  {
    "path": "after/template/cpp/weak_ptr.template",
    "chars": 533,
    "preview": "VimL:\" weak_ptr File Template, Luc Hermitte, 28th Apr 2014\nVimL:\" hint: std/boost::weak_ptr<>\nVimL: let s:value_start = "
  },
  {
    "path": "after/template/cpp/while-getline.template",
    "chars": 457,
    "preview": "VimL:\" while-getline File Template, Luc Hermitte, 06th Sep 2012\nVimL:\" hint: while(std::getline(stream,line)) { action; "
  },
  {
    "path": "after/template/dox/author.template",
    "chars": 183,
    "preview": "VimL:\" C++ Doxygen snippet for authors, Luc Hermitte\nVimL:\" hint: @author\nVimL: let s:marker_open  = '<+'\nVimL: let s:ma"
  },
  {
    "path": "after/template/dox/code.template",
    "chars": 341,
    "preview": "VimL:\" doxygen <code/> File Template, Luc Hermitte, 11th Apr 2012\nVimL:\" hint: <code>|</code>\nVimL: let s:marker_open  ="
  },
  {
    "path": "after/template/dox/em.template",
    "chars": 179,
    "preview": "VimL:\" doxygen <em/> snippet, Luc Hermitte, 11th Apr 2012\nVimL:\" hint: <em>|</em>\nVimL: let s:text = s:Surround(1, lh#ma"
  },
  {
    "path": "after/template/dox/file.template",
    "chars": 455,
    "preview": "VimL:\" dox/file Template, Luc Hermitte\nVimL:\" hint: /** @file ... */\nVimL: let s:value_start  = '¡'\nVimL: let s:value_en"
  },
  {
    "path": "after/template/dox/function.template",
    "chars": 610,
    "preview": "VimL:\" C++ Doxygen snippet for functions, Luc Hermitte\nVimL:\" Meant to be used through the command :DOX\nVimL:\" hint: /**"
  },
  {
    "path": "after/template/dox/group.template",
    "chars": 398,
    "preview": "VimL:\" Doxygen local group File-Template, Luc Hermitte, 26th Jan 2011\nVimL:\" hint: Doxygen local group\nVimL: let s:marke"
  },
  {
    "path": "after/template/dox/html.template",
    "chars": 326,
    "preview": "VimL:\" doxygen <+html+> snippets, Luc Hermitte, 11th Apr 2012\nVimL:\" hint: <html-tag>|</html-tag>\nVimL: let s:marker_ope"
  },
  {
    "path": "after/template/dox/ingroup.template",
    "chars": 357,
    "preview": "VimL:\" $Id$\nVimL:\" dox/ingroup File Template, Luc Hermitte, 23rd Dec 2013\nVimL:\" hint: /**@ingroup ... */\nVimL: let s:va"
  },
  {
    "path": "after/template/dox/since.template",
    "chars": 236,
    "preview": "VimL:\" C++ Doxygen snippet for since tag, Luc Hermitte\nVimL:\" hint: @since Version\nVimL: let s:value_start = '¡'\nVimL: l"
  },
  {
    "path": "after/template/dox/tt.template",
    "chars": 185,
    "preview": "VimL:\" doxygen <tt/> File Template, Luc Hermitte, 11th Apr 2012\nVimL:\" hint: <tt>|</tt>\nMuT:  let s:text = s:Surround(1,"
  },
  {
    "path": "autoload/lh/cpp/AnalysisLib_Class.vim",
    "chars": 18141,
    "preview": "\" ========================================================================\n\" File:         autoload/lh/cpp/AnalysisLib_C"
  },
  {
    "path": "autoload/lh/cpp/AnalysisLib_Function.vim",
    "chars": 33559,
    "preview": "\"=============================================================================\n\" File:         autoload/lh/cpp/AnalysisL"
  },
  {
    "path": "autoload/lh/cpp/GotoFunctionImpl.vim",
    "chars": 24156,
    "preview": "\"=============================================================================\n\" File:         autoload/lh/cpp/GotoFunct"
  },
  {
    "path": "autoload/lh/cpp/UnmatchedFunctions.vim",
    "chars": 4481,
    "preview": "\"=============================================================================\n\" File:         autoload/lh/cpp/Unmatched"
  },
  {
    "path": "autoload/lh/cpp/abs_rel.vim",
    "chars": 1794,
    "preview": "\"=============================================================================\n\" File:\t\tautoload/lh/cpp/abs_rel.vim     "
  },
  {
    "path": "autoload/lh/cpp/analyse.vim",
    "chars": 8435,
    "preview": "\"=============================================================================\n\" File:         autoload/lh/cpp/analyse.v"
  },
  {
    "path": "autoload/lh/cpp/constructors.vim",
    "chars": 14433,
    "preview": "\"=============================================================================\n\" File:         autoload/lh/cpp/construct"
  },
  {
    "path": "autoload/lh/cpp/enum.vim",
    "chars": 8463,
    "preview": "\"=============================================================================\n\" File:         autoload/lh/cpp/enum.vim "
  },
  {
    "path": "autoload/lh/cpp/ftplugin.vim",
    "chars": 1830,
    "preview": "\"=============================================================================\n\" File:\t\tautoload/lh/cpp/ftplugin.vim    "
  },
  {
    "path": "autoload/lh/cpp/include.vim",
    "chars": 4434,
    "preview": "\"=============================================================================\n\" File:         autoload/lh/cpp/include.v"
  },
  {
    "path": "autoload/lh/cpp/libclang.vim",
    "chars": 3425,
    "preview": "\"=============================================================================\n\" File:         autoload/lh/cpp/libclang."
  },
  {
    "path": "autoload/lh/cpp/macros.vim",
    "chars": 3266,
    "preview": "\"=============================================================================\n\" File:         autoload/lh/cpp/macros.vi"
  },
  {
    "path": "autoload/lh/cpp/option.vim",
    "chars": 2894,
    "preview": "\"=============================================================================\n\" File:         autoload/lh/cpp/option.vi"
  },
  {
    "path": "autoload/lh/cpp/override.vim",
    "chars": 15341,
    "preview": "\"=============================================================================\n\" File:         autoload/lh/cpp/override."
  },
  {
    "path": "autoload/lh/cpp/refactor.vim",
    "chars": 4076,
    "preview": "\"=============================================================================\n\" File:         autoload/lh/cpp/refactor."
  },
  {
    "path": "autoload/lh/cpp/scope.vim",
    "chars": 2824,
    "preview": "\"=============================================================================\n\" File:         autoload/lh/cpp/scope.vim"
  },
  {
    "path": "autoload/lh/cpp/snippets.vim",
    "chars": 25426,
    "preview": "\"=============================================================================\n\" File:         autoload/lh/cpp/snippets."
  },
  {
    "path": "autoload/lh/cpp/style.vim",
    "chars": 1995,
    "preview": "\"=============================================================================\n\" File:\t\tautoload/lh/cpp/style.vim       "
  },
  {
    "path": "autoload/lh/cpp/tags.vim",
    "chars": 5882,
    "preview": "\"=============================================================================\n\" File:         autoload/lh/cpp/tags.vim "
  },
  {
    "path": "autoload/lh/cpp/types.vim",
    "chars": 6018,
    "preview": "\"=============================================================================\n\" File:         autoload/lh/cpp/types.vim"
  },
  {
    "path": "autoload/lh/cpp/understand.vim",
    "chars": 4168,
    "preview": "\"=============================================================================\n\" File:         autoload/lh/cpp/understan"
  },
  {
    "path": "autoload/lh/cpp.vim",
    "chars": 5380,
    "preview": "\"=============================================================================\n\" File:         autoload/lh/cpp.vim      "
  },
  {
    "path": "autoload/lh/dox.vim",
    "chars": 6961,
    "preview": "\"=============================================================================\n\" File:         autoload/lh/cpp/dox.vim  "
  },
  {
    "path": "doc/API.md",
    "chars": 1554,
    "preview": "## lh-cpp API\n\n### C++ Flavour\n\nThese functions permit to set the C++ flavour currently used.\n\nThe typical use case of t"
  },
  {
    "path": "doc/Doxygen.md",
    "chars": 3451,
    "preview": "## File-templates\nlh-cpp & [mu-template](http://github.com/LucHermitte/mu-template) come with\ntunable project headers (t"
  },
  {
    "path": "doc/Enums.md",
    "chars": 2895,
    "preview": "lh-cpp provides the following features related to enums:\n  * [generation of a scoped and iterable enumerated type](#enum"
  },
  {
    "path": "doc/TODO.md",
    "chars": 2758,
    "preview": "# lh-cpp TO DO list\n\n## Folding\n\n - [ ] if only `{`, search next line\n - [ ] `do` `while`\n - [ ] embedded `#if`\n\n## synt"
  },
  {
    "path": "doc/c.html",
    "chars": 31538,
    "preview": "<HTML>\n<HEAD>\n    <META http-equiv=\"content-type\" content=\"text/html;charset=iso-8859-1\">\n    <META name=\"AUTHOR\" conten"
  },
  {
    "path": "doc/lh-cpp-readme.txt",
    "chars": 47134,
    "preview": "*lh-cpp-readme.txt*     C & C++ ftplugins short presentation (v2.2.0)\n                        For Vim version 7.x.    La"
  },
  {
    "path": "doc/options.md",
    "chars": 24683,
    "preview": "## lh-cpp Options\n\n### Contents\n\n  * [Options types](#options-types)\n    * [Global options: `g:`_{option-name}_](#global"
  },
  {
    "path": "doc/snippets.md",
    "chars": 43860,
    "preview": "# lh-cpp Snippets, templates and wizards\n\n## Contents\n\n  * [Remarks](#remarks)\n  * [Control Statements](#control-stateme"
  },
  {
    "path": "doc/types.md",
    "chars": 1066,
    "preview": "## lh-cpp Type DataBase\n\nlh-cpp provides a database for most standard types and some semi-standard\ntypes, i.e.  [Boost]("
  },
  {
    "path": "ftplugin/c/LoadHeaderFile.vim",
    "chars": 1020,
    "preview": "\" LoadHeaderFile\n\" Last Change: 29th july 2001 by Luc Hermitte\n\" -> Split lines and change indentation in order to fit w"
  },
  {
    "path": "ftplugin/c/c_AddInclude.vim",
    "chars": 3930,
    "preview": "\"=============================================================================\n\" File:         ftplugin/c/c_AddInclude.v"
  },
  {
    "path": "ftplugin/c/c_Doxygen.vim",
    "chars": 6242,
    "preview": "\"=============================================================================\n\" File:\t\tftplugin/c/c_Doxygen.vim        "
  },
  {
    "path": "ftplugin/c/c_UnmatchedFunctions.vim",
    "chars": 3324,
    "preview": "\"=============================================================================\n\" File:         ftplugin/c/c_UnmatchedFun"
  },
  {
    "path": "ftplugin/c/c_complete_include.vim",
    "chars": 3862,
    "preview": "\"=============================================================================\n\" File:         ftplugin/c/c_complete_inc"
  },
  {
    "path": "ftplugin/c/c_doc.vim",
    "chars": 4440,
    "preview": "\"=============================================================================\n\" File:         ftplugin/c/c_doc.vim     "
  },
  {
    "path": "ftplugin/c/c_gcov.vim",
    "chars": 3246,
    "preview": "\"=============================================================================\n\" File:         ftplugin/c/c_gcov.vim    "
  },
  {
    "path": "ftplugin/c/c_menu.vim",
    "chars": 5946,
    "preview": "\"=============================================================================\n\" File:\t\tftplugin/c/c_menu.vim           "
  },
  {
    "path": "ftplugin/c/c_mu-template_api.vim",
    "chars": 2008,
    "preview": "\"=============================================================================\n\" File:\t\tftplugin/c/c_mu-template_api.vim"
  },
  {
    "path": "ftplugin/c/c_navigate_functions.vim",
    "chars": 4903,
    "preview": "\"=============================================================================\n\" File:         ftplugin/c/c_navigate_fun"
  },
  {
    "path": "ftplugin/c/c_pvs-2-qf.vim",
    "chars": 4464,
    "preview": "\"=============================================================================\n\" File:         ftplugin/c/c_pvs-2-qf.vim"
  },
  {
    "path": "ftplugin/c/c_set.vim",
    "chars": 3092,
    "preview": "\" ========================================================================\n\" File:\t\tftplugin/c/c_set.vim\n\" Author:\tLuc H"
  },
  {
    "path": "ftplugin/c/c_show_scope.vim",
    "chars": 1541,
    "preview": "\"=============================================================================\n\" File:         ftplugin/c/c_show_scope.v"
  },
  {
    "path": "ftplugin/c/c_snippets.vim",
    "chars": 9746,
    "preview": "\"=============================================================================\n\" File:         ftplugin/c/c_snippets.vim"
  },
  {
    "path": "ftplugin/c/c_stl.vim",
    "chars": 3259,
    "preview": "\"=============================================================================\n\" File:\t\tftplugin/c/c_stl.vim\n\" Author:\tL"
  },
  {
    "path": "ftplugin/c/c_switch-enum.vim",
    "chars": 2015,
    "preview": "\"=============================================================================\n\" File:\t\tftplugin/c/c_switch-enum.vim    "
  },
  {
    "path": "ftplugin/c/flistmaps.vim",
    "chars": 1052,
    "preview": "\" flist.vim maps for Vim\n\"  Author  : Charles E. Campbell, Jr.\n\" Copyright: Charles E. Campbell, Jr.\n\" License  : refer "
  },
  {
    "path": "ftplugin/c/keep_pound_if_path.vim",
    "chars": 1697,
    "preview": "\"=============================================================================\n\" File:         ftplugin/c/keep_pound_if_"
  },
  {
    "path": "ftplugin/c/previewWord.vim",
    "chars": 6918,
    "preview": "\"=============================================================================\n\" File:         ftplugin/c/previewWord.vi"
  },
  {
    "path": "ftplugin/c/word.list",
    "chars": 18607,
    "preview": "__cpp_aggregate_bases\n__cpp_aggregate_nsdmi\n__cpp_aggregate_paren_init\n__cpp_alias_templates\n__cpp_aligned_new\n__cpp_att"
  },
  {
    "path": "ftplugin/cpp/changelog",
    "chars": 9630,
    "preview": "[08 Dec 2005] {{{1\n(*) cpp_set.vim {{{2\n    (*) mapping to <m-t> => insert \"typename\" (after a '<', or after\n    \"typede"
  },
  {
    "path": "ftplugin/cpp/cpp_AddMissingScope.vim",
    "chars": 1630,
    "preview": "\"=============================================================================\n\" File:         ftplugin/cpp/cpp_AddMissi"
  },
  {
    "path": "ftplugin/cpp/cpp_BuildTemplates.vim",
    "chars": 15088,
    "preview": "\" ========================================================================\n\" File:         ftplugin/cpp/cpp_BuildTemplat"
  },
  {
    "path": "ftplugin/cpp/cpp_Constructor.vim",
    "chars": 2142,
    "preview": "\"=============================================================================\n\" File:\t\tftplugin/cpp/cpp_Constructor.vim"
  },
  {
    "path": "ftplugin/cpp/cpp_Enum.vim",
    "chars": 1535,
    "preview": "\"=============================================================================\n\" File:         ftplugin/cpp/cpp_Enum.vim"
  },
  {
    "path": "ftplugin/cpp/cpp_FindContextClass.vim",
    "chars": 9709,
    "preview": "\" ========================================================================\n\" File:\t\tftplugin/cpp/cpp_FindContextClass.vi"
  },
  {
    "path": "ftplugin/cpp/cpp_GotoFunctionImpl.vim",
    "chars": 14897,
    "preview": "\" ========================================================================\n\" File:\t\tftplugin/cpp/cpp_GotoFunctionImpl.vi"
  },
  {
    "path": "ftplugin/cpp/cpp_InsertAccessors.vim",
    "chars": 10572,
    "preview": "\" ========================================================================\n\" File:\t\tftplugin/cpp/cpp_InsertAccessors.vim"
  },
  {
    "path": "ftplugin/cpp/cpp_Inspect.vim",
    "chars": 2978,
    "preview": "\"=============================================================================\n\" File:         ftplugin/cpp/cpp_Inspect."
  },
  {
    "path": "ftplugin/cpp/cpp_Override.vim",
    "chars": 1394,
    "preview": "\"=============================================================================\n\" File:\t\tftplugin/cpp/cpp_Override.vim   "
  },
  {
    "path": "ftplugin/cpp/cpp_options-commands.vim",
    "chars": 2388,
    "preview": "\"=============================================================================\n\" File:\t\tftplugin/cpp/cpp_options-command"
  },
  {
    "path": "ftplugin/cpp/cpp_options.vim",
    "chars": 6675,
    "preview": "\" ========================================================================\n\" File:\t\tftplugin/cpp/cpp_InsertAccessors.vim"
  },
  {
    "path": "ftplugin/cpp/cpp_refactor.vim",
    "chars": 3212,
    "preview": "\"=============================================================================\n\" File:         ftplugin/cpp/cpp_refactor"
  },
  {
    "path": "ftplugin/cpp/cpp_set.vim",
    "chars": 2900,
    "preview": "\" ========================================================================\n\" File:         ftplugin/cpp/cpp_set.vim     "
  },
  {
    "path": "ftplugin/cpp/cpp_snippets.vim",
    "chars": 7745,
    "preview": "\"=============================================================================\n\" File:         ftplugin/cpp/cpp_snippets"
  },
  {
    "path": "ftplugin/idl_set.vim",
    "chars": 3220,
    "preview": "\"=============================================================================\n\" File:         ftplugin/cpp/idl_set.vim "
  },
  {
    "path": "mkVba/mk-lh-cpp.vim",
    "chars": 7273,
    "preview": "\"=============================================================================\n\" File:\t\tmkVba/mk-lh-cpp.vim\n\" Author:\tLu"
  },
  {
    "path": "plugin/homeLikeVC++.vim",
    "chars": 3162,
    "preview": "\"=============================================================================\n\" File:\t\tplugin/homeLikeVC++.vim\n\" Author"
  },
  {
    "path": "plugin/omap-param.vim",
    "chars": 3856,
    "preview": "\"=============================================================================\n\" File:         plugin/omap-param.vim    "
  },
  {
    "path": "script/PVS2qf.xsl",
    "chars": 1509,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<xsl:stylesheet xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\" version=\"1.0\">\n "
  },
  {
    "path": "spec/abstract-class_spec.rb",
    "chars": 6063,
    "preview": "# encoding: UTF-8\nrequire 'spec_helper'\nrequire 'pp'\n\n\nRSpec.describe \"C++ abstract class wizard\", :abstract, :cpp, :cla"
  },
  {
    "path": "spec/base-class-NV_spec.rb",
    "chars": 6283,
    "preview": "# encoding: UTF-8\nrequire 'spec_helper'\nrequire 'pp'\n\n\nRSpec.describe \"C++ non virtual base class wizard\", :base_nv, :cp"
  },
  {
    "path": "spec/base-class_spec.rb",
    "chars": 5819,
    "preview": "# encoding: UTF-8\nrequire 'spec_helper'\nrequire 'pp'\n\n\nRSpec.describe \"C++ base class wizard\", :base, :cpp, :class do\n  "
  },
  {
    "path": "spec/class-with-attributes_spec.rb",
    "chars": 4138,
    "preview": "# encoding: UTF-8\nrequire 'spec_helper'\nrequire 'pp'\n\n\nRSpec.describe \"C++ class w/ attributes wizard\", :cpp, :class, :w"
  },
  {
    "path": "spec/clonable-class_spec.rb",
    "chars": 10838,
    "preview": "# encoding: UTF-8\nrequire 'spec_helper'\nrequire 'pp'\n\n\nRSpec.describe \"C++ clonable class wizard\", :clonable, :cpp, :cla"
  },
  {
    "path": "spec/constructor-command_spec.rb",
    "chars": 6836,
    "preview": "# encoding: UTF-8\nrequire 'spec_helper'\nrequire 'pp'\n\n\n# ======[ :Constructor {{{1\n# Tests with parameters are done in *"
  },
  {
    "path": "spec/deps_spec.rb",
    "chars": 1123,
    "preview": "# encoding: UTF-8\nrequire 'spec_helper'\nrequire 'pp'\n\n\nRSpec.describe \"C++ check dependencies are loaded\", :cpp, :deps d"
  },
  {
    "path": "spec/empty-exception-class_spec.rb",
    "chars": 3662,
    "preview": "# encoding: UTF-8\nrequire 'spec_helper'\nrequire 'pp'\n\n\nRSpec.describe \"C++ empty-exception class wizard\", :empty_excepti"
  },
  {
    "path": "spec/exception-class_spec.rb",
    "chars": 5647,
    "preview": "# encoding: UTF-8\nrequire 'spec_helper'\nrequire 'pp'\n\n\nRSpec.describe \"C++ exception class wizard\", :exception, :cpp, :c"
  },
  {
    "path": "spec/spe_func_spec.rb",
    "chars": 12847,
    "preview": "# encoding: UTF-8\nrequire 'spec_helper'\nrequire 'pp'\n\n\n# ======[ Special functions {{{1\n# Tests with parameters are done"
  }
]

// ... and 20 more files (download for full content)

About this extraction

This page contains the full source code of the LucHermitte/lh-cpp GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 220 files (806.7 KB), approximately 243.8k tokens, and a symbol index with 34 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!