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 , 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 ... 2 | Surrounds the current ... | | `(` | `()«»` | `()` | word | | `[` | `[]«»` | 1 | 1 | | `[` after a `[` | `[[]]«»` | n/a | n/a | | `]` before `]]` | close all `]]` | n/a | n/a | | `[` | | `[]` | word | | `{` | `{}«»`3 | `{}` | word | | `{` | | `{\n\n}«»` | line | | < | `<>«»` after `#include`, or `template` on the same line | | | | `"` (1 double quote) | `""«»` | 1 | 1 | | `""` | | `""` | word | | `'` | `''«»` | 1 | 1 | | `''` (2 single quotes) | | `''` | word | | `;` | closes all parenthesis after the cursor -- if there is nothing else | | | ##### Notes: * 1 Not defined to avoid hijacking default vim key bindings. * 2 The visual mode mappings do not surround the current marker/placeholder selected, but trigger the INSERT-mode mappings instead. * 3 The exact behavior of this mapping has changed with release r719 (on Google Code). Now, no newline is inserted by default. However, hitting `` in the middle of a pair of curly-bracket will expand into `{\n\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 `` 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 `if,` with `maplocalleader` assigned by default to the coma `,`. ##### Expression-condition surrounding mappings In the same idea, `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 <>«»` ; * `` inserts `typedef`, or `typename` depending on what is before the cursor ; * `` inserts `return`, and tries to correctly place the semicolon, and a placeholder, depending on what follows the cursor ; * `be`, `rbe` replace `(foo)` with `(foo.begin(),foo.end())` (or `rbegin`/`rend`) ; * `se`: attempt to fill-in a `switch-case` from an enumerated type ; * `,sc` | `,dc` | `,rc` | `,cc` | `,lc` surround the selection with ; `static_cast<>()`, `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` ; * `` inserts `std::`, `` inserts `boost:` ; * `?:` expands into `? «» : «»;` ; * `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. * `` 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), `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 `` and `` 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 ", "maintainer" : "Luc Hermitte ", "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" ? "" : "")') assert(¡s:Surround(1, '<+assertion+>')¡);<+s:TerminalPlaceHolder()+> ================================================ FILE: after/template/c/comment.template ================================================ VimL:" comment File Template, Luc Hermitte , 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+> * *

Semantics
*

  • Value, mathematical: it's an absolute position *
  • <+absolute position+> * <+
  • 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+> * *

    Semantics
    *

  • Value, mathematical: it's relative position *
  • <+relative position+> * <+
  • 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 , 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::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': '', '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("")') MuT: let s:_array_size = 'std::extent::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 // 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 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 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("")') 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("")') 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 , 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 , 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 Imperfect C++, 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("")') std::cerr << <++>; ================================================ FILE: after/template/cpp/chrono-how-long.template ================================================ VimL:" chrono-how-long File Template, Luc Hermitte , 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("")') 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(<+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("")') 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 , 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("")') VimL: call s:AddPostExpandCallback('lh#dev#import#add("")') 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("")') 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("")') 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 , 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": ""}}) 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 , 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::ends_with(<+input+>, <+prefix_searched+>) ================================================ FILE: after/template/cpp/entity-class.template ================================================ VimL:" entity-class File Template, Luc Hermitte , 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("")') 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("")') 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("")') MuT: if lh#cpp#use_cpp11() VimL: call s:AddPostExpandCallback('lh#dev#import#add("")') MuT: else VimL: call s:AddPostExpandCallback('lh#dev#import#add("")') MuT: endif VimL: call s:AddPostExpandCallback('lh#dev#import#add("")') 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": "Licence"}] 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("")') 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 , 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("")') 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 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(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("")') std::forward<<+s:type+>>(<+s:var+>)<+s:TerminalPlaceHolder()+> ================================================ FILE: after/template/cpp/getter.template ================================================ VimL:" getter File Template, Luc Hermitte , 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 , 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 , 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 , 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 , 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 , 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 , 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 , 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 , 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 , 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("")') 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("")') 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("")') 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 , 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 ================================================ 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("")') 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::path<++> ================================================ FILE: after/template/cpp/ptr_vector.template ================================================ VimL:" ptr_vector File Template, Luc Hermitte , 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_vector<¡s:Surround(1, '<+type+>')¡> <++> ================================================ FILE: after/template/cpp/ref_setter.template ================================================ VimL:" setter File Template, Luc Hermitte , 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 , 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<¡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("")') std::set<¡s:Surround(1, '<+type+>')¡><+s:TerminalPlaceHolder()+> ================================================ FILE: after/template/cpp/setter.template ================================================ VimL:" setter File Template, Luc Hermitte , 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("")') std::shared_ptr<¡s:Surround(1, '<+type+>')¡> <++> MuT: else VimL: call s:AddPostExpandCallback('lh#dev#import#add("")') 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("")') 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("")') 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 , 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::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("")) 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("")') std::string<+s:TerminalPlaceHolder()+> ================================================ FILE: after/template/cpp/swap-function.template ================================================ VimL:" swap-function File Template, Luc Hermitte , 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("")') 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 > 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 , 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("")') 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("")') 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("")') 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("")') 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 , 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("")') 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("")') std::weak_ptr<¡s:Surround(1, '<+type+>')¡> <++> MuT: else VimL: call s:AddPostExpandCallback('lh#dev#import#add("")') 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("")') 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 File Template, Luc Hermitte, 11th Apr 2012 VimL:" hint: | 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 snippet, Luc Hermitte, 11th Apr 2012 VimL:" hint: | VimL: let s:text = s:Surround(1, lh#marker#txt()) <+s:text+><+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: | 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: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 File Template, Luc Hermitte, 11th Apr 2012 VimL:" hint: | MuT: let s:text = s:Surround(1, lh#marker#txt()) <+s:text+><+s:TerminalPlaceHolder()+> ================================================ FILE: autoload/lh/cpp/AnalysisLib_Class.vim ================================================ " ======================================================================== " File: autoload/lh/cpp/AnalysisLib_Class.vim {{{1 " Author: Luc Hermitte " " License: GPLv3 with exceptions " 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::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\+\)\@' 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: 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 {{{ 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 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 {{{ function! s:TemplateSpecs() abort endfunction " }}} " ========================================================================== " Search for the direct base classes {{{ 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 " " License: GPLv3 with exceptions " " 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' 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 = '\\|<<\|>>\|==\| \)' " 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\' let s:re_volatile_member_fn = ')\s*\zs\' let s:re_throw_spec = ')\s*\%(\%(\\|\\)\s\+\)\=\(\(\zs.*\ze\))' " let s:re_noexcept_spec = ')\s*\%(\%(\\|\\)\s\+\)\=\\((\zs.*\ze)\)\=' let s:re_noexcept_spec = '\\%((\zs.*\ze)\)\=' let s:re_defined_by_compiler_prefix = ')\s*\%(\%(\\|\\)\s*\)\=\%(\\%((.*)\)\=\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 = '\' let s:re_final = '\' let s:re_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 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\') 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, '\%(\\s*\([-+*/=!^%]\s*\)\=\)\@ 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 (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*(\|\', \ 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*\%(\\s*\)\='. \ '\%(\%('.s:type_simple.'\|\s\+\)\+\|'.s:type_scope.'\)'. \ '\%(\\|\*\|&\|\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" " 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, '^\([^(]\{-}\\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*\(\\s*\)\='. " \ '\(\('.s:type_simple.'\|\s\+\)\+\|\<\I\i*\>\)'. " \ '\(\\|\*\|&\|\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 " " License: GPLv3 with exceptions " " 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 extention " (*) reuse a know buffer if it already exists -- i.e.: not limited to " readable files " (*) facultative option: extension of the file where to put the " definition of the function. " (*) Fix :GOTOIMPL to work even if &isk contains ":" " (*) Fix :GOTOIMPL to support operators like += " v2.2.0 " (*) Use new alternate-lite API to determine the destination file " (*) Update options to support specialization " (*) Fix extra space introduced by `:MOVETOIMPL` " (*) Update to new lh-tags v3.0 and lh-dev new API " v2.2.1 " (*) override and final cannot be used outside class definition " TODO: " (*) add knowledge about C99/C++11 new numeric types " (*) :MOVETOIMPL should not expect the open-brace "{" to be of the same " line as the function signature. " (*) Check how to convert the return, and the parameters, types to their " fully-qualified names if required in the function definition. " }}}1 "============================================================================= let s:cpo_save=&cpo set cpo&vim "------------------------------------------------------------------------ " ## Misc Functions {{{1 " # Version {{{2 function! lh#cpp#GotoFunctionImpl#version() return s:k_version endfunction " # Debug {{{2 let s:verbose = get(s:, 'verbose', 0) function! lh#cpp#GotoFunctionImpl#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#GotoFunctionImpl#debug(expr) abort return eval(a:expr) endfunction " ## Functions {{{1 " # Public {{{2 "------------------------------------------------------------------------ " Function: lh#cpp#GotoFunctionImpl#MoveImpl() "{{{3 " The default values for 'HowToShowVirtual', 'HowToShowStatic' and " 'HowToShowDefaultParams' can be overridden momentarily. " Parameters: None function! lh#cpp#GotoFunctionImpl#MoveImpl(...) abort try let a_save = @a let s = @/ let [end_proto, proto] = lh#dev#c#function#get_prototype(line('.'), 0, 1) if empty(proto) throw "No prototype found under the cursor." endif " move to the start of the definition call setpos('.', end_proto) " this puts us one char behind the definition start if lh#position#char_at_mark('.') !~ '[:{]' normal! h endif if proto[-1:] == ':' " select everything till the open bracket. " this won't work with C++11 initialiser-lists extended to {} silent exe "normal! \"ad/{\" else let @a = '' endif silent normal! "Ad% " For some reason, the previous command insert a leading newline let @a = substitute(@a, '^\_s*', '', '') " Add the ';' at the end what precedes, but not on a single line call search('\S', 'b') silent :exe "normal! A;\" " Search the prototype (once again!), from a compatible position (on the " closing bracket) call search(')', 'b') " TODO: For now, search the protype once again... " `"Ad%` sets regtype to "V". When pasted, it introduces a newline " => we need to prevent that if exists('*setreg') call setreg('a', @a, 'v') endif :exe "normal! :GOTOIMPL ".join(a:000, ' ')."\va{\"ap=a{" " was: " :exe "normal! \f{\"ac%;\:GOTOIMPL ".join(a:000, ' ')."\va{\"ap=a{" finally let @a = a_save let @/ = s endtry endfunction "------------------------------------------------------------------------ " Function: lh#cpp#GotoFunctionImpl#GrabFromHeaderPasteInSource "{{{3 " The default values for 'HowToShowVirtual', 'HowToShowStatic' and " 'HowToShowDefaultParams' can be overridden momentarily. " Parameters: 'ShowVirtualon', 'ShowVirtualoff', 'ShowVirtual0', 'ShowVirtual1', " 'ShowStaticon', '..off', '..0' or '..1' " 'ShowExplicitcon', '..off', '..0' or '..1' " 'ShowDefaultParamson', '..off', '..0', '..1', or '..2' " TODO: add C++11 override and final let s:option_value = '\%(on\|off\|\d\+\)$' function! lh#cpp#GotoFunctionImpl#GrabFromHeaderPasteInSource(...) abort let expected_extension = call('s:CheckOptions', a:000) let ft = &ft " 1- Retrieve the context {{{4 " 1.1- Get the class name,if any -- thanks to cpp_FindContextClass.vim let className = lh#cpp#AnalysisLib_Class#CurrentScope(line('.'), '##') " 1.2- Get the whole prototype of the function (even if on several lines) let proto = lh#dev#c#function#get_prototype(line('.'), 1) if "" == proto call lh#common#error_msg('cpp#GotoFunctionImpl.vim: We are not uppon the declaration of a function prototype!') return endif " 2- Build the result strings {{{4 try let isk_save = &isk set isk-=: let impl2search = s:BuildRegexFromImpl(proto,className) if impl2search.isWithoutDefinition call lh#common#error_msg("cpp#GotoFunctionImpl.vim:\n\n". \ "=delete and =default functions don't have an implementation!") return endif if impl2search.ispure call lh#common#error_msg("cpp#GotoFunctionImpl.vim:\n\n". \ "Pure virtual functions don't have an implementation!") " TODO: actually, they can have one. Add a confirm dialog return endif " 3- Add the string into the implementation file {{{4 call lh#cpp#GotoFunctionImpl#open_cpp_file(expected_extension) if &ft != ft exe 'setf '.ft endif " Search or insert the C++ implementation if !s:Search4Impl((impl2search.regex).'\_s*[{:]', className) let impl = s:BuildFunctionSignature4impl(proto,className) " Todo: Support looking into other files like the .inl file " Insert the C++ code at the end of the file call lh#cpp#GotoFunctionImpl#insert_impl(impl) endif finally let &isk = isk_save endtry " call confirm(impl, '&ok', 1) " }}}4 endfunction "------------------------------------------------------------------------ " Function: lh#cpp#GotoFunctionImpl#insert_impl(impl) {{{3 function! lh#cpp#GotoFunctionImpl#insert_impl(impl) abort let p = s:SearchLineToAddImpl() if -1 != p call s:InsertCodeAtLine(a:impl, p) let s:FunctionImpl = a:impl else " Otherwise, we use a method somehow like the one used by Robert: " We store the text to insert in a specific variable and wait for manual " insertion of the text. let s:FunctionImpl = a:impl call lh#common#warning_msg(":GOTOIMPL cannot determine where the function definition should be inserted." \ ."\nUse :PASTEIMPL to paste the code prepared." \ ."\nSee ftplugin/cpp/cpp_options.vim to tune the placement heuristic") endif endfunction "------------------------------------------------------------------------ " Function: lh#cpp#GotoFunctionImpl#open_cpp_file(expected_extension) {{{3 function! lh#cpp#GotoFunctionImpl#open_cpp_file(expected_extension) abort call s:Verbose('Opening file with extension `%1`', a:expected_extension) if expand('%:e') =~? 'cpp\|c\|C\|cxx\|txx' " already within the .cpp file return endif try " neutralize mu-template jump to marker feature let cleanup = lh#on#exit() \.restore('g:mt_jump_to_first_markers') let g:mt_jump_to_first_markers = 0 let split_opt = lh#cpp#GotoFunctionImpl#_find_alternates(a:expected_extension) if !empty(split_opt) let split_opt = lh#path#to_relative(split_opt) call s:DoSplit(split_opt) endif finally " restore mu-template call cleanup.finalize() endtry endfunction " Function: lh#cpp#GotoFunctionImpl#InsertCodeAtLine() {{{3 function! lh#cpp#GotoFunctionImpl#InsertCodeAtLine() abort return s:InsertCodeAtLine() endfunction " # Private {{{2 " Function: s:CheckOptions(...) {{{3 function! s:CheckOptions(...) abort " 0- Check options {{{4 let s:ShowVirtual = lh#ft#option#get('ShowVirtual', &ft, 1) let s:ShowStatic = lh#ft#option#get('ShowStatic', &ft, 1) let s:ShowExplicit = lh#ft#option#get('ShowExplicit', &ft, 1) let s:ShowDefaultParams = lh#ft#option#get('ShowDefaultParams', &ft, 1) let expected_extension = '' if 0 != a:0 let i = 0 while i < a:0 let i += 1 let varname = substitute(a:{i}, '\(.*\)'.s:option_value, '\1', '') if varname !~ 'ShowVirtual\|ShowStatic\|ShowExplicit\|ShowDefaultParams' " Error {{{5 if !empty(expected_extension) call lh#common#error_msg( \ 'cpp#GotoFunctionImpl.vim::GrabFromHeaderPasteInSource: extension already set to <'.expected_extension.'>') return else let expected_extension = a:{i} endif else " }}}4 let val = matchstr(a:{i}, s:option_value) if val == 'on' | let val = 1 elseif val == 'off' | let val = 0 elseif val !~ '\d\+' call lh#common#error_msg( \ 'cpp#GotoFunctionImpl.vim::GrabFromHeaderPasteInSource: Invalid value for parameter : <'.varname.'>') return endif " exe "let s:".varname."= val" let s:{varname} = val " call confirm(s:{varname}.'='.val, '&ok', 1) endif endwhile endif return expected_extension endfunction "------------------------------------------------------------------------ " Function: s:BestExtensionFor(root_name) {{{3 function! s:BestExtensionFor(root_name, expected_extension) abort if !empty(a:expected_extension) | return a:expected_extension | endif let Best_ext = lh#ft#option#get('ext_4_impl_file', &ft, 'cpp') let best_ext = type(Best_ext) == type(function('has')) \ ? Best_ext(a:root_name) \ : Best_ext return best_ext endfunction "------------------------------------------------------------------------ " Function: s:BuildRegexFromImpl(impl,className) {{{3 " Build the regex that will be used to search the signature in the " implementations file function! s:BuildRegexFromImpl(impl,className) abort let impl2search=lh#cpp#AnalysisLib_Function#SignatureToSearchRegex(a:impl,a:className) let g:impl2search2 = impl2search return impl2search " }}}4 endfunction "------------------------------------------------------------------------ " Function: s:Search4Impl(re_impl, scope):bool {{{3 function! s:Search4Impl(re_impl, scope) abort " 0- Pretransformations {{{4 let required_ns = matchstr(a:scope, '^.*\ze#::#') " 1- Memorize position {{{4 let l0 = line('.') " 2- Loop until the implementation is found, {{{4 " *and* the scope (namespaces) matches normal! gg " let l = 1 while 1 " l > 0 " a- search for an acceptable implementation {{{5 " Note: re_impl looks like : " 'type \(\(ns1::\)\=ns2::\)\=cl1::cl2::function(...)' let l = search(a:re_impl, 'W') if l <= 0 | break | endif " b- Get the current namespace at the line found {{{5 let ns_list = lh#cpp#AnalysisLib_Class#available_namespaces(l) " c- Build the function name that must be found on the current line {{{5 " The function aname also contain the scope " let req_proto = matchstr(required_ns, current_ns. " \ (current_ns == '') ? '.*$' : '::\zs.*$') " d- Retrieve the actual function name (+ relative scope) {{{5 let z=@" let fe=&foldenable set nofoldenable let mv = l."gg".virtcol('.').'|' if search('(', 'W') <= 0 " echoerr "Weird Error!!!" endif silent exe 'normal! v'.mv.'y' let &foldenable=fe let current_proto = matchstr(@", '\%(::\|\<\I\i*\>\|\\s*\(||\|&&\|[-+*/^%=]=\=\)\=\|\~\)\+\ze($') let proto0= @" let @" = z " Todo: purge comments within current_proto " e- Check if really found {{{5 for ns in ns_list " if match(required_ns, '^'.ns) == 0 " \ && (req_proto == current_proto) let current = ns . ((ns != "") ? '::' : '' ).current_proto if ("" != required_ns) && (required_ns !~ '.*::$') let required_ns .= '::' endif " call confirm('required_ns='.required_ns. " \ "\ncurrent_proto=".current_proto. " \ "\ncurrent_ns=".ns. " \ "\n".l."=".getline('.'). " \ "\n\nmv=".mv."\nproto0=".proto0."\ncurrent=".current, " \ '&ok', 1) " \ "\n\nreq_proto=".req_proto. if match(current,'^'.required_ns) == 0 return l endif endfor " }}}5 endwhile " 2.b- Not found {{{4 exe l0 return 0 " }}}4 endfunction "------------------------------------------------------------------------ " Function: s:BuildFunctionSignature4impl " {{{3 let s:k_operators = '\\|<<\|>>\)' function! s:BuildFunctionSignature4impl(proto,className) abort let proto = lh#cpp#AnalysisLib_Function#AnalysePrototype(a:proto) let g:implproto = proto let re_qualifiers = [] " 1.a- XXX if you want virtual commented in the implementation: {{{4 if s:ShowVirtual let re_qualifiers += ['\'] endif " 1.b- XXX if you want static commented in the implementation: {{{4 if s:ShowStatic let re_qualifiers += ['\'] endif " 1.b- XXX if you want explicit commented in the implementation: {{{4 if s:ShowExplicit let re_qualifiers += ['\'] endif let comments = matchstr(proto.qualifier, join(re_qualifiers, '\|')) if !empty(comments) let comments = '/*'.comments.'*/ ' endif " 2- Handle default params, if any. {{{4 " 0 -> "" : ignored " 1 -> "/* = value */" : commented " 2 -> "/*=value*/" : commented, spaces trimmed " 3 -> "/*value*/" : commented, spaces trimmed, no equal sign if s:ShowDefaultParams == 0 | let pattern = '\2' elseif s:ShowDefaultParams == 1 | let pattern = '/* = \1 */\2' elseif s:ShowDefaultParams == 2 | let pattern = '/*=\1*/\2' elseif s:ShowDefaultParams == 3 | let pattern = '/*\1*/\2' else | let pattern = '\2' endif " let implParams = [] for param in proto.parameters call s:Verbose("Parameter: %1", param) " TODO: param type may need to be fully-qualified, see 4.2 let sParam = (get(param, 'nl', 0) ? "\n" : '') \ . (param.type) . ' ' . (param.name) \ . substitute((param.default), '\(.\+\)', pattern, '') " echo "param=".param call add(implParams, sParam) endfor let implParamsStr = join(implParams, ', ') " @todo: exceptions specifications " 3- Add '::' to the class name (if any).{{{4 let className = a:className . (""!=a:className ? '::' : '') " let impl = substitute(impl, '\%(\~\s*\)\=\%(\<\i\+\>\|'.s:k_operators.'\)\('."\n".'\|\s\)*(', " \ className.'\0', '') " 4- Add scope to other types {{{4 " 4.1- ... return type " return type is stored in function signature extracted by ... ctags let session = lh#tags#session#get() let ltags = session.tags call session.finalize() let all_ret_dicts = filter(copy(ltags), 'v:val.name == '.string(proto.return)) let all_rets = lh#list#get(all_ret_dicts, 'class', '') " let all_rets = lh#list#transform(all_ret_dicts, [], 'v:1_.class') let all_rets = lh#list#unique_sort(all_rets) if len(all_rets) > 1 let all_rets = ['::'] + all_rets let choice = lh#ui#confirm('Where does <'.(proto.return).'> comes from?', \ join(all_rets, "\n"), 1) if choice == 0 | let scope = [] elseif choice == 1 | let scope = [''] else | let scope = [all_rets[choice-1]] endif elseif len(all_rets) == 1 let scope = all_rets else let scope = [] endif let scope += [proto.return] let return = join(scope, '::') " 4.2- ... parameters types " 4.3- ... constexpr " TODO: Check: not sure this really makes sense: constexpr function shall " be inlined if proto.constexpr let return = 'constexpr ' . return endif " 5- Return{{{4 " TODO: some styles like to put return types and function names on two " different lines let unstyled = comments \ . return . ' ' \ . className \ . join(proto.name, '::') \ . '('.implParamsStr . ')' \ . (proto.const ? ' const' : '') \ . (proto.volatile ? ' volatile' : '') \ . (!empty(proto.throw) ? ' throw ('.join(proto.throw, ',').')' : '') \ . (!empty(proto.noexcept) ? ' ' . proto.noexcept : '') \ . "{}" let styles = lh#style#get(&ft) let res = unstyled if !empty(styles) let styled = lh#style#apply(unstyled) let res = styled endif return res "}}}4 endfunction "------------------------------------------------------------------------ " Function: s:SearchLineToAddImpl() {{{3 function! s:SearchLineToAddImpl() abort let Position = lh#ft#option#get('FunctionPosition', &ft, 0) " Default value for FunctionPosArg may change depending on FunctionPosition if type(Position) == type(function('has')) " -- function (direct) {{{4 return Position() elseif Position == 1 || type(Position) == type('') " -- search pattern {{{4 " Default: EOF let FunctionPosArg = lh#ft#option#get('FunctionPosArg', &ft, '\%$') let s=search(FunctionPosArg) if 0 == s call lh#common#error_msg("cpp#GotoFunctionImpl.vim: Can't find the pattern\n". \' <(bpg):cpp'.&ft.'_FunctionPosArg>: '.FunctionPosArg) return -1 else return s endif elseif Position == 0 " -- offset from end {{{4 let FunctionPosArg = lh#ft#option#get('FunctionPosArg', &ft, 0) return line('$') - FunctionPosArg elseif Position == 2 " -- function (indirect) {{{4 let FunctionPosArg = lh#ft#option#get('FunctionPosArg', &ft) if lh#option#is_unset(FunctionPosArg) call lh#common#error_msg('cpp#GotoFunctionImpl.vim: No positionning '. \ 'function defined thanks to <(bpg):cpp'.&ft.'_FunctionPosArg>') return -1 elseif type(FunctionPosArg) == type(function('has')) return FunctionPosArg() elseif (type(FunctionPosArg) == type('')) && !exists('*'.FunctionPosArg) call lh#common#error_msg('cpp#GotoFunctionImpl.vim: The function '. \ '<(bpg):cpp'.&ft.'_FunctionPosArg> is not defined') return -1 endif exe "return ".FunctionPosArg."()" elseif Position == 3 " -- non-automatic insertion {{{4 return -1 endif " }}}4 endfunction "------------------------------------------------------------------------ " Function: s:InsertCodeAtLine([code [,line]]) {{{3 function! s:InsertCodeAtLine(...) abort if a:0 >= 2 | let p = a:2+1 | let impl = a:1 elseif a:0 >= 1 | let p = line('.') | let impl = a:1 else | let p = line('.') | let impl = s:FunctionImpl endif " Check namespace value let ns = lh#cpp#AnalysisLib_Class#CurrentScope(p, 'namespace') let ns0 = ns let impl0 = impl " call confirm('ns ='.ns."\nimpl=".impl, '&Ok', 1) while ns != "" let n0 = matchstr(ns, '^.\{-}\ze\%(::\|$\)') if impl =~ '\s'.n0.'\%(::\|#::#\)' " call confirm('trim: '.n0, '&OK', 1) let impl = substitute(impl, '\(\s\)'.n0.'\%(::\|#::#\)', '\1', 'g') else call lh#common#error_msg( 'cpp#GotoFunctionImpl.vim: Namespaces mismatch!!!'. \ "\n\nCan't insert <". \ matchstr(impl0, '\%(::\|#::#\|\<\I\i*\>\)*\ze\_s*('). \ '> within the namespace <'.ns.'>') " let g:impl0=impl0 return endif let ns = matchstr(ns, '::\zs.*$') " call confirm('ns ='.ns."\nimpl=".impl, '&Ok', 1) endwhile " Change my namespace delimiters (#::#) to normal scope delimiters (::) let impl = substitute(impl, '#::#', '::', '') . "\n" " Unfold folders otherwise there could be side effects with ':put' let folder=&foldenable set nofoldenable " Insert the default function implementation at position 'p' if p > line('$') if getline('$') !~ '^\s*$' let impl="\n".impl endif let p=line('$') endif silent exe p."put=impl" " Note: unlike 'put', 'append' can't insert multiple lines. " call append(p, impl) " Reindent the newly inserted lines let nl = strlen(substitute(impl, "[^\n]", '', 'g')) - 1 let p += 1 silent exe p.','.(p+nl).'v/^$/normal! ==' " Restore folding let &foldenable=folder endfunction "------------------------------------------------------------------------ " Function: lh#cpp#GotoFunctionImpl#_find_alternates(expected_extension) {{{3 function! lh#cpp#GotoFunctionImpl#_find_alternates(expected_extension) abort let files = lh#alternate#_find_alternates() " on current file if len(files.existing) == 1 return files.existing[0] elseif !empty(files.existing) let lFiles = files.existing else let lFiles = files.theorical endif let result = lh#path#select_one(lFiles, "What should be the name of the new file?") return result endfunction "------------------------------------------------------------------------ " Split Options: {{{3 " Function: s:SplitOption() {{{4 " @return the type of split desired: "n)o split", "v)ertical" (default one) or " "h)orizontal"/ function! s:SplitOption() abort if exists('g:cpp_Split') if g:cpp_Split =~ 'v\%[ertical]' | return 'v' elseif g:cpp_Split =~ 'h\%[orizontal]' | return 'h' else | return 'n' endif endif " default: vertical split return 'v' endfunction " Internal constants {{{4 " s:split_{a.vim or vim built-in commands}_{split n/h/v} = command to execute " --a.vim let s:split_a_n = 'A' let s:split_a_h = 'AS' let s:split_a_v = 'AV' " --no a.vim " @todo don't split if the buffer is opened (while the file does not exists " yet) let s:split_n_n = 'e' let s:split_n_h = 'sp' let s:split_n_v = 'vsp' " Function: s:DoSplit(arg) {{{4 function! s:DoSplit(arg) abort call lh#buffer#jump(a:arg, s:split_n_{s:SplitOption()}) endfunction " }}}2 " Functions }}}1 "------------------------------------------------------------------------ let &cpo=s:cpo_save "============================================================================= " vim600: set fdm=marker: ================================================ FILE: autoload/lh/cpp/UnmatchedFunctions.vim ================================================ "============================================================================= " File: autoload/lh/cpp/UnmatchedFunctions.vim {{{1 " Author: Luc Hermitte " " Version: 1.1.0 " Created: 14th Feb 2008 " Last Update: $Date$ "------------------------------------------------------------------------ " Description: description " "------------------------------------------------------------------------ " Installation: install details " History: history " TODO: " (*) Do not mess with history and @/ " (*) Support an update command " }}}1 "============================================================================= command! -nargs=1 FEcho :echo s: let s:cpo_save=&cpo set cpo&vim "------------------------------------------------------------------------ " ## Functions {{{1 " # Debug {{{2 function! lh#cpp#UnmatchedFunctions#verbose(level) let s:verbose = a:level endfunction function! s:Verbose(expr) if exists('s:verbose') && s:verbose echomsg a:expr endif endfunction function! lh#cpp#UnmatchedFunctions#debug(expr) return eval(a:expr) endfunction " ## Menu {{{1 " ==========================[ Menu ]==================================== function! s:AddToMenu(lines, fns, kind) for fn in a:fns let line = fn.filename.'| No '.a:kind.' found for ' \. lh#cpp#AnalysisLib_Function#BuildSignatureAsString(fn) call add(a:lines, line) endfor endfunction function! s:BuildMenu(unmatched) let res = ['--abort--'] call s:AddToMenu(res, a:unmatched.declarations, "definition") call s:AddToMenu(res, a:unmatched.definitions, "declaration") return res endfunction function! lh#cpp#UnmatchedFunctions#Display(className) let unmatched = lh#cpp#AnalysisLib_Function#SearchUnmatched(a:className) let choices = s:BuildMenu(unmatched) " return let b_id = lh#buffer#dialog#new( \ 'Unmatched('.substitute(a:className, '[^A-Za-z0-9_.]', '_', 'g' ).')', \ 'Unmatched functions for '.a:className, \ 'bot below', \ 0, \ 'lh#cpp#UnmatchedFunctions#select', \ choices \) " Added the lonely functions to the b_id let lUnmatched = unmatched.declarations call extend(lUnmatched, unmatched.definitions) let b_id['unmatched'] = lUnmatched " Syntax and co call s:PostInitDialog() return '' endfunction function! s:PostInitDialog() if has("syntax") syn clear " syntax region UFNbOcc start='^--' end='$' contains=UFNumber,UFName syntax match UFSignature /.*$/ contained syntax match UFFile /^ [^-][^|]\+/ contained nextgroup=UFText syntax match UFText /| No .* found for / contained nextgroup=UFSignature syntax region UFLine start='^ [^-]' end='$' contains=UFFile,UFText,UFSignature syntax region UFExplain start='@' end='$' contains=UFStart syntax match UFStart /@/ contained syntax match Statement /--abort--/ " Help highlight link UFExplain Comment highlight link UFStart Ignore " Lines highlight link UFLine Normal highlight link UFFile Directory highlight link UFText Normal highlight link UFSignature Identifier endif endfunction function! lh#cpp#UnmatchedFunctions#select(results) abort if len(a:results.selection) > 1 " this is an assert throw "Functions-Matcher: We are not supposed to select several functions" endif let selection = a:results.selection[0] if selection == 0 | call lh#buffer#dialog#quit() | return | endif " let unmatched = b:dialog.unmatched " let cmd = b:cmd let choices = a:results.dialog.choices echomsg '-> '.choices[selection] " echomsg '-> '.info[selection-1].filename . ": ".info[selection-1].cmd if exists('s:quit') | :quit | endif " let selected_unmatched = a:results.dialog.unmatched[selection-1] call lh#buffer#jump(selected_unmatched.filename, 'sp') normal! gg try " todo: save history and @/ let save_magic = &magic set nomagic exe selected_unmatched.cmd finally let &magic = save_magic endtry endfunction " ==========================[ Highlight ]=============================== " @todo " Active HL in buffers where there are unmatched functions decl/def " }}}1 "------------------------------------------------------------------------ let &cpo=s:cpo_save "============================================================================= " vim600: set fdm=marker: ================================================ FILE: autoload/lh/cpp/abs_rel.vim ================================================ "============================================================================= " File: autoload/lh/cpp/abs_rel.vim {{{1 " Author: Luc Hermitte " " Version: 1.1.0 " Created: 12th May 2009 " Last Update: $Date$ "------------------------------------------------------------------------ " Description: " Generative functions for the cpp/abs-rel.template file " "------------------------------------------------------------------------ " Installation: install details " History: history " TODO: missing features " }}}1 "============================================================================= let s:cpo_save=&cpo set cpo&vim "------------------------------------------------------------------------ " ## Functions {{{1 " # Debug {{{2 function! lh#cpp#abs_rel#verbose(level) let s:verbose = a:level endfunction function! s:Verbose(expr) if exists('s:verbose') && s:verbose echomsg a:expr endif endfunction function! lh#cpp#abs_rel#debug(expr) return eval(a:expr) endfunction "------------------------------------------------------------------------ function! lh#cpp#abs_rel#canonicalortodoxform(clsname, required) if !a:required | return "" | endif let text = "/** Protected Copy constructor.\n*/\n" let text .= a:clsname."(".a:clsname." const& rhs_);\n" let text .= "/** Protected Assignment operator.\n*/\n" let text .= a:clsname." & operator=(".a:clsname." const& rhs_);" " let text = Marker_Txt("sorry not implemented yet>") . ";\n" return text endfunction "------------------------------------------------------------------------ let &cpo=s:cpo_save "============================================================================= " vim600: set fdm=marker: ================================================ FILE: autoload/lh/cpp/analyse.vim ================================================ "============================================================================= " File: autoload/lh/cpp/analyse.vim {{{1 " Author: Luc Hermitte " " Version: 2.2.0. let s:k_version = '220' " Created: 08th Apr 2016 " Last Update: 31st Aug 2018 "------------------------------------------------------------------------ " Description: " Various functions to analyse C and C++ codes " "------------------------------------------------------------------------ " History: «history» " TODO: «missing features» " }}}1 "============================================================================= let s:cpo_save=&cpo set cpo&vim "------------------------------------------------------------------------ " ## Misc Functions {{{1 " # Version {{{2 function! lh#cpp#analyse#version() return s:k_version endfunction " # Debug {{{2 let s:verbose = get(s:, 'verbose', 0) function! lh#cpp#analyse#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#analyse#debug(expr) abort return eval(a:expr) endfunction "------------------------------------------------------------------------ " ## Exported functions {{{1 " Function: lh#cpp#analyse#var_type(name [,default]) {{{3 function! lh#cpp#analyse#var_type(name,...) abort try let p = getpos('.') let cleanup = lh#on#exit() \.register('call setpos(".",'.string(p).')') if a:name =~ '^\s*$' return call('s:NoDecl', [a:name]+a:000) endif if searchdecl(a:name) == 0 " First: let Vim find the variable definitions let def_line = getline('.') call s:Verbose('Definition of %1 found line %2: %3', a:name, line('.'), def_line) else " Then: search in the tags DB (it may be an attribute from the current " class) let session = lh#tags#session#get() let [var_kind] = session.indexer.get_kind_flags(&ft, ['variable', 'v', 'l']) let tags = session.tags let pat = '.*\<'.a:name.'\>.*' " FIXME: get the scopename of the current function as well=> ClassName::foobar() let classname = lh#cpp#AnalysisLib_Class#CurrentScope(line('.'), 'class') let defs = filter(copy(tags), 'v:val.name =~ classname."::".pat || (v:val.name =~ pat && s:GetClassName(v:val) =~ classname)') call s:Verbose('Attributes of %1 matching %2: %3', classname, pat, defs) let t_vars = filter(copy(defs), 'index(var_kind, v:val.kind)>=0') if empty(t_vars) return call('s:NoDecl', [a:name]+a:000) elseif len(t_vars) == 1 let def_line = t_vars[0].cmd else throw "Too many matching variables" endif endif let def_line = substitute(def_line, '\s*;\s*$\|\s*=.*', '', '') let def_line = substitute(def_line, '^\s*', '', '') let def = split(def_line, ',') " split function lists call filter(def, 'v:val =~ "\\<".a:name."\\s*$"') let var = lh#dev#option#call('function#_analyse_parameter', &ft, def[0]) return var.type finally call cleanup.finalize() if exists('session') call session.finalize() endif endtry endfunction " Function: lh#cpp#analyse#token(name, ...) {{{3 " TODO: finish function! lh#cpp#analyse#token(name, ...) abort let session = lh#tags#session#get() let tags = session.tags let type_kinds = session.indexer.get_kind_flags('cpp', 'classes\|structure names\|enumeration names\|typedefs') try " 1- check whether its a variable or a type " 1.1- ask clang, if available " 1.2- ask ctags, if available " todo? filter on the exact name as well ? let pat = '.*\<'.a:name.'\>.*' " let defs = taglist(pat) let defs = filter(copy(tags), 'v:val.name =~ pat') if !empty(defs) let t_types = lh#list#copy_if(defs, [], 'v:1_.kind == "g"') let var_kinds = 'lvx' if lh#tags#ctags_flavour() =~ 'utags' let var_kinds .= 'z' " parameters endif let t_vars = lh#list#copy_if(defs, [], 'v:1_.kind =~ "['.var_kinds.']"') " nominal case: one type if len(t_types) > 1 let t_types = lh#dev#tags#keep_full_names(t_types) endif if len(t_vars) > 1 let t_vars = lh#dev#tags#keep_full_names(t_vars) endif if len(t_types) == 1 && empty(t_vars) let res = (a:0 > 0) ? (a:1) : {} let res['type'] = t_types[0] return res elseif len(t_vars) == 1 && empty(t_types) let res = { 'var': t_vars[0] } if a:0 > 0 throw "Variable ".string(a:1)." referencing another variable: ".string(res) endif elseif !empty(t_types) && !empty(t_vars) throw "Too many compatible identifiers match the alleged ".(a:name)." symbol" elseif empty(t_types) && empty(t_vars) "No compatible identifier match the alleged symbol "but it can be something to search with searchdecl let res = {} else throw "unexpected case" endif else let res = {} endif " 1.3- or searchdecl otherwise if empty(res) let pos = getpos('.') try let not_found = searchdecl(a:name, 1) if not_found | return {} | endif " Type or variable ? let line = getline('.') if line =~ 'enum\s\+\(class\s\+\)\='.(a:name) " type let res = (a:0 > 0) ? (a:1) : {} let res['type'] = {'pos':getpos('.'), 'name': (a:name)} return res else " variable! " todo: factorize this common pattern 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 type = matchstr(line, '.*[(),{};]\s\*\<.*\>\ze\s\+'.a:name) let type = matchstr(line, s:re_qualified_name.'\ze\s\+'.a:name) if type =~ '^\s*$' throw "Cannot find an enum type related to the ".a:name." variable defined line ".line('.') endif let res = { 'var': {'name': (a:name), 'pos':getpos('.')}, 'type': {'name': type}} if a:0 > 0 throw "Variable ".string(a:1)." referencing another variable: ".string(res) endif let res = lh#cpp#analyse#token(type, res) return res endif finally call setpos('.', pos) endtry endif " 2- find the type definition finally call session.finalize() endtry endfunction " ## Internal functions {{{1 " Function: s:NoDecl(name, [default]) {{{3 function! s:NoDecl(name, ...) abort if a:0 == 0 throw "Cannot find variable <".a:name."> declaration. Impossible to deduce its type." else return a:1 endif endfunction " Function: s:GetClassName(dict) {{{3 function! s:GetClassName(dict) abort return get(a:dict, "class", get(a:dict, "struct", "")) endfunction " Function: lh#cpp#analyse#context([line]) {{{3 " https://vi.stackexchange.com/a/11942/626 function! lh#cpp#analyse#context(...) abort let line = get(a:, 1, line('.')) let fn = lh#dev#find_function_boundaries(line) if fn.lines[0] <= line && line <= fn.lines[1] " This is a function call lh#assert#value(fn).has_key('fn') let kinds = filter(['struct', 'class', 'namespace'], 'has_key(fn.fn, v:val)') call lh#assert#value(kinds).not().empty() let scope = join( \ [ get({'public': '+', 'private': '-', 'protected': '#'}, get(fn.fn, 'access', ''), '') \ , substitute(get(fn.fn, 'typeref', ''), '^typename:', '', '') \ , fn.fn[kinds[0]] . '::' . fn.fn.name . get(fn.fn, 'signature') \ ], ' ') else " classes, structs, namespaces, ... " TODO: don't move the cursor let scope = lh#cpp#AnalysisLib_Class#CurrentScope(line, 'any') endif return scope endfunction "------------------------------------------------------------------------ " }}}1 "------------------------------------------------------------------------ let &cpo=s:cpo_save "============================================================================= " vim600: set fdm=marker: ================================================ FILE: autoload/lh/cpp/constructors.vim ================================================ "============================================================================= " File: autoload/lh/cpp/constructors.vim {{{1 " Author: Luc Hermitte " " License: GPLv3 with exceptions " " Version: 2.2.0 " Created: 09th Feb 2009 " Last Update: 05th Sep 2018 "------------------------------------------------------------------------ " Description: " Helper MMIs to generate constructors " Deported functions used by ftplugin/cpp/cpp_Constructor.vim " "------------------------------------------------------------------------ " History: " v1.1.0: Creation " v2.0.0 31st May 2012 " License GPLv3 w/ extension " v.2.0.0b4 " New commands: :ConstructorCopy, :ConstructorDefault, " :ConstructorInit, :AssignmentOperator " Requirements: " - mu-template 3.0.8 " - lh-dev " TODO: " - select all attributes by default " - permit to change the order of the attributes in the constructor parameters " list (with , for instance " - align parameters on multiple lines, and init-lists " - have init-constructors rely on a mu-template snippet " - rely of libclang (databases?) " - Extend to C++11 move constructors & co " - Use universal ctags typeref attribute when available to obtain types " }}}1 "============================================================================= let s:cpo_save=&cpo set cpo&vim "------------------------------------------------------------------------ " ## Functions {{{1 " # Debug {{{2 function! lh#cpp#constructors#verbose(level) let s:verbose = a:level endfunction function! s:Verbose(expr) if exists('s:verbose') && s:verbose call lh#common#echomsg_multilines(a:expr) endif endfunction function! lh#cpp#constructors#debug(expr) abort return eval(a:expr) endfunction " # API {{{2 "Function: s:Attributes(classname) {{{3 function! s:Attributes(classname) abort " fetch the attributes let attributes = lh#dev#class#attributes(a:classname, 1) " The attributes need to be sorted by their order of definition in the class " definition " todo: do not assume the attributes comes from the same file/class if len(attributes) == 0 | return attributes | endif for attr in attributes let signature = attr.cmd let attr['fullsignature' ] = s:Regex2Sig(signature) " ctags doesn't extract attribute type... let attr.type = matchstr(attr.fullsignature, '^\s*\zs.\{-}\s\+\ze\S\+\s*$') endfor unlet attr let filename = attributes[0].filename " The buffer may not be associated to a real file, in that case, use its " current content. let bid = bufnr(filename) if bid >= 0 let buffer = getbufline(bid, 1, '$') else call lh#assert#true(filereadable(filename), "Cannot read lines from a file that cannot be read...") let buffer = readfile(filename) endif let search = join(lh#list#transform(attributes,[], 'escape(matchstr(v:1_.cmd,"/^\\s*\\zs.*\\ze\\s*;"),"*")'), '\|') call filter(buffer, 'v:val =~ '.string(search)) call map(buffer, 'matchstr(v:val,"\\s*\\zs.*\\ze\\s*;")') let sorted_attributes = [] for attr in buffer let p = lh#list#Find_if(attributes, 'v:val.fullsignature == '.string(attr)) " assert p!=-1 if p == -1 throw "lh#cpp#constructors.s:Attributes: unexpected attribute: ".string(attr) endif call add(sorted_attributes, attributes[p]) endfor return sorted_attributes endfunction "Function: lh#cpp#constructors#Main {{{3 function! lh#cpp#constructors#Main(...) abort if a:0 == 0 || a:1 == 'init' call lh#cpp#constructors#InitConstructor() elseif a:1 =~ 'assign' call lh#cpp#constructors#AssignmentOperator() else call lh#cpp#constructors#GenericConstructor(a:1) endif endfunction " Function: lh#cpp#constructors#InitConstructor() {{{3 function! lh#cpp#constructors#InitConstructor() abort " 1- Obtain current class name let classname = lh#cpp#AnalysisLib_Class#CurrentScope(line('.'),'any') call s:Verbose ("classname=".classname) " 2- Obtain attributes functions let attributes = s:Attributes(classname) call s:Verbose ("attributes=".join(attributes,"\n")) if !empty(attributes) " 3- Propose to select the functions to override call s:Display(classname, attributes) " 4- Insert them in the current class " -> asynchrounous else " 3.bis- do it synchronously let where_it_started = getpos('.') let where_it_started[0] = bufnr('%') call lh#cpp#constructors#_expand_selection(classname, [], [], where_it_started) endif endfunction " Function: lh#cpp#constructors#AssignmentOperator() {{{3 function! lh#cpp#constructors#AssignmentOperator() abort " 1- Obtain current class name let classname = lh#cpp#AnalysisLib_Class#CurrentScope(line('.'),'any') call s:Verbose ("classname=".classname) " 2- Obtain attributes functions let attributes = s:Attributes(classname) call s:Verbose ("attributes=".join(attributes,"\n")) " 3- Insert the assignment-operator declaration let params = {} let params.clsname = classname let params.attributes = attributes " remove scope from attribute name call lh#list#map_on(attributes, 'name', 'substitute(v:val, ".*::", "", "")') try let cleanup = lh#on#exit() \.restore('g:mt_jump_to_first_markers') let g:mt_jump_to_first_markers = 0 call lh#mut#expand_and_jump(0, 'cpp/assignment-operator', params) finally call cleanup.finalize() endtry " 4- Move its implementation, if any, to the right place if getline('.') =~ '}$' normal! % while line('.') > 1 && getline('.') =~ '\v^\s*\{|^\s*$' normal! k endwhile call lh#cpp#GotoFunctionImpl#MoveImpl() endif endfunction " Function: lh#cpp#constructors#GenericConstructor(kind) {{{3 function! lh#cpp#constructors#GenericConstructor(kind) abort " 1- Obtain current class name let classname = lh#cpp#AnalysisLib_Class#CurrentScope(line('.'),'any') call s:Verbose ("classname=".classname) " 2- Obtain attributes functions let attributes = s:Attributes(classname) let g:attributes = attributes call s:Verbose ("attributes=".join(attributes,"\n")) " 3- Insert the *-constructor declaration try let cleanup = lh#on#exit() \.restore('g:mt_jump_to_first_markers') let g:mt_jump_to_first_markers = 0 exe 'MuTemplate cpp/'.a:kind.'-constructor' finally call cleanup.finalize() endtry " 4- Go-to its implementation and fill-it " Last line inserted should be the constructor signature " 4.1- goto impl is at the right place " MOVETOIMPL doesn't know how to ignore initialization-list " => We don't use the constructor snippets at their full capacity for now, " and thus duplicate their attribute-duplication code. GOTOIMPL normal! % " 4.2- Prepare init-list code let rhs = lh#naming#param('rhs').'.' let init_list=[] for attribute in attributes let attrb_name = matchstr(attribute.fullsignature, '^\s*.\{-}\s\+\zs\S\+\ze\s*$') if a:kind == 'copy' call add(init_list, attrb_name.'('.lh#cpp#snippets#duplicate_param(rhs.attrb_name, attribute.type).')') elseif a:kind == 'default' call add(init_list, attrb_name.'()') endif endfor " 4.3- Insert the init-list if !empty(init_list) let impl_lines=[] call add(impl_lines, ': '.init_list[0]) if len(init_list) > 0 call extend(impl_lines, lh#list#transform(init_list[1:], [], '", ".v:1_')) endif put!=impl_lines endif endfunction " # Internals {{{2 " Function: lh#cpp#constructors#_complete(A,L,P) {{{3 function! lh#cpp#constructors#_complete(A,L,P) abort return filter(['init', 'copy', 'default', 'assign'], 'v:val =~ "^".a:A.".*"') endfunction " # GUI {{{2 " ==========================[ Menu ]==================================== " Function: s:Access(attr) {{{3 function! s:Access(attr) abort if has_key(a:attr, 'access') if a:attr.access == 'public' | return '+' elseif a:attr.access == 'protected' | return '#' elseif a:attr.access == 'private' | return '-' else | return '?' endif else | return '?' endif endfunction function! s:Regex2Sig(regex) abort let sig = substitute(a:regex, '\v/\^\s*(.{-})\s*;\s*\$/', '\1', '') return sig endfunction " Function: s:AddToMenu(lines, attrs) {{{3 function! s:AddToMenu(lines, attrs) abort " 1- Compute max function length let max_length = 0 let attrs=[] " for overloads in a:attrs " for attr in overloads for attr in a:attrs " this damned ctags does not store the type of the attribute ... let length = lh#encoding#strlen(attr.fullsignature) if length > max_length | let max_length = length | endif call add(attrs, attr) endfor " endfor " 2- Build the result for attr in attrs let line = s:Access(attr).' '.attr.fullsignature \ . repeat(' ', max_length-lh#encoding#strlen(attr.fullsignature)) call add(a:lines, line) endfor endfunction " Function: s:BuildMenu(declarations) {{{3 function! s:BuildMenu(declarations) abort let res = ['--abort--'] call s:AddToMenu(res, a:declarations) return res endfunction " Function: s:Display(className, declarations) {{{3 function! s:Display(className, declarations) abort let choices = s:BuildMenu(a:declarations) " return let b_id = lh#buffer#dialog#new( \ 'C++Constructor('.substitute(a:className, '[^A-Za-z0-9_.]', '_', 'g' ).')', \ 'Construct-Initializable fields for '.a:className, \ 'bot below', \ 1, \ 'lh#cpp#constructors#select', \ choices \) call lh#buffer#dialog#add_help(b_id, '@| +==public, #==protected, -==private in one of the ancestor class', 'long') " Added the lonely functions to the b_id let b_id['declarations'] = a:declarations let b_id['classname'] = a:className " Syntax and co call s:PostInitDialog() return '' endfunction " Function: s:PostInitDialog() {{{3 function! s:PostInitDialog() abort if has("syntax") syn clear " todo: fix syntax names " syntax region UFNbOcc start='^--' end='$' contains=UFNumber,UFName " syntax match CTRtype /.\{-}$/ contained nextgroup=CTRname syntax match CTRname /\S*\s*$/ contained syntax match CTRtagged /^\*/ contained " syntax match UFFile /^ [^-][^[]\+/ contained nextgroup=UFText " syntax match UFText /| No .* found for / contained nextgroup=UFSignature syntax region CTRLine start='^[ *] [^-]' end='$' contains=CTRtagged,CTRtype,CTRname syntax region CTRExplain start='@' end='$' contains=CTRStart syntax match CTRStart /@/ contained syntax match Statement /--abort--/ " Help highlight link CTRExplain Comment highlight link CTRStart Ignore " Lines highlight link CTRLine type highlight link CTRtagged Statement " highlight link CTRtype Comment highlight link CTRname Identifier endif endfunction " Function: lh#cpp#constructors#_expand_selection(results) {{{3 function! lh#cpp#constructors#_expand_selection(classname, sig_params, init_list, where_it_started) abort " 0- prepare the init-ctr signature let len = lh#list#accumulate2(a:sig_params, 0, 'v:1_ + strlen(v:2_)') \ + lh#encoding#strlen(a:classname) + 2*len(a:sig_params) \ + 3 " (); if len > &tw-&sw let sig = [a:classname . '(' ] call extend(sig, lh#list#transform(a:sig_params[0:len(a:sig_params)-2], [], 'v:1_ . ","')) call add(sig, a:sig_params[-1].')') let header_lines = sig else let sig = a:classname.'('. join(a:sig_params, ', ') . ')' let header_lines = [substitute(sig, '\s\+', ' ', 'g')] endif let impl_lines = deepcopy(header_lines) let header_lines[-1] .= ';' " 1- insert it in the .h " Go back to the original buffer, and insert the built lines call lh#buffer#find(a:where_it_started[0]) if 0==append(a:where_it_started[1]-1, header_lines) exe (a:where_it_started[1]-1).',+'.(len(header_lines)-1).'normal! ==' call s:Verbose((a:where_it_started[1]-1).',+'.(len(header_lines)-1).'normal! ==') endif " TODO: auto-dox " 2- insert the default impl (see gotoimpl) in the .cpp, don't forget the " init-list let impl_lines[0] = a:classname . '::' . impl_lines[0] if !empty(a:init_list) call add(impl_lines, ': '.a:init_list[0]) if len(a:init_list) > 0 call extend(impl_lines, lh#list#transform(a:init_list[1:], [], '", ".v:1_')) endif endif call extend(impl_lines, [ '{', '}']) let impl = join(impl_lines, "\n") call lh#cpp#GotoFunctionImpl#open_cpp_file('') call lh#cpp#GotoFunctionImpl#insert_impl(impl) endfunction " Function: lh#cpp#constructors#select(results) {{{3 function! lh#cpp#constructors#select(results) abort call lh#buffer#dialog#quit() if len(a:results.selection)==1 && a:results.selection[0]==0 return endif " if exists('s:quit') | :quit | endif " let unmatched = b:dialog.unmatched " let cmd = b:cmd " let choices = a:results.dialog.choices let sig_params = [] let init_list = [] for selection in a:results.selection " echomsg '-> '.choices[selection] " echomsg '-> '.info[selection-1].filename . ": ".info[selection-1].cmd " let one_selected_attr = a:results.dialog.declarations[selection-1] let attrb_type = matchstr(one_selected_attr.fullsignature, '^\s*\zs.\{-}\s\+\ze\S\+\s*$') let attrb_name = matchstr(one_selected_attr.fullsignature, '^\s*.\{-}\s\+\zs\S\+\ze\s*$') let param_name = lh#cpp#style#attribute2parameter_name(attrb_name) call add(sig_params, lh#dev#cpp#types#ConstCorrectType(attrb_type).' '.param_name) call add(init_list, attrb_name.'('.param_name.')') " echomsg string(selected_virt) endfor let classname = a:results.dialog.classname call lh#cpp#constructors#_expand_selection(a:results.dialog.classname, \ sig_params, init_list, \ a:results.dialog.where_it_started) endfunction "------------------------------------------------------------------------ " }}}1 "------------------------------------------------------------------------ let &cpo=s:cpo_save "============================================================================= " vim600: set fdm=marker: ================================================ FILE: autoload/lh/cpp/enum.vim ================================================ "============================================================================= " File: autoload/lh/cpp/enum.vim {{{1 " Author: Luc Hermitte " " License: GPLv3 with exceptions " let s:k_version = 220 " Version: 2.2.0 " Created: 06th Jan 2011 " Last Update: 31st Aug 2018 "------------------------------------------------------------------------ " Description: " Support autoload-plugin for :SwitchEnum. " "------------------------------------------------------------------------ " Requirements: " Requires Vim7+, lh-dev, lh-vim-lib " }}}1 "============================================================================= let s:cpo_save=&cpo set cpo&vim "------------------------------------------------------------------------ " ## Misc Functions {{{1 " # Version {{{2 function! lh#cpp#enum#version() return s:k_version endfunction " # Debug {{{2 let s:verbose = get(s:, 'verbose', 0) function! lh#cpp#enum#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#enum#debug(expr) return eval(a:expr) endfunction "------------------------------------------------------------------------ " ## Exported functions {{{1 " Function: lh#cpp#enum#expand_enum_to_switch() {{{3 function! lh#cpp#enum#expand_enum_to_switch() abort let enum_name = GetCurrentKeyword() let def = lh#cpp#enum#get_definition(enum_name) let ns = lh#cpp#AnalysisLib_Class#available_namespaces(line('.')) let values = [] for enum in def.values let simplified = map(copy(ns), 'substitute(enum, "^".v:val."::", "", "")') let shortest = lh#list#arg_min(ns, function('len')) call lh#assert#true(shortest >= 0 && shortest < len(simplified)) let values += [simplified[shortest]] endfor let def.values = lh#list#unique_sort(values) " TODO: recognize whether this is a type or surround it with markers let def.expr = def.name call s:Verbose('Generate swith from enum %1 -> %2', enum_name, def) if !empty(def) normal! diw call MuTemplate('c/switch', def) " todo: delete enum_name if MuTemplate() expands endif endfunction " Function: lh#cpp#enum#analyse_token(name, ...) {{{3 function! lh#cpp#enum#analyse_token(name, ...) abort let session = lh#tags#session#get() let tags = session.tags " "variable" => regex let [var_kind, enum_kind] = session.indexer.get_kind_flags(&ft, ['variable', 'v', 'l'], ['enumeration name', 'g']) try " 1- check whether its a variable or a type " 1.1- ask clang, if available " 1.2- ask ctags, if available " todo? filter on the exact name as well ? let pat = '.*\<'.a:name.'\>.*' " let defs = taglist(pat) let defs = filter(copy(tags), 'v:val.name =~ pat') if !empty(defs) let t_enums = filter(copy(defs), 'index(enum_kind, v:val.kind)>=0') let t_vars = filter(copy(defs), 'index(var_kind, v:val.kind)>=0') " nominal case: one type if len(t_enums) > 1 let t_enums = lh#dev#tags#keep_full_names(t_enums) endif if len(t_vars) > 1 let t_vars = lh#dev#tags#keep_full_names(t_vars) endif if len(t_enums) == 1 && empty(t_vars) let res = (a:0 > 0) ? (a:1) : {} let res['type'] = t_enums[0] return res elseif len(t_vars) == 1 && empty(t_enums) let res = { 'var': t_vars[0] } if a:0 > 0 throw "Variable ".string(a:1)." referencing another variable: ".string(res) endif elseif !empty(t_enums) && !empty(t_vars) throw "Too many compatible identifiers match the alleged ".(a:name)." enum" elseif empty(t_enums) && empty(t_vars) "No compatible identifier match the alleged enum "but it can be something to search with searchdecl let res = {} else throw "unexpected case" endif else let res = {} endif " 1.3- or searchdecl otherwise if empty(res) let pos = getpos('.') try let not_found = searchdecl(a:name, 1) if not_found | return {} | endif " Type or variable ? let line = getline('.') if line =~ 'enum\s\+\(class\s\+\)\='.(a:name) " type let res = (a:0 > 0) ? (a:1) : {} let res['type'] = {'pos':getpos('.'), 'name': (a:name)} return res else " variable! " todo: factorize this common pattern 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 type = matchstr(line, '.*[(),{};]\s\*\<.*\>\ze\s\+'.a:name) let type = matchstr(line, s:re_qualified_name.'\ze\s\+'.a:name) if type =~ '^\s*$' throw "Cannot find an enum type related to the ".a:name." variable defined line ".line('.') endif let res = { 'var': {'name': (a:name), 'pos':getpos('.')}, 'type': {'name': type}} if a:0 > 0 throw "Variable ".string(a:1)." referencing another variable: ".string(res) endif let res = lh#cpp#enum#analyse_token(type, res) endif finally call setpos('.', pos) endtry endif return res " 2- find the type definition finally call session.finalize() endtry endfunction " Function: lh#cpp#enum#get_definition(name) {{{2 function! lh#cpp#enum#get_definition(name) abort let what = lh#cpp#enum#analyse_token(a:name) if empty(what) throw "Cannot obtain information on the alleged ".(a:name)." enum" endif " A- case when the enum follows lh-cpp enum pattern: " struct MyEnum { " enum type { E1, E2, ...., MAX__ }; " }; if what.type.name =~ "::type$" " 1- ask ctags " TODO: check weither the else case is enough if has_key(what.type, 'struct') let super = what.type.struct elseif has_key(what.type, 'class') let super = what.type.class else ... ? endif let enum_values = taglist(super) call filter(enum_values, 'get(v:val, "kind", "") == "e"') else " Other cases, with no guaranties if has_key(what.type, 'struct') let super = what.type.struct elseif has_key(what.type, 'class') let super = what.type.class else let super = '.' endif let enum_values = taglist(super) let enum_name = matchstr(what.type.name, '\(.*::\)\=\zs.*') call filter(enum_values, 'get(v:val, "kind", "") == "e" && get(v:val, "enum", "")=~ enum_name') endif let res = {'type': what.type.name, 'name': (a:name)} let enum_values = lh#dev#tags#keep_full_names(enum_values) let res['values'] = lh#list#get(enum_values, 'name') return res endfunction " Function: lh#cpp#enum#_new(...) {{{2 function! lh#cpp#enum#_new(...) abort try " Inhibits the jump part in lh#mut#expand_and_jump() let cleanup = lh#on#exit() \.restore_option('mt_jump_to_first_markers') \.restore('b:cpp_last_enum') let b:mt_jump_to_first_markers = 0 " What is the current scope ? let scope = lh#cpp#AnalysisLib_Class#CurrentScope(line('.'), 'any') if !empty(scope) | let scope .= '::' | endif " Insert the enum definition let last_line = call('lh#mut#expand_and_jump', [0, 'cpp/enum2']+a:000) let last_enum = b:cpp_last_enum call append(last_line, '') call cursor(last_line+1, 1) " Goto to its associated definition file call lh#cpp#GotoFunctionImpl#open_cpp_file('') " And insert the non-inlined function definitions call call('lh#mut#expand_and_jump', [0, 'cpp/enum2-impl', last_enum]) finally " Restores mt_jump_to_first_markers call cleanup.finalize() endtry endfunction "------------------------------------------------------------------------ " ## Internal functions {{{1 " }}}1 "------------------------------------------------------------------------ let &cpo=s:cpo_save "============================================================================= " vim600: set fdm=marker: ================================================ FILE: autoload/lh/cpp/ftplugin.vim ================================================ "============================================================================= " File: autoload/lh/cpp/ftplugin.vim {{{1 " Author: Luc Hermitte " " License: GPLv3 with exceptions " " Version: 2.0.0 " Created: 11th Sep 2008 " Last Update: $Date$ "------------------------------------------------------------------------ " Description: " Provides lh#cpp#ftplugin#OptionalClass(...) that can be used to write " :commands in ftplugins that tries to deduce the name of the current " class if none is provided. " }}}1 "============================================================================= let s:cpo_save=&cpo set cpo&vim "------------------------------------------------------------------------ " ## Functions {{{1 " # Debug {{{2 function! lh#cpp#ftplugin#verbose(level) let s:verbose = a:level endfunction function! s:Verbose(expr) if exists('s:verbose') && s:verbose echomsg a:expr endif endfunction function! lh#cpp#ftplugin#debug(expr) return eval(a:expr) endfunction "------------------------------------------------------------------------ " # Public {{{2 function! lh#cpp#ftplugin#OptionalClass(...) if a:0 != 0 if type(a:1) == type("") && strlen(a:1)>0 return a:1 elseif type(a:1) == type([]) if len(a:1) > 0 && strlen(a:1[0]) > 0 return a:1[0] endif endif endif let classname = lh#cpp#AnalysisLib_Class#CurrentScope(line('.'),'class') return classname endfunction "------------------------------------------------------------------------ let &cpo=s:cpo_save "============================================================================= " vim600: set fdm=marker: ================================================ FILE: autoload/lh/cpp/include.vim ================================================ "============================================================================= " File: autoload/lh/cpp/include.vim {{{1 " Author: Luc Hermitte " " Version: 002 " Created: 28th Apr 2014 " Last Update: 01st Oct 2018 "------------------------------------------------------------------------ " Description: " «description» " "------------------------------------------------------------------------ " History: «history» " TODO: «missing features» " }}}1 "============================================================================= let s:cpo_save=&cpo set cpo&vim "------------------------------------------------------------------------ " ## Misc Functions {{{1 " # Version {{{2 let s:k_version = 2 function! lh#cpp#include#version() return s:k_version endfunction " # Debug {{{2 let s:verbose = 0 function! lh#cpp#include#verbose(...) if a:0 > 0 | let s:verbose = a:1 | endif return s:verbose endfunction function! s:Verbose(expr) if s:verbose echomsg a:expr endif endfunction function! lh#cpp#include#debug(expr) return eval(a:expr) endfunction "------------------------------------------------------------------------ " ## Exported functions {{{1 " Function: lh#cpp#include#add(filename, ...) {{{3 " @return if anything was added " usages " - add('"filename"') " - add('') " - add('', 'first') " ou 'last' " - add('filename', 0) -> "filename" " - add('filename', 1) -> " - add('filename', 0, 'first') -> "filename" " - add('filename', 1, 'first') -> function! lh#cpp#include#add(filename, ...) abort keepjumps normal! gg " Analyse arguments let filename0 = substitute(a:filename, '[<"]\(\f\+\)[>"]', '\1', '') let offset = 0 if a:filename[0] == '<' let useAngleBrackets = 1 elseif a:filename[0] == '"' let useAngleBrackets = 0 elseif a:0 > 0 let useAngleBrackets = a:1 let offset = 1 else let useAngleBrackets = 0 endif if useAngleBrackets let filename = '<'.filename0.'>' else let filename = '"'.filename0.'"' endif let where = a:0 > offset ? a:000[offset] : 'last' let l = search('^#\s*include\s*["<]'.filename0.'\>', 'c') " todo: parameter to inhibit this from mu-template if l > 0 call lh#common#warning_msg(filename." is already included") return 0 endif if where == "last" keepjumps normal! G let line = search('^#\s*include', 'b') if line == 0 " no other #include found => like first return lh#cpp#include#add(filename, 'first') endif elseif where == "first" keepjumps normal! gg let line = search('^#\s*include', 'c') if line == 0 " try after the first #include " Search for the #ifndef/#define in case of include files let line = search('^#ifndef \(\k\+\)\>.*\n#define \1\>') if line > 0 let line += 1 elseif line('$') == 1 " empty file let line = 0 else " Search for after the file headers let line = 1 while line <= line('$') let ll = getline(line) if !lh#syntax#is_a_comment_at(line, 1) && !lh#syntax#is_a_comment_at(line, len(ll)+1) && ll !~ '^\s*\*' " Sometimes doxygen comments don't have a synstack break endif let line += 1 endwhile let line -= line != line('$') call cursor(line, 0) endif endif endif let text='#include '.filename call append(line, text) " silent put=line call lh#common#warning_msg(text . ' added') return 1 endfunction " Function: lh#cpp#include#add_c_std(filename, ...) {{{3 " Specialization of lh#cpp#include#add() for C standard header files " that shall become when included from a C++ file. function! lh#cpp#include#add_c_std(filename, ...) abort let ft = &ft let filename = (ft == 'cpp') ? ('c'.a:filename) : (a:filename.'.h') let filename = '<' . filename . '>' return call(function('lh#cpp#include#add'), [filename]+ a:000) endfunction "------------------------------------------------------------------------ " ## Internal functions {{{1 " }}}1 "------------------------------------------------------------------------ let &cpo=s:cpo_save "============================================================================= " vim600: set fdm=marker: ================================================ FILE: autoload/lh/cpp/libclang.vim ================================================ "============================================================================= " File: autoload/lh/cpp/libclang.vim {{{1 " Author: Luc Hermitte " " License: GPLv3 with exceptions " " Version: 2.2.1. let s:k_version = '221' " Created: 28th Nov 2019 " Last Update: 28th Nov 2019 "------------------------------------------------------------------------ " Description: " Adapt results from vim-clang " "------------------------------------------------------------------------ " History: «history» " TODO: «missing features» " }}}1 "============================================================================= if ! (lh#has#plugin('autoload/clang.vim') && clang#can_plugin_be_used()) finish endif let s:cpo_save=&cpo set cpo&vim let s:k_has_compil_hints = lh#has#plugin('autoload/lh/compil_hints.vim') "------------------------------------------------------------------------ " ## Misc Functions {{{1 " # Version {{{2 function! lh#cpp#libclang#version() return s:k_version endfunction " # Debug {{{2 let s:verbose = get(s:, 'verbose', 0) function! lh#cpp#libclang#verbose(...) if a:0 > 0 | let s:verbose = a:1 | endif return s:verbose endfunction function! s:Log(expr, ...) abort call call('lh#log#this',[a:expr]+a:000) endfunction function! s:Verbose(expr, ...) abort if s:verbose call call('s:Log',[a:expr]+a:000) endif endfunction function! lh#cpp#libclang#debug(expr) abort return eval(a:expr) endfunction "------------------------------------------------------------------------ " ## API functions {{{1 " # Ancestors {{{2 function! s:add_info_to_qf(qf, balloons, info, level, balloon_ctx) abort " {{{3 let info = a:info.location let info.text = a:level. '+- '.a:info.access.' '.a:info.spelling call add(a:qf, info) let balloon_ctx = ' : '.a:info.access.' '.a:info.spelling . a:balloon_ctx call add(a:balloons, balloon_ctx) if has_key(a:info, 'parents') call map(copy(a:info.parents), 's:add_info_to_qf(a:qf, a:balloons, v:val, "| ".a:level, balloon_ctx)') endif endfunction " Function: lh#cpp#libclang#show_ancestors(...) {{{3 " TODO: " - Support to pass an optional class name " - Add option to choose qflist or loclist function! lh#cpp#libclang#show_ancestors(...) abort let [parents, current] = clang#parents() let qf = [] let qf += [extend(current.location, {'text': current.name})] let balloons = [' : inspected leaf'] call map(copy(parents), 's:add_info_to_qf(qf, balloons, v:val, "", "")') call setqflist(qf) if lh#has#properties_in_qf() call setqflist([], 'a', {'title': current.name . ' base classes'}) if s:k_has_compil_hints call lh#compil_hints#set_balloon_format({k, v -> l:current.name . l:balloons[v.key]}) endif endif if exists(':Copen') Copen else copen endif endfunction "------------------------------------------------------------------------ " ## Internal functions {{{1 "------------------------------------------------------------------------ " }}}1 "------------------------------------------------------------------------ let &cpo=s:cpo_save "============================================================================= " vim600: set fdm=marker: ================================================ FILE: autoload/lh/cpp/macros.vim ================================================ "============================================================================= " File: autoload/lh/cpp/macros.vim {{{1 " Author: Luc Hermitte " " Version: 2.2.0. let s:k_version = '220' " Created: 30th Jun 2016 " Last Update: 30th Jun 2016 "------------------------------------------------------------------------ " Description: " API related to C and C++ macros " "------------------------------------------------------------------------ " History: «history» " TODO: «missing features» " }}}1 "============================================================================= let s:cpo_save=&cpo set cpo&vim "------------------------------------------------------------------------ " ## Misc Functions {{{1 " # Version {{{2 function! lh#cpp#macros#version() return s:k_version endfunction " # Debug {{{2 let s:verbose = get(s:, 'verbose', 0) function! lh#cpp#macros#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#macros#debug(expr) abort return eval(a:expr) endfunction "------------------------------------------------------------------------ " ## Exported functions {{{1 " # Clean `#if` " Function: lh#cpp#macros#keep(bool) {{{3 " Remove the true/false path into a `#if ... #else ... #endif` construct " TODO: support `defined(...)`, `#elif`, ... function! lh#cpp#macros#keep(bool) abort " 0- Requirements " 0.1- Check matchit is installed if !exists('g:loaded_matchit') runtime macros/matchit.vim if !exists('g:loaded_matchit') throw 'Cannot trim `#if..#else..#endif` path without matchit' endif endif " 0.2- Be sure we're on the `#if 0/1` line let line = getline('.') if line !~ '\v^#\s*if\s+[01]' throw 'Cursor not on a `#if 0|1` line. Cannot trim paths.' endif " 1- Note line numbers normal! ^ let l_if = line('.') normal % let l = line('.') if getline(l) =~ '\v^#\s*else' let l_else = l normal % let l = line('.') endif " Not an elif here! if getline(l) !~ '\v^#\s*endif' throw '`#endif` expected (`#elif` is not supported yet)' endif let l_endif = line('.') " 2- Trim (starting from the end) let keep_start = (line =~ '\v^#\s*if\s+1') == eval(a:bool) let l_last_if = keep_start ? l_if : l_else let l_first_else = keep_start ? l_else : l_endif call s:Verbose('Keeping the `#%1` case -- :%2,%3d | %4,%5d', keep_start ? 'if' : 'else', l_first_else, l_endif, l_if, l_last_if) silent! exe l_first_else.','.l_endif.'d _' silent! exe l_if.','.l_last_if.'d _' endfunction "------------------------------------------------------------------------ " ## Internal functions {{{1 "------------------------------------------------------------------------ " }}}1 "------------------------------------------------------------------------ let &cpo=s:cpo_save "============================================================================= " vim600: set fdm=marker: ================================================ FILE: autoload/lh/cpp/option.vim ================================================ "============================================================================= " File: autoload/lh/cpp/option.vim {{{1 " Author: Luc Hermitte " " Version: 2.2.0 " Created: 05th Apr 2012 " Last Update: 08th Mar 2018 "------------------------------------------------------------------------ " Description: " Options for lh-cpp " " Deprecated: " This nl_before_bracket API has been deprecated in favour of AddStyle! " "------------------------------------------------------------------------ " Installation: " Drop this file into {rtp}/autoload/lh/cpp " Requires Vim7+, lh-dev " }}}1 "============================================================================= let s:cpo_save=&cpo set cpo&vim "------------------------------------------------------------------------ " ## Misc Functions {{{1 " # Version {{{2 let s:k_version = 2 function! lh#cpp#option#version() return s:k_version endfunction " # Debug {{{2 let s:verbose = 0 function! lh#cpp#option#verbose(...) if a:0 > 0 | let s:verbose = a:1 | endif return s:verbose endfunction function! s:Verbose(expr) if s:verbose echomsg a:expr endif endfunction function! lh#cpp#option#debug(expr) return eval(a:expr) endfunction "------------------------------------------------------------------------ " ## Exported functions {{{1 " # Preferences regarding how control statements are expanded {{{2 " Possible values: 0 (default)/1 " Applies to: if (){}, else{}, for (;;){}, while(){}, switch, catch, ... " Function: lh#cpp#option#nl_before_bracket() {{{3 " Write each '(' on a new line; -> if \n() ... {} function! lh#cpp#option#nl_before_bracket() call s:Deprecated() return lh#ft#option#get('nl_before_bracket', &ft, 0) endfunction " Function: lh#cpp#option#nl_before_curlyB() {{{3 " Write each '{' on a new line; -> if ...() \n {} function! lh#cpp#option#nl_before_curlyB() call s:Deprecated() return lh#ft#option#get('nl_before_curlyB', &ft, 0) endfunction " Function: lh#cpp#option#multiple_namespace_on_same_line() {{{3 " Write each "namespace Foo {" on a same line function! lh#cpp#option#multiple_namespaces_on_same_line() return lh#ft#option#get('multiple_namespaces_on_same_line', &ft, 1) endfunction "------------------------------------------------------------------------ " ## Internal functions {{{1 " # Deprecated {{{2 let s:deprecated_notified = 0 function! s:Deprecated() echomsg "lh#cpp#option#nl_before_bracket() API has been deprecated, please use lh#style#*() and AddStyle instead." let s:deprecated_notified = 1 endfunction " }}}1 "------------------------------------------------------------------------ let &cpo=s:cpo_save "============================================================================= " vim600: set fdm=marker: ================================================ FILE: autoload/lh/cpp/override.vim ================================================ "============================================================================= " File: autoload/lh/cpp/override.vim {{{1 " Author: Luc Hermitte " " License: GPLv3 with exceptions " " Version: 2.3.0 let s:k_version = '230' " Created: 15th Apr 2008 " Last Update: 02nd Dec 2019 "------------------------------------------------------------------------ " Description: description " "------------------------------------------------------------------------ " Installation: " ctags requirements: fields: m: implementation, i: inheritance " History: history " TODO: " (*) Cache the LoadTags accesses until the related tags file is updated " (*) Sort result: " - first: the less overridden functions " - last: the ones already overridden for the current class " (*) Build and insert the prototypes ; try to fetch the doc as well " (*) Add override C++11 keyword, with vimscript API " }}}1 "============================================================================= let s:cpo_save=&cpo set cpo&vim "------------------------------------------------------------------------ " ## Misc Functions {{{1 " # Version {{{2 function! lh#cpp#override#version() return s:k_version endfunction " # Debug {{{2 let s:verbose = get(s:, 'verbose', 0) function! lh#cpp#override#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#override#debug(expr) abort return eval(a:expr) endfunction " # Script ID {{{2 function! s:getSID() abort return eval(matchstr(expand(''), '\zs\d\+\ze_getSID$')) endfunction let s:k_script_name = s:getSID() " ## Functions {{{1 " # API {{{2 " Function: lh#cpp#override#root_function(classname/ancestors, funcname) {{{3 function! lh#cpp#override#root_function(classname, funcname) abort let result = [] " todo: do not sort ancestors (find the inheritance (tree) order) because " some virtual functions are not marked virtual in childs let ancestors = type(a:classname) == type([]) ? a:classname : lh#dev#class#ancestors(a:classname) for base in ancestors let functions = taglist('\v<'.base.'>::<'.a:funcname.'>') " Shall we make sure they are virtual ? " call filter(functions, 'v:val.implementation =~ "virtual"') " Shall we make sure the name is correct ? " call filter(virtual_fcts, 'v:val.name =~ a:funcname') let result += functions endfor " TODO: filter the root function only. Let's suppose for now that it's the " last one. " We may have to take care of diamong of hell. return result endfunction " Function: s:OverrideableFunctions(classname) {{{3 function! s:OverrideableFunctions(classname) abort let result = {} " todo: do not sort ancestors (find the inheritance (tree) order) because " some virtual functions are not marked virtual in childs let ancestors = lh#dev#class#ancestors(a:classname) " Build the list of inherited overrideable functions for base in ancestors " - "::" because "inherits:" does not resolves the contextual namespaces " (see omnicppcomplete for a better Ancestors function ?) " - "\>" strips the symbols from nested classes let base_pattern = ((base =~ '::') ? '^' : '::') . base . '\>' let functions = lh#cpp#AnalysisLib_Function#LoadTags(base_pattern) let declarations = lh#cpp#AnalysisLib_Function#SearchAllDeclarations(functions) " - only keep virtual functions let virtual_fcts = filter(declarations, 'v:val.implementation =~ "virtual"') for fn in virtual_fcts let fn2 = copy(fn) let name = matchstr(fn.name, '^[^(]*::\zs.*$') let context = matchstr(fn.name, '^[^(]*::\ze.*$') let fn2.defined_in = [ context ] let fn2.name = name if !has_key(result, name) let result[name] = [ fn2 ] else for overload in result[name] if lh#cpp#AnalysisLib_Function#IsSame(overload, fn2) " an override call add(overload.defined_in, context) " echomsg "SAME: " . string(overload). " -- " . string(fn2) else " new overload call add(result[name], fn2) " echomsg "DIFF: " . string(overload). " -- " . string(fn2) endif endfor endif endfor " echomsg "fct(".base."=".string(virtual_fcts) endfor " And now Identify which functions are already overridden " ::classname\> is no good with tagslist ... " let class_pattern = ((a:classname =~ '::') ? '^' : '::') . a:classname . '\>' let class_pattern = '\<' . a:classname . '\>' let functions = lh#cpp#AnalysisLib_Function#LoadTags(class_pattern) let declarations = lh#cpp#AnalysisLib_Function#SearchAllDeclarations(functions) " don't restrict to virtual as sometimes it is implicit " let virtual_fcts = filter(declarations, 'v:val.implementation =~ "virtual"') for fn in declarations let name = matchstr(fn.name, '^[^(]*::\zs.*$') let fn.name = name if has_key(result, name) for overload in result[name] if lh#cpp#AnalysisLib_Function#IsSame(overload, fn) " an override let overload.overriden = 1 echomsg "SAME: " . string(overload). " -- " . string(fn) else echomsg "DIFF: " . string(overload). " -- " . string(fn) endif endfor endif endfor let flattened = [] for decl in values(result) call extend(flattened, decl) endfor return flattened endfunction " Function: s:OverrideFunction(function_tag) {{{3 function! s:OverrideFunction(function_tag) abort " a- open the related file in a new window let filename = a:function_tag.filename call lh#window#create_window_with('sp '.filename) try " b- search the exact signature let signature = a:function_tag.fullsignature let g:signature = signature let regex_signature = lh#cpp#AnalysisLib_Function#SignatureToSearchRegex(signature, '').regex " todo: support embedded comment within the optional "= 0" part let regex_signature .= '\s*\(=\s*0\s*\)\=;' let lineno = search(regex_signature) if lineno <= 0 throw "Override: cannot find ".signature." declaration in ".filename endif " c- extract all the relevant text (beware of =0) let code = lh#cpp#AnalysisLib_Function#GetFunctionPrototype(lineno, 1) let code = substitute(code, '\s*=\s*0\s*;$', '', '') finally " quit the split-opened window :q endtry " d- copy the function back. " todo: open all the related files in a scratch buffer, and fetch the exact " signatures + the comments let lines = [] call add(lines, code.';') " where is the return type ? call add(lines, '') return lines endfunction " Vimscript API {{{3 function! s:vim_get_classname() abort " {{{4 let classname = lh#cpp#AnalysisLib_Class#CurrentScope(line('.'),'any') return classname endfunction function! s:vim_get_overridable_functions(classname) abort " {{{4 let virtual_fcts = s:OverrideableFunctions(classname) for fn in virtual_fcts let signature = lh#cpp#AnalysisLib_Function#BuildSignatureAsString(fn) let fn['fullsignature' ] = signature endfor return virtual_fcts endfunction function! s:vim_override(function_tag) abort " {{{4 return s:OverrideFunction(a:function_tag) endfunction function! s:make_vimscript_API() abort " {{{4 let res = lh#object#make_top_type({'API': 'vimscript'}) call lh#object#inject(res, 'get_classname', 'vim_get_classname', s:k_script_name) call lh#object#inject(res, 'get_overridable_functions', 'vim_get_overridable_functions', s:k_script_name) call lh#object#inject(res, 'override', 'vim_override', s:k_script_name) return res endfunction " libclang API {{{3 function! s:libclang_get_classname() abort " {{{4 let classname = pyxeval('findClass().spelling') return classname endfunction function! s:libclang_get_overridable_functions(classname) abort " {{{4 " Given the way it works, we don't need to forward the classname: we will get " another cursor to it. let virtual_fcts = clang#non_overridden_virtual_functions() for fn in virtual_fcts let signature = substitute(fn.signature, '(', fn.name.'(', '') let fn['fullsignature' ] = signature endfor return virtual_fcts endfunction function! s:libclang_override(function_tag) abort " {{{4 call s:Verbose("Overriding: %1", a:function_tag) let extent = a:function_tag.extent if resolve(fnamemodify(extent.file, ':p')) == resolve(expand('%:p')) " Current buffer may have been changed since last save " => need to use its current state let lines = getline(1, '$') else " libclang has certainly parsed a saved file => use readfile let lines = readfile(extent.filename) endif call s:Verbose("Extract %1 from %2: l:%3, c:%4 ... l:%5, c:%6", \ a:function_tag.name, extent.filename, \ extent.start.lnum, extent.start.col, \ extent.end.lnum, extent.end.col) let lines = lines[(extent.start.lnum-1) : (extent.end.lnum-1)] let lines[0] = lines[0][extent.start.col-1 :] let lines[-1] = lines[0][: extent.end.col] call s:Verbose("Definition found: %1", lines) " TODO: could be "final" instead let lines[0] = substitute(lines[0], '\s*virtual\s\+', '', '') let lines[-1] = substitute(lines[-1], '\s*=\s*0', ' '.lh#cpp#snippets#override(), '') return lines endfunction function! s:make_libclang_API() abort " {{{4 let res = lh#object#make_top_type({'API': 'libclang'}) call lh#object#inject(res, 'get_classname', 'libclang_get_classname', s:k_script_name) call lh#object#inject(res, 'get_overridable_functions', 'libclang_get_overridable_functions', s:k_script_name) call lh#object#inject(res, 'override', 'libclang_override', s:k_script_name) return res endfunction " # Main {{{2 function! lh#cpp#override#Main() abort if lh#has#plugin('autoload/clang.vim') && clang#can_plugin_be_used() let api = s:make_libclang_API() else let api = s:make_vimscript_API() endif " 1- Obtain current class name let classname = api.get_classname() call s:Verbose ("classname=".classname) " 2- Obtain overrideable functions let virtual_fcts = api.get_overridable_functions(classname) call s:Verbose ("virtual fct=".string(virtual_fcts)) let g:decls = virtual_fcts " 3- Propose to select the functions to override call s:Display(classname, virtual_fcts, api) " 4- Insert them in the current class " -> asynchrounous endfunction " # GUI {{{2 " ==========================[ Menu ]==================================== " Function: s:Access(fn) {{{3 function! s:Access(fn) abort if has_key(a:fn, 'access') if a:fn.access == 'public' | return '+' elseif a:fn.access == 'protected' | return '#' elseif a:fn.access == 'private' | return '-' else | return '?' endif else | return '?' endif endfunction " Function: s:Overriden(fn) {{{3 function! s:Overriden(fn) abort return has_key(a:fn, 'overriden') ? '!' : ' ' endfunction " Function: s:AddToMenu(lines, fns) {{{3 function! s:AddToMenu(lines, fns) abort " 1- Compute max function length let max_length = 0 let fns=[] " for overloads in a:fns " for fn in overloads for fn in a:fns let signature = fn.fullsignature let length = lh#encoding#strlen(signature) if length > max_length | let max_length = length | endif call add(fns, fn) endfor " endfor " 2- Build the result for fn in fns let line = s:Overriden(fn).s:Access(fn).' '.fn.fullsignature \ . repeat(' ', max_length-lh#encoding#strlen(fn.fullsignature)) \ . ' ' . string(fn.defined_in) call add(a:lines, line) endfor endfunction " Function: s:BuildMenu(declarations) {{{3 function! s:BuildMenu(declarations) abort let res = ['--abort--'] call s:AddToMenu(res, a:declarations) return res endfunction " Function: s:Display(className, declarations, api) {{{3 function! s:Display(className, declarations, api) abort let choices = s:BuildMenu(a:declarations) " return let b_id = lh#buffer#dialog#new( \ 'C++Override('.substitute(a:className, '[^A-Za-z0-9_.]', '_', 'g' ).')', \ 'Overrideable functions for '.a:className, \ 'bot below', \ 1, \ 'lh#cpp#override#select', \ choices \) call lh#buffer#dialog#add_help(b_id, '@| !==already overridden function in '.a:className, 'long') call lh#buffer#dialog#add_help(b_id, '@| +==public, #==protected, -==private in one of the ancestor class', 'long') " Added the lonely functions to the b_id let b_id['declarations'] = a:declarations let b_id['api'] = a:api " Syntax and co call s:PostInitDialog() return '' endfunction " Function: s:PostInitDialog() {{{3 function! s:PostInitDialog() abort if has("syntax") syn clear " todo: fix syntax names " syntax region UFNbOcc start='^--' end='$' contains=UFNumber,UFName syntax match UFSignature /.*$/ contained syntax match UFFile /^ [^-][^[]\+/ contained nextgroup=UFText syntax match UFText /| No .* found for / contained nextgroup=UFSignature syntax region UFLine start='^ [^-]' end='$' contains=UFFile,UFText,UFSignature syntax region UFExplain start='@' end='$' contains=UFStart syntax match UFStart /@/ contained syntax match Statement /--abort--/ " Help highlight link UFExplain Comment highlight link UFStart Ignore " Lines highlight link UFLine Normal highlight link UFFile Directory highlight link UFText Normal highlight link UFSignature Identifier endif endfunction " Function: lh#cpp#override#select(results) {{{3 function! lh#cpp#override#select(results) abort if len(a:results.selection)==1 && a:results.selection[0]==0 call lh#buffer#dialog#quit() return endif if exists('s:quit') | :quit | endif " let unmatched = b:dialog.unmatched " let cmd = b:cmd let choices = a:results.dialog.choices let lines = [] for selection in a:results.selection " echomsg '-> '.choices[selection] " echomsg '-> '.info[selection-1].filename . ": ".info[selection-1].cmd " let selected_virt = a:results.dialog.declarations[selection-1] " echomsg string(selected_virt) let api = a:results.dialog.api call extend(lines, api.override(selected_virt)) endfor " Go back to the original buffer, and insert the built lines let where_it_started = a:results.dialog.where_it_started call lh#buffer#find(where_it_started[0]) if 0==append(where_it_started[1]-1, lines) silent exe (where_it_started[1]-1).',+'.(len(lines)-1).'normal! ==' " echo (where_it_started[1]-1).',+'.(len(lines)-1).'normal! ==' endif endfunction " }}}1 "------------------------------------------------------------------------ let &cpo=s:cpo_save "============================================================================= " vim600: set fdm=marker: ================================================ FILE: autoload/lh/cpp/refactor.vim ================================================ "============================================================================= " File: autoload/lh/cpp/refactor.vim {{{1 " Author: Luc Hermitte " " License: GPLv3 with exceptions " " Version: 2.2.1. let s:k_version = '221' " Created: 21st Feb 2019 " Last Update: 21st Feb 2019 "------------------------------------------------------------------------ " Description: " Various helpers function for refactorizing C++ code " "============================================================================= let s:cpo_save=&cpo set cpo&vim "------------------------------------------------------------------------ " ## Misc Functions {{{1 " # Version {{{2 function! lh#cpp#refactor#version() return s:k_version endfunction " # Debug {{{2 let s:verbose = get(s:, 'verbose', 0) function! lh#cpp#refactor#verbose(...) if a:0 > 0 | let s:verbose = a:1 | endif return s:verbose endfunction function! s:Log(expr, ...) abort call call('lh#log#this',[a:expr]+a:000) endfunction function! s:Verbose(expr, ...) abort if s:verbose call call('s:Log',[a:expr]+a:000) endif endfunction function! lh#cpp#refactor#debug(expr) abort return eval(a:expr) endfunction "------------------------------------------------------------------------ " ## Exported functions {{{1 " Function: lh#cpp#refactor#modernize(code) {{{3 " Things transformed: " - typedef -> using " - NULL -> nullptr " - auto_ptr -> unique_ptr function! lh#cpp#refactor#modernize(code) abort let code = a:code if lh#option#get('cpp_modernize.typedef2using', 1) let code = substitute(code, '\v\_s+(\_[^;]{-})\_s+(\k+)\_s*;', 'using \2 = \1;', 'g') endif if lh#option#get('cpp_modernize.align_using', 1) " Correctly aligning require to use virtcol() that can only be used on " buffers, not on strings. " Fortunatelly, identifier cannot contain multi-byte characters, and the " only traps are tabs mixed in with spaces. In order to simplify, we will " suppose a size of tab &tabstop " " The objective is to align `=` signs in using directives that are identically " indented. let lines = split(code, "\n") " dictionary: {indent -> max col of '='} let maxes = {} function! maxes._register(line) abort " let suppose (for now) that tabs never follow spaces in our case... let indent = strlen(substitute(matchstr(a:line, '\v^\s\+'), "\t", '\=repeat(" ", &ts)', 'g')) let col = strlen(substitute(matchstr(a:line, '\v^\s*using\zs[^=]+'), "\t", '\=repeat(" ", &ts)', 'g')) if !has_key(self, indent) let self[indent] = col else let self[indent] = max([self[indent], col]) endif return [col, indent] endfunction " 1- computes best col for '=' let l2 = map(copy(lines), {k,v -> maxes._register(v)}) " 2- apply it let offsets = map(copy(lines), {k,v -> repeat(' ', 1+l:maxes[l2[k][1]]-l2[k][0])}) " echomsg string(offsets) call map(lines, {k,v -> substitute(v, '\v^\s*using\s+.{-}\zs\s+\ze\=', offsets[k], '')}) " echomsg string(lines) " echomsg string(l2) let code = join(lines, "\n") endif if lh#option#get('cpp_modernize.nullptr', 1) let code = substitute(code, '\v', 'nullptr', 'g') endif return code endfunction "------------------------------------------------------------------------ " ## API functions {{{1 " Function: lh#cpp#refactor#_modernize() {{{3 function! lh#cpp#refactor#_modernize() range abort silent let code = lh#visual#cut() let code = lh#cpp#refactor#modernize(code) silent put!=code endfunction "------------------------------------------------------------------------ " }}}1 "------------------------------------------------------------------------ let &cpo=s:cpo_save "============================================================================= " vim600: set fdm=marker: ================================================ FILE: autoload/lh/cpp/scope.vim ================================================ "============================================================================= " File: autoload/lh/cpp/scope.vim {{{1 " Author: Luc Hermitte " " Version: 2.0.0b10 " Created: 25th Jun 2014 " Last Update: $Date$ "------------------------------------------------------------------------ " Description: " Support autoload plugin for ftplugin/cpp/cpp_AddMissingScope.vim " }}}1 "============================================================================= let s:cpo_save=&cpo set cpo&vim "------------------------------------------------------------------------ " ## Misc Functions {{{1 " # Version {{{2 let s:k_version = 200 function! lh#cpp#scope#version() return s:k_version endfunction " # Debug {{{2 let s:verbose = 0 function! lh#cpp#scope#verbose(...) if a:0 > 0 | let s:verbose = a:1 | endif return s:verbose endfunction function! s:Verbose(expr) if s:verbose echomsg a:expr endif endfunction function! lh#cpp#scope#debug(expr) return eval(a:expr) endfunction "------------------------------------------------------------------------ " ## API functions {{{1 " Function: lh#cpp#scope#_add_missing() {{{3 function! lh#cpp#scope#_add_missing() abort let [id, info] = lh#cpp#tags#fetch("add-missing-scope") try " Filter out constructors let isk_save = &isk set isk-=: call filter(info, "! (v:val.kind =~ 'f' && v:val.name=~'.*\\<\\(\\k\\+\\)::\\1')") " Build the list of names let names = {} for t in info if ! has_key(names, t.name) let names[t.name] = {} endif let names[t.name][t.kind[0]] = '' endfor " Check the number of possible choices if len(info) > 1 call lh#common#error_msg("add-missing-scope: too many acceptable tags for `" \ .id."': ".string(names)) return endif let name = keys(names)[0] if name == id call lh#common#warning_msg("add-missing-scope: `".id."' is already expanded") return endif " build the new line set isk+=: let line = getline('.') let head = matchstr(line[:col('.')-1], '.*\ze\<\k\+$') let tail = line[lh#encoding#strlen(head):] let missing = matchstr(name, '.*\ze'.id) call setline(line('.'), head.missing.tail) finally let &isk = isk_save endtry endfunction "------------------------------------------------------------------------ " ## Exported functions {{{1 "------------------------------------------------------------------------ " ## Internal functions {{{1 "------------------------------------------------------------------------ let &cpo=s:cpo_save "============================================================================= " vim600: set fdm=marker: ================================================ FILE: autoload/lh/cpp/snippets.vim ================================================ "============================================================================= " File: autoload/lh/cpp/snippets.vim {{{1 " Author: Luc Hermitte " " License: GPLv3 with exceptions " " Version: 2.2.0. let s:k_version = '220' " Created: 03rd Nov 2015 " Last Update: 08th Mar 2018 "------------------------------------------------------------------------ " Description: " Tool functions to help write snippets (ftplugin/c/c_snippets.vim) " "------------------------------------------------------------------------ " History: «history» " TODO: «missing features» " }}}1 "============================================================================= let s:cpo_save=&cpo set cpo&vim "------------------------------------------------------------------------ " ## Misc Functions {{{1 " # Version {{{2 function! lh#cpp#snippets#version() return s:k_version endfunction " # Debug {{{2 let s:verbose = get(s:, 'verbose', 0) function! lh#cpp#snippets#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#snippets#debug(expr) abort return eval(a:expr) endfunction "------------------------------------------------------------------------ " ## Exported functions {{{1 " # snippets functions {{{2 " Function: lh#cpp#snippets#def_abbr(key, expr) {{{3 function! lh#cpp#snippets#def_abbr(key, expr) abort if getline('.') =~ '^\s*#' return a:key endif " Default behaviour if type(a:expr) == type({}) " This is a switch let exprs = filter(items(a:expr), 'eval(v:val[0])') call lh#assert#value(exprs).not().empty("No case found for the mapping ". string(a:key)." --> ".string(a:expr)) let expr = exprs[0][1] else let expr = a:expr endif let rhs = lh#style#apply(expr) return lh#map#insert_seq(a:key, rhs) endfunction " Function: lh#cpp#snippets#def_map(key, expr1, expr2) {{{3 function! lh#cpp#snippets#def_map(key, expr1, expr2) abort if lh#brackets#usemarks() return "\=lh#map#no_context2('".a:key."',lh#map#build_map_seq('".a:expr2."'))\" else return "\=lh#map#no_context2('".a:key."', '".a:expr1."')\" endif endfunction " Function: lh#cpp#snippets#insert_return() {{{3 function! lh#cpp#snippets#insert_return() abort let c = col('.') - 1 let l = getline('.') let l = strpart(l, c) if l =~ '^\s*$' return lh#map#build_map_seq('return ;!mark!\==0:call lh#cpp#snippets#_goto_return_semicolon()\i') else let spacesLen = strlen(matchstr(l, '^\s*')) let stripCmd = (spacesLen!=0) ? '\'.'ct'.l[spacesLen] : '' echo stripCmd if stridx(l, ';') != -1 return lh#map#build_map_seq(stripCmd.'return \==0:call lh#cpp#snippets#_goto_return_semicolon()\a') elseif stridx(l, '}') != -1 return lh#map#build_map_seq(stripCmd.'return ;!mark!\==0:call lh#cpp#snippets#_goto_return_semicolon()\i') else return lh#map#build_map_seq(stripCmd.'return \==A;') endif endif endfunction " Function: lh#cpp#snippets#insert_if_not_after(key, what, pattern) {{{3 function! lh#cpp#snippets#insert_if_not_after(key, what, pattern) abort let c = col('.') - 1 let l = getline('.') let l = strpart(l, 0, c) if l =~ a:pattern.'\s*$' return a:key else return lh#cpp#snippets#def_abbr(a:key, a:what) endif endfunction " Function: lh#cpp#snippets#insert_if_not_before(key, what, pattern) {{{3 function! lh#cpp#snippets#insert_if_not_before(key, what, pattern) abort let c = col('.') - 1 let l = getline('.') let l = strpart(l, c) if l =~ '^\s*'.a:pattern return a:key else return lh#cpp#snippets#def_abbr(a:key, a:what) endif endfunction " Function: lh#cpp#snippets#typedef_typename() {{{3 function! lh#cpp#snippets#typedef_typename() abort return lh#cpp#snippets#insert_if_not_after('typename ', 'typedef ', '\S') endfunction " Function: lh#cpp#snippets#current_namespace(default) {{{3 function! lh#cpp#snippets#current_namespace(default) abort let ns = lh#ft#option#get('project_namespace', &ft, '') return empty(ns) ? a:default : (ns.'::') endfunction " Function: lh#cpp#snippets#select_expr_4_surrounding() {{{3 function! lh#cpp#snippets#select_expr_4_surrounding() abort " Go to the first non blank character of the line :normal! ^ " Search either the first semin-colon or the end of the line. :call search(';\|\s*$', 'c') " If we are not at the end of the line if getline('.')[col('.')-1] =~ ';\|\s' " If it is followed by blanck characters if strpart(getline('.'), col('.')) =~ '^\s*$' " then trim the ';' (or the space) and every thing after exe "normal! \"_d$" else " otherwise replace the ';' by a newline character, and goto the end of " the previous line (where the line has been cut) exe "normal! \"_s\n\k$" endif endif " And then select till the first non blank character of the line :normal! v^ endfunction " Function: lh#cpp#snippets#begin_end() {{{3 " In std::foreach and std::find algorithms, ..., expand 'algo(container§)' " into: " - 'algo(container.begin(),container.end()§)', " - 'algo(container.rbegin(),container.rend()§)', " - 'algo(container.cbegin(),container.cend()§)', " - 'algo(begin.(container),end.(container)§)', " - 'algo(rbegin.(container),rend.(container)§)', " - 'algo(cbegin.(container),cend.(container)§)', " " Objectives: support redo/repeat " Constants {{{4 let s:k_begin_end_fmt = { \ 'c++98': '%1.%2()', \ 'std': 'std::%2(%1)', \ 'boost': 'boost::%2(%1)', \ 'adl': '%2(%1)' \ } let s:k_end = { \ 'begin' : 'end', \ 'rbegin' : 'rend', \ 'cbegin' : 'cend', \ 'crbegin': 'crend' \ } let s:k_begin_end_inc = { \ 'c++98': [], \ 'std': [''], \ 'boost': ['', ''], \ 'adl': [] \ } function! s:Style() " {{{4 let style = lh#option#get('cpp_begin_end_style') if lh#option#is_unset(style) unlet style let style \ = lh#cpp#use_cpp11() ? 'std' \ : 'c++98' " \ : lh#cpp#is_boost_used() ? 'boost' endif return style endfunction function! lh#cpp#snippets#_select_begin_end(cont, function) " {{{4 let style = s:Style() return lh#fmt#printf(s:k_begin_end_fmt[style], a:cont, a:function) endfunction " Function: lh#cpp#snippets#_include_begin_end() {{{3 function! lh#cpp#snippets#_include_begin_end() abort let style = s:Style() " TODO: find a better way to organize options return lh#option#get('cpp_begin_end_includes', get(s:k_begin_end_inc, style, [])) endfunction function! lh#cpp#snippets#_begin_end(begin) abort " {{{4 let saved_pos = getpos('.') let char_c = lh#position#char_at_pos(getpos('.')) let accept_at_current = char_c == '(' ? 'c' : '' if searchpair('(',',',')','bW'.accept_at_current,'lh#syntax#skip()') == 0 \ && searchpair('(',',',')','bW','lh#syntax#skip()') == 0 " Test necessary because 'c' flag and Skip() don't always work well together throw "Not on a parameter" endif " Goto next character call search('.') let pos = [line('.'), col('.')] call setpos('.', saved_pos) " let g:saved_pos = saved_pos " let g:pos = pos if saved_pos[1] == pos[0] && saved_pos[2] == pos[1] " No container under the cursor => use placeholders let cont = lh#marker#txt('container') return lh#cpp#snippets#_select_begin_end(cont, a:begin). ', ' .lh#cpp#snippets#_select_begin_end(cont, s:k_end[a:begin]) endif " Let's suppose same line " TODO: " - add \s after ",", but not after "(" => use apply style on " - previous.head, " - and ', '.head " " Extract container name (and leading whitespace) from the two positions let cont = lh#position#extract(pos, saved_pos[1:2]) " Check we aren't selecting too many things if pos[0] != saved_pos[1] && cont =~ '{[^}]*$' throw "lvalue not in a function call, cannot expand begin/end on it." endif " Add .begin/.end on "foo(bar)" ? if lh#position#char_at(saved_pos[1], saved_pos[2]-1) == ')' let choice = lh#ui#which('lh#ui#confirm', 'Do you really want to call begin() *and* end() on a function result?', "&Yes\n&No", 2) if choice == 'No' return "" endif endif " Number of characters to delete = len - nb of "\n" let len = lh#encoding#strlen(cont) \ - len(substitute(cont, "[^\n]", '', 'g')) " trim trailing spaces, but not those at the start let [all, head, cont; rest] = matchlist(cont, '\v^(\_s*)(.{-})\_s*$') if pos[1] == 1 && head =~ '^\s\+$' " text on a new line => head2 shall induce a new line " TODO: support styling option: "\n, " or ",\n" let head2 = "\n" else let head2 = "" endif if empty(cont) " No container under the cursor => use placeholders let cont = lh#marker#txt('container') endif " Build the string to "insert" let res = repeat("\", len) \ . head . lh#cpp#snippets#_select_begin_end(cont, a:begin). \ ', '.head2 .lh#cpp#snippets#_select_begin_end(cont, s:k_end[a:begin]) " if pos[0] != saved_pos[1] " When clear characters at the start of the line, it jumps over indent " => we force sw to 1 let sw=shiftwidth() set sw=1 let res .= "\:set sw=".sw."\" " endif return res endfunction " Function: lh#cpp#snippets#_convert_cast(cast_type) {{{3 " TODO: have s:k_cast_fmt be a [bg]:({ft}_) option. " Beware the following list is duplicated in ftplugin/cpp/cpp_snippets.vim let s:k_cast = { \ 'sc': 'static_cast', \ 'dc': 'dynamic_cast', \ 'cc': 'const_cast', \ 'rc': 'reinterpret_cast', \ 'lc': 'boost::lexical_cast' \ } let s:k_cast_fmt = '%1<%2>(%3)' function! lh#cpp#snippets#_convert_to_cpp_cast(cast_type) abort " Extract text to convert let c_cast = lh#visual#selection() " Strip the possible brackets around the expression " matchlist seems to cause an odd error on multiline C cast expressions: it " have the fucntion called again. let [all, type, expr ; tail] = matchlist(c_cast, '\v^\(\_s*(.{-})\_s*\)\_s*(.{-})\_s*$') let expr = substitute(expr, '\v^\(\s*(.{-})\s*\)$', '\1', '') " " Build the C++-casting from the C casting let new_cast = lh#fmt#printf(s:k_cast_fmt, s:k_cast[a:cast_type], type, expr) " let new_cast = a:cast_type.'<'.type.'>('.expr.')' " Do the replacement silent exe "normal! gvs".new_cast."\" endfunction "------------------------------------------------------------------------ " # Functions for mu-template template-files {{{2 " Function: lh#cpp#snippets#_merge_include_data(name_and_maybe_more, data2) {{{3 function! lh#cpp#snippets#_merge_include_data(name_and_maybe_more, data2) abort let data = copy(a:data2) if type(a:name_and_maybe_more) == type({}) " No "name" key => error let name = a:name_and_maybe_more.name call extend(data, a:name_and_maybe_more) call remove(data, 'name') else let name = a:name_and_maybe_more endif return {name : data} endfunction " Function: lh#cpp#snippets#parents(parents) {{{3 function! lh#cpp#snippets#parents(parents) abort let includes = [] let list = [] for parent in a:parents for [name, data] in items(parent) let type_info = lh#cpp#types#get_info(name) let list += [ \ get(data, 'visibility', 'public') . ' ' \ .(get(data, 'virtual', 0) ? 'virtual ' : '') \ .type_info.typename_for_header() \ ] if has_key(data, 'includes') call lh#list#flat_extend(includes, data['includes']) endif if has_key(type_info, 'includes') call extend(includes, type_info.includes) endif endfor endfor let res = '' if !empty(list) let res = len(list) > 1 ? "\n" : " " let res .= ': '.join(list, "\n, ") endif call lh#list#unique_sort(includes) return [res, includes] endfunction " Function: lh#cpp#snippets#constructor_name(class) {{{3 function! lh#cpp#snippets#constructor_name(class) abort " Assert len(values(a:class)) == 1 let data = split(keys(a:class)[0], '::') let data += [data[-1]] let res = join(data, '::') return res endfunction " Function: lh#cpp#snippets#_filter_functions(list, visibility) {{{3 " Function: lh#cpp#snippets#_filter_functions(list, field, value) function! lh#cpp#snippets#_filter_functions(list, ...) abort if a:0 == 1 let value = a:1 let field = 'visibility' let default = 'public' elseif a:0 == 2 let value = a:2 let field = a:1 let default = '' else call lh#assert#unexpected('Incorrect number of argument in lh#cpp#snippets#_filter_functions -> '.string(a:000)) endif let res = copy(a:list) if value == "public" call filter(res, 'get(v:val, field, "public") == value && get(v:val, "how", "") != "deleted"') elseif value == "protected" call filter(res, 'get(v:val, field, "public") == value') elseif value == "private" call filter(res, 'get(v:val, field, "public") == value || get(v:val, "how", "") == "deleted"') else "visi=none, or other fields call filter(res, 'get(v:val, field, default) == value') endif return res endfunction " Function: lh#cpp#snippets#nullptr() {{{3 function! lh#cpp#snippets#nullptr(...) abort return lh#option#get('cpp_nullptr', lh#cpp#use_cpp11() ? 'nullptr' : '0') endfunction " Function: lh#cpp#snippets#noexcept([condition]) {{{3 function! lh#cpp#snippets#noexcept(...) abort let noexcept = lh#option#get('cpp_noexcept') let args = empty(a:000) ? '' : '('.a:1.')' if lh#option#is_set(noexcept) return lh#fmt#printf(noexcept, args) endif if lh#cpp#use_cpp11() return 'noexcept'.args else return 'throw()' endif endfunction " Function: lh#cpp#snippets#deleted() {{{3 function! lh#cpp#snippets#deleted() abort let deleted = lh#option#get('cpp_deleted') let args = empty(a:000) ? '' : a:1 if lh#option#is_set(deleted) return deleted endif if lh#cpp#use_cpp11() return '= delete' else return '/* = delete */' endif endfunction " Function: lh#cpp#snippets#override() {{{3 function! lh#cpp#snippets#override() abort let override = lh#option#get('cpp_override') let args = empty(a:000) ? '' : a:1 if lh#option#is_set(override) return override endif if lh#cpp#use_cpp11() return 'override' else return '/* override */' endif endfunction " Function: lh#cpp#snippets#defaulted() {{{3 function! lh#cpp#snippets#defaulted() abort let defaulted = lh#option#get('cpp_defaulted') let args = empty(a:000) ? '' : a:1 if lh#option#is_set(defaulted) return defaulted endif if lh#cpp#use_cpp11() return '= default' else " Don't know how to default functions in C++98 return '/* = default */' endif endfunction " Function: lh#cpp#snippets#pure() {{{3 function! lh#cpp#snippets#pure() abort return "= 0" endfunction " Function: lh#cpp#snippets#return_ptr_type(type) {{{3 function! lh#cpp#snippets#return_ptr_type(type) abort let return_type = lh#option#get('cpp_return_ptr_type') let args = empty(a:000) ? '' : a:1 if lh#option#is_set(return_type) return printf(return_type, a:type) endif call lh#mut#_add_post_expand_callback('lh#dev#import#add("")') if lh#cpp#use_cpp11() return 'std::unique_ptr<'.a:type.'>' else return 'std::auto_ptr<'.a:type.'>' endif endfunction " Function: lh#cpp#snippets#make_ptr(type, args) {{{3 function! lh#cpp#snippets#make_ptr(type_dynamic, type_static, args) abort let make_ptr = lh#option#get('cpp_make_ptr') let args = empty(a:000) ? '' : a:1 if lh#option#is_set(make_ptr) return lh#fmt#printf(make_ptr, a:type_static, a:type_dynamic, a:args) else unlet make_ptr endif call lh#mut#_add_post_expand_callback('lh#dev#import#add("")') if lh#cpp#use_cpp14() " upcast is implicit with unique_ptr => using only the dynamic type let make_ptr = 'std::make_unique(%3)' elseif lh#cpp#use_cpp11() " upcast is implicit with unique_ptr => using only the dynamic type let make_ptr = 'std::unique_ptr<%2>(new %2(%3))' else let make_ptr = 'std::auto_ptr<%1>(new %2(%3))' endif return lh#fmt#printf(make_ptr, a:type_static, a:type_dynamic, a:args) endfunction " Function: lh#cpp#snippets#requires_destructor(attributes) {{{3 " - T* will require a destructor in current class " - auto_ptr<> will require a destructor in current class, even an empty (this " is because otherwise we can't garanty the deletion function called is the " right one) " - unique_ptr<>, doesn't require anything " - Let's suppose other types to follow RAII => don't need " - still an option in case code is not idiomatic and destructors may be needed function! lh#cpp#snippets#requires_destructor(attributes) abort return lh#list#find_if(a:attributes, 'lh#cpp#snippets#_this_param_requires_a_destructor(v:val)') >= 0 endfunction " Function: lh#cpp#snippets#requires_copy_operations(attributes) {{{3 " - pointer, references, uncopyable types (stream, mutex, lock, entities, ...) => yes function! lh#cpp#snippets#requires_copy_operations(attributes) abort return lh#list#find_if(a:attributes, 'lh#cpp#snippets#_this_param_requires_copy_operations(v:val)') >= 0 endfunction " Function: lh#cpp#snippets#shall_explicit_defaults() {{{3 function! lh#cpp#snippets#shall_explicit_defaults() abort return lh#cpp#use_cpp11() && lh#option#get("cpp_explicit_default", 0) endfunction " Function: lh#cpp#snippets#build_param_list(parameters) {{{3 " Fields: " - name " - type " - default " - nl (bool) function! lh#cpp#snippets#build_param_list(parameters) abort " 1- Handle default params, if any. {{{4 let l:ShowDefaultParams = lh#ft#option#get('ShowDefaultParams', &ft, 1) " 0 -> "" : ignored " 1 -> "/* = value */" : commented " 2 -> "/*=value*/" : commented, spaces trimmed " 3 -> "/*value*/" : commented, spaces trimmed, no equal sign if l:ShowDefaultParams == 0 | let pattern = '' elseif l:ShowDefaultParams == 1 | let pattern = '/* = \1 */' elseif l:ShowDefaultParams == 2 | let pattern = '/*=\1*/' elseif l:ShowDefaultParams == 3 | let pattern = '/*\1*/' else | let pattern = '' endif " 2- Build the string to return {{{4 let implParams = [] for param in a:parameters let sParam = (get(param, 'nl', '0') ? "\n" : '') \ . get(param, 'type', lh#marker#txt('type')) . ' ' . lh#naming#param(param.name) if has_key(param, 'default') let sParam .= substitute(param.default, '\v(.+)', pattern, '') endif " echo "param=".param call add(implParams, sParam) endfor let implParamsStr = join(implParams, ', ') return implParamsStr endfunction " Function: lh#cpp#snippets#duplicate_param(param) {{{3 function! lh#cpp#snippets#duplicate_param(param, type) abort if lh#cpp#snippets#_this_param_requires_copy_operations(a:type) return lh#fmt#printf(lh#marker#txt('duplicate(%1)'), a:param) else return a:param endif endfunction " # Functions to tune mu-template class skeleton {{{2 " Function: lh#cpp#snippets#new_function_list() {{{3 function! s:public() dict abort " {{{4 return lh#cpp#snippets#_filter_functions(self.list, "public") endfunction function! s:protected() dict abort " {{{4 return lh#cpp#snippets#_filter_functions(self.list, "protected") endfunction function! s:private() dict abort " {{{4 return lh#cpp#snippets#_filter_functions(self.list, "private") endfunction function! s:add(fns) dict abort " {{{4 let self.list += a:fns for fn in a:fns call extend(fn, {'add_new': function(s:getSNR('AddNew'))}) endfor return self endfunction function! s:insert(fn) dict abort " {{{4 call extend(a:fn, {'add_new': function(s:getSNR('AddNew'))}) call insert(self.list, a:fn) return self endfunction function! s:get(id) dict abort " {{{4 if type(a:id) == type('name') let res = filter(copy(self.list), 'has_key(v:val, "name") && v:val.name =~ a:id') else let res = filter(copy(self.list), 's:FunctionMatchesDescription(v:val, a:id)') endif return res endfunction function! s:get1(id, ...) dict abort " {{{4 let matching_functions = self.get(a:id) if len(matching_functions) > 1 throw "lh-cpp: Too many functions match ".string(a:id) elseif empty(matching_functions) " New reference created, and returned let new_fn = a:0 > 0 ? a:1 : {} " Force the searched pattern onto the function to return, at least this, " is correct call extend(new_fn, a:id) call self.add([new_fn]) return new_fn endif endfunction function! s:filter(descr) dict abort " {{{4 let res = filter(copy(self.list), 's:FunctionMatchesDescription(v:val, a:descr)') return res endfunction function! s:reverse() dict abort "{{{4 return reverse(self.list) endfunction function! lh#cpp#snippets#new_function_list() abort " {{{4 let fl = lh#object#make_top_type({ 'list': []}) let fl.public = function(s:getSNR('public')) let fl.protected = function(s:getSNR('protected')) let fl.private = function(s:getSNR('private')) let fl.add = function(s:getSNR('add')) let fl.insert = function(s:getSNR('insert')) let fl.get = function(s:getSNR('get')) let fl.get1 = function(s:getSNR('get1')) let fl.filter = function(s:getSNR('filter')) let fl.reverse = function(s:getSNR('reverse')) " Return object {{{4 return fl " }}}4 endfunction function! s:AddNew(dst) dict abort return extend(self, a:dst, 'keep') endfunction "------------------------------------------------------------------------ " ## Internal functions {{{1 " # Misc {{{2 " s:getSNR([func_name]) {{{3 function! s:getSNR(...) if !exists("s:SNR") let s:SNR=matchstr(expand(''), '\d\+_\zegetSNR$') endif return s:SNR . (a:0>0 ? (a:1) : '') endfunction " Function: s:FunctionMatchesDescription(fn, descr) {{{3 function! s:FunctionMatchesDescription(fn, descr) for [k, v] in items(a:descr) if ! has_key(a:fn, k) || a:fn[k] != v return 0 endif return 1 endfor endfunction " Function: lh#cpp#snippets#_this_param_requires_a_destructor(attribute) {{{3 " see lh#cpp#snippets#requires_destructor(attributes) function! lh#cpp#snippets#_this_param_requires_a_destructor(attribute) abort if !lh#dev#cpp#types#IsPointer(a:attribute.type) " TODO: We may need another option as well. Or a list of types ? return 0 elseif a:attribute.type =~ '\vauto_ptr|[*]' return 1 elseif a:attribute.type =~ '\v^[a-z0-9]*_ptr|non_null' " let's suppose scoped_ptr, unique_ptr, ... " "*_ptr" follows standard naming style, we can expect this is not an " unsafe pointer type return 0 elseif lh#option#get('cpp_always_a_destructor_when_there_is_a_pointer_attribute', 0) return 1 else return 0 endif endfunction " Function: lh#cpp#snippets#_this_param_requires_copy_operations(attribute) {{{3 function! lh#cpp#snippets#_this_param_requires_copy_operations(attribute) abort let type = type(a:attribute) == type({}) ? a:attribute.type : a:attribute if lh#dev#cpp#types#is_not_owning_ptr(type) return 0 elseif lh#dev#cpp#types#IsPointer(type) return 1 else " TODO: recognize non publicy copyable types return 0 endif endfunction " Function: lh#cpp#snippets#_decode_selected_attributes(text) {{{3 " TODO: ask which ones shall be used: " - in init-ctr param list " - to generate setters and/or getter function! lh#cpp#snippets#_decode_selected_attributes(text) abort let res = [] for attr in split(a:text, "\n") let attr = matchstr(attr, '^\s*\zs.\{-}\ze;*\s*$') let attr_data = lh#dev#option#call('function#_analyse_parameter', &ft, attr, 1) let attr_data.name = lh#naming#param(attr_data.name) let res += [ attr_data ] endfor return res endfunction " # snippet functions {{{2 " Function: lh#cpp#snippets#_goto_return_semicolon() {{{3 function! lh#cpp#snippets#_goto_return_semicolon() abort let p = getpos('.') let r = search('return.*;', 'e') if r == 0 | call setpos('.', p) | endif endfunction " Function: lh#cpp#snippets#_has_a_non_copyable_parent(parents) {{{3 " I'll just test is there is a public parent. From there, let's suppose public " base classes are noncopyable. " I'll trust the end-user to have objects from hierarchies to respect " entity-semantics and be noncopyable (or possibly clonable) " NB: I should may be test for a private inheritance to a "\cNon_*Copyable" " class. function! lh#cpp#snippets#_has_a_non_copyable_parent(parents) abort let public_parents = filter(copy(a:parents), 'get(v:val, "visibility", "public") == "public"') let res = ! empty(public_parents) return res endfunction "------------------------------------------------------------------------ " }}}1 "------------------------------------------------------------------------ let &cpo=s:cpo_save "============================================================================= " vim600: set fdm=marker: ================================================ FILE: autoload/lh/cpp/style.vim ================================================ "============================================================================= " File: autoload/lh/cpp/style.vim {{{1 " Author: Luc Hermitte " " License: GPLv3 with exceptions " " Version: 2.0.0 " Created: 10th Feb 2009 " Last Update: 08th Mar 2018 "------------------------------------------------------------------------ " Description: " General coding style functions " "------------------------------------------------------------------------ " History: " v1.1.0: Creation " v2.0.0: License GPLv3 w/ extension " TODO: " - Refactor to build on top of lh#dev " - Integrate style preferences used by InsertAccessors " }}}1 "============================================================================= let s:cpo_save=&cpo set cpo&vim "------------------------------------------------------------------------ " ## Functions {{{1 " # Debug {{{2 function! lh#cpp#style#verbose(level) let s:verbose = a:level endfunction function! s:Verbose(expr) if exists('s:verbose') && s:verbose echomsg a:expr endif endfunction function! lh#cpp#style#debug(expr) return eval(a:expr) endfunction " # Style accessors {{{2 function! lh#cpp#style#get(datakind, pos) let value = lh#option#get(a:datakind.a:pos, '') return value endfunction " # Names conversion {{{2 " Function: lh#cpp#style#attribute2parameter_name(attrb_name) {{{3 function! lh#cpp#style#attribute2parameter_name(attrb_name) let core_name = lh#naming#variable(a:attrb_name) let param_name = lh#naming#param(core_name) if param_name == a:attrb_name let param_name = lh#marker#txt(param_name) endif return param_name endfunction "------------------------------------------------------------------------ let &cpo=s:cpo_save "============================================================================= " vim600: set fdm=marker: ================================================ FILE: autoload/lh/cpp/tags.vim ================================================ "============================================================================= " File: autoload/lh/cpp/tags.vim {{{1 " Author: Luc Hermitte " " Version: 2.3.0 let s:k_version = 230 " Created: 25th Jun 2014 " Last Update: 22nd May 2019 "------------------------------------------------------------------------ " Description: " API functions to obtain symbol declarations " }}}1 "============================================================================= let s:cpo_save=&cpo set cpo&vim "------------------------------------------------------------------------ " ## Misc Functions {{{1 " # Version {{{2 function! lh#cpp#tags#version() return s:k_version endfunction " # Debug {{{2 let s:verbose = get(s:, 'verbose', 0) function! lh#cpp#tags#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#tags#debug(expr) abort return eval(a:expr) endfunction "------------------------------------------------------------------------ " ## Exported functions {{{1 " Function: lh#cpp#tags#find_compiler() {{{3 " Let's assume C++ and not C " TODO: support C function! lh#cpp#tags#find_compiler() abort runtime autoload/lh/cmake.vim if exists('*lh#cmake#get_variables') try let compiler = lh#cmake#get_variables('CMAKE_CXX_COMPILER').CMAKE_CXX_COMPILER.value return compiler catch /.*/ " The project isn't under CMake endtry endif if exists('$CXX') return $CXX elseif executable('c++') return 'c++' elseif executable('g++') return 'g++' elseif executable('clang++') return 'clang++' endif endfunction " Function: lh#cpp#tags#compiler_includes([compiler]) {{{3 " Fetch standard includes (hard coded in the compiler) " TODO: find a way to support intel compiler let s:compiler_includes = {} function! lh#cpp#tags#compiler_includes(...) abort let compiler = a:0 > 0 ? a:1 : lh#cpp#tags#find_compiler() if ! has_key(s:compiler_includes, compiler) " Let's assume a *nix compiler (g++, clang++) let includes = split(lh#os#system(compiler . ' -E -xc++ - -Wp,-v < /dev/null'), "\n") call filter(includes, 'v:val =~ "^ "') call map(includes, 'lh#path#simplify(v:val[1 :])') " Note that it should contain /usr/include & all let s:compiler_includes[compiler] = includes endif return s:compiler_includes[compiler] endfunction " Function: lh#cpp#tags#strip_included_paths(filename, includes) {{{3 function! lh#cpp#tags#strip_included_paths(filename, includes) let filename = a:filename if !empty(a:includes) if filename[0] == '/' " absolute => try to remove things from b:includes and/or b:sources_root let filename = lh#path#strip_start(filename, a:includes) endif else let filename_simplify = lh#ft#option#get('filename_simplify_for_inclusion', &ft, ':t') let filename = fnamemodify(filename, filename_simplify) endif return filename endfunction " Function: lh#cpp#tags#get_included_paths([default]) {{{3 function! s:as_list(p) abort return type(a:p) == type([]) ? a:p : [a:p] endfunction function! lh#cpp#tags#get_included_paths(...) let includes = [] " sources_root: from mu-template & lh-suite(s) " paths.sources: from lh#project let sources_root = lh#option#get(['sources_root', 'paths.sources']) if lh#option#is_set(sources_root) let includes += [lh#path#to_dirname(sources_root)] endif " paths.includes: new paths from lh#project " includes: old path let def_includes = lh#option#get(['paths.includes', 'includes']) if lh#option#is_set(def_includes) call map(copy(def_includes), 'extend(includes, s:as_list(type(v:val)==type(function("has")) ? call(v:val,[]) : v:val))') call filter(includes, '!empty(v:val)') elseif a:0 > 0 let includes += type(a:1) == type([]) ? a:1 : split(a:1, ',') endif return lh#list#unique_sort(includes) endfunction " Function: lh#cpp#tags#fetch(feature) {{{3 function! lh#cpp#tags#fetch(feature) abort let id = eval(s:TagsSelectPolicy()) try let isk_save = &isk set isk-=: let info = taglist('.*\<'.id.'$') finally let &isk = isk_save endtry if len(info) == 0 throw a:feature.": no tags for `".id."'" endif " Filter for function definitions and #defines, ... let accepted_kinds = lh#ft#option#get('tag_kinds_for_inclusion', &ft, '[dfptcs]') call filter(info, "v:val.kind =~ ".string(accepted_kinds)) " Filter for include files only let accepted_files = lh#ft#option#get('file_regex_for_inclusion', &ft, '\.h') call filter(info, "v:val.filename =~? ".string(accepted_files)) " Is there any symbol left ? if len(info) == 0 throw a:feature.": no acceptable tag for `".id."'" endif " Strip the leading path that won't ever appear in included filename let includes = lh#cpp#tags#get_included_paths() for val in info let val.filename = lh#cpp#tags#strip_included_paths(val.filename, includes) endfor " call map(info, "v:val.filename = lh#cpp#tags#strip_included_paths(v:val.filename, includes)") " And remove redundant info let info = lh#tags#uniq_sort(info) return [id, info] endfunction "------------------------------------------------------------------------ " ## Internal functions {{{1 function! s:TagsSelectPolicy() let select_policy = lh#option#get('tags_select', "expand('')", 'bg') return select_policy endfunction " }}}1 "------------------------------------------------------------------------ let &cpo=s:cpo_save "============================================================================= " vim600: set fdm=marker: ================================================ FILE: autoload/lh/cpp/types.vim ================================================ "============================================================================= " File: autoload/lh/cpp/types.vim {{{1 " Author: Luc Hermitte " " Version: 2.2.0. let s:k_version = '220' " Created: 15th Dec 2015 " Last Update: 15th Dec 2015 "------------------------------------------------------------------------ " Description: " C++ types database " "------------------------------------------------------------------------ " History: «history» " TODO: «missing features» " }}}1 "============================================================================= let s:cpo_save=&cpo set cpo&vim "------------------------------------------------------------------------ " ## Misc Functions {{{1 " # Version {{{2 function! lh#cpp#types#version() return s:k_version endfunction " # Debug {{{2 if !exists('s:verbose') let s:verbose = 0 endif function! lh#cpp#types#verbose(...) if a:0 > 0 | let s:verbose = a:1 | endif return s:verbose endfunction function! s:Verbose(expr) if s:verbose echomsg a:expr endif endfunction function! lh#cpp#types#debug(expr) return eval(a:expr) endfunction "------------------------------------------------------------------------ " ## Types DB {{{1 " TODO: support: several entries behind a same name -> boost::shared_ptr, " std::shared_ptr " # Fetch information " Function: lh#cpp#types#get_info(type [, default-value]) {{{3 " TODO: support also std::vector function! lh#cpp#types#get_info(type, ...) abort let res = get(s:types, a:type, a:0 ? a:1 : {"type" : a:type, "name" : a:type, 'unknown':1}) function! res.typename_for_header(...) abort let type = [] if has_key(self, 'namespace') && !empty(self.namespace) let type += [self.namespace] endif " In case there isn't enough let nb = max(lh#string#matches(self.type, '\v\%\zs\d+')) let args = a:000 + map(range(len(a:000)+1, nb), 'lh#marker#txt("T".v:val)') let type += [call('lh#fmt#printf', [self.type] + args)] return join(type, '::') endfunction return res endfunction " Function: lh#cpp#types#get_includes(type) {{{3 function! lh#cpp#types#get_includes(type) abort let info = get(s:types, a:type, {'includes': []}) return info.includes endfunction " # Filling functions {{{2 function! s:PrepareHeaders(includes, name) " {{{3 return map(lh#list#flatten([a:includes]), 'lh#fmt#printf("<".v:val.">", a:name)') endfunction function! s:ExtractName(type) " {{{3 return substitute(a:type, '\v\<.*', '', '') endfunction function! s:RegisterTypes(list, namespace, ...) " {{{3 let types = map(copy(a:list), '{"name": s:ExtractName(v:val), "namespace": a:namespace, "type": v:val}') if a:0 > 0 call map(types, 'extend(v:val, {"includes": s:PrepareHeaders(a:1, v:val.name)})') else call map(types, 'extend(v:val, {"includes": ["<".v:val["name"].">"]})') endif call map(types, '{(v:val["name"]) : v:val}') for type in types call extend(s:types, type) endfor endfunction " # Fill the DB {{{2 let s:types = {} " * Standard types {{{3 " - types with no template parameters {{{4 let s:std_types = ['fstream', 'string', 'stringstring', 'istream', 'ostream', 'regex', 'thread', 'mutex', 'shared_mutex', 'condition_variable', 'future', 'exception'] call s:RegisterTypes(s:std_types, 'std') " - types with template parameters {{{4 let s:std_types = [ \ 'array<%1,%2>', 'bitset<%1>', 'complex<%1>', 'deque<%1>', \ 'forward_list<%1>', 'function<%1>', 'hash<%1>', 'initializer_list<%1>', \ 'list<%1>', 'map<%1,%2>', 'multimap<%1,%2>', 'multiset<%1>', \ 'priority_queue<%1>', 'queue<%1>', 'set<%1>', 'stack<%1>', 'tuple<%1>', \ 'unordered_map<%1>', 'unordered_multimap<%1,%2>', \ 'unordered_multiset<%1>', 'unordered_set<%1>', 'vector<%1>' \] call s:RegisterTypes(s:std_types, 'std') " - types defined elsewhere {{{4 let s:std_types = [ \ 'runtime_error', 'logic_error', 'domain_error', 'out_of_range', \ 'future_error', 'invalid_argument', 'range_error', 'overflow_error', \ 'underflow_error', 'regex_error', 'system_error', 'bad_cast', \ 'bad_alloc', 'bad_typeid', 'bad_weak_ptr', 'bad_function_call', \ 'bad_array_new_length', 'bad_exception' \] call s:RegisterTypes(s:std_types, 'std', 'stdexcept') let s:std_types = [ \ 'timed_mutex', 'recursive_mutex', 'recursive_timed_mutex', 'lock_guard', \ 'unique_lock', 'shared_lock' \] call s:RegisterTypes(s:std_types, 'std', 'mutex') call s:RegisterTypes(['shared_timed_mutex'], 'std', 'shared_mutex') call s:RegisterTypes(['condition_variable_any'], 'std', 'condition_variable') call s:RegisterTypes(['promise', 'packaged_task', 'shared_future'], 'std', 'future') call s:RegisterTypes(['pair'], 'std', 'utility') call s:RegisterTypes(['chrono::time_point<%1>', 'chrono::duration<%1>'], 'std', 'chrono') call s:RegisterTypes(['nullptr_t'], 'std', 'cstddef') call s:RegisterTypes(['hash<%1>'], 'std', 'functional') call s:RegisterTypes(['size_t'], 'std',['cstddef', 'cstdio', 'cstring', 'ctime', 'cstdlib', 'cwchar']) " call s:RegisterTypes(['size_t'], '',['stddef.h', 'stdio.', 'string.h', 'time.h', 'wchar.h']) " * Boost types {{{3 " - types defined in header file w/ same name {{{4 let s:boost_types = ['noncopyable' \] call s:RegisterTypes(s:boost_types, 'boost', 'boost/%1.hpp') " - types defined elsewhere {{{4 let s:boost_types = [ \ 'ptr_array<%1>', 'ptr_deque<%1>', 'ptr_list>%1>', 'ptr_map<%1,2>', \ 'ptr_multi_set<%1>', 'ptr_multimap<%1,2>', 'ptr_set<%1>', \ 'ptr_vector<%1>' \] call s:RegisterTypes(s:boost_types, 'boost', ['boost/ptr_container.hpp', 'boost/ptr_container/%1.hpp']) " }}}1 "------------------------------------------------------------------------ let &cpo=s:cpo_save "============================================================================= " vim600: set fdm=marker: ================================================ FILE: autoload/lh/cpp/understand.vim ================================================ "============================================================================= " File: autoload/lh/cpp/understand.vim {{{1 " Author: Luc Hermitte " " Version: 2.2.0. let s:k_version = '220' " Created: 30th Jun 2016 " Last Update: 30th Jun 2016 "------------------------------------------------------------------------ " Description: " Plugin that imports understand csv to browse codecheck results. " " Format expected: " file:line:col: check ; check msg; check detail; other things " Note this is not the default output format: you'll have to change a few " semi-colons into colons. " " Usage: " (draft version that needs to be enhanced) " Load the .csv with: " :let u = lh#cpp#understand#init('checks.csv') " Choose which violations shall be displayed: " :call u.filter(['6-4-5', 'Unused Variables'], 'check') " Navigate the violations presented into the quickfix window: " :h :cn / :h :cp / :h quickfix " "------------------------------------------------------------------------ " TODO: " - define commands to add some ergonomy into these functions " - read a real .csv file " - Extract the qf filtering functions to lh-vim-lib " }}}1 "============================================================================= let s:cpo_save=&cpo set cpo&vim "------------------------------------------------------------------------ " ## Misc Functions {{{1 " # Version {{{2 function! lh#cpp#understand#version() return s:k_version endfunction " # Debug {{{2 let s:verbose = get(s:, 'verbose', 0) function! lh#cpp#understand#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#understand#debug(expr) abort return eval(a:expr) endfunction "------------------------------------------------------------------------ " ## Exported functions {{{1 " Function: lh#cpp#understand#init(cvs_file) {{{2 function! lh#cpp#understand#init(cvs_file) abort let d = {} " This way all bufnr are defined exe 'cgetfile ' . a:csv_file let d.data = getqflist() let d.data = map(d.data, 's:analyse_violation(v:val)') let d.checks = lh#list#possible_values(d.data, 'check') let d.filenames = lh#list#possible_values(d.data, 'filename') let d.filter = function('s:filter') return d endfunction "------------------------------------------------------------------------ " ## Internal functions {{{1 " Function: s:violation_list2dict(v) {{{2 function! s:violation_list2dict(v) return \ { 'filename': a:v[1] \ , 'lnum' : a:v[2] \ , 'col' : a:v[3] \ , 'check' : a:v[4] \ , 'results' : a:v[5] \ , 'entity' : a:v[6] \ , 'rem' : a:v[7] \ , 'text' : join(a:v[4:], ';') \ } endfunction " Function: s:filter(elements, what) dict abort {{{2 function! s:filter(elements, what) dict abort let regex = '\v'.join(map(copy(a:elements), 'escape(v:val, "\\\\()<>{}+=")'), '|') let res = filter(copy(self.data), 'v:val[a:what] =~ regex') call setqflist(res) return res endfunction " Function: s:analyse_violation(v) {{{2 function! s:analyse_violation(v) abort let v = a:v let infos = split(v.text, ';') let v.check = infos[0] let v.results = infos[1] let infos[1] = substitute(infos[1], '\v^"\s*(.*)\s*"$', '\1', '') let infos[1] = substitute(infos[1], '""""', '"', 'g') let v.results = infos[1] let v.entity = infos[2] " let v.pattern = v.entity let v.rem = infos[3:] let v.filename = bufname(v.bufnr) let v.text = join(infos, ' ; ') return v endfunction "------------------------------------------------------------------------ " }}}1 "------------------------------------------------------------------------ let &cpo=s:cpo_save "============================================================================= " vim600: set fdm=marker: ================================================ FILE: autoload/lh/cpp.vim ================================================ "============================================================================= " File: autoload/lh/cpp.vim {{{1 " Author: Luc Hermitte " " License: GPLv3 with exceptions " " Version: 2.2.1 let s:k_version = '221' " Created: 08th Jun 2014 " Last Update: 25th Sep 2019 "------------------------------------------------------------------------ " Description: " Various C++ related functions " " - C++ flavour detection " }}}1 "============================================================================= let s:cpo_save=&cpo set cpo&vim "------------------------------------------------------------------------ " ## Misc Functions {{{1 " # Version {{{2 function! lh#cpp#version() return s:k_version endfunction " # Debug {{{2 let s:verbose = 0 function! lh#cpp#verbose(...) if a:0 > 0 | let s:verbose = a:1 | endif return s:verbose endfunction function! s:Verbose(expr) if s:verbose echomsg a:expr endif endfunction function! lh#cpp#debug(expr) return eval(a:expr) endfunction "------------------------------------------------------------------------ " ## Exported functions {{{1 " # Obtain C++ flavour (03, TR1, 11, 14, 17, 20) {{{2 " @note this set of functions deprecates lh#dev#cpp#use_cpp11() " Function: lh#cpp#get_flavour() {{{3 " @return a value among: 03 (C++98/03), 05 (TR1), 11 (C++11), 14, 17, 20 function! lh#cpp#get_flavour() " First check a dedicated set of variables let flavour = lh#option#get('cpp_std_flavour', 0) if flavour != 0 | return flavour | endif let flavour = s:CheckFlavour() if flavour != 0 | return flavour | endif " then, check $CXXFLAGS if exists('$CXXFLAGS') let std=matchstr($CXXFLAGS, '-std=\zs\S\+\ze') if !empty(std) return s:DecodeStdFlavour(std) endif endif " Or CMAKE CXXFLAGS let flags = '' try " The following may fail if lh-cmake is not installed " or if the project isn't using CMake let flags = lh#cmake#get_variables('CXXFLAGS') catch /.*/ endtry " Or compile_commands.json database " as newer versions of CMake use the CXX_STANDARD property that " doesn't set any variable that can be fetched. if empty(flags) try " The following may fail if build-tools-wrapper is not installed " or if the project isn't using CMake let prj_dirname = lh#project#_check_project_variables( \ ['paths.sources', 'project_sources_dir', ['BTW_project_config', '_.paths.sources']]) let dbs = lh#path#glob_as_list( \ [lh#btw#compilation_dir(), prj_dirname], \ 'compile_commands.json', 0) if !empty(dbs) let db = dbs[0] let l_flags = filter(readfile(db), 'v:val =~ "-std="') let flags = empty(l_flags) ? '' : l_flags[0] endif catch /.*/ endtry endif " And ... decode! if !empty(flags) let std=matchstr(flags, '-std=\zs\S\+\ze') if !empty(std) return s:DecodeStdFlavour(std) endif endif return 03 endfunction " Function: lh#cpp#use_TR1() {{{3 function! lh#cpp#use_TR1(...) let flavour = lh#cpp#get_flavour() return flavour == 05 endfunction " Function: lh#cpp#use_cpp11([and_no_more = 0]) {{{3 function! lh#cpp#use_cpp11(...) let flavour = lh#cpp#get_flavour() if a:0 == 0 || a:1 == 0 return flavour >= 11 else return flavour == 11 endif endfunction " Function: lh#cpp#use_cpp14([and_no_more = 0]) {{{3 function! lh#cpp#use_cpp14(...) let flavour = lh#cpp#get_flavour() if a:0 == 0 || a:1 == 0 return flavour >= 14 else return flavour == 14 endif endfunction " Function: lh#cpp#use_cpp17([and_no_more = 0]) {{{3 function! lh#cpp#use_cpp17(...) let flavour = lh#cpp#get_flavour() if a:0 == 0 || a:1 == 0 return flavour >= 17 else return flavour == 17 endif endfunction " Function: lh#cpp#use_cpp20([and_no_more = 0]) {{{3 function! lh#cpp#use_cpp20(...) let flavour = lh#cpp#get_flavour() if a:0 == 0 || a:1 == 0 return flavour >= 20 else return flavour == 20 endif endfunction "------------------------------------------------------------------------ " ## Internal functions {{{1 " # C++ flavour " Function: s:CheckFlavour() {{{3 function! s:CheckFlavour() if lh#option#get('cpp_use_TR1', 0) | return 05 | endif let flavours = { \ 'cpp03': 03, \ 'cpp05': 05, \ 'cpp11': 11, \ 'cpp14': 14, \ 'cpp17': 17, \ 'cpp20': 20 \ } " TODO: use filter! for kv in reverse(items(flavours)) if lh#option#get('cpp_use_'.kv[0], 0) return kv[1] endif endfor return 0 endfunction " Function: s:DecodeStdFlavour(std) {{{3 function! s:DecodeStdFlavour(std) let std = matchstr(a:std, '\(gnu++\|c++\)\zs.*') if std =~ '\(98\|03\)' | return 03 elseif std =~ '\(11\|0x\)' | return 11 elseif std =~ '\(14\|1y\)' | return 14 elseif std =~ '\(17\|1z\)' | return 17 elseif std =~ '\(20\|2a\)' | return 20 else | return 03 endif endfunction " }}}1 "------------------------------------------------------------------------ let &cpo=s:cpo_save "============================================================================= " vim600: set fdm=marker: ================================================ FILE: autoload/lh/dox.vim ================================================ "============================================================================= " File: autoload/lh/cpp/dox.vim {{{1 " Author: Luc Hermitte " " License: GPLv3 with exceptions " let s:k_version = 221 " Version: 2.2.1 " Created: 22nd Feb 2011 " Last Update: 22nd Nov 2019 "------------------------------------------------------------------------ " Description: " Set of functions to generate Doxygen tags in respect of the current " style. " }}}1 "============================================================================= let s:cpo_save=&cpo set cpo&vim "------------------------------------------------------------------------ " ## Misc Functions {{{1 " # Version {{{2 function! lh#dox#_version() return s:k_version endfunction " # Debug {{{2 let s:verbose = get(s:, 'verbose', 0) function! lh#dox#verbose(...) if a:0 > 0 | let s:verbose = a:1 | endif return s:verbose endfunction function! s:Verbose(expr) if s:verbose echomsg a:expr endif endfunction function! lh#dox#debug(expr) return eval(a:expr) endfunction "------------------------------------------------------------------------ " ## Exported functions {{{1 " # doxygen comment generation {{{2 " Function: lh#dox#comment_leading_char() {{{3 function! lh#dox#comment_leading_char() return lh#ft#option#get('dox_CommentLeadingChar', &ft, '*') endfunction " Function: lh#dox#tag_leading_char() {{{3 function! lh#dox#tag_leading_char() return lh#ft#option#get('dox_TagLeadingChar', &ft, '@') " alternative: \ endfunction " Function: lh#dox#tag(tag) {{{3 function! lh#dox#tag(tag) return lh#dox#tag_leading_char().substitute(a:tag, '\s\+$', lh#ft#option#get('dox_sep', &ft, ' '), '') endfunction " Function: lh#dox#semantics(text) {{{3 " TODO: s/text/list function! lh#dox#semantics(text) return '

    Semantics
    ' endfunction " Function: lh#dox#throw([text]) {{{3 function! lh#dox#throw(...) let throw = lh#ft#option#get('dox_throw', &ft, 'throw ') let res = '' if !empty(throw) let res .= lh#dox#tag(throw) if a:0==0 || empty(a:1) let res = lh#marker#txt(res) else let res .= a:1 endif else if a:0!=0 && ! empty(a:1) let res .= lh#dox#tag('throw ') . a:1 endif endif return res endfunction " Function: lh#dox#ingroup([text]) {{{3 function! lh#dox#ingroup(...) let text = a:0==0 || empty(a:1) ? lh#option#get('dox.group.name', lh#marker#txt('group')) : a:1 let ingroup = lh#ft#option#get('dox_ingroup', &ft, 0) if ingroup =~? '^y\%[es]$\|^a\%[lways]$\|1' let res = lh#dox#tag('ingroup ').text elseif ingroup =~? '^no$\|^n\%[ever]$\|0' let res = '' elseif type(ingroup) == type('') let res = lh#dox#tag('ingroup ').ingroup else " maybe let res = lh#marker#txt(lh#dox#tag('ingroup ').(a:0==0?'':a:1)) endif return res endfunction " Function: lh#dox#brief([text]) {{{3 function! lh#dox#brief(...) let text = a:0==0 || empty(a:1) ? lh#marker#txt('brief explanation').'.' : a:1 if text[-1:] != '.' |let text .= '.' | endif let brief = lh#ft#option#get('dox_brief', &ft, 'short') if brief =~? '^y\%[es]$\|^a\%[lways]$\|1' let res = lh#dox#tag('brief ').text elseif brief =~? '^no$\|^n\%[ever]$\|0\|^s\%[hort]$' let res = text else " maybe let res = lh#marker#txt(lh#dox#tag('brief ')).text endif return res endfunction " Function: lh#dox#param({dir,name,text) {{{3 function! lh#dox#param(param) let res = lh#dox#tag("param") if type(a:param) == type({}) if has_key(a:param, "dir") let dir = a:param.dir if stridx(dir, '[') == -1 let dir = '[' . dir .']' endif let res .= dir endif if has_key(a:param, "name") | let res .= " ".(a:param.name) | endif let res .= ' '. a:param.text else let res .= ' ' . a:param endif return res endfunction " Function: lh#dox#author() {{{3 function! lh#dox#author_value(...) abort if a:0 && !empty(a:1) > 0 return a:1 endif let author = lh#ft#option#get('dox_author', &ft, '') if author =~ '^g:.*' if exists(author) return {author} " return tag . {author} . lh#marker#txt('') else return lh#marker#txt('author-name') endif elseif strlen(author) == 0 return lh#marker#txt('author-name') else return author endif endfunction function! lh#dox#author(...) abort let author_tag = lh#ft#option#get('dox_author_tag', &ft, 'author') let tag = lh#dox#tag(author_tag. ' ') return tag . call('lh#dox#author_value', a:000) endfunction " Function: lh#dox#since(...) {{{3 function! lh#dox#since_value(...) abort let ver = lh#option#get('ProjectVersion', a:0==0 ? lh#marker#txt('1.0') : a:1) return ver endfunction function! lh#dox#since(...) abort let tag = lh#dox#tag('since ') return tag . 'Version '.call('lh#dox#since_value', a:000) endfunction "------------------------------------------------------------------------ " # fn_comments object {{{2 " Function: lh#dox#_parameter_direction(type) {{{3 function! lh#dox#_parameter_direction(type) abort " todo: enhance the heuristics. " - add string_view, span, mdspan " First strip any namespace/scope stuff " Support for boost smart pointers, custom types, ... if a:type =~ '\%(\\s*[&*]\=\|const_\%(reference\|iterator\)\|&&\|\%(unique\|auto\)_ptr\)\s*$' \ . '\|^\s*\(\\)' return '[in]' elseif a:type =~ '\%([&*]\|reference\|pointer\|iterator\|_ptr\)\s*$' return '[' . lh#marker#txt('in,') . 'out]' elseif lh#dev#cpp#types#is_base_type(a:type, 0) return '[in]' else return lh#marker#txt('[in]') endif endfunction " Function: lh#dox#new_function(brief) {{{3 function! lh#dox#new_function(brief) abort let res = {'brief': a:brief, 'param': [], 'pre': []} function! res.add_param(param) " {{{4 " dict with: "dir", "name", "text" " if no "dir", but a "type" => compute "dir" let param = a:param let name = lh#naming#param(param.name) if !has_key(param, 'dir') let param.dir = lh#dox#_parameter_direction(param.type) endif if !has_key(param, 'text') let param.text = lh#marker#txt(name.'-explanations') endif if has_key(param, 'type') && lh#dev#cpp#types#is_pointer(param.type) let self.pre += [ '`'.name.' != '.lh#cpp#snippets#nullptr().'`' . lh#marker#txt()] endif let self.param += [ param ] endfunction " }}}4 return res endfunction "------------------------------------------------------------------------ " ## Internal functions {{{1 "------------------------------------------------------------------------ let &cpo=s:cpo_save "============================================================================= " vim600: set fdm=marker: ================================================ FILE: doc/API.md ================================================ ## lh-cpp API ### C++ Flavour These functions permit to set the C++ flavour currently used. The typical use case of these functions is to adapt code snippets to best fit the idioms of the language, or to select the more standard type/function/construct available. #### Examples See for instance: - [`array_size` snippet](snippets.md#array_size) - [`namespace` snippet](snippets.md#namespace) - [`shared_ptr` snippet](snippets.md#shared_ptr) - [`static_assert` snippet](snippets.md#static_assert) - [`begin`-`end` expander](features.md#begin_end) #### Functions ##### `lh#cpp#get_flavour()` __Returns__: the current C++ flavour (03, 05, 11, 14, or 17) The flavour is obtained from [`(bg)_cpp_std_flavour`, `$CXXFLAGS`, or `$CMAKE_CXXFLAGS`](options.md#bgcpp_std_flavour-and-cxxflags). ##### `lh#cpp#use_TR1()` __Returns__: whether TR1 (or more is supported). This function checks [`lh#cpp#get_flavour()`](lh#cpp#get_flavour) result >= '05'. In order to check for TR1 and only TR1, test `lh#cpp#use_TR1() & !lh#cpp#use_cpp11()`. ##### `lh#cpp#use_cpp11()` __Returns__: whether C++11 (or more) is supported This function relies on [`lh#cpp#get_flavour()`](lh#cpp#get_flavour) ##### `lh#cpp#use_cpp14()` __Returns__: whether C++14 (or more) is supported This function relies on [`lh#cpp#get_flavour()`](lh#cpp#get_flavour) ##### `lh#cpp#use_cpp17()` __Returns__: whether C++17 (or more) is supported This function relies on [`lh#cpp#get_flavour()`](lh#cpp#get_flavour) #### Tests See [tests/lh/test-flavours.vim](tests/lh/test-flavours.vim). ================================================ FILE: doc/Doxygen.md ================================================ ## File-templates lh-cpp & [mu-template](http://github.com/LucHermitte/mu-template) come with tunable project headers (the default is quite bad I have to admit). You'll have to override `templates/c/internals/c-file-header.template` to something like: ```c++ /**<+File brief line+> * <+lh#dox#tag('file ').s:filename+> * <+lh#dox#ingroup()+> * <+lh#dox#author()+>, creation * <+lh#dox#tag('copyright ')+><+strftime('%Y')+> Copyright-Holder-name * <+lh#dox#since('ProjectVersion')+> * <+lh#dox#tag('date ').strftime('%Y %b %d')+> creation *

    Licence:

    Your Project Licence * * PROJECTNAME project. */ ``` (All the other stuff is already taken care of: include guards will be added automatically in header files, and `foo.h` will be automatically included in `foo.c(pp)`) Then, in a local vimrc, you'll have to set the [following options](options.md#doxygen-related-options): * `(bpg):({ft}_)dox_author` * `(bpg):({ft}_)dox_group` * `(bpg):ProjectVersion` ## Snippets Several C++ snippets for classes and functions automatically generate doxygen documentation. See [doxygen related options](options.md#doxygen-related-options), [class snippets](snippets.md#classes) and [Doxygen snippets](snippets.md#doxygen) for more information on the subject. ## `:DOX` lh-cpp provides the `:DOX` command that analyses the current function signature to build a doxygen skeleton. The ([configurable](#configuration)) skeleton will have: * a brief line * a list of _in_, _out_, or _inout_ `@parameters` * a `@return` tag, if something is returned * `@exception` specifications if known * other tags like `@version` * etc. ### Examples Given ```c++ std::string f( std::vector & v, std::unique_ptr foo, int i, SomeType v, std::string const& str, int *pj); ``` `:DOX` will produce: ```c++ /** * «brief explanation». * «details» * @param[«in,»out] v «v-explanations» * @param«[in]» foo «foo-explanations» * @param[in] i «i-explanations» * @param«[in]» v «v-explanations» * @param[in] str «str-explanations» * @param[«in,»out] pj «pj-explanations» * * @return «std::string» * «@throw » * @pre foo != NULL«» * @pre pj != NULL«» */ std::string f( std::vector & v, std::unique_ptr foo, int i, SomeType v, std::string const& str, int *pj); ``` You can see: * `«»` used as a [placeholder](https://github.com/LucHermitte/lh-brackets) to jump to ; * references interpreted as _out_ and possibly _in_ parameters ; * const-references interpreted as _in_ parameters ; * parameters of known types correctly recognized as _in_ parameters ; * parameters of unknown types could be proxys/pointers and thus they could act as _out_ parameters instead ; * pointer types are recognized as such, and `:DOX` suggest adding a precondition of non-nullity in their case ; * a few other tags left to the user to fill in as nothing could be deduced from the function signature. ### `:DOX` specific options All [doxygen related options](options.md#doxygen-related-options) apply. More over, `:DOX` has other dependencies: * `lh#dev#cpp#types#is_base_type()` can be tuned to influence whether parameters taken by copy are considered as _in_ parameters through: * `(bpg):({ft}_)base_type_pattern` * `lh#dev#cpp#types#is_pointer()` is used to recognize pointer types. ================================================ FILE: doc/Enums.md ================================================ lh-cpp provides the following features related to enums: * [generation of a scoped and iterable enumerated type](#enum-snippet) * [for-snippet for the iterable enum](#enum-iteration) * [automated generation of a switch-case statement from an enum](#switch-case-generation) ### Enum snippet lh-cpp ships a [µtemplate](http://github.com/LucHermitte/mu-template) snippet that expands `enum` into an enum definition with the following properties: * C++ scoped (no `MYENUM_VAL1`, `MYENUM_VAL2`, ... but `MYENUM::VAL1`, `MYENUM::VAL2`, ...) (which can be taken advantage of in C++ template functions) * the number of elements is automatically provided (which can be used, for instance, into static assertions in order to check that an associated array of strings has a consistant dimension) * iterable with no need to explicitly cast an `int` into the enum type. Let's say you answer "`MyEnum`" when requested with the enum name, the following will be inserted: ```C++ struct MyEnum { 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 MyEnum::type& operator++(MyEnum::type& e_) { return e_ = MyEnum::next(e_); } inline MyEnum::type operator++(MyEnum::type&e_, int) { const MyEnum::type tmp = e_; e_ = MyEnum::next(e_); return tmp; } ``` ### Enum iteration In order to take advantage of the particular format of the [iterable enum](#enum-snippet), a [µtemplate](http://github.com/LucHermitte/mu-template) snippet is provided to iterate over all enumerated values. `for-enum` will expand into: ```C++ for (MyEnum::type «e» = MyEnum::type() ; «e» != MyEnum::MAX__ ; ++«e» ) { «» }«» ``` ### switch-case generation Given an [iterable enum](#enum-snippet) variable or type name, type this name and then hit `se`. lh-cpp will fill [µtemplate](http://github.com/LucHermitte/mu-template) switch-case snippets with all possible values from the enum type. e.g. with: ```C++ struct MyEnum { enum type { V1, V2, V42, MAX__ }; ... MyEnum::type some_enum_var; ``` in INSERT-mode `some_enum_var^Xse` expands into: ```C++ switch (some_enum_var) { case MyEnum::V1: { «MyEnum::V1-code»; break; } case MyEnum::V2: { «MyEnum::V2-code»; break; } case MyEnum::V42: { «MyEnum::V42-code»; break; } default: { «default-code»; break; } }«» ``` As of today this feature requires a ctags database containing all the tags related to the enum, and an [iterable enum](#enum-snippet). (I plan to support [C++0x class-enums](http://en.wikipedia.org/wiki/C%2B%2B0x#Strongly_typed_enumerations) and to find eventually an alternative to ctags) ================================================ FILE: doc/TODO.md ================================================ # lh-cpp TO DO list ## Folding - [ ] if only `{`, search next line - [ ] `do` `while` - [ ] embedded `#if` ## syntax highlight - [ ] detect `case` - [X] without a `break`, or a `return`, or `continue`, or a `goto`, or `- [[fallthrough]]` - [ ] `break;} case` is incorrectly recognized - [ ] `default` is not recognized - [ ] detect raw pointers - [ ] detect calls to `malloc`/`free`/... - [ ] detect calls to `delete` (outside destructors) - [ ] detect calls to `new` (C++14) - [ ] detect C casts - [X] ignore `void foo() const` - [ ] ignore `decltype(auto) foo;` - [ ] ignore `f(12)(13)(14)` ## snippets / wizard ### class wizard - [ ] Doc!! - [X] Options - [ ] Snippets - [ ] Class kinds - [ ] CRTP - [ ] arithmetic class - [ ] clonable simpl. or interactive - [ ] value w/ manual copy (& swap) - [ ] NVI ? - [ ] template class - [ ] enum class (only tests?) - [ ] singleton (test) - [ ] Simplified way to generate new classes w/ attribs & all - [ ] class features - [ ] Check inline TODOs - [ ] attributes - [ ] use snippet if there is one with the same type name, idem for inheritance -> require patch on <+s:Include()+> in mu-template - [ ] dox functions - [ ] test w/ and w/o - [X] default constructor - [X] copy constructor - [X] init constructor - [X] destructor - [X] assignment operator - [X] copy'n'swap -> `swap` - [ ] `what` - [ ] attributes - [ ] types & classes - [ ] pointer means invariant - [ ] move contructor - [ ] move assignment-operator - [ ] Enforce «rule of all or nothing» - [ ] Special functions need atomic tests - [X] default constructor - [X] copy constructor - [X] init constructor - [X] destructor - [X] assignment operator - [X] copy'n'swap - [ ] C++11 - [ ] w/ TBW `:MuT cpp/class attributes=foo:int,#bar:string parents=Bar,-Toto` - [X] `:Constructor` ### Other snippets - [ ] `` snippets should use cpp/begin-end - [ ] lambda - [ ] Check `:InsertEnum` -> tests - [X] Fix `:MuTemplate c/swith un deux` - [ ] Find a better way to pass options to `:MuTemplate` command in order to take advantage of cpp/class snippets. For instance: ``` " +==public, #==protected, -==private :MuT cpp/class attributes=foo:int,#bar:string parents=Bar,-Toto ``` ## misc - [ ] Register options for completion & co into menus, `:Set` and `:Toggle` - [ ] Have lh#dev#import rely on lh#cpp#types, or the other way around - [ ] `:MOVETOIMPL` doesn't work on constructors when there is an initialization-list ================================================ FILE: doc/c.html ================================================ Luc Hermitte's VIM C/C++ ftplugins
    Luc Hermitte's VIM C/C++ ftplugins Saturday 30th November 2002

    VIM ftplugins for editing C & C++ files

      I propose/present here a set of VIM ftplugins designed for editing C++ files and C files.

      You will found all the links for downloading the described files at the end of this part.

    ftplugin for C programming

      The script that follow is meant to be placed into one of your {rtp}/ftplugin/c/ directories.

      c_set.vim defines many things that I found useful when programming in C. They could be used for C++ and Java programming as well.

      Features and Originalities

      • Well there exist, over the WWW, a lot of configurations and mappings regarding C programming. Once again you will find in this file shortcuts for if, else, elif (I know it is not a C keyword, but else if are), for, while, switch and main.
        What is unique is the fact that if you type if in insert mode, it will automatically expand into ...
            if () {
            } 
        ... in respect of the context. I.e.: within comments or strings (delimited by single or double quotes) if is not expanded. If keyword characters precede the typing, if is not expanded as well. Thus variables like tarif can be used without getting any headache.
        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 ,.
        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. common_brackets.vim), if could be expanded into :

            if () {
        	
            }
        

        I do not present more precisely the other mappings alike. There are twin mappings !

      • Some other abbreviations ease the insertion of some formatted comments.
      • And of course there are some very classical settings for C editing.

      Dependencies :

      • VIM 6.0+
      • misc_map.vim defines two functions used in every mapping and abbreviation of the language keywords ; it enables to define context dependent macros.
      • common_bracket.vim defines a set of mappings that ease the management of brackets, quotes, parenthesis, etc.. These mappings are customized for C & C++ programming.
      • a.vim very nice when we want to swap between .h, .inl and .c and .cpp files. Could be found of sourceforge -- not critical regarding the mappings defined.
      • LoadHeaderFile.vim very nice in order to go to included files. Could be found of sourceforge -- not critical regarding the mappings defined.

    ftplugins for C++ programming

      The script that follow is meant to be placed into one of your {rtp}/ftplugin/cpp/ directories.

      Classical features : cpp_set.vim

      cpp_set.vim :
      • sources c_set.vim,
      • specializes some settings like the format of comments ;
      • adds 2-3 new mappings for try & catch ;
      • adds shortcuts for public:, protected:, private:, template<>, virtual and std:: ;
      • defines /*<space> that expands into :/** */
        and /** that expands into :
        	/**
        	 */ 
      • proposes the insert-mode mapping <c-x>be that expands algo(container_expr) into algo(container_expr.begin(), container_expr.end()), where represents the current cursor position.

      Enhanced features

      The more interesting part comes with four new files full of functions and commands :
      • cpp_options.vim that is the ideal place for custom C++ preferences.
      • cpp_BuildTemplates.vim defines my own template preferences regarding the format of comments and classes -- many headers plus some doxygen constructs.
      • cpp_FindContextClass.vim extracts the name of the class the cursor is within.
      • cpp_InsertAccessors.vim defines certainly one of the two most useful features : an easy way to add (to a class) new attributes and their accessors and mutators (get and set methods).
      • cpp_GotoFunctionImpl.vim defines the second most useful feature : a way to jump from the prototype to the implementation of a function, and if the implementation has not beeing defined yet, an empty implementation is inserted in the .cpp file.

    Some explanations about the enhanced C++ ftplugins

      All the scripts that follow are meant to be placed into one of your {rtp}/ftplugin/cpp/ directories.

    cpp_options-commands.vim & cpp_options.vim

      cpp_options.vim is the ideal place for custom C++ preferences like the prefix and postfix notations used for member data and their accessors, the file where inlines should go, if accessors must be inlined, etc. ; this file is used to configure cpp_BuildTemplates.vim, cpp_InsertAccessors.vim and cpp_GotoFunctionImpl.vim.

      Drop it into your {rtp}/ftplugin/cpp/ directory ; it will be shared by all your projects. And if for a particular project other rules are required, copy and specialize this file into every directory containing the C++ source files.

      cpp_options-commands.vim only defines the command :CheckOptions that is used by the other scripts to load the correct options (i.e. cpp_options.vim).

    cpp_BuildTemplates.vim

      This file defines my own template preferences regarding the format of comments and classes -- many "rulers" plus some doxygen constructs. You may not be directly interested in this file ; moreover, it will evolve to take advantage of Gergely Kontra's mu-template. The commands are :

      • ;HE <main class name> which produces a template for the header file dedicated to the specified class name.
      • ;CL <main class name> which produces a class template for specified class name.
      • ;BL <title> which produces three lines of '=' around the title -- BigLines.
      • ;GR <group title> which inserts a Doc++/Doxygen group -- GRoup.
      • ;MGR <group title> which inserts a Doc++/Doxygen group plus a comment line -- MegaGRoup.
      • ;RI <class name> which moves the cursor to the desired (regarding cpp_options.vim::g:inlinesPlace) location for the implementation of the inlines of the current class -- ReachInlines. The functions that the command calls are quite complex and heavily rely on the Big Line format. So if you want to change the format, you will have to adapt the function Cpp_search4line() and some other script variables. All the underlying functions used by this command are very important for the cpp_InsertAccessors.vim::AddAccessor command. So, be very careful in your customizations.
      cpp_BuildTemplates.vim needs an old version of a.vim.

    cpp_FindContextClass.vim

      Given a line number, the function (in this ftplugin) extracts the name of the most embedded class around the specified line.

      A this time, the template are not managed.

      For something like :

       1:
       2:    class A
       3:    {
       4:        // ... 
       5:        class B {
       6:            // ... 
       7:        };
       8:        // ... 
       9:        class C {
      10:            // ... 
      11:        };
      12:    };
      13:
      
      The possible retrieved class names are : "" [1, 13], "A" [2-4,8,12], "A::B" [5-7] and "A::C" [9-11].

      This script is required by cpp_InsertAccessors.vim and cpp_GotoFunctionImpl.vim.

    cpp_InsertAccessors.vim

      This file defines an easy way to add new attributes, their accessors (get methods) and their mutators (set methods) to a class.
      I may use "accessor" to also designate the "mutator".

      The built accessors are moreover const and ref. correct in the sense of the item 43 of Herb Sutter's Exceptional C++. BTW, if you extend (with typedefs) the list of base types, you will have to extend the function Cpp_IsBaseType().

      To use this feature, place the cursor where you want your attributes (internal data members) to be written to, then press ;AA. Then first, you will be asked for the type of the new attribute and its name. And then, you will be asked whether you want :

      • a get accessor or may be a proxy-get accessor -- cf. Scott Meyer's More Effective C++ for instance ;
      • a set mutator -- may be a proxy-set one ;
      • a reference accessor -- may be a proxy-ref one ;
      Finally, you will have to move the accessors to their desired location.

      Regarding the customization facilities, through cpp_options.vim you can :

      • specify the notation you want to use for the internal data member ; for instance here are some common notations : m_Foo (Microsoft's one), Foo_ (Herb Sutter's one), _Foo (the one you should forget about), Foo (the very lazy one), etc..
      • specify the notation you want to use for the accessors ; for instance the get accessor to the attribute Foo could be "GetFoo()", or "getFoo()", or "get_Foo()" and so on. And the same for the set and the reference accessors.
      • specify how you want the implementation of the accessors to appear :
        • within the declaration of the class -- lazy behavior that should disappear thanks to this VIM script ;
        • as inlines : either at the end of the header file containing the class declaration or in a separate inline file ;
        • as non-inlines in the implementation file (.cpp).

      Here is a little example of header file and the corresponding inline file generated for :

      • g:implPlace=1 -- implemented as inlines ;
      • g:inlinesPlace=1 -- inlines in a separate file ;
      • an int attribute named AnInteger for which I asked for a get, a set and a reference accessor.
      • an CComplexThing attribute named AComplexThing for which I asked for a proxy-get (of type CT_Proxy), a set and a reference accessor ;
      As you can, see, the declarations have to be moved !

      Note : the inline and the definition files don't need to exist. They are generated automatically.

    cpp_GotoFunctionImpl.vim

      This file defines an easy way to jump from a function-prototype to its implementation ; if the implementation does exist yet, a default one is generated on the fly.

      This ftplugin has been first inspired by Leif Wickland's VIM TIP#335 (on sourceforge) and Robert Kelly IV's improvments. Then I added what I've been waiting to do for a longtime: a way to jump the implementation of a function.

      Some other features :

      • Works with member and non-member functions. If the class is nested into other classes, the real class name will be used ;
      • Accepts prototypes written on several lines, but it won't be able to detect the return type if it is not written on the same line as the function's name.
        If you get a message saying you're not within a function-prototype, may be it comes from your cursor placement : it must be between the line of the function's name and before the closing parenthesis.
      • Any comment ending a line (within the function-prototype) will be trimmed.
      • Compatible with mu-template : i.e. it won't complains or do any weird and undesired thing.
      • Options are set into cpp_options.vim and can be overriden when invoking the command.

      The ftplugin defines :

      • the command :GIMPL (GOTO_IMPL) that will provoke the jump ; The cursor must be placed between the line of the function's name and the corresponding closing parenthesis.
      • the INSERT mode mapping <C-X>i ;
      • the normal mode mappings ;GI and <C-W>i.
      The mappings can be overrided by adding, in a file loaded before this ftplugin, something like :
      	imap <buffer> whateverIWant <Plug>GotoImpl
      	nmap <buffer> whateverIWant <Plug>GotoImpl
      	

      Several options are available (idea from Robert Kelly IV) :

      • ShowVirtual (0/1) : determines whether we want the virtuality of the member function to be reminded along with the implementation ;
      • ShowStatic (0/1) : determines whether we want the staticity of the function to be reminded ;
      • ShowDefaultParam (0/1/2) : determines whether we want the default value of the parameters to be remininded to us.
      [0: no reminder ; 1: text with comments ; 2: like 1, but the spaces are trimmed]
      The default values for these options are taken into cpp_options.vim that can define the variables: g:cpp_ShowVirtual, g:cpp_ShowStatic and g:cpp_ShowDefaultParams.
      However, when using the command :GIMPL, we can specify values for these different options. The format beeing : <name_of_the_option>(\d\+\|on\|off). For instance :
      :GIMPL ShowVirtualoff ShowDefaultParams2.

    Downloads

      .
      lh-cpp.tar.gz
      <raw file>
      30th  November  2002
      This tarball contains all the following files and a copy of all the files they rely on.
      So, if you plan to have a complete and easy installation of my C & C++ ftplugins, unpack this tarball archive into one directory from your 'runtimepath'.
      c_set.vim
      <raw file>
      12th  November  2002

      VIM 6.x only
      The main C ftplugin. It defines several settings plus a lot of mappings for C keywords.
      more info...
      Requires : misc_map.vim, common_bracket.vim. Wants a.vim and LoadHeaderFile.vim.
      cpp_set.vim
      <raw file>
      12th  November  2002

      VIM 6.x only
      The main C++ ftplugin. It defines some new mappings for C++ keywords, enhanced the comments management and loads all the other C++ plugins.
      more info...
      Requires : c_set.vim, and every following cpp_.*.vim.
      cpp_options-commands.vim
      <raw file>
      12th  November  2002
      Script in charge of the management of the options.
      I.e. it loads the appropriate options-file.
      more info...
      Needed by : cpp_BuildTemplates.vim, cpp_GotoFunctionImpl.vim and cpp_InsertAccessors.vim.
      cpp_options.vim
      <raw file>
      12th  November  2002
      The options-file, designated place for customizing the policies of the following files. It is meant to be overriden into your current working directory.
      more info...
      Needed by : cpp_BuildTemplates.vim, cpp_GotoFunctionImpl.vim and cpp_InsertAccessors.vim.
      cpp_BuildTemplates.vim
      <raw file>
      12th  November  2002

      VIM 6.x only
      Defines some template preference for the formats of comments and classes.
      more info...
      Requires : a.vim
      parse-class.sed
      <raw file>
      15th  March  2002
      Multi-line extraction of class names. Depreciated ; Used to be required by cpp_FindContextClass.vim
      cpp_FindContextClass.vim
      <raw file>
      12th  November  2002

      VIM 6.x only
      Extracts name of classes.
      more info...

      cpp_InsertAccessors.vim
      <raw file>
      12th  November  2002

      VIM 6.x only
      Enables to easily add attributes and their accessors.
      more info...
      Requires : cpp_options.vim, cpp_BuildTemplates.vim, cpp_FindContextClass.vim, a.vim.
      cpp_GotoFunctionImpl.vim
      <raw file>
      12th  November  2002

      VIM 6.x only
      Defines a command and some mappings to jump from a function prototype to its implementation ; if the implementation does exist yet, a default one is generated on the fly.
      more info...
      Requires : cpp_options.vim, cpp_FindContextClass.vim, a.vim.
      lh-cpp-readme.txt The VIM documentation for all these scripts. Written as a part of the tarball archive.
      a.vim Commands to switch between source files and header files. Maintained on sourceforce.
      LoadHeaderFile.vim Loads a file from a #include line. Maintained on sourceforce.
      mu-template.vim
      Local copy: mu-template.vim
      <raw file>
      30th  November  2002

      Archive with some templates: mu-template.tar.gz
      VIM 6.x only
      Gergely Kontra's script. It permits to (automatically) load template files. Little to little, I will use this plugin to replace some of my cpp_BuildTemplates.vim's functions.
      The version I propose here has been enhanced to support many other things and to be compatible with my other scripts.
      Initial version maintained on sourceforce;
      Can takes advantage of searchInRuntime.vim

    Back to the ftplugings page hermitte@free.fr
    ================================================ FILE: doc/lh-cpp-readme.txt ================================================ *lh-cpp-readme.txt* C & C++ ftplugins short presentation (v2.2.0) For Vim version 7.x. Last change: 30th Jun 2016 By Luc Hermitte ------------------------------------------------------------------------------ This a very short guide to the C&C++ ftplugin suite lh-cpp Contents~ |lh-cpp-features| The features proposed by the ftplugins |lh-cpp-first-steps| Your first steps with these ftplugins |Files-from-lh-cpp| The files that compose the archive |add-local-help| Instructions on installing this file (:helptags %:h) ------------------------------------------------------------------------------ *lh-cpp-features* Features~ |C_settings| Various settings |brackets-for-C| Bracketing system |C_control-statements| Control statements for C editing (for, if, etc) |C_switch_enum| Expands an enum into a switch statement |C_snippets| Other C snippets and shortcuts |C++_control-statements| Control statements for C++ editing (try, ...) |C++_accessors| C++ accessors & some templates skeletons |C++_jump_implementation| Jumping to functions-implementation |C++_function_doxygenation| Doxygenize a function prototype |C++_templates| Skeletons, snippets, and wizards provided |C_snippet_realloc| |C++_template_new| |C++_template_class| |C++_template_default-constructor| |C++_template_copy-constructor| |C++_template_copy-and-swap| |C++_template_assignment-operator| |C++_template_destructor| |C++_Override| Function overriding helper |C++_unmatched_functions| Search for declared ad undefined functions (or the other way around) |C++_inspection| Inspection of various properties (children, ancestors, ...) |C++_options| Options for different features (i.e. ftplugins) ...|C++_doxygen-options| Options related to Doxygen. |lh-cpp_API| Functions available to write your own ftplugins and templates. ...|lh#cpp#dox#| Doxygen related functions |mu-template.txt| Gergely Kontra's mu-template |previewWord.vim| Georgi Slavchev's previewWord.vim |C_folding| |C++_folding| C & C++ folding |search-in-runtimepath| Searching in various directories lists - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *C_settings* Various settings from c_set.vim~ File: ftplugin/c/*c_set.vim* Vim-options~ 'formatoptions' is set `to' `croql' 'cindent' is set. 'cinoptions' is set to `g0,t0` (`g0,t0,h1s` for C++ with |cpp_set.vim|). 'define' is set to recognize defines and constants. 'comments' is set to `sr:/*,mb:*,exl:*/,://` 'isk' is completed with `#`, thus `#if` is considered to be a keyword, and looses `-` this `ptr->foo` is correctly separated. 'ch' is set to 2. 'showmode' is unset. 'dictionary' is completed with `{rtp}/ftplugin/c/word.list`. 'complete' is completed with `k`, and looses `i` (to prevent interminable header-file parsing) 'localleader' is set to `,`, unless it is already defined. 'suffixesadd' is completed with `.h` and `.c`. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *brackets-for-C* Bracketing system~ Files: |bracketing.base.vim| & |common_brackets.vim| Requires: |lh-brackets| (needed); |Triggers.vim| (supported) Help: License: The generated code is under license exception to GPLv3 Options: |[bg]:usemarks| (0/[1]) to enable the insertion of |markers|. |g:marker_prefers_select| (0/[1]) select or echo the text within marker. |g:marker_select_empty_marks| (0/[1]). select or delete markers on !jump! and many more that are pointless here. Mappings defined in this particular configuration: |!mark!| inserts a |marker| -- default: «» |!jump!| jumps to the next marker |!jumpB!| jumps to the previous marker || shortcut to !mark! ; can be redefined || shortcut to !jump! ; can be redefined || shortcut to !jumpB! ; can be redefined imaps { {\n\n} + |markers| (if |[bg]:usemarks|==1) and cursor positioned #{ {} + |markers| (if |[bg]:usemarks|==1) and cursor positioned ( () + |markers| (if |[bg]:usemarks|==1) and cursor positioned [ [] + |markers| (if |[bg]:usemarks|==1) and cursor positioned " "" + |markers| (if |[bg]:usemarks|==1) and cursor positioned ' '' + |markers| (if |[bg]:usemarks|==1) and cursor positioned toggles the 4 previous mappings ; requires |Triggers.vim| toggles the value of |[bg]:usemarks| ; requires |Triggers.vim| < expands into !mark! if the opening angle-bracket immediatelly follows `#include`, a C++ cast, `template` or `typename`. Otherwise, it is not expanded. n&vmap: {, (, '', "", [ Surround the current selection (or word in |Normal-mode|) with the bracket-like character used in the mapping. { Insert a pair of curly brackets around the current line (/visual selection). It is done in respect of |[bg]:usemarks|. + some mappings from auxtex.vim to manipulate brackets *x* ** : delete a pair of brackets *(* replaces the current pair of brackets with parenthesis *[* replaces the current pair of brackets with square brackets *{* replaces the current pair of brackets with curly brackets *<* replaces the current pair of brackets with angle brackets *\* toggles the backslash on a pair of brackets NB: The brackets mappings only insert the markers when |[bg]:usemarks|==1, and outside comments and string contexts. They are buffer relative. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *C++_current_function* *C++_[[* *C++_][* |[[| and |][| have been overriden for C++ functions. Instead of jumping to the previous/next `{`/`}` in the first column, they jump to the start/end of the current function. On this topic, |lh-dev| also provides |v_if| and |o_if| mappings that select the current function (this feature is not restricted to C++). - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *C_control-statements* C Control statements~ File: ftplugin/cpp/|c_snippets.vim| Requires: |lh-brackets| (needed) Help: License: The generated code is under license exception to GPLv3 Mappings and abbreviations defined: [always buffer-relative] abbr: if if {\n} + |markers| (if |[bg]:usemarks|==1) *C_if* + cursor positioned abbr: elif else if {\n} + ... *C_elif* abbr: else if {\n} + ... *C_else* abbr: while while {\n} + ... *C_while* abbr: do do{\n}while() + ... *C_do* abbr: for for(;;) {\n} + ... *C_for* abbr: switch switch {\n} + ... *C_switch* abbr: Ymain int main() \n{\n} + ... *C_main* n&vmap: if , elif, else, wh, for & main Insert the control-statement around the current line (/visual selection). It is also done in respect of |[bg]:usemarks|. n&vmap: if , elif, wh, for The current line (/visual selection) is used as the conditional expression of the control statement inserted. It is also done in respect of |[bg]:usemarks|. Options: * Regarding the control statements (|C_if|, |C_else|, |C_while|, |C_for|, |C_switch|), the style to apply on the inserted snippets is defined thanks to lh-dev |:AddStyle| command. [By default, K&R way of placing brackets is used] Note: in the past, this plugin was relying on *g:c_nl_before_bracket* and *g:c_nl_before_curlyB* to control brackets placement. These options have been deprecated. They are still used however in one last place: the |C++_accessors| feature. NB: * |[bg]:usemarks| is still taken into account. * Works even if the bracketing system is not installed or deactivated (with ). * Not tested with other bracketing systems than the one I propose. * Within comment-, string- or character-context, the abbreviations are not expanded. Variables like 'tarif' can be used with no problem. * These abbreviations will not insert undesired white-space. * Also contains my different settings. * To tune more precisely how the lines are indented, check 'cindent'. * If the visual selection exactly matches a |marker|, then the visual-mode mappings will result in the use of the equivalent abbreviations. * The normal- and visual-modes mappings do respect the current coding style (see |lhdev-style|). - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *C_switch_enum* *SwitchEnum* Mapping: ~ *i_CTRL-X_se* expands the name of the enum (type, or variable) before the cursor into a switch statement. Given: > enum E { NO, YES, MAX__ }; E var; varse < will expand into: > switch (var) { case YES: «YES-code»; break; case NO: «NO-code»; break; default: «default-code»; break; } Requirements:~ This feature requires a ctags database where to fetch the enum definition. It also requires |lh-dev|, and |mu-template|. Known issues:~ At this time, the plugin is not capable of respecting the declaration order of the enumerated values. The switch will iterate on the enumerated values following the lexical order. Options~ The default mapping to |i_CTRL-X_se| can be overridden with for instance: > imap se SwitchEnum - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *C_snippets* Other snippets and shortcuts from c_snippets.vim~ File: ftplugin/c/*c_snippets.vim* License: The generated code is under license exception to GPLv3 Mappings and abbreviations~ *#n* Expands into "#include", in respect of the context. *#d* Expands into "#define", in respect of the context. *#i* Expands into "#ifdef", in respect of the context. *#e* Expands into "#endif", in respect of the context. ** Expands into "return ;" *?:* Expands into "?...:...;" ** Surrounds the selection with `/*...*/` *i_CTRL-X_i* Completes the current path before the cursor as a file to be included. Search the files into the *(bpg):paths.includes* variable (list of directory glob patterns -- see |wildcard|). See also lh-dev |n_CTRL-X_i| *0* Surrounds the line selected with `#if 0...#endif` *1* Surrounds the line selected with `#if 0...#else\n#endif` See also the *c/comment* snippet that takes a count to determine where the `#else` should go. See also |KeepPoundIfPath|. To prevent these Mappings and abbreviations to be defined, set |g:lh_cpp_snippets| to 0. On the subject of `#if 0/1...#else...#endif`, the command *:KeepPoundIfPath* can remove the trUe or the false path. It takes one parameter: 1 or 0 to indicate which path must be kept. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *C++_control-statements* C++ Control statements and other shortcuts~ File: ftplugin/cpp/*cpp_snippets.vim* Requires: |C_control-statements| Help: License: The generated code is under license exception to GPLv3 Mappings and abbreviations defined: [always buffer-relative] abbr: namespace namespace {\n} + markers and cursor pos. *C_namespace* expanded only in it does not follow `using` abbr: try try{\n}catch(){\n} + markers and cursor pos. *C_try* abbr: catch catch(){\n} + markers and cursor positioned *C_catch* abbr: pub public: *C_pub* abbr: pro protected: *C_pro* abbr: pri private: *C_pri* abbr: tpl template<> *C_tpl* abbr: virt virtual *C_virt* abbr: delate delta abbr: firend friend imap: std:: *Ci_META-s* imap: boost:: or boost/ *Ci_META-b* imap: luc_lib:: *Ci_META-l* (very personal mapping you won't need) imap: "typedef"/"template" depending on the context *Ci_META-t* imap: be *Ci_CTRL-X_be* imap: rbe *Ci_CTRL-X_rbe* Duplicates the text within parenthesis, add a comma between the two occurrences, and append `.begin()` and `.end()` (or `rbegin()`, `rend()`) to each. Depending of the option *[bg]:({ft}_)begin_end_style* , the function used could be member functions, or free unqualified (or not) functions. Possible values are: - `c++98` -> ``%1.%2()`,` default in C++98 - `std` -> ``std::%2(%1)`,` default in C++11 (|lh#cpp#use_cpp11()|) - `boost` -> ``boost::%2(%1)`,` default in C++11 (|lh#cpp#use_cpp11()|) - `adl` -> ``%2(%1)`,` default in C++11 (|lh#cpp#use_cpp11()|) With %1 being replaced with the container, and %2 with `begin` or `end`. imap: /* /** */!mark! *C++_comments* imap: /*! /**\n*/!mark! n&vmap: try , catch , ns (-> "namespace{\n}") Insert the previous text around the current line (/visual selection). It also done in respect of |[bg]:usemarks|. n&vmap: catch The current line (/visual selection) is used as the formal parameter of the catch-block. It is also done in respect of |[bg]:usemarks|. *n_,dc* *n_,rc* *n_,sc* *n_,cc* *n_,lc* *v_,dc* *v_,rc* *v_,sc* *v_,cc* *v_,lc* n&vmap: dc, rc, sc, cc, lc Insert `dynamic_cast`, `reinterpret_cast`, `static_cast`, `const_cast` or `boost::lexical_cast` the selected text is used as the expression to coercise. The cursor is placed between the angle brackets. *n_,,dc* *n_,,rc* *n_,,sc* *n_,,cc* *v_,,dc* *v_,,rc* *v_,,sc* *v_,,cc* n&vmap: dc, rc, sc, cc Replace the selected C-cast by `dynamic_cast`, `reinterpret_cast`, `static_cast` or `const_cast`. The expression and the type it's coerciced to are automatically decoded. NB: * All the remarks from |C_control-statements| apply. * The current coding style (see |lhdev-style|) apply to |C_namespace|, |C_try| and |C_catch|. To prevent these mappings and abbreviations to be defined, set |g:lh_cpp_snippets| to 0. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *C++_accessors* *getter* *setter* C++ accessors & some templates~ Files: *cpp_BuildTemplates.vim* , *cpp_InsertAccessors.vim* Help: License: The generated code is under license exception to GPLv3 Requires: |a.vim| (optional) Options: |C++_accessors_options| Commands: Associated mappings *:ADDATTRIBUTE* *;AA* (do it, cursor on the "private" line) Interactive procedure to add a new set of attribute + its optimized const-correct getter & setter. See also: ||refactor-extract-getter| and ||refactor-extract-setter|. *:HEADER* {name} *;HE* Header file template Deprecated, prefer |C++_file-template| *:CLASS* {name} *;CL* Class declaration template Deprecated, prefer |C++_class-template| *:BLINES* {name} *;BL* Inserts rulers *:GROUP* {name} *;GR* Inserts a Doc++ group *:MGROUP* {name} *;MGR* Inserts a Doc++ group + a ruler *:REACHINLINE* {name} *;RI* Reaches the place where inlines are defined *C++_accessors_options* Options: See |lhdev-naming| options. *(b|g):{ft_}accessor_comment_get* *(b|g):{ft_}accessor_comment_proxy_get* *(b|g):{ft_}accessor_comment_set* *(b|g):{ft_}accessor_comment_proxy_set* *(b|g):{ft_}accessor_comment_ref* *(b|g):{ft_}accessor_comment_proxy_ref* => strings to customize the comments "%a" will be substituted by the name of the attribute. *(b|g):{ft_}implPlace* where accessor-definitions occur 0 -> Near the prototype/definition (Java's way) 1 -> Within the inline section of the header/inline/current file 2 -> Within the implementation file (.cpp) 3 -> Use the pimpl idiom (In the Todo-List) *g:inlinesPlace* where inlines are written 0 -> In the inline section of the header/current file 1 -> In the inline section of a dedicated inline file |g:c_nl_before_curlyB| : newline before '{' This will eventually be deprecated in favour of |lhdev-style|. Notes: * Everything here match my preferences regarding code presentation * The |:ADDATTRIBUTE| command (that inserts an attribute, its accessor and its mutator -- getter and setter) requires that some formating is respected -- you will certainly have to adapt it. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *C++_jump_implementation* Jumping to functions-implementation~ Help: License: The generated code is under license exception to GPLv3 Inspiration:Leif Wickland's VIM TIP #135, and Robert Kelly IV for many features. Commands: Associated mappings *:GOTOIMPL* {options} *n_;GI* *i_CTRL-X_GI* [Insert mode default mapping] Go to the implementation of the current function, if the implementation does not exist yet, a default one will be provided. To change the keybindings: *GotoImpl* *:MOVETOIMPL* {options} *n_;MI* *i_CTRL-X_MI* [Insert mode default mapping] Move the implementation of the current inline function. To change the keybindings: *MoveToImpl* *:PASTEIMPL* *n_;PI* *i_CTRL-X_PI* [Insert mode default mapping] Insert the function-implementation on the next line To change the keybindings: *PasteImpl* Special features: * Supports member and non-member functions ; * Scopes due to nested classes or namespaces are correctly supported: + function names are produced according to the current (where the function is declared) scope (nested classes + namespaces), + jumps and insertions respect the current (where the insertion happens) namespace ; * Comments from the declaration stripped ; * Comments in the implementation ignored (jumping only feature) ; * Parameters names can be changed (as they have no incidence on the signature) ; * "virtual", "static" and default argument values can be commented ; * The insertion of the default implementation can be automated and deeply customized ; * Not allowed to jump/insert to the implementation of pure virtual functions ("virtual t f(...) = 0;") ; * Will refuse to jump/insert from anything else that functions- declarations. Still lazy ; may hang on member variables. * Check the history for other minor details. Options: *(bg):[{ft}_]ext_4_impl_file* (text) This option specifies the default file-extension of the file where the function definition should go. Can be overridden on the fly with: :GOTOIMPL {ext} *(bg):[{ft}_]ShowVirtual* (0/[1]) When true, if the function is virtual, then the comment /*virtual*/ will be added at the beginning of the proposed implementation. Can be overridden on the fly with: :GOTOIMPL ShowVirtual0/1 *(bg):[{ft}_]ShowStatic* (0/[1]) When true, if the function is static, then the comment /*static*/ will be added at the beginning of the proposed implementation. Can be overridden on the fly with: :GOTOIMPL ShowStatic0/1 *(bg):[{ft}_]ShowExplicit* (0/[1]) When true, if the function is explicit then the comment /*explicit*/ will be added at the beginning of the proposed implementation. Can be overridden on the fly with: :GOTOIMPL ShowExplicit0/1 *(bg):[{ft}_]ShowDefaultParams* (0/[1]/2/3) Determines if a comment will be added for every parameter having a default value -- according to the function-signature. 0 -> No reminder 1 -> /* = {theDefaultValue} */ 2 -> /*={theDefaultValue}*/ 3 -> /*{theDefaultValue}*/ Can be overridden on the fly with: :GOTOIMPL ShowDefaultParam0/1 *(g):[{ft}_]FunctionPosition* ([0]/1/2/3) & *(g):[{ft}_]FunctionPosArg* ([0]) Determines where the default implementation, for a function not yet defined, should be placed. We are placed ... 0 -> ... at |g:cpp_FunctionPosArg| lines from the end of the file. 1 -> ... at the line after the first occurrence of the pattern |g:cpp_FunctionPosArg|. By default, |cpp_options.vim| places us after: > /*============*/ /*===[ «» ]===*/ /*============*/ < ... That I use to insert with |:BLINES| 2 -> ... according the hook (user-defined VimL-function) |g:cpp_FunctionPosArg|. By default, |cpp_options.vim| asks us for a title (actually a regex pattern), and places us after: > /*=====================*/ /*===[ {the_title} ]===*/ /*=====================*/ < ... That I still use to insert with |:BLINES| 3 -> ... nowhere, and nothing is inserted. The insertion must be done _manually_ thanks to |:PASTEIMPL|. Note: If the placement fails, it will still be possible to insert manually the default function-implementation thanks to |:PASTEIMPL|. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *C++_templates* C++ skeletons and wizards~ lh-cpp provides several template-files expanded thanks to |mu-template|. *C++_template_new* New C/C++ file~ When a new C or C++ (non-existing) file is opened, |mu-template| provides a default skeleton. ... new header file~ A header-file will have a header (where one's can put copyright information, RCS tags, etc.), anti-reinclusion guards. Some parts of what is generated can be globally overridden, or overridden only for project specific needs ; see |MuT-paths-override|. The variation points are: - the template-file {rtp}/template/c/internals/c-file-header.template where file header is specified ; - the template-file {rtp}/template/c/internals/c-header-guard.template where the computation of the header guard name, *s:guard* , is done ; - |b:sources_root| that can be used to specify the project root directory -- this information is used by the default header-guard name policy. ... new implementation file~ An implementation-file will have a header, and if a header-file (and even an inline (.inl) file) file with the "same" name is found, it will be included. The variation points are: - the template-file {rtp}/template/c/internals/c-file-header.template where file header is specified ; - the template-file {rtp}/template/c/section-sep.template that is used to specify the format of section header ; - the template-file {rtp}/template/c/internals/c-header-content.template that is meant to be overridden if some default content is always expected like a C++ namespace. - |(bg):cpp_included_paths|, |List| that is used to search for the related header-file to include. *C++_template_class* New C++ class~ This skeleton-file acts as a wizard. It first asks the user the name of the new C++ class if it hasn't specified (by default it's the name of the current file). Then it asks what semantics the class shall have: - value-semantics (stack-based, copyable, assignable, and may be comparable) ; - Stack-based semantics, but non copyable ; - Entity semantics, and non copyable ; - Entity semantics, but clonable. See the following articles if you want some more C++ insights on the implications of the question: - - [French] Accordingly to user's choice, default functions for the class will be generated, or inhibited. If you'd rather have more control over what is done, use instead the templates |C++_template_copy-and-swap|, |C++_template_copy-constructor|, |C++_template_assignment_operator|. To-do: |C++_template_destructor| that detects visibility to add <+virtual+> or nothing. To-do: support C++11 copy inhibition syntax To-do: support C++11 move-construction and move-assignement. The variation points are: - |(bg):[{ft}_]dox_CommentLeadingChar|, |(bg):[{ft}_]dox_TagLeadingChar|, |(bg):[{ft}_]dox_brief|, |(bg):[{ft}_]dox_ingroup|, |(bg):[{ft}_]dox_author_tag|, |(bg):[{ft}_]dox_author|, - |(bg):dox_group| NB: As I've reached the conclusion that everything shall be sorted into doxygen groups, I force the presence of this doxygen tag. - CppDox_ClassWizard() - the template-file {rtp}/template/cpp/internals/function-comment.template that is used to order the documentation tags associated to generated functions. This template file introduced its own variation points: - *(bg):[{ft_}]pre_desc_ordered_tags* default= ["ingroup", "brief", "param", "return", "throw", "invariant", "pre", "post"] - *(bg):[{ft_}]post_desc_ordered_tags* default= ["note", "warning"] - |(bg):[{ft_}]template_expand_doc| - the template-file {rtp}/template/cpp/internals/formatted-comment.template that is used to convert the final list of documentation tag into the embedded comments. The default format used is Doxygen format. *:Constructor* *:ConstructorInit* *:ConstructorDefault* *C++_template_default-constructor* *:ConstructorCopy* *C++_template_copy-constructor* *C++_template_copy-and-swap* *:AssignmentOperator* *C++_template_assignment-operator* *C++_template_destructor* Snippets for constructors and related functions~ Various |mu-template| snippets are provided to insert construction/destruction related functions. All detect the current class-name, they can receive some other parameters. (to be documented) They will apply naming conventions from |lh#dev#naming| See |C++_template_class| documentation for a more complete list of the parameters and other variation points involved in these snippets. They can also be run from |:Constructor| (or the other commands). In that case, a ctag database will be used to find which attributes the current class is made of in order to fill the implementation of the function as weel as we can. TODO: rely of libclang when ctags in not used *C_snippet_realloc* Snippet for realloc()~ realloc() is a tricky C function that most C developers mis-use. One shall never write: > p = realloc(p, new_size); but instead: > T* p_temp = realloc(p, new_size); if (!p_temp) { free(p) ; + other reset ; + error notification ; return false; } p = p_temp; Hence this snippet aimed at simpliying our life. |lh-refactor| defines |:FixRealloc| that corrects the first snippet above by the second one. -- this command is likelly fall back in |lh-cpp| scope in future versions. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *C++_Override* *:Override* Function overridding helper~ > :Override - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *C++_unmatched_functions* *:CppDisplayUnmatchedFunctions* Search for declared ad undefined functions (or the other way around)~ > :CppDisplayUnmatchedFunctions - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *C++_inspection* Inspection of various properties~ *:Ancestor* [classname] *:Children* [!] [namespace] [classname] - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *C++_options* C++ options~ lh-cpp supports many options directly, or indirectly (through |mu-template| for instance). *C++_options_global* Some options are global, i.e. they applies on the current vim session for all open files. They are implemented as vim |global-variable|s. *C++_options_local* Other options are local, i.e. restricted to each buffer. This does not prevent us to have an option having the same value in several buffers, however changing the value of the option in one buffer won't affect the value of the option in other buffers. They are implemented as vim |buffer-variable|s. Semantically speaking, there are two kind of local options: - options specific to a filetype ; - options specific to a project. NB: lh-cpp doesn't use the other kinds of vim variables as options (|window-variable|s, |tabpage-variable|s). *C++_options_local_filetype* These options are meant to be set in |ftplugins|. Actually they are of two natures: vim |options| (indenting settings, etc.), and vim |buffer-variable|s ((ft)plugins settings). Most of lh-cpp options are expected to begin with "cpp_". As a consequence, they won't actually clash with equivalent settings from other filetypes. Other plugins I'm maintaining (see |lh-refactor| for instance) support multi-filetype options, which support default values that can be overridden for specific filetypes (by appending "{ft}_" to the name of the options when setting them), or specific projects. See |lhdev-filetype| for the actual naming policy. *C++_options_local_project* These options are meant to be set by plugins oriented to the management of projects. Typical examples are |project.vim|, or one of the numerous |local_vimrc| plugin (I'm also maintaining one...). Once again one can set vim |options| or |buffer-variable|s in the buffer specific zone of its |local_vimrc|. *C++_options_local_conclusion* Default options for a specific filetype shall be defined as |buffer-variable|s (/vim local |options|) in a |ftplugin| placed in $HOME/.vim/ftplugin/cpp/ (or /c/) (or the windows equivalent location, see 'runtimepath'). Project specific settings shall override the previous default settings in |local_vimrc|s. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *C++_doxygen-options* C++ options for doxygen~ *(bg):[{ft}_]dox_CommentLeadingChar* Character used at «»?; default: "*" *(bg):[{ft}_]dox_TagLeadingChar* Character used to introduce tags: "!"/"[@]" *(bg):[{ft}_]dox_brief* Shall we have a @brief tag? -> yes/no/[short] *(bg):[{ft}_]dox_ingroup* Shall we have a @ingroup tag? -> yes/[no] *(bg):dox_group* Name of the doxygen group. *(bg):[{ft}_]dox_author_tag* Name of the tag to use: ["author"]/"authors" *(bg):[{ft}_]dox_author* Name(s) of the author(s). *(bg):[{ft_}]template_expand_doc* is a boolean option (default: 1) Tells whether embedded documentation (as comments) shall be generated when template-files are expanded. Used by: - the template-file {rtp}/template/cpp/internals/function-comment.template - the template-file {rtp}/template/cpp/internals/formatted-comment.template - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Michael Sharpe's a.vim~ File: a.vim Notes: * An old version of this plugin is required by |cpp_BuildTemplates.vim|. The latest version doesn't suit as I use its private functions... * Otherwise, it is really nice and useful with C programming - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Georgi Slavchev's previewWord.vim~ File: *previewWord.vim* Requires: |Triggers.vim| (supported) Notes: From a vim tip on sourceforge. ; Not required by anything Option: *g:previewIfHold* ([0]/1) Automatic search when the cursor hold its position ? Mappings: Looks for the declaration of the function name under the cursor. Toggles on/off the automatic search when the cursor hold its position. Defined only if |Triggers.vim| is installed. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *C_folding* *C++_folding* C & C++ folding~ Files: fold/c-fold.vim fold/cpp-fold.vim Notes: * Initially developed by Johannes Zellner * To test and use them, drop them your ftplugin folders or look at cleaner solutions like the one used by Johannes Zellner. * Need to be tuned ; there are still some imperfections I haven't fixed yet. The major one beeing that the plugin may drastiscally slow down the loading of any C or C++ file. ------------------------------------------------------------------------------ *lh-cpp-first-steps* First steps with lh-cpp-ftplugins~ The first steps with these ftplugins can be quite disorienting. I expect you did read the |lh-cpp-features| section before trying to write your first C or C++ files with the new ftplugins activated. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Step 1 : Opening a C or C++ file~ You do ~ > vim foo.h or : > vim :e foo.h < Then you see ~ -> the new buffer filled with many things. Don't worry, it is a feature set by default: a template skeleton is inserted in the new buffer. This is done thanks to |mu-template|. If you don't like this feature ~ -> you have several options : (*) you don't want template skeletons at all: then you can erase |mu-template.vim| and the {rtp}/after/templates/ folder (*) you don't want template skeletons to be inserted automatically: then add into your .vimrc: > let g:mt_IDontWantTemplatesAutomaticallyInserted = 1 < You will still have the possibility to _explicitly_ insert a template skeleton with: > :MuTemplate c " for the C skeleton :MuTemplate cpp " for the C++ skeleton :MuTemplate cpp/class " for a heavily documented classes :MuTemplate cpp/singleton " for Scott Meyers' singleton model. :MuTemplate cpp/stream-extractor " for op<< (beta, smart & slow) :MuTemplate cpp/stream-inserter " for op>> (beta, smart & slow) :MuTemplate cpp/my-cpp " for a specific C++ skeleton (*) you don't want C++ skeleton (only) be inserted automatically, [ie: you are OK for HTML and other skeletons] : Then override the file {rtp}/after/template/cpp.template Don't change anything else than the extension of the file. See |MuT-paths-override|. (*) you don't like the template skeletons I propose to you: easy ! Override them. See |MuT-paths-override|. (*) you don't want to be in insert- or select-mode and at an odd place when opening a new file: This is |mu-template|'s fault. Deactivate this feature thanks to the option: |g:mt_jump_to_first_markers|. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Step 2 : Writing code and control statements~ You write ~ > if (foo) Then you see ~ > if ((foo)«») { «» }«» This is also a feature. Except you are not supposed to type "if (foo)", but only "if foo". You should by the way notice that "if", "else", "for", ... are expanded only within normal code context: not within comments or strings contexts. Try for instance: '// if foo' or '"if foo"' If you don't like this feature ~ (*) What the hell are those '«»' characters that appear ? They are |markers|. They are supposed to help us reaching the next position in the file where we are supposed to add code. By default hit || (/||) to jump to the next (/previous) marker. (If you are using vim and not gvim, the mappings will be binded to ) If you don't want them, hit to toggle their activation state (only if |Triggers.vim| is installed), or set |[bg]:usemarks| to 0 into your .vimrc. You should also be able to simply erase the file |bracketing.base.vim| (*) You want some "\n" before the '(': Easy: tell it to |:AddStyle| * in $HOME/.vim/after/plugin/my-style.vim: > :AddStyle -ft=c -prio=10 ( \n(\n < * or in a |local_vimrc|: > :AddStyle -b -ft=c -prio=10 ( \n(\n (*) You want some "\n" between ')' and '{': Easy: tell it to |:AddStyle| * in $HOME/.vim/after/plugin/my-style.vim: > :AddStyle -ft=c -prio=10 { \n{\n < * or in a |local_vimrc|: > :AddStyle -b -ft=c -prio=10 { \n{\n (*) You don't want the control statements to be expanded: Then, don't install |c_set.vim| and |cpp_set.vim|. Instead look and take the stuff you could be interested in, like for instance some vim-|options|. If you only see~ > if (foo) Then, it is probable that you haven't configured Vim to support ftplugins. To do this, add one of the following lines into your .vimrc: > filetype plugin on filetype plugin indent on " is fine as well Check |:filetype-plugin-on| for more info. ------------------------------------------------------------------------------ *lh-cpp_API* lh-cpp API~ Here are the function made available to write your own ftplugins and template-files. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *lh#cpp#dox#* Doxygen related functions~ The following functions are parametrized, see |C++_doxygen-options|. - Purely stylistic options~ *lh#dox#comment_leading_char()* @see |(bg):[{ft}_]dox_CommentLeadingChar| *lh#dox#tag_leading_char()* @see |(bg):[{ft}_]dox_TagLeadingChar| *lh#dox#tag()* @returns |lh#dox#tag_leading_char()| + parameter - Semantics options, i.e. that return a tag and sometimes more~ *lh#dox#semantics()* @returns "

    Semantics
    " *lh#dox#ingroup()* @param name @see |(bg):[{ft}_]dox_ingroup| *lh#dox#brief()* @see |(bg):[{ft}_]dox_brief| *lh#dox#param()* @param p parameter description: text, or |Dictionary| {dir: in,out,inout; name}. @return lh#dox#tag("param") + p *lh#dox#author()* @param names (optional) @returns lh#dox#tag(|(bg):[{ft}_]dox_author_tag|) + names or |(bg):[{ft}_]dox_author| if no names specified - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *lh#cpp#ftplugin#* Convinience functions for ftplugin definitions only~ *lh#cpp#ftplugin#OptionalClass()* Function that can be used to write |:command|s in |ftplugins| that tries to deduce the name of the current C++ class if none is provided. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *lh#cpp#style* Functions dedicated to obtain information on the current style~ *lh#cpp#style#get()* @param datakind @param pos @returns lh#option#get(datakind + pos, '') *lh#cpp#style#attribute2parameter_name()* @param attrb_name Applies the chosen naming style for parameters to a attribute name. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *lh#cpp#AnalysisLib_Function#* Functions dedicated to the analysis of C/C++ functions~ *lh#cpp#AnalysisLib_Function#GetFunctionPrototype()* *lh#cpp#AnalysisLib_Function#GetListOfParams()* *lh#cpp#AnalysisLib_Function#AnalysePrototype()* *lh#cpp#AnalysisLib_Function#HaveSameSignature()* *lh#cpp#AnalysisLib_Function#BuildSignatureAsString()* *lh#cpp#AnalysisLib_Function#IsSame()* *lh#cpp#AnalysisLib_Function#LoadTags()* *lh#cpp#AnalysisLib_Function#SearchUnmatched()* *lh#cpp#AnalysisLib_Function#SearchAllDeclarations()* *lh#cpp#AnalysisLib_Function#SignatureToSearchRegex2()* *lh#cpp#AnalysisLib_Function#SignatureToSearchRegex()* *lh#cpp#AnalysisLib_Function#TrimParametersNames()* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *lh#cpp#AnalysisLib_Class#* Functions dedicated to the analysis of C/C++ classes~ *lh#cpp#AnalysisLib_Class#SearchClassDefinition()* *lh#cpp#AnalysisLib_Class#CurrentScope()* *lh#cpp#AnalysisLib_Class#BaseClasses0()* *lh#cpp#AnalysisLib_Class#GetClassTag()* *lh#cpp#AnalysisLib_Class#FetchDirectParents()* *lh#cpp#AnalysisLib_Class#Ancestors()* *lh#cpp#AnalysisLib_Class#FetchDirectChildren()* *lh#cpp#AnalysisLib_Class#used_namespaces()* *lh#cpp#AnalysisLib_Class#attributes()* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *lh#cpp#tags#* Functions analysis current situation~ *lh#cpp#tags#find_compiler()* Returns the current known C++ compiler. Works best on CMake projects when |lh-cmake| is installed. Looks into `$CXX` or returns which of `c++`, `g++` or `clang++` is found first. *lh#cpp#tags#compiler_includes()* Returns the standard (hard-coded) include directories associated to the current C++ compiler (|lh#cpp#tags#find_compiler()|). *lh#cpp#tags#get_included_paths()* Returns declared included paths: - the first between |(bpg):sources_root| (deprecated) and |(bpg):paths.sources| - the first between |(bpg):paths.includes| and |(bpg):includes| (deprecated), or optional |list| passed. *lh#cpp#tags#strip_included_paths()* Returns the first parameter (a filename) stripped of its leading dirname that belongs to the |list| of include directories (likelly obtained with |lh#cpp#tags#get_included_paths()|). *lh#cpp#tags#fetch()* Look up the symbol under the cursor in the |tag| database in header files And returns its relevant information. Tuned by the options *(bpg):[{ft}_]tag_kinds_for_inclusion* and *(bpg):[{ft}_]file_regex_for_inclusion* ------------------------------------------------------------------------------ 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. TODO:~ - c_compile.vim / BTW ------------------------------------------------------------------------------ © Luc Hermitte, 2001-2016 CC by SA 3.0 VIM: let b:VS_language = 'american' vim:ts=8:sw=4:tw=80:fo=tcq2:isk=!-~,^*,^\|,^\":ft=help: ================================================ FILE: doc/options.md ================================================ ## lh-cpp Options ### Contents * [Options types](#options-types) * [Global options: `g:`_{option-name}_](#global-options-g_option-name_) * [Local/project-wise options: `p:`_{option-name}_ or `b:`_{option-name}_](#localproject-wise-options-p_option-name_-or-b_option-name_) * [Project-wise options with default: `(bpg):`_{option-name}_](#project-wise-options-with-default-bpg_option-name_) * [[lh-dev options](https://github.com/LucHermitte/lh-dev#options-1): `(bpg):`_[{filetype}__]{option-name}_](#lh-dev-optionshttpsgithubcomluchermittelh-devoptions-1-bpg_filetype__option-name_) * [Option list](#option-list) * [`(bpg):cpp_always_a_destructor_when_there_is_a_pointer_attribute'`](#bpgcpp_always_a_destructor_when_there_is_a_pointer_attribute) * [`(bpg):cpp_std_flavour` and `$CXXFLAGS`](#bpgcpp_std_flavour-and-cxxflags) * [`(bpg):({ft}_)FunctionPosArg`, `(bpg):({ft}_)FunctionPosition`](#bpgft_functionposarg-bpgft_functionposition) * [`(bpg):({ft}_)ShowDefaultParams`, `(bpg):({ft}_)ShowExplicit`, `(bpg):({ft}_)ShowStatic`, `(bpg):({ft}_)ShowVirtual`](#bpgft_showdefaultparams-bpgft_showexplicit-bpgft_showstatic-bpgft_showvirtual) * [`(bpg):accessor_comment_get`, `(bpg):accessor_comment_set`, `(bpg):accessor_comment_ref`](#bpgaccessor_comment_get-bpgaccessor_comment_set-bpgaccessor_comment_ref) * [`(bpg):({ft}_)alternateSearchPath`](#bpgft_alternatesearchpath) * [`(bpg):cpp_begin_end_includes`](#bpgcpp_begin_end_includes) * [`(bpg):cpp_begin_end_style`](#bpgcpp_begin_end_style) * [`(bpg):c_menu_name`, `(bpg):c_menu_priority`, `(bpg):cpp_menu_name`, `(bpg):cpp_menu_priority`](#bpgc_menu_name-bpgc_menu_priority-bpgcpp_menu_name-bpgcpp_menu_priority) * [`(bpg):cpp_defaulted`](#bpgcpp_defaulted) * [`(bpg):cpp_defines_to_ignore`](#bpgcpp_defines_to_ignore) * [`(bpg):cpp_deleted`](#bpgcpp_deleted) * [`(bpg):cpp_noexcept`](#bpgcpp_noexcept) * [`(bpg):cpp_noncopyable_class`](#bpgcpp_noncopyable_class) * [`(bpg):cpp_nullptr`](#bpgcpp_nullptr) * [`(bpg):cpp_explicit_default`](#bpgcpp_explicit_default) * [`(bpg):cpp_make_ptr`](#bpgcpp_make_ptr) * [`(bpg):cpp_noexcept`](#bpgcpp_noexcept) * [`(bpg):cpp_return_ptr_type`](#bpgcpp_return_ptr_type) * [`(bpg):cpp_root_exception`](#bpgcpp_root_exception) * [`(bpg):cpp_use_copy_and_swap`](#bpgcpp_use_copy_and_swap) * [`(bpg):cpp_use_nested_namespaces`](#bpgcpp_use_nested_namespaces) * [`g:c_no_assign_in_condition`](#gc_no_assign_in_condition) * [`g:c_no_hl_fallthrough_case`](#gc_no_hl_fallthrough_case) * [`g:cpp_no_catch_by_reference`](#gcpp_no_catch_by_reference) * [`g:cpp_no_hl_c_cast`](#gcpp_no_hl_c_cast) * [`g:cpp_no_hl_funcdef`](#gcpp_no_hl_funcdef) * [`g:cpp_no_hl_throw_spec`](#gcpp_no_hl_throw_spec) * [`(bpg):({ft}_)array_size`](#bpgft_array_size) * [`(bpg):({ft}_)exception_args`](#bpgft_exception_args) * [`(bpg):({ft}_)exception_type`](#bpgft_exception_type) * [`(bpg):({ft}_)ext_4_impl_file`](#bpgft_ext_4_impl_file) * [`(bpg):({ft}_)file_regex_for_inclusion`](#bpgft_file_regex_for_inclusion) * [`(bpg):({ft}_)filename_simplify_for_inclusion`](#bpgft_filename_simplify_for_inclusion) * [`(bpg):({ft}_)gcov_files_path`](#bpgft_gcov_files_path) * [`(bpg):({ft}_)guard_headers_with`](#bpgft_guard_headers_with) * [`(bpg):({ft}_)implPlace`](#bpgft_implplace) * [`g:inlinesPlace`](#ginlinesplace) * [`(bpg):({ft}_)includes`](#bpgft_includes) * [`(bpg):({ft}_)multiple_namespaces_on_same_line`](#bpgft_multiple_namespaces_on_same_line) * [`(bpg):({ft}_)nl_before_bracket` (deprecated)](#bpgft_nl_before_bracket-deprecated) * [`(bpg):({ft}_)nl_before_curlyB` (deprecated)](#bpgft_nl_before_curlyb-deprecated) * [`(bpg):({ft}_)pre_desc_ordered_tags`, `(bpg):({ft}_post_desc_ordered_tags)`](#bpgft_pre_desc_ordered_tags-bpgft_post_desc_ordered_tags) * [`(bpg):({ft}_)project_namespace`](#bpgft_project_namespace) * [`(bpg):({ft}_)tag_kinds_for_inclusion`](#bpgft_tag_kinds_for_inclusion) * [`(bpg):tags_select`](#bpgtags_select) * [`(bpg):({ft}_)template_expand_doc`](#bpgft_template_expand_doc) * [`(bpg):xsltproc`](#bpgxsltproc) * [Doxygen related options](#doxygen-related-options) * [`(bpg):({ft}_)dox_CommentLeadingChar`](#bpgft_dox_commentleadingchar) * [`(bpg):({ft}_)dox_TagLeadingChar`](#bpgft_dox_tagleadingchar) * [`(bpg):({ft}_)dox_author_tag`](#bpgft_dox_author_tag) * [`(bpg):({ft}_)dox_author`](#bpgft_dox_author) * [`(bpg):({ft}_)dox_brief`](#bpgft_dox_brief) * [`(bpg):({ft}_)dox_group`](#bpgft_dox_group) * [`(bpg):({ft}_)dox_ingroup`](#bpgft_dox_ingroup) * [`(bpg):({ft}_)dox_sep`](#bpgft_dox_sep) * [`(bpg):({ft}_)dox_throw`](#bpgft_dox_throw) * [`(bpg):ProjectVersion`](#bpgprojectversion) ### Options types ##### Global options: `g:`_{option-name}_ They are best set from the `.vimrc`; ##### Local/project-wise options: `p:`_{option-name}_ or `b:`_{option-name}_ They are best set from a [`local_vimrc` file](https://github.com/LucHermitte/local_vimrc); See [lh-vim-lib](https://github.com/LucHermitte/lh-vim-lib/blob/master/doc/Project.md) regarding `p:options`. ##### Project-wise options with default: `(bpg):`_{option-name}_ Their default value can be set in the `.vimrc`, but its best to set them from a [`local_vimrc` file](https://github.com/LucHermitte/local_vimrc); ##### [lh-dev options](https://github.com/LucHermitte/lh-dev#options-1): `(bpg):`_[{filetype}__]{option-name}_ ### Option list #### `(bpg):cpp_always_a_destructor_when_there_is_a_pointer_attribute'` Boolean option that enforces the expansion of a destructor in classes that have pointer attributes, even when it isn't required. **Default value:** 0 (false) **See:** * [`lh#cpp#snippets#_this_param_requires_a_destructor`](APID.md#lhcppsnippets_this_param_requires_a_destructor) which is used in turn by ... * [`lh#cpp#snippets#requires_destructor`](APID.md#lhcppsnippetsrequires_destructor) which is used in turn by ... * [`cpp/internals/class-skeleton.template`](snippets.md#cppinternalsclass-skeleton.template) #### `(bpg):cpp_std_flavour` and `$CXXFLAGS` These options are exploited by [C++ flavour decoding functions](API.md#c++-flavour) The expected values for `(bpg):cpp_std_flavour` are "03", "05" (TR1), "11", "14", or "17". Other values will lead into Unspecified Behaviour. **warning:** "98" is not a valid value. If `(bpg):cpp_std_flavour` is not set, the flavour will be extracted from the `-std=` option in `$CXXFLAGS` or else from the CMake `$CMAKE_CXXFLAGS` option. Valid values are `-std=c++98`, `-std=c++03`, `-std=c++0x`, `-std=c++11`, `-std=c++1y`, `-std=c++14`, `-std=c++1z`, `-std=c++17` (the `-std=gnu++xx` ones are also handled) **Note:** The `$CMAKE_CXXFLAGS` option is obtained thanks to [lh-cmake](https://github.com/LucHermitte/lh-cmake). BTW, this plugin is not automatically installed with lh-cpp (if you are using a dependencies aware plugin manager like VAM or vim-flavor ; with dependencies unaware plugin managers, you'll will also have to install it as well) #### `(bpg):({ft}_)FunctionPosArg`, `(bpg):({ft}_)FunctionPosition` Determines where the default implementation, for a function not yet defined, should be placed by [`:GOTOIMPL`](features.md#gotoimpl). We are placed ... - 0 -> ... at `cpp_FunctionPosArg` lines from the end of the file. - 1 -> ... at the line after the first occurrence of the pattern `cpp_FunctionPosArg`. By default, we are placed after: > ```C++ /*============*/ /*===[ «» ]===*/ /*============*/ ``` That I use to insert with `:BLINES` - 2 -> ... according the hook (user-defined VimL-function) `cpp_FunctionPosArg`. By default, we are asked for a title (actually a regex pattern), and placed after: ```C++ /*=====================*/ /*===[ {the_title} ]===*/ /*=====================*/ ``` ... That I still use to insert with |:BLINES| - 3 -> ... nowhere, and nothing is inserted. The insertion must be done _manually_ thanks to [`:PASTEIMPL`](features.md#pasteimpl) . #### `(bpg):({ft}_)ShowDefaultParams`, `(bpg):({ft}_)ShowExplicit`, `(bpg):({ft}_)ShowStatic`, `(bpg):({ft}_)ShowVirtual` Boolean options used by [`:GOTOIMPL`](features.md#gotoimpl). They tells whether the C++ keywords `explicit`, `static` or `virtual` shall be kept in the empty implementation skeleton generated for a function declaration. Same thing for default parameter values. Default values to all: 1 (true) #### `(bpg):accessor_comment_get`, `(bpg):accessor_comment_set`, `(bpg):accessor_comment_ref` Strings to customize the comments inserted on `:ADDATTRIBUTE`. `"%a"` will be substituted with the name of the attribute. #### `(bpg):({ft}_)alternateSearchPath` Tells how to alternate between a source file and a header file. Default value: `'sfr:../source,sfr:../src,sfr:../include,sfr:../inc'` According to alternate.vim documentation: A path with a prefix of `"wdr:"` will be treated as relative to the working directory (i.e. the directory where vim was started.) A path prefix of `"abs:"` will be treated as absolute. No prefix or `"sfr:"` will result in the path being treated as relative to the source file (see sfPath argument). A prefix of `"reg:"` will treat the pathSpec as a regular expression substitution that is applied to the source file path. The format is: ``` reg: ``` - `` seperator character, we often use one of `[/|%#]` - `` is what you are looking for - `` is the output pattern - `` can be `g` for global replace or empty EXAMPLE: `'reg:/inc/src/g/'` will replace every instance of `'inc'` with `'src'` in the source file path. It is possible to use match variables so you could do something like: ``` 'reg:|src/\([^/]*\)|inc/\1||' ``` (see `help :substitute`, `help pattern` and `help sub-replace-special` for more details) NOTE: a.vim uses `,` (comma) internally so DON'T use it in your regular expressions or other pathSpecs unless you update the rest of the a.vim code to use some other seperator.mentation: #### `(bpg):cpp_begin_end_includes` Tells which header files shall be includes when expanding `begin()`/`end()`. This option is meant to override the include files returned by [`lh#cpp#snippets#_include_begin_end()`](API.md#lhcppsnippets_include_begin_end). **See:** `CTRL-X_be`, `CTRL-X_cbe`, `CTRL-X_rbe`, `CTRL-X_crbe`, [`cpp/b-e` snippet](snippets.md#cppb-e) #### `(bpg):cpp_begin_end_style` Tells which style to use to generate a couple of calls to `begin()`/`end()`: - "`c++98`": -> `container.begin()` - "`std`": -> `std::begin(container)` - "`boost`": -> `boost::begin(container)` - "`adl`": -> `begin(container)` **See:** `CTRL-X_be`, `CTRL-X_cbe`, `CTRL-X_rbe`, `CTRL-X_crbe`, [`cpp/b-e` snippet](snippets.md#cppb-e) #### `(bpg):c_menu_name`, `(bpg):c_menu_priority`, `(bpg):cpp_menu_name`, `(bpg):cpp_menu_priority` These options tells where the |menu| for all C and C++ item goes. See `:h :menu` #### `(bpg):cpp_defaulted` String option. **Default Value:** `= default` **See:** API function [`lh#cpp#snippets#defaulted()`](API.md#lhcppsnippetsdefaulted) #### `(bpg):cpp_defines_to_ignore` Regex (default: none) that specifies which patterns (`#define`) shall be ignored when parsing the source code to detect the current scope (`ns1::..::nsn::cl1::.....cln`). **See:** API functions - [`lh#cpp#AnalysisLib_Class#SearchClassDefinition()`](API.md#lh-cpp-analysislib_class-searchclassdefinition) - [`lh#cpp#AnalysisLib_Class#CurrentScope()`](API.md#lh-cpp-analysislib_class-currentscope) #### `(bpg):cpp_deleted` String option. **Default Value:** `= delete` **See:** API function [`lh#cpp#snippets#deleted()`](API.md#lhcppsnippetsdeleted) #### `(bpg):cpp_noexcept` String format option (for [`lh#fmt#printf()`](https://github.com/LucHermitte/lh-vim-lib)) **Default Value:** `noexcept%1` in C++11, `throw()` in C++98 **See:** * [`lh#fmt#printf()`](https://github.com/LucHermitte/lh-vim-lib)) * API function [`lh#cpp#snippets#nullptr()`](API.md#lhcppsnippetsnoexcept) #### `(bpg):cpp_noncopyable_class` Policy option that is used to tell how classes are made non-copyable. * by inheriting from a dedicated noncopyable class. ``` {"name": "ITK::NonCopyable", "include": ""} ``` If the class is known by the [type database](types.md) , there is no need to explicit which file shall be included: ``` {"name": "boost:noncopyable"} ``` * by explictly deleting copy operations (with `= delete` in C++11, or with declared but undefined private copy operations). This done by setting the option to an empty string. **Default value:** `{"name": "boost:noncopyable"}` **See:** * [Type database](types.md) * [`cpp/base-class.template`](snippets.md#cppbaseclass.template) * [`cpp/internals/class-skeleton.template`](snippets.md#cppinternalsclass-skeleton.template) #### `(bpg):cpp_nullptr` Returned by `lh#cpp#snippets#nullptr()`. **Default Value:** `nullptr` in C++11, `0` in C++98/03. **Other Typical values:** `NULL`, `ITK_NULLPTR_, etc. **See:** API function [`lh#cpp#snippets#nullptr()`](API.md#lhcppsnippetsnullptr) #### `(bpg):cpp_explicit_default` Boolean option that forces to explicitly add `= default` in snippets when C++11 is detected. **Warning:** For now, this option has priority over [`(bpg):cpp_noncopyable_class`](#bpgcpp_noncopyable_class). i.e. deleted copy operations will still appear even if the class inherits from a _non-copyable_ class. **Default value:** undefined (=> ask the user) **See:** * [`lh#cpp#snippets#shall_explicit_defaults()`](API.md#lhcppsnippetsshall_explicit_defaults) which encapsulates its use. * [`cpp/internals/class-skeleton.template`](snippets.md#cppinternalsclass-skeleton.template) which uses its result #### `(bpg):cpp_make_ptr` String format option for [`lh#fmt#printf()`](https://github.com/LucHermitte/lh-vim-lib)). It tells how pointers are best created. Used only from [cpp/clonable-clas.template](snippets.md#cppclonable-clas.template) snippet. **Default Value**: * C++14: `std::make_unique(%3)` * C++11: `std::unique_ptr<%2>(new %2(%3))` * C++98: `std::auto_ptr<%1>(new %2(%3))` **See:** * [cpp/clonable-clas.template](snippets.md#cppclonable-clas.template) which uses it * [`(bpg):cpp_return_ptr_type`](#bpgcpp_return_ptr_type) #### `(bpg):cpp_noexcept` String format option (for [`lh#fmt#printf()`](https://github.com/LucHermitte/lh-vim-lib)) **Default Value:** `override` in C++11, `/* override */` in C++98 **See:** * [`lh#fmt#printf()`](https://github.com/LucHermitte/lh-vim-lib)) #### `(bpg):cpp_return_ptr_type` String format option for `printf()` (TODO: migrate to [`lh#fmt#printf()`](https://github.com/LucHermitte/lh-vim-lib))). It tells how pointers are best returned from functions. Used only from [cpp/clonable-clas.template](snippets.md#cppclonable-clas.template) snippet. **Default Value**: * C++11: `std::unique_ptr<>` * C++98: `std::auto_ptr<>` **See:** * [cpp/clonable-clas.template](snippets.md#cppclonable-clas.template) which uses it * [`(bpg):cpp_make_ptr`](#bpgcpp_make_ptr) #### `(bpg):cpp_root_exception` TDB #### `(bpg):cpp_use_copy_and_swap` Boolean option that suggest to use copy-and-swap idiom when expanding assignment-operator snippet directly, or indirectly through value classes snippets. **Default value:** 0 (false) **See:** * [`cpp/assignment-operator.template`](snippets.md#cppassignment-operator.template) which uses it directly * [`cpp/internals/class-skeleton.template`](snippets.md#cppinternalsclass-skeleton.template) which uses it indirectly #### `(bpg):cpp_use_nested_namespaces` Boolean option that enables the generation of _nested_ namespaces in C++17 codes with [`namespace` snippet](snippets.md#cppnamespace). __Default value:__ is 1 (true). #### `g:c_no_assign_in_condition` Boolean option that disables syntax highlighting that detects assignments in conditions. __Default value:__ is 0 (false). #### `g:c_no_hl_fallthrough_case` Boolean option that disables syntax highlighting that detects uses of `case` that fall through other `case`s. This feature isn't detecting correctly situation like: `break; } case`, that why it's disabled for the moment. __Default value:__ is 1 (true). #### `g:cpp_no_catch_by_reference` Boolean option that disables syntax highlighting that detects exceptions caught by value. __Default value:__ is 0 (false). #### `g:cpp_no_hl_c_cast` Boolean option that disables syntax highlighting that detects C casts in C++. __Default value:__ is 0 (false). #### `g:cpp_no_hl_funcdef` Boolean option that disables syntax highlighting that hightlight function definitions. __Default value:__ is 0 (false). #### `g:cpp_no_hl_throw_spec` Boolean option that disables syntax highlighting that detects throw specifications in C++. __Default value:__ is 0 (false). #### `(bpg):({ft}_)array_size` Tells how ` [cpp/array_size`](snippets.md#cpparray_size) snippet shall behave. This variable is meant to be a dictionary than contains the following entries: - `"file"`: Filename to be included. - `"funcname"`: Text to be included when the snippet is expanded. The special `"%1"` placeholder will be replaced with the array name. __Default value:__ not defined **See:** - [`cpp/array_size` snippet](snippets.md#cpparray_size) #### `(bpg):({ft}_)exception_args` Arguments to inject in the exception called in [`throw` snippet](snippets.md#cppthrow). #### `(bpg):({ft}_)exception_type` Exception type to use in snippets like the [`throw` snippet](snippets.md#cppthrow). __Default__ is `std::runtime_error` #### `(bpg):({ft}_)ext_4_impl_file` Tells the extension to use when [`:GOTOIMPL`](features.md#gotoimpl) generates a new implementation skeleton for a function. __Default__ is ".cpp". #### `(bpg):({ft}_)file_regex_for_inclusion` Regex used by API function [`lh#cpp#tags#fetch()`](API.md#lh-cpp-tags-fetch) to filter filenames to keep. __Default value:__ "`\.h`" #### `(bpg):({ft}_)filename_simplify_for_inclusion` Tells API function [`lh#cpp#tags#strip_included_paths()`](API.md#lh-cpp-tags-strip_included_paths) how to simplify filenames with |`fnamemodify()`|. __Default value:__ "`:t`" #### `(bpg):({ft}_)gcov_files_path` This option tells where gcov files are expected. The default value is the same path as the one where the current file is. **See:** `g` which permits to swap between a `.gcov` file and its source. #### `(bpg):({ft}_)guard_headers_with` This option tells how multiple inclusions of header files is prevented. This can be done with (portable) `#ifndef SOME_GUARD` + `#define SOME_GUARD`, or with `#pragma once` (non-standard) directive. Valid values for this option are: `ifndef`, `ifndef,pragma`, or `pragma` **Note:** This option is actually used by the default template-file from mu-template. #### `(bpg):({ft}_)implPlace` Tells where a generated accessor shall go (with `:ADDATTRIBUTE`): - 0 -> Near the prototype/definition (Java's way) - 1 -> Within the inline section of the header/inline/current file - 2 -> Within the implementation file (.cpp) - 3 -> Use the pimpl idiom (In the Todo-List) #### `g:inlinesPlace` Where inlines are written on `:ADDATTRIBUTE` - 0 -> In the inline section of the header/current file - 1 -> In the inline section of a dedicated inline file #### `(bpg):({ft}_)includes` Option used by the C-ftplugin that completes the names of files to include. The options tells which directories shall be searched. __Default value:__ is vim option `&path` **See:** `` (`i_CTRL-X_I`) and `OpenIncludes` (`n_CTRL_L`) #### `(bpg):({ft}_)multiple_namespaces_on_same_line` Boolean option wrapped into API function [`lh#cpp#option#multiple_namespaces_on_same_line()`](API.md#lh-cpp-option-multiple-namespaces-on-same-line). __Default value:__ 1 (true) Permits snippets like [`namespace`](snippets.md#cppnamespace) to write all names on a same line (when _nested namespaces_ aren't supported). i.e: ```C++ // If true namespace ns1 { namespace ns2 { } } // namespaces ns1::ns2 // If false namespace ns1 { namespace ns2 { } // namespace ns1::ns2 } // namespace ns1 ``` #### `(bpg):({ft}_)nl_before_bracket` (deprecated) #### `(bpg):({ft}_)nl_before_curlyB` (deprecated) #### `(bpg):({ft}_)pre_desc_ordered_tags`, `(bpg):({ft}_post_desc_ordered_tags)` In [`function-comment` snippet](snippets.md#cppinternalsinternalsfunction-comment), these |List| options tell in which order the various documentation information are inserted around the description the user will have to type: The default before the user typed information is: - "_ingroup_", "_brief_", "_tparam_", "_param_", "_return_", "_throw_", "_invariant_", "_pre_", "_post_" The default after the user typed information is: - "_note_", "_warning_" #### `(bpg):({ft}_)project_namespace` Name of the project namespace used by the snippet [`namespace`](snippets.md#cppnamespace). __Default value:__ the placeholder `«ns»` This is also what is returned by API function [`lh#cpp#snippets#current_namespace()`](API.md#lh-cpp-snippets#current_namespace) -- in that case, the default value used is an empty string. #### `(bpg):({ft}_)tag_kinds_for_inclusion` Regex used by API function [`lh#cpp#tags#fetch()`](API.md#lh-cpp-tags-fetch) to filter tags kind to keep. __Default value:__ "`[dfptcs]`" #### `(bpg):tags_select` Tags selection policy used by API function [`lh#cpp#tags#fetch()`](API.md#lh-cpp-tags-fetch). __Default value:__ "`expand('')`". #### `(bpg):({ft}_)template_expand_doc` Boolean option used in snippets to tell whether documentation generation is required. **See:** - [`formatted-comment` snippet](snippets.md#cppinternalsformatted-comment) - [`function-comment` snippet](snippets.md#cppinternalsfunction-comment) #### `(bpg):xsltproc` Path to where the executable `xsltproc` is. __Default Value:__ `xsltproc`. This options is used by the C-ftplugin that converts PVS-studio output into a format compatible with quickfix. **See:** `:PVSLoad`, `:PVSIgnore`, `:PVSShow` and `:PVSRedraw` #### Doxygen related options ##### `(bpg):({ft}_)dox_CommentLeadingChar` Tells which character to use on each line of a Doxygen comment. __Default value:__ `"*"` Wrapped in API function [`lh#dox#comment_leading_char()`](API.md#lh-dox-comment_leading_char) ##### `(bpg):({ft}_)dox_TagLeadingChar` Tells which character to use on each line of a Doxygen comment. __Default value:__ `"*"`. Other typical value: `"!"` Wrapped in API function [`lh#dox#tag_leading_char()`](API.md#lh-dox-tag_leading_char) ##### `(bpg):({ft}_)dox_author_tag` Tells which tag to use to introduce authors. __Default value:__ `"author"`. Wrapped in API function [`lh#dox#author()`](API.md#lh-dox-author) ##### `(bpg):({ft}_)dox_author` Returns the default value to use as the author tagged in Doxygen comments. __Default value:__ None Wrapped in API function [`lh#dox#author()`](API.md#lh-dox-author) ##### `(bpg):({ft}_)dox_brief` Tells if `brief` tag shall be used. __Default value:__ `"short"`. __Other possible values:__ `"yes"/"always"/"1"`, `"no"/"never"/"0"/"short"` Wrapped in API function [`lh#dox#brief()`](API.md#lh-dox-brief) ##### `(bpg):({ft}_)dox_group` Default Doxygen group name used in snippets and templates. __Default value:__ the placeholder `«Project»` **See:** - [`dox/ingroup` snippet](snippets.md#doxingroup) - [`dox/file` snippet](snippets.md#doxfile) - [`cpp/class` snippet](snippets.md#cppclass) - [`cpp/singleton` snippet](snippets.md#cppsingleton) - [`cpp/enum2` snippet](snippets.md#cppenum2) ##### `(bpg):({ft}_)dox_ingroup` Tells if `ingroup` tag shall be used. __Default value:__ `"0"`. __Other possible values:__ `"yes"/"always"/"1"`, `"no"/"never"/"0"`, or a group name to use. Wrapped in API function [`lh#dox#ingroup()`](API.md#lh-dox-ingroup) ##### `(bpg):({ft}_)dox_sep` Tells which character use between a tag and its value. __Default value:__ `" "`. Other typical value: `"\t"` Wrapped in API function [`lh#dox#tag()`](API.md#lh-dox-tag) ##### `(bpg):({ft}_)dox_throw` Tells which tag name to use to document exceptions. __Default value:__ `"throw"`. Other typical value: `"exception"` Wrapped in API function [`lh#dox#throw()`](API.md#lh-dox-throw) ##### `(bpg):ProjectVersion` Version of the project. Can be used in Doxygen comment through API function [`lh#dox#since()`](API.md#lh-dox-since). ### TODO: Options to be documented ##### `(bpg):({ft}_)place_const_after_type` Used in `lh#dev#cpp#types#const_correct_type()` Default: true ================================================ FILE: doc/snippets.md ================================================ # lh-cpp Snippets, templates and wizards ## Contents * [Remarks](#remarks) * [Control Statements](#control-statements) * [cpp/catch](#cppcatch) * [cpp/for-enum](#cppfor-enum) * [cpp/for-iterator](#cppfor-iterator) * [cpp/for-range](#cppfor-range) * [cpp/fori](#cppfori) * [cpp/foriN](#cppforin) * [cpp/namespace](#cppnamespace) * [cpp/throw](#cppthrow) * [cpp/try](#cpptry) * [cpp/while-getline](#cppwhile-getline) * [Standard (and boost) Types](#standard-and-boost-types) * [cpp/auto_ptr](#cppauto_ptr) * [cpp/auto_ptr-instance](#cppauto_ptr-instance) * [cpp/file](#cppfile) * [cpp/list](#cpplist) * [cpp/map](#cppmap) * [cpp/noncopyable](#cppnoncopyable) * [cpp/path](#cpppath) * [cpp/ptr_vector](#cppptr_vector) * [cpp/set](#cppset) * [cpp/shared_ptr](#cppshared_ptr) * [cpp/string](#cppstring) * [cpp/unique_ptr](#cppunique_ptr) * [cpp/unordered_map](#cppunordered_map) * [cpp/unordered_set](#cppunordered_set) * [cpp/vector](#cppvector) * [cpp/weak_ptr](#cppweak_ptr) * [Standard (and boost) Functions and Idioms](#standard-and-boost-functions-and-idioms) * [c/assert](#cassert) * [c/rand_init](#crand_init) * [c/realloc](#crealloc) * [cpp/array_size](#cpparray_size) * [cpp/internals/get-b-e](#cppinternalsget-b-e) * [cpp/b-e](#cppb-e) * [cpp/cerr](#cppcerr) * [cpp/cin](#cppcin) * [cpp/copy](#cppcopy) * [cpp/copy-back_inserter](#cppcopy-back_inserter) * [cpp/cout](#cppcout) * [cpp/ends_with](#cppends_with) * [cpp/erase-remove](#cpperase-remove) * [cpp/forward](#cppforward) * [cpp/iss](#cppiss) * [cpp/oss](#cpposs) * [cpp/sort](#cppsort) * [cpp/starts_with](#cppstarts_with) * [cpp/static_assert](#cppstatic_assert) * [cpp/typeid](#cpptypeid) * [Classes](#classes) * [Class Elements](#class-elements) * [cpp/assignment-operator](#cppassignment-operator) * [cpp/bool-operator](#cppbool-operator) * [cpp/copy-and-swap](#cppcopy-and-swap) * [cpp/copy-constructor](#cppcopy-constructor) * [cpp/default-constructor](#cppdefault-constructor) * [cpp/destructor](#cppdestructor) * [cpp/operator-binary](#cppoperator-binary) * [cpp/stream-extractor](#cppstream-extractor) * [cpp/stream-inserter](#cppstream-inserter) * [Class Patterns](#class-patterns) * [cpp/abs-rel](#cppabs-rel) * [cpp/abstract-class](#cppabstract-class) * [cpp/base-class](#cppbase-class) * [cpp/base-class-non-virtual](#cppbase-class-non-virtual) * [cpp/class](#cppclass) * [cpp/empty-exception-class](#cppempty-exception-class) * [cpp/enum](#cppenum) * [cpp/enum2](#cppenum2) * [cpp/enum2-impl](#cppenum2-impl) * [cpp/exception-class](#cppexception-class) * [cpp/singleton](#cppsingleton) * [cpp/traits](#cpptraits) * [Doxygen](#doxygen) * [dox/author](#doxauthor) * [dox/code](#doxcode) * [dox/em](#doxem) * [dox/file](#doxfile) * [dox/function](#doxfunction) * [dox/group](#doxgroup) * [dox/html](#doxhtml) * [dox/ingroup](#doxingroup) * [dox/since](#doxsince) * [dox/tt](#doxtt) * [Miscellaneous](#miscellaneous) * [c/comment](#ccomment) * [cpp/benchmark](#cppbenchmark) * [cpp/otb-sug-latex](#cppotb-sug-latex) * [cpp/otb-sug-snippet](#cppotb-sug-snippet) * [cpp/utf8](#cpputf8) * [Internal templates](#internal-templates) * [cpp/internals/abs-rel-shared](#cppinternalsabs-rel-shared) * [cpp/internals/class-skeleton](#cppinternalsclass-skeleton) * [cpp/internals/formatted-comment](#cppinternalsformatted-comment) * [cpp/internals/function-comment](#cppinternalsfunction-comment) * [cpp/internals/stream-common](#cppinternalsstream-common) * [cpp/internals/stream-implementation](#cppinternalsstream-implementation) * [cpp/internals/stream-signature](#cppinternalsstream-signature) ## Remarks * Styling options from [lh-style](https://lh-style.readthedocs.io/en/latest/code-formatting.html) are applied on the snippets. In other words, the code presented here may be formatted differently regarding spaces and newlines. * [Placeholders](http://github.com/LucHermitte/lh-brackets) are represented within «French quotation marks». * Default snippets from [mu-template](http://github.com/LucHermitte/mu-template) aren't documented yet. * About variation points ... TBD * About so called snippet _parameter_ ... TBD * About surrounding numbers ... TBD ## Control Statements #### cpp/catch **Produces:** ```C++ catch(«...») { «catch-code» } ``` **Surround:** 1. The selection can be surrounded to become the catch-code #### cpp/for-enum **Produces:** ```C++ for («Enum»::type «exception_type»(«exception_args»)=«Enum»::type() ; «exception_type»(«exception_args»)!=«Enum»::MAX__ ; ++«exception_type»(«exception_args»)) { «code» } ``` **Surround:** 1. The selection can be surrounded to become the loop code **Note:** * This snippet is meant to be used with [cpp/enum](#cppenum) snippets #### cpp/for-iterator **Produces:** ```C++ for («clsname»::«const_»iterator «b»=«cont»begin(), «exception_type»(«exception_args»)=«cont».end() ; «b»!=«exception_type»(«exception_args») ; ++«b») { «code» } ``` **Surround:** 1. The selection can be surrounded to become the loop code **Notes:** * Container name («cont»), and iterators names («b» and «exception_type»(«exception_args»)) are asked to the end user #### cpp/for-range **Produces:** ```C++ for («type» «elem» : «range») { «code» } ``` **Parameters:** * _type_, default: `auto&&` * _elem_, default: `e` * _range_, default: `«range»` **Surround:** 1. The selection can be surrounded to become the loop code #### cpp/fori **Produces:** ```C++ for («int» «i»=0;«i»!=«N»;++«i») { «code» } ``` **Surround:** 1. The selection can be surrounded to become the loop code #### cpp/foriN **Produces:** ```C++ for («std::size_t» «i»=0, «N»=...;«i»!=«N»;++«i») { «code» } ``` **Surround:** 1. The selection can be surrounded to become the loop code #### cpp/namespace **Produces:** `namespace «ns» { ... } // «ns»` **Parameters:** * _ns_, default: `(bpg):[{ft}_]project_namespace` **Options:** * [`(bpg):[{ft}_]project_namespace`](options.md#bpgft_project_namespace), which defaults to `«ns»` * [`lh#cpp#use_cpp17()`](options.md#bpgcpp_std_flavour) * [`(bpg):cpp_use_nested_namespaces`](options.md#bpgcpp_use_nested_namespaces) **Surround:** 1. The selection can be surrounded to become the namespace code **Notes:** * If the namespace parameter is `foo::bar`, this snippet produces two nested namespace definitions. * If C++17 flavour is selected, and `(bpg):cpp_use_nested_namespaces` is true, then a C++17 _nested namespace_ will be used. #### cpp/throw **Produces:** * `throw «exception_type»(«exception_args»);«»` (within code context) * or `@throw «exception_type»«»` (within Doxygen comments) **Parameters:** * `exception_text`, default: cpp/internals/formatted-comm **Options:** * `(bpg):({ft}_)exception_type`, default: `std:runtime_error` * `(bpg):({ft}_)exception_args`, default: `v:1_`, functor that gets `exception_txt` injected as parameter. A typical value would be: ```vim :let b:exception_args = 'v:1_.lh#marker#txt(", ".b:cpp_project_namespace."::ExitCode::")' ``` Note that this expression dynamically adapts to the current `b:cpp_project_namespace`, and to the current marker characters. * Doxygen related options: * [`(bpg):({ft_}dox_TagLeadingChar)`](options.mg#bpgft_dox_tagleadingchar) * [`(bpg):({ft_}dox_throw)`](options.mg#bpgft_dox_throw) **Relies on:** * [`lh#dox#tag()`](API.md#lhdoxtag) * [`lh#dox#throw()`](API.md#lhdoxthrow) **Also includes:** * `` if `exception_type` starts with `std::` #### cpp/try **Produces:** ```C++ try { «code» } catch(«std::exception const& e») { «catch-code» } ``` **Surround:** 1. The selection can be surrounded to become the try-code 2. The selection can be surrounded to become the catch-code #### cpp/while-getline **Produces:** ```C++ while(std::getline(«stream»,«line»)) { «code»; } ``` **Surround:** 1. The selection can be surrounded to become the loop code **Also includes:** * `` ## Standard (and boost) Types #### cpp/auto_ptr **Produces:** `std::auto_ptr<«type»>` **Surround:** 1. The selection can be surrounded to become the value type **Also includes:** * `` #### cpp/auto_ptr-instance **Produces:** `std::auto_ptr<«type»> ptr(new «type»(args));` **Surround:** 1. The selection can be surrounded to become the value type **Also includes:** * `` **Notes:** * I hesitate to call it `cpp/make_auto_ptr` #### cpp/file **Produces:** `«i»fstream f(«filename»);` **Surround:** 1. The selection can be surrounded to become the filename **Also includes:** * `` #### cpp/list **Produces:** `std::list<«type»> «»` **Surround:** 1. The selection can be surrounded to become the value type **Also includes:** * `` #### cpp/map **Produces:** `std::map<«key»,«value»> «»` **Surround:** 1. The selection can be surrounded to become the value type 2. The selection can be surrounded to become the key type **Also includes:** * `` #### cpp/noncopyable **Produces:** `boost::noncopyable` **Also includes:** * `` #### cpp/path **Produces:** `boost::filesystem::path` **Also includes:** * `` #### cpp/ptr_vector **Produces:** `boost::ptr_vector<«type»> «»` **Surround:** 1. The selection can be surrounded to become the value type **Also includes:** * `` #### cpp/set **Produces:** `std::set<«type»> «»` **Surround:** 1. The selection can be surrounded to become the value type **Also includes:** * `` #### cpp/shared_ptr **Produces:** * `std::shared_ptr<«type»> «»`, in [C++11 or more](options.md#bpgcpp_std_flavour) * `boost::shared_ptr<«type»> «»`, otherwise **Options:** * [`lh#cpp#use_cpp11()`](options.md#bpgcpp_std_flavour) **Surround:** 1. The selection can be surrounded to become the value type **Also includes:** * `` in C++11 * `` otherwise #### cpp/string **Produces:** `std::string «»` **Also includes:** * `` #### cpp/unique_ptr **Produces:** `std::unique_ptr<«type»>` **Surround:** 1. The selection can be surrounded to become the value type **Also includes:** * `` #### cpp/unordered_map **Produces:** `std::unordered_map<«key»,«value»> «»` **Surround:** 1. The selection can be surrounded to become the value type 2. The selection can be surrounded to become the key type **Also includes:** * `` #### cpp/unordered_set **Produces:** `std::unordered_set<«key»,«value»> «»` **Surround:** 1. The selection can be surrounded to become the value type 2. The selection can be surrounded to become the key type **Also includes:** * `` #### cpp/vector **Produces:** `std::vector<«type»> «»` **Surround:** 1. The selection can be surrounded to become the value type **Also includes:** * `` #### cpp/weak_ptr **Produces:** * `std::weak_ptr<«type»> «»`, in [C++11 or more](options.md#bpgcpp_std_flavour) * `boost::weak_ptr<«type»> «»`, otherwise **Options:** * [`lh#cpp#use_cpp11()`](options.md#bpgcpp_std_flavour) **Surround:** 1. The selection can be surrounded to become the value type **Also includes:** * `` in C++11 * `` otherwise ## Standard (and boost) Functions and Idioms #### c/assert **Produces:** `assert(«assertion»)` **Surround:** 1. The selection can be surrounded to become the «assertion» **Also includes:** * `` in C, `` in C++ #### c/rand_init **Produces:** `srand(time(NULL));` **Also includes:** * `` in C, `` in C++ * `` in C, `` in C++ **TODO:** * Adapt the snippet to C++11 new random functions #### c/realloc **Produces:** ```C++ type lhs = (type) realloc(ptr, size); macro if (! lhs) { macro free(ptr); macro ptr = NULL; macro count = 0; macro «error_message»; macro return false macro } macro ptr = lhs; ``` **Parameters:** * A dictionary that contains: * `"ptr"`, default `«p»` * `"lhs"`, default `new ` + _ptr_ * `"type"`, default `«clsname»` * `"count"`, default `«count»` * `"size"`, default _count_ `* sizeof(`_type_`)` * `"realloc"`, default `realloc` * `"free"`, default `free` * `"false"`, default `false` * `"macro"`, default: an empty string, expected value: `\\` #### cpp/array_size **Produces:** ```C++ // C++98/03 array_size(«array») // C++11 std::extent::value` // C++17 std::size(«array») ``` Or whatever is specified into [`(bpg):({ft}_)array_size`](options.md#bpgcpp_array_size). Up to C++14, it's recommended to follow the instructions generated as comments, and to put an equivalent of C++17 `std::size()` in a header file and use it. Let's say the function is named `myarray_size()` and put into `myrange.h`, then define into your project configuration file (e.g. a [`_vimrc_local.vim`](https://github.com/LucHermitte/local_vimrc)): ```vim let b:cpp_array_size = {'file': 'myrange.h', 'funcname': 'myarray_size(%1)'} ``` **Parameters:** * _array_, default «array» **Options:** * [`lh#cpp#use_cpp11()` and `lh#cpp#use_cpp17()`](options.md#bpgcpp_std_flavour) * [`(bpg):({ft}_)array_size`](options.md#bpgcpp_array_size) **Surround:** 1. The selection can be surrounded to become the array name **Also includes:** * `` in C++11 and C++14 * `` from C++17 onward **Notes:** * In C++98/03, the definition of `array_size()` macro is provided along the way **TODO:** * Define the unsafe C equivalent `c/array_size`: `sizeof «array»/sizeof «array»[0]` * In C++17, detect whether there is a `using std::size` in the context to rely on ADL and/or [`(bpg):cpp_begin_end_style`](options.md#bpgft_begin_end_style) equals "adl ;" #### cpp/internals/get-b-e **Assign values to mu-template snippet variables:** * `s:begin` * `s:end` * `s:container` Their values will be: * either `std::begin(«container»)` and `std::end(«container»)` if [C++11 flavour](options.md#bpgcpp_std_flavour) is used, or if [`(bpg):cpp_begin_end_style`](options.md#bpgft_begin_end_style) equals "std ;" * or `boost::begin(«container»)` and `boost::end(«container»)` if [`(bpg):cpp_begin_end_style`](options.md#bpgft_begin_end_style) equals "boost ;" * or `begin(«container»)` and `end(«container»)` if [`(bpg):cpp_begin_end_style`](options.md#bpgft_begin_end_style) equals "adl ;" * or `«container».begin()` and `«container».end()` otherwise. **Also includes:** * `` when [`(bpg):cpp_begin_end_style`](options.md#bpgcpp_begin_end_style) is `"std"` * `` and `` when [`(bpg):cpp_begin_end_style`](options.md#bpgcpp_begin_end_style) is `"boost"` * or whatever [`(bpg):cpp_begin_end_includes`](options.md#bpgcpp_begin_end_includes) specifies **Parameters:** * _container_, default: «container» **Surround:** 1. The selection can be surrounded to become the container name **Options:** * [C++11 flavour](options.md#bpgcpp_std_flavour) * [`(bpg):cpp_begin_end_style`](options.md#bpgcpp_begin_end_style) * [`(bpg):cpp_begin_end_includes`](options.md#bpgcpp_begin_end_includes) #### cpp/b-e **Produces:** * either `std::begin(«container»), std::end(«container»)` if [C++11 flavour](options.md#bpgcpp_std_flavour) is used, or if [`(bpg):cpp_begin_end_style`](options.md#bpgft_begin_end_style) equals "std" ; * or `boost::begin(«container»), boost::end(«container»)` if [`(bpg):cpp_begin_end_style`](options.md#bpgft_begin_end_style) equals "boost" ; * or `«container».begin(), «container».end()` if [`(bpg):cpp_begin_end_style`](options.md#bpgft_begin_end_style) equals "adl" ; * or `begin(«container»), end(«container»)` otherwise. **Also includes:** * `` when [`(bpg):cpp_begin_end_style`](options.md#bpgcpp_begin_end_style) is `"std"` * `` and `` when [`(bpg):cpp_begin_end_style`](options.md#bpgcpp_begin_end_style) is `"boost"` * or whatever [`(bpg):cpp_begin_end_includes`](options.md#bpgcpp_begin_end_includes) specifies **Parameters:** * _container_, default: «container» **Surround:** 1. The selection can be surrounded to become the container name **Options:** * [C++11 flavour](options.md#bpgcpp_std_flavour) * [`(bpg):cpp_begin_end_style`](options.md#bpgcpp_begin_end_style) * [`(bpg):cpp_begin_end_includes`](options.md#bpgcpp_begin_end_includes) **Variation Points:** * [`cpp/internals/get-b-e`](#cppinternalsget-b-e) snippet #### cpp/cerr **Produces:** `std::cerr <<` **Also includes:** * `` #### cpp/cin **Produces:** `std::cin >>` **Also includes:** * `` #### cpp/copy **Produces:** `std::copy(first, last, dest)` **Parameters:** * _container_, default: «container» **Surround:** 1. The selection can be surrounded to become the container name **Also includes:** * `` **TODO:** * Use `cpp/b-e` snippet #### cpp/copy-back_inserter **Produces:** `std::copy(«origin».begin(), «origin».end(), std::back_inserter(«dest»));` **Parameters:** * _origin_, default: «origin» * _dest_, default: «destination» **Surround:** 1. The selection can be surrounded to become the container name 2. The selection can be surrounded to become the destination name **Also includes:** * `` * `` **TODO:** * Use `cpp/b-e` snippet #### cpp/cout **Produces:** `std::cout <<` **Also includes:** * `` #### cpp/ends_with **Produces:** `boost::algorithm::ends_with(«input», «prefix_searched»)` **Also includes:** * `` #### cpp/erase-remove **Produces:** `erase-remove idiom` **Parameters:** * _container_, default: «container» **Surround:** 1. The selection can be surrounded to become the container name **Also includes:** * `` **TODO:** * Use `cpp/b-e` snippet #### cpp/forward **Produces:** `forward<«type»>(«var»)` **Parameters:** * _type_, default: «type» * _var_, default: «var» **Surround:** 1. The selection can be surrounded to become the variable 2. The selection can be surrounded to become the type #### cpp/iss **Produces:** ```C++ std::istringstream iss(str); if (iss >> «») { ... } ``` **Also includes:** * `` #### cpp/oss **Produces:** ```C++ std::ostringstream oss(str); oss << «»; ``` **Also includes:** * `` #### cpp/sort **Produces:** `std::sort(range.begin(), range.end());` **Parameters:** * _range_, default: «range» **Surround:** 1. The selection can be surrounded to become the range name **Also includes:** * `` **TODO:** * Use `cpp/b-e` snippet #### cpp/starts_with **Produces:** `boost::algorithm::starts_with(«input», «prefix_searched»)` **Also includes:** * `` #### cpp/static_assert **Produces:** ```C++ // C++11 static_assert(«cond», «msg») // C++98/03 BOOST_STATIC_ASSERT(«cond») ``` **Parameters:** * _condition_, default: «condition» * _message_, default: «message» **Options:** * [C++11 flavour](options.md#bpgcpp_std_flavour) **Also includes:** * ``, in C++98/03 #### cpp/typeid **Produces:** `typeid(«type»).name()` **Parameters:** * _type_, default: «type» **Surround:** 1. The selection can be surrounded to become the type **Also includes:** * `` ## Classes ### Class Elements #### cpp/assignment-operator **Produces:** `«clsname»& operator=(«clsname» const&);` **Parameters:** 1. `"clsname"`, the class name, default: automatically deduced by [`lh#cpp#AnalysisLib_Class#CurrentScope`](API.md#lhcppanalysislib_classcurrentscope), «clsname» otherwise 2. `"use_copy_and_swap"`: boolean, default: asked to the end-user * `"copy-constructor"`: (dictionary) * "visibility": *"public"*/"protected"/"private" * "how": *""*/"deleted"/"defaulted" **Options:** * [lh-style naming conventions](https://lh-style.readthedocs.io/en/latest/naming.html) * [`(bpg):cpp_use_copy_and_swap`](#bpgcpp_use_copy_and_swap) **Variation Points:** * [`cpp/copy-and-swap`](#cppcopy-and-swap) snippet, if the idiom is used * [`cpp/internals/function-comment`](#cppinternalsfunction-comment) snippet **Relies on:** * [`cpp/copy-and-swap`](#cppcopy-and-swap) * [`cpp/internals/get-class-name`](#cppinternalsget-class-name) * [`cpp/internals/function-comment`](#cppinternalsfunction-comment) **TODO:** * Detect C++11 to insert `noexcept` (through a variation point (snippet/option) as some frameworks have their own macro/keyword for `noexcept`) #### cpp/bool-operator **Produces:** A safe `bool operator` compatible with C++98/03 **Notes:** * The code produced follows the pattern presented by Matthew Wilson in _Imperfect C++_, Addisson-Welsey, §24.6 **See:** * The [snippet code](../after/template/cpp/bool-operator.template) **TODO:** * Detect C++11 to produce an `explicit bool operator()` instead. #### cpp/copy-and-swap **Produces:** `assignment operator + swap` ```C++ // + comments generated with cpp/function-comment T& operator=(R rhs) { this->swap(rhs); return * this; } // + comments generated with cpp/function-comment void swap(T & other); ``` **Parameters:** 1. `"clsname"`, the class name, default: automatically deduced by [`lh#cpp#AnalysisLib_Class#CurrentScope`](API.md#lhcppanalysislib_classcurrentscope), «clsname» otherwise **Options:** * [lh-style naming conventions](https://lh-style.readthedocs.io/en/latest/naming.html) **Variation Points:** * [`cpp/internals/function-comment`](#cppinternalsfunction-comment) snippet **TODO:** * Detect C++11 to insert `noexcept` (through a variation point (snippet/option) as some frameworks have their own macro/keyword for `noexcept`) #### cpp/copy-constructor **Produces:** `T(T const&);` **Parameters:** 1. `"clsname"`, the class name, default: automatically deduced by [`lh#cpp#AnalysisLib_Class#CurrentScope`](API.md#lhcppanalysislib_classcurrentscope), «clsname» otherwise * `"copy-constructor"`: (dictionary) * "visibility": *"public"*/"protected"/"private" * "how": *""*/"deleted"/"defaulted" **Options:** * [lh-style naming conventions](https://lh-style.readthedocs.io/en/latest/naming.html) **Variation Points:** * [`cpp/internals/function-comment`](#cppinternalsfunction-comment) snippet **TODO:** * Add move copy-constructor, and move assignment-operator * Detect C++11 to insert `noexcept` (through a variation point (snippet/option) as some frameworks have their own macro/keyword for `noexcept`) #### cpp/default-constructor **Produces:** `T();` **Parameters:** 1. `"clsname"`, the class name, default: automatically deduced by [`lh#cpp#AnalysisLib_Class#CurrentScope`](API.md#lhcppanalysislib_classcurrentscope), «clsname» otherwise * `"default-constructor"`: (dictionary) * "visibility": *"public"*/"protected"/"private" * "how": *""*/"deleted"/"defaulted" **Options:** * [lh-style naming conventions](https://lh-style.readthedocs.io/en/latest/naming.html) **Variation Points:** * [`cpp/internals/function-comment`](#cppinternalsfunction-comment) snippet **TODO:** * Detect C++11 to insert `noexcept` (through a variation point (snippet/option) as some frameworks have their own macro/keyword for `noexcept`) #### cpp/destructor **Produces:** `«virtual »~T();` **Parameters:** 1. `"clsname"`, the class name, default: automatically deduced by [`lh#cpp#AnalysisLib_Class#CurrentScope`](API.md#lhcppanalysislib_classcurrentscope), «clsname» otherwise 2. `"is_virtual"`: boolean, default: «virtual » * `"copy-constructor"`: (dictionary) * "visibility": *"public"*/"protected"/"private" * "how": *""*/"deleted"/"defaulted"/"pure" **Variation Points:** * [`cpp/internals/function-comment`](#cppinternalsfunction-comment) snippet **Options:** * [lh-style naming conventions](https://lh-style.readthedocs.io/en/latest/naming.html) #### cpp/operator-binary **Produces:** ```C++ «clsname» operator«X»(«clsname» lhs, «clsname» const& rhs) { return lhs «X»= rhs; } ``` **Parameters:** * `"operator"`: binary operation name, default: «X» * `"clsname"`, the class name, default: automatically deduced by [`lh#cpp#AnalysisLib_Class#search_closest_class`](API.md#lhcppanalysislib_classsearch_closest_class) **Options:** * [lh-style naming conventions](https://lh-style.readthedocs.io/en/latest/naming.html) **Note:** * The code generated may change to encompass C++11 best practices and performances. See [some experimentations I've done](http://github.com/LucHermitte/LucHermitte.github.io/source/_posts/code/test-arithmetic-operators). **TODO:** * [`cpp/internals/function-comment`](#cppinternalsfunction-comment) snippet #### cpp/stream-extractor **Produces:** `istream& operator>>(istream &, class-type)` **Relies on:** * [`cpp/internals/stream-common`](#cppinternalsstream-common) #### cpp/stream-inserter **Produces:** `ostream& operator<<(ostream &, class-type)` **Relies on:** * [`cpp/internals/stream-common`](#cppinternalsstream-common) ### Class Patterns The following snippets will generate new classes that follow the chosen semantics as closely as possible. The currently supported semantics and idioms are: * _class_, the simpliest snippet, unaware of anything * _value class_, copyable, comparable * _entity class_, non-copyable * _base class non virtual_, **NOT** deletable through a pointer to the parent * _base class_, deletable through a pointer to the parent * _abstract class_ * _interface_ (synonym to _abstract class_, for the moment) * _clonable class_, bastard class, neither a real entity nor a value class. * _singleton_ * _exception_ * _empty exception_ * _traits_ **Surrounding:** When used to surround a list of attributes (type + name), these will produce classes with: * all these attributes, * plus an initializing constructor that'll forward parameters to construct the attributes, * plus all the related copy operations when the class has value semantics, and when there are non trivially-correctly copiable attributes (like a non view-pointer). If you don't want to see an attribute used when generating these operations, add the attribute later, manually. Currently, neither _getters_ no _setters_ are generated automatically. As a few others I [consider](http://martinfowler.com/bliki/GetterEradicator.html) [them](http://www.adam-bien.com/roller/abien/entry/encapsulation_violation_with_getters_and) [to](http://stackoverflow.com/questions/565095/are-getters-and-setters-poor-design-contradictory-advice-seen) [be](http://www.javaworld.com/article/2073723/core-java/why-getter-and-setter-methods-are-evil.html) [bad](http://www.yegor256.com/2014/09/16/getters-and-setters-are-evil.html) [practice](https://pragprog.com/articles/tell-dont-ask) . For now, use [vim-refactor](http://github.com/LucHermitte/vim-refactor) to generate [const correct](https://isocpp.org/wiki/faq/const-correctness) getters and setters that follow the [naming policy](https://lh-style.readthedocs.io/en/latest/naming.html) configured for my plugins. **API:** All these snippets can be used programmatically to generate even more complex classes. See the [related `*-class_spec.rb` tests](../spec). **Licencing:** Unlike other snippets, a few class patterns are under a BSL license. #### cpp/abs-rel TBD **Licence:** BSL #### cpp/abstract-class **Produces:** A base class to inherit from with: * A virtual pure public destructor * A protected default constructor (unless specified otherwise) * Non-copy-ability enforced **Parameters:** * Any parameter passed to [`cpp/internals/class-skeleton`](#cppinternalsclass-skeleton) **Options:** * Any options used by [`cpp/internals/class-skeleton`](#cppinternalsclass-skeleton). In particular: * [`lh#cpp#use_cpp11()`](options.md#bpgcpp_std_flavour) * [`(bpg):cpp_deleted`](options.md#bpgcpp_deleted) * [`(bpg):cpp_noncopyable_class`](#bpgcpp_noncopyable_class) **Relies on:** * [`cpp/base-class`](#cppbase-class) * [`cpp/entity-class`](#cppentity-class) * [`cpp/internals/class-skeleton`](#cppinternalsclass-skeleton) #### cpp/base-class **Produces:** A base class to inherit from with: * A virtual public destructor, not necessarily pure (see [`cpp/abstract-class`](#cppabstract-class)) * A protected default constructor (unless specified otherwise) * Non-copy-ability enforced **Parameters:** * Any parameter passed to [`cpp/internals/class-skeleton`](#cppinternalsclass-skeleton) **Options:** * Any options used by [`cpp/internals/class-skeleton`](#cppinternalsclass-skeleton). In particular: * [`lh#cpp#use_cpp11()`](options.md#bpgcpp_std_flavour) * [`(bpg):cpp_deleted`](options.md#bpgcpp_deleted) **Relies on:** * [`cpp/entity-class`](#cppentity-class) * [`cpp/internals/class-skeleton`](#cppinternalsclass-skeleton) #### cpp/base-class-non-virtual **Produces:** A base class to inherit from with: * A protected non-virtual destructor * A protected default constructor (unless specified otherwise) * Non-copy-ability enforced **Parameters:** * Any parameter passed to [`cpp/internals/class-skeleton`](#cppinternalsclass-skeleton) **Options:** * Any options used by [`cpp/internals/class-skeleton`](#cppinternalsclass-skeleton). In particular: * [`lh#cpp#use_cpp11()`](options.md#bpgcpp_std_flavour) * [`(bpg):cpp_deleted`](options.md#bpgcpp_deleted) **Relies on:** * [`cpp/entity-class`](#cppentity-class) * [`cpp/internals/class-skeleton`](#cppinternalsclass-skeleton) **Screencast:** ![base-class-non-virtual snippet demo](screencast-snippet-baseNV-class.gif "Snippet demo for a base class with a non virtual destructor") #### cpp/class **Produces:** a simplistic class definition, unaware of semantics. **Parameters:** * Any parameter passed to [`cpp/internals/class-skeleton`](#cppinternalsclass-skeleton) **Options:** * [`(bpg):dox_group`](options.md#bpgdox_group) , default: «Project» * [`(bpg):({ft_}dox_TagLeadingChar)`](options.mg#bpgft_dox_tagleadingchar) * Any options used by [`cpp/internals/class-skeleton`](#cppinternalsclass-skeleton). **Relies on:** * [`cpp/internals/class-skeleton`](#cppinternalsclass-skeleton) **Todo:** * Have all class variations in their own template-file, and have the wizard glob compatible files to ask the use which one he prefers * Enhance the semantics (see _Big Rule of Two_ in C++98/03, Rule of _All or Nothing_ is C++11). We should have: * value-semantics, no resources * value-semantics, responsible for one resource * value-semantics, with RAII encapsulated resource(s) #### cpp/empty-exception-class TBD: #### cpp/entity-class **Produces:** A non-copiable class. **Parameters:** * Any parameter passed to [`cpp/internals/class-skeleton`](#cppinternalsclass-skeleton) **Options:** * Any options used by [`cpp/internals/class-skeleton`](#cppinternalsclass-skeleton). In particular: * [`lh#cpp#use_cpp11()`](options.md#bpgcpp_std_flavour) * [`(bpg):cpp_deleted`](options.md#bpgcpp_deleted) **Relies on:** * [`cpp/internals/class-skeleton`](#cppinternalsclass-skeleton) #### cpp/enum TBD: **See:** [lh-cpp enums generation](Enums.md) #### cpp/enum2 TBD Meant to be used through [`:InsertEnum`](Enum.md#enum-snippet) command. **Options:** * [`(bpg):({ft}_)dox_group`](#options.md#bpgft_dox_group) * [`(bpg):cpp_begin_end_style`](options.md#bpgft_begin_end_style) * [`lh#cpp#use_cpp11()` and `lh#cpp#use_cpp17()`](options.md#bpgcpp_std_flavour) * [`(bpg):({ft}_)array_size`](options.md#bpgcpp_array_size) * `(bpg):({ft}_)exception_type`, default: `std:runtime_error` * `(bpg):({ft}_)exception_args`, default: `v:1_`, functor that gets `exception_txt` injected as parameter **Variation Points/Relies on:** * [`cpp/array_size`](#cpparray_size) snippet * [`cpp/static_assert`](#cppstatic_assert) snippet * [`cpp/throw`](#cppthrow) snippet * [`cpp/internals/formatted-comment`](#cppinternalsformatted-comment) snippet **See:** [lh-cpp enums generation](Enums.md#enum-snippet) #### cpp/enum2-impl TBD: Meant to be used through [`:InsertEnum`](Enum.md#enum-snippet) command. **Options:** * `(bpg):({ft}_)exception_type`, default: `std:runtime_error` * `(bpg):({ft}_)exception_args`, default: `v:1_`, functor that gets `exception_txt` injected as parameter * [`(bpg):cpp_begin_end_style`](options.md#bpgcpp_begin_end_style) * [`(bpg):cpp_begin_end_includes`](options.md#bpgcpp_begin_end_includes) **Variation Points/Relies on:** * [`cpp/throw`](#cppthrow) snippet * [`cpp/internals/get-b-e`](#cppinternalsget-b-e) snippet * [`cpp/internals/formatted-comment`](#cppinternalsformatted-comment) snippet **See:** [lh-cpp enums generation](Enums.md#enum-snippet) #### cpp/exception-class TBD: #### cpp/interface **Produces:** An interface class to inherit from with: * A virtual pure public destructor * A protected default constructor (unless specified otherwise) * Non-copy-ability enforced **Parameters:** * Any parameter passed to [`cpp/internals/class-skeleton`](#cppinternalsclass-skeleton) **Options:** * Any options used by [`cpp/internals/class-skeleton`](#cppinternalsclass-skeleton). In particular: * [`lh#cpp#use_cpp11()`](options.md#bpgcpp_std_flavour) * [`(bpg):cpp_deleted`](options.md#bpgcpp_deleted) * [`(bpg):cpp_noncopyable_class`](#bpgcpp_noncopyable_class) **Relies on:** * [`cpp/base-class`](#cppbase-class) * [`cpp/entity-class`](#cppentity-class) * [`cpp/internals/class-skeleton`](#cppinternalsclass-skeleton) **Note:** * At this moment, there is no difference between the `cpp/interface` and the [`cpp/abstract-class`](#cppabstract-class) snippets. I may eventually add simplified support for [NVI](https://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Non-Virtual_Interface) idiom in `cpp/interface` snippet. #### cpp/singleton **Produces:** Wizard that produces a singleton class definition **Parameters:** * _singleton name_, default: asked to the user **Options:** * [`(bpg):dox_group`](options.md#bpgdox_group) , default: «Project» * [`(bpg):({ft_}dox_TagLeadingChar)`](options.mg#bpgft_dox_tagleadingchar) **Notes:** * A Doxygen documentation skeleton is inserted * The user is asked to choose the kind of singleton implementation he desires * Scott Meyer's singleton (local-static, MT-safe (C++11), lazy-construction supported) * My own appreciation of what a singleton shall look like (MT-safe, no lazy construction, but explicit initialisation) **Also includes:** * `` **Variation Points:** * mu-template "c/section-sep" snippet **Relies on:** * `CppDox_SingletonWizard()` **Todo:** * Have all singleton variations in their own template-file, and have the wizard glob compatible files to ask the use which one he prefers * Use [cpp/internals/function-comment](#cppinternalsfunction-comment) #### cpp/traits **Produces:** traits-class ```C++ /** «name» traits class. */ template struct «name»_traits { <++> }; ``` ## Doxygen #### dox/author **Produces:** `@author` **Options:** * [`(bpg):({ft_}dox_author_tag)`](options.mg#bpgft_dox_author_tag) * [`(bpg):({ft_}dox_author)`](options.mg#bpgft_dox_author) * [`(bpg):({ft_}dox_TagLeadingChar)`](options.mg#bpgft_dox_tagleadingchar) **Relies on:** * [`lh#dox#author()`](API.md#lhdoxauthor) #### dox/code **Produces:** `«code»` **Parameters:** * «code», default: empty placeholder «» **Options:** * [`(bpg):({ft_}dox_TagLeadingChar)`](options.mg#bpgft_dox_tagleadingchar) **Surround:** 1. The selection can be surrounded by `` tags. **Relies on:** * [`lh#dox#tag()`](API.md#lhdoxtag) #### dox/em **Produces:** `cpp/internals/formatted-comm` **Parameters:** * cpp/internals/formatted-comm, default: empty placeholder «» **Options:** * [`(bpg):({ft_}dox_TagLeadingChar)`](options.mg#bpgft_dox_tagleadingchar) **Surround:** 1. The selection can be surrounded by `` tags. **Relies on:** * [`lh#dox#tag()`](API.md#lhdoxtag) #### dox/file **Produces:** `/** @file ... */` **Options:** * [`(bpg):dox_group`](options.md#bpgdox_group) , default: «Project» * [`(bpg):ProjectVersion`](options.md#bpgproject_version) , default: «1.0» * [`(bpg):({ft_}dox_TagLeadingChar)`](options.mg#bpgft_dox_tagleadingchar) **Notes:** * The filename written with the `@file` tag is deduced from `expand(%:t)` **Relies on:** * [`lh#dox#tag()`](API.md#lhdoxtag) * [`lh#dox#since()`](API.md#lhdoxsince) **TODO:** * Recognize SVN/CVS context to not always include RCS tags like `$Id$` #### dox/function **Produces:** `/** @ingroup, @params, @exceptions, @pre, ... */` **Note:** * This snippet is used to organize the various elements computed by [`:DOX`](features.md#DOX) * Its internal are likely to change in the future to factorize the code with `autoload/lh/dox.vim` and other snippets like [cpp/internals/function-comment](#cppinternalsfunction-comment) #### dox/group **Produces:** Doxygen local group ```C++ //@{ «» //@} ``` **Surround:** 1. The selection can be surrounded by the group tags #### dox/html **Produces:** `cpp/internals/formatted-comm` **Parameters:** * cpp/internals/formatted-comm, default: empty placeholder «» **Options:** * [`(bpg):({ft_}dox_TagLeadingChar)`](options.mg#bpgft_dox_tagleadingchar) **Surround:** 1. The selection can be surrounded by the html-tags 2. The selection can become the HTML tags **Relies on:** * [`lh#dox#tag()`](API.md#lhdoxtag) #### dox/ingroup **Produces:** `/**@ingroup ... */` **Options:** * [`(bpg):dox_group`](options.md#bpgdox_group) , default: «Project» * [`(bpg):({ft_}dox_TagLeadingChar)`](options.mg#bpgft_dox_tagleadingchar) **Relies on:** * [`lh#dox#tag()`](API.md#lhdoxtag) #### dox/since **Produces:** `@since Version` **Options:** * [`(bpg):ProjectVersion`](options.md#bpgproject_version) , default: «1.0» * [`(bpg):({ft_}dox_TagLeadingChar)`](options.mg#bpgft_dox_tagleadingchar) **Relies on:** * [`lh#dox#tag()`](API.md#lhdoxtag) * [`lh#dox#since()`](API.md#lhdoxsince) #### dox/tt **Produces:** `cpp/internals/formatted-comm` **Parameters:** * cpp/internals/formatted-comm, default: empty placeholder «» **Options:** * [`(bpg):({ft_}dox_TagLeadingChar)`](options.mg#bpgft_dox_tagleadingchar) **Surround:** 1. The selection can be surrounded by `` tags. **Relies on:** * [`lh#dox#tag()`](API.md#lhdoxtag) ## Miscellaneous #### c/comment **Produces:** * in insert-mode, or with no count when surrounding: ```C++ #if 0 «code;» #endif ``` * with a count when surrounding: ```C++ #if 1 v:count first lines #else remaining lines #endif ``` **Options:** * `v:count`, when surrounding **Surround:** 1. The selection can be surrounded by this snippet. #### cpp/benchmark #### cpp/otb-sug-latex #### cpp/otb-sug-snippet #### cpp/utf8 ## Internal templates #### cpp/internals/abs-rel-shared #### cpp/internals/class-skeleton This template file can be assimilated to the core routine used to generate all C++ classes (values, entities, base classes, interfaces, exceptions, etc). **Parameters** * `comments`: List of Doxygen entries for the class that are passed to [cpp/internals/formatted-comment](#cppinternalsformatted-comment). * `clsname`: The name of the class to generate. * `final`: Boolean that tells whether the class is `final` (C++11) * `noncopyable`/`copyable`: Tells whether the copyability of the class is known (0 or 1), or unknown (-1) * `functions`: List of functions to declare in the class -- object built through `lh#cpp#snippets#new_function_list()` * `public|protected|private`: * `signature` * `implementation` * `visibility`: `'public'`, `'protected'`, `'private'`, `'none'` * `how`: `'deleted'`, `'defaulted'`, `'pure'`, `''` * `virtual` * `comments` * `attributes`: List of attributes to declare in the class -- elements are tag entries, or built with `lh#cpp#snippets#_decode_selected_attributes()`. Typical keys are: * `name` * `type` * `functions` * `parents`: List that describes the parent classes * Special functions: Parameters that tune the various special functions: * `init-constructor` * `default-constructor` * `copy-constructor` * `destructor` * `assignment-operator` Typical keys are: * `visibility`: `'public'`, `'protected'`, `'private'`, `'none'` * `how`: `'deleted'`, `'defaulted'`, `'pure'`, `''` * `virtual` * `comments` **TODO:** * find a way to order members * find a way to group members * option to disable comments in defaulted functions * C++11 move copy & move assign * Enforce rule of "all or nothing" * Find a way to specify attributes to use in init-ctr and w/ getters/setters when surrounding. * Add option to force copiable classes to always be `final` * Add option to force the generation of getters and setters when surrounding attributes. #### cpp/internals/formatted-comment #### cpp/internals/function-comment #### cpp/internals/stream-common **Produces:** The empty definition for a stream operation. **Parameters** * `s:direction`: `i` or `o` **Notes:** * `s:clsname`: The name of the current class/type is searched with `Cpp_SearchClassDefinition()`, it will be asked to the user if none is found * `s:friend` is assigned to `friend` if a class was found * `s:const` is assigned to `const` if a class was found * `s:op`, `s:type` and `s:stream_param` are deduced from `s:direction` **Relies on:** * [`cpp/internals/stream-signature`](#cppinternalsstream-signature) * [`cpp/internals/stream-implementation`](#cppinternalsstream-implementation) #### cpp/internals/stream-implementation **Produces:** ```C++ { return «s:stream_param» «s:op» «fields»; } ``` **Parameters** * `s:stream_param`: `is` or `os` * `s:op`: `>>` or `<<` * `s:direction`: `i` or `o` **Options:** * [lh-style naming conventions](https://lh-style.readthedocs.io/en/latest/naming.html) **Also includes:** * `` if `s:direction == "i"` * or `` if `s:direction == "o"` #### cpp/internals/stream-signature **Produces:** ```C++ «s:friend»«s:type»& operator«s:op»(«s:type» & «s:stream_param», «s:clsname» «s:const»& v) ``` **Parameters** * `s:clsname`: The name of the class/type the operator applies to. * `s:stream_param`: `is` or `os` * `s:type`: `std::istream` or `std::ostream` * `s:op`: `>>` or `<<` * `s:friend`: `friend` or empty string * `s:const`: `const` or empty string **Options:** * [lh-style naming conventions](https://lh-style.readthedocs.io/en/latest/naming.html) ================================================ FILE: doc/types.md ================================================ ## lh-cpp Type DataBase lh-cpp provides a database for most standard types and some semi-standard types, i.e. [Boost](http://www.boost.org) types. ### Accessing type information #### `lh#cpp#types#get_info(type[, default-value])` Function that returns the type information associated to `type`. If no information is found for `type`, the `default-value` will be returned. A type information is a dictionary object made of: * `"name"`: simplified name of the type (acts as a key to retrieve its associated information) * `"namespace"`: its namespace * `"type"`: the full type name (with template parameters) * `"includes`"`: list of headers file that may define the type. * `"typename_for_header(...)"` function. See the [related unit test](../tests/lh/test-types.vim) #### `lh#cpp#types#get_includes(type)` Returns the list of header files that are know to define the `type`. ### Current database status The best way to see which types are defined is to consult the source code of [autoload/lh/cpp/types.vim](../autoload/lh/cpp/types.vim). ================================================ FILE: ftplugin/c/LoadHeaderFile.vim ================================================ " LoadHeaderFile " Last Change: 29th july 2001 by Luc Hermitte " -> Split lines and change indentation in order to fit within 80 cols " -> Change the way the filename is extracted from the include line " Maintainer: Garner Halloran (garner@havoc.gtf.org) if !exists( "g:loaded_LoadHeaderFile" ) ""finish ""endif let g:loaded_LoadHeaderFile = 1 fun! LoadHeaderFile( arg, loadSource ) if match( a:arg, "#include" ) >= 0 " extract the file name let matchPattern = '\s*#include\s*\(<\|"\)\(.*\)\(>\|"\)\s*' let $filename = substitute( a:arg, matchPattern, '\2', 'g') if strlen($filename) != 0 " if loadSource is 1, then replace .h with .cpp and load that file " instead if a:loadSource == 1 let $filename = substitute( $filename, '\V.h', ".cpp", "" ) " if loadSource is 2, then replace .h with .c and load that file " instead elseif a:loadSource == 2 let $filename = substitute( $filename, '\V.h', ".c", "" ) endif sfind $filename return endif endif endfun endif ================================================ FILE: ftplugin/c/c_AddInclude.vim ================================================ "============================================================================= " File: ftplugin/c/c_AddInclude.vim {{{1 " Author: Luc Hermitte " " License: GPLv3 with exceptions " " Version: 2.1.3 let s:k_version = 213 " Created: 22nd May 2012 " Last Update: 28th Oct 2015 "------------------------------------------------------------------------ " Description: " This ftplugin defines a mapping to insert missing includes (given we " know which symbol shall be defined...) " "------------------------------------------------------------------------ " Installation: " Drop this file into {rtp}/ftplugin/c " Requires Vim7+, lh-dev " History: " v2.0.0 GPLv3 w/ exception " TODO: " Handle the case where several files are found " Move to autoload plugin " Recognize commented includes " }}}1 "============================================================================= finish " This ftplugin has been deprecated in favour of lh-dev/ImportModule feature " Buffer-local Definitions {{{1 " Avoid local reinclusion {{{2 if &cp || (exists("b:loaded_ftplug_c_AddInclude") \ && (b:loaded_ftplug_c_AddInclude >= s:k_version) \ && !exists('g:force_reload_ftplug_c_AddInclude')) finish endif let b:loaded_ftplug_c_AddInclude = s:k_version let s:cpo_save=&cpo set cpo&vim " Avoid local reinclusion }}}2 "------------------------------------------------------------------------ " Local mappings {{{2 nnoremap InsertInclude :call InsertInclude() if !hasmapto('InsertInclude', 'n') nmap i InsertInclude endif "============================================================================= " Global Definitions {{{1 " Avoid global reinclusion {{{2 if &cp || (exists("g:loaded_ftplug_c_AddInclude") \ && (g:loaded_ftplug_c_AddInclude >= s:k_version) \ && !exists('g:force_reload_ftplug_c_AddInclude')) let &cpo=s:cpo_save finish endif let g:loaded_ftplug_c_AddInclude = s:k_version " Avoid global reinclusion }}}2 "------------------------------------------------------------------------ " Functions {{{2 " Note: most filetype-global functions are best placed into " autoload/«your-initials»/c/«c_AddInclude».vim " Keep here only the functions are are required when the ftplugin is " loaded, like functions that help building a vim-menu for this " ftplugin. function! s:InsertInclude() abort " If there are several choices, ask which one to use. " But first: check the files. let [id, info] = lh#cpp#tags#fetch("insert-include") let files = {} for t in info if ! has_key(files, t.filename) let files[t.filename] = {} endif let files[t.filename][t.kind[0]] = '' endfor " NB: there shouldn't be any to prioritize between p and f kinds as the " filtering on include files shall get rid of the f kinds (that exist along " with a prototype) if len(files) > 1 call lh#common#error_msg("insert-include: too many acceptable tags for `" \ .id."': ".string(files)) return endif mark ' let fullfilename = keys(files)[0] let filename = fullfilename " this is the full filename " echo filename try call lh#cpp#include#add(filename, fullfilename=~ '\\|\') catch /^insert-include:.* is already included/ call lh#common#warning_msg("insert-include: ".filename.", where `" \ .id."' is defined, is already included") endtry echo "Use CTRL-O to go back to previous cursor position" endfunction " Functions }}}2 "------------------------------------------------------------------------ let &cpo=s:cpo_save "============================================================================= " vim600: set fdm=marker: ================================================ FILE: ftplugin/c/c_Doxygen.vim ================================================ "============================================================================= " File: ftplugin/c/c_Doxygen.vim {{{1 " Author: Luc Hermitte " " License: GPLv3 with exceptions " " Version: 2.2.0 let s:k_version = 220 " Created: 22nd Nov 2005 " Last Update: 26th Nov 2019 "------------------------------------------------------------------------ " Description: " Provides the command :DOX that expands a doxygened documentation for " the current C|C++ function. " " :DOX tries to guess various things like: " - the direction ([in], [out], [in,out]) of the parameters " - pointers that should not be null " - ... " " It also comes with the following template-file: " - a\%[uthor-doxygen] + CTRL-R_TAB " " " Options: " - [bg]:[&ft_]dox_CommentLeadingChar " - [bg]:[&ft_]dox_TagLeadingChar " - [bg]:[&ft_]dox_author_tag " - [bg]:[&ft_]dox_ingroup " - [bg]:[&ft_]dox_brief " - [bg]:[&ft_]dox_throw " "------------------------------------------------------------------------ " Installation: See |lh-cpp-readme.txt| " Dependencies: Mu-template " }}}1 "============================================================================= if version < 700 finish " Vim 7 required endif "============================================================================= " Avoid buffer reinclusion {{{1 if exists('b:loaded_ftplug_c_Doxygen') && !exists('g:force_reload_c_Doxygen') finish endif let b:loaded_ftplug_c_Doxygen = s:k_version let s:cpo_save=&cpo set cpo&vim " }}}1 "------------------------------------------------------------------------ " Commands and mappings {{{1 " todo: arguments (with auto completion) for brief, ingroup, author, since, ... " todo: align arguments and their descriptions command! -buffer -nargs=0 DOX :call s:Doxygenize() " Commands and mappings }}}1 "============================================================================= " Avoid global reinclusion {{{1 if exists("s:loaded_c_Doxygen") \ && !exists('g:force_reload_c_Doxygen') let &cpo=s:cpo_save finish endif let s:loaded_c_Doxygen_vim = 1 " Avoid global reinclusion }}}1 "------------------------------------------------------------------------ " Functions {{{1 " require Cpp_GetListOfParams and Cpp_GetFunctionPrototype function! CppDox_snippet(tagname, commentLeadingChar) let varType = type(g:CppDox_{a:tagname}_snippet) if varType == type([]) " List let sValue = join(g:CppDox_{a:tagname}_snippet, "\n".a:commentLeadingChar) else let sValue = g:CppDox_{a:tagname}_snippet endif if strlen(sValue) != 0 let sValue = a:commentLeadingChar . sValue endif " echomsg a:tagname . " -> " . sValue return sValue endfunction " Function: s:Doxygenize() {{{2 function! s:Doxygenize() abort let cleanup = lh#on#exit() \.restore('g:CppDox_Params_snippet') \.restore('g:CppDox_preconditions_snippet') \.restore('g:CppDox_return_snippet') \.restore('g:CppDox_exceptions_snippet') \.restore('g:CppDox_ingroup_snippet') \.restore('g:CppDox_brief_snippet') try " Obtain informations from the function at the current cursor position. let info = lh#cpp#AnalysisLib_Function#get_function_info(line('.'), 0) let params = info.parameters let ret = info.return " Build data to insert " " Parameters & preconditions let g:CppDox_Params_snippet = [] let g:CppDox_preconditions_snippet = [] for param in get(info, 'tparams', []) " @tparam let sValue = \ lh#dox#tag("tparam") \ . ' ' . param.name \ . ' ' . lh#marker#txt((param.name).'-explanations') call add (g:CppDox_Params_snippet, sValue) endfor for param in params " @param let sValue = \ lh#dox#tag("param") \ . lh#dox#_parameter_direction(param.type) \ . ' ' . param.name \ . ' ' . lh#marker#txt((param.name).'-explanations') call add (g:CppDox_Params_snippet, sValue) " pointer ? -> default non null precondition " todo: add an option if we don't want that by default (or even better, use " clang to check whether an assert is being used for that purpose...) if lh#dev#cpp#types#IsPointer(param.type) let sValue = \ lh#dox#tag("pre") \ . ' '.(param.name).' != NULL' \ . lh#marker#txt() call add(g:CppDox_preconditions_snippet, sValue) endif endfor " Ingroup let g:CppDox_ingroup_snippet = lh#dox#ingroup() " Brief let g:CppDox_brief_snippet = lh#dox#brief('') if ret =~ 'void\|^$' let g:CppDox_return_snippet = '' else let g:CppDox_return_snippet = lh#dox#tag('return ').lh#marker#txt(ret) endif " empty => <+@throw None+> " list => n x @throw list " non-existant => markerthrow " noexcept let noexcept = get(info, 'noexcept') if !empty(noexcept) if noexcept == 'noexcept' let noexcept = 'None' else let noexcept = 'None if `'.noexcept.'`' endif let g:CppDox_exceptions_snippet = lh#dox#throw(noexcept) elseif !has_key(info, 'throw') || len(info.throw) == 0 let g:CppDox_exceptions_snippet = lh#dox#throw() else let throws = info.throw let empty_marker = lh#marker#txt('') if len(throws) == 1 && strlen(throws[0]) == 0 let g:CppDox_exceptions_snippet = lh#dox#throw('None').empty_marker else call map(throws, 'lh#dox#throw(v:val). empty_marker') let g:CppDox_exceptions_snippet = throws endif endif " goto begining of the function if has_key(info, 'start') exe info.start.line endif :put!='' " Load the template :MuTemplate dox/function finally call cleanup.finalize() endtry endfunction " Functions }}}1 "------------------------------------------------------------------------ let &cpo=s:cpo_save "============================================================================= " vim600: set fdm=marker: ================================================ FILE: ftplugin/c/c_UnmatchedFunctions.vim ================================================ "============================================================================= " File: ftplugin/c/c_UnmatchedFunctions.vim {{{1 " Author: Luc Hermitte " " License: GPLv3 with exceptions " " Version: 2.2.0 let s:k_version = '220' " Created: 14th Feb 2008 " Last Update: 14th Mar 2017 "------------------------------------------------------------------------ " Description: description " "------------------------------------------------------------------------ " Installation: install details " History: history " TODO: missing features " }}}1 "============================================================================= " Buffer-local Definitions {{{1 " Avoid local reinclusion {{{2 if exists("b:loaded_ftplug_c_UnmatchedFunctions") && !exists('g:force_reload_ftplug_c_UnmatchedFunctions') finish endif let s:cpo_save=&cpo set cpo&vim " Avoid local reinclusion }}}2 "------------------------------------------------------------------------ " Local mappings {{{2 vnoremap u :call DisplaySelected() nmap u viwu "------------------------------------------------------------------------ " Local commands {{{2 command! -b -nargs=? CppDisplayUnmatchedFunctions :call DisplayCmd() "============================================================================= " Global Definitions {{{1 " Avoid global reinclusion {{{2 if exists("g:loaded_ftplug_c_UnmatchedFunctions") && !exists('g:force_reload_ftplug_c_UnmatchedFunctions') let &cpo=s:cpo_save finish endif " Avoid global reinclusion }}}2 "------------------------------------------------------------------------ " Functions {{{2 " Note: most filetype-global functions are best placed into " autoload/your-initials/cpp/c_UnmatchedFunctions.vim " Keep here only the functions are are required when the ftplugin is " loaded, like functions that help building a vim-menu for this " ftplugin. function! s:DisplaySelected() let a_save = @a try normal! gv"ay call lh#cpp#UnmatchedFunctions#Display(@a) finally let @a = a_save endtry endfunction function! s:DisplayCmd(...) if a:0 > 0 " todo: support option -file/-class let what \ = (a:1 =~ '-f\%[ile]') ? 'File' \ : (a:1 =~ '-c\%[lass]') ? 'Class' \ : a:1 else let what = lh#ui#which( 'lh#ui#confirm', \ "Displaying unmatched functions for the current ...", \ "&Class\n&File\n&Abort", 1) endif let id = '' if what == 'Class' let id = lh#cpp#AnalysisLib_Class#CurrentScope(line('.'), 'any') elseif what == 'File' let id = expand('%:t') elseif what != "" && what !='Abort' let id = what endif if strlen(id) > 0 " echomsg 'lh#cpp#UnmatchedFunctions#Display('.id.')' call lh#cpp#UnmatchedFunctions#Display(id) else echohl WarningMsg echo 'abort' echohl None endif endfunction " }}}1 "------------------------------------------------------------------------ let &cpo=s:cpo_save "============================================================================= " vim600: set fdm=marker: ================================================ FILE: ftplugin/c/c_complete_include.vim ================================================ "============================================================================= " File: ftplugin/c/c_complete_include.vim {{{1 " Author: Luc Hermitte " " Version: 2.2.1 let s:k_version = 221 " Created: 08th Nov 2011 " Last Update: 16th Jan 2019 "------------------------------------------------------------------------ " Description: " Mapping to complete #include filename not based on &path (as " |i_CTRL-X_CTRL-F| is). " The completion is based instead on {bg}:{ft_}_includes_path + &include " "------------------------------------------------------------------------ " Installation: " Drop this file into {rtp}/ftplugin/c " Requires Vim7+, lh-vim-lib 2.2.7+ " «install details» " History: «history» " TODO: «missing features» " }}}1 "============================================================================= " Buffer-local Definitions {{{1 " Avoid local reinclusion {{{2 let s:cpo_save=&cpo set cpo&vim if &cp || (exists("b:loaded_ftplug_c_complete_include") \ && (b:loaded_ftplug_c_complete_include >= s:k_version) \ && !exists('g:force_reload_ftplug_c_complete_include')) let &cpo=s:cpo_save finish endif let b:loaded_ftplug_c_complete_include = s:k_version " Avoid local reinclusion }}}2 "------------------------------------------------------------------------ " Local mappings {{{2 inoremap CompleteIncludes =Complete() if !hasmapto('CompleteIncludes', 'i') imap i CompleteIncludes endif nnoremap OpenIncludes :call Open() if !hasmapto('OpenIncludes', 'n') nmap i OpenIncludes endif "============================================================================= " Global Definitions {{{1 " Avoid global reinclusion {{{2 if exists("g:loaded_ftplug_c_complete_include") \ && (g:loaded_ftplug_c_complete_include >= s:k_version) \ && !exists('g:force_reload_ftplug_c_complete_include') let &cpo=s:cpo_save finish endif let g:loaded_ftplug_c_complete_include = s:k_version " Avoid global reinclusion }}}2 "------------------------------------------------------------------------ " Functions {{{2 " Note: most filetype-global functions are best placed into " autoload/«your-initials»/c/«c_complete_include».vim " Keep here only the functions are are required when the ftplugin is " loaded, like functions that help building a vim-menu for this " ftplugin. " Function: s:Complete() {{{3 function! s:Complete() abort let cleanup = lh#on#exit() \.restore('&isk') try set isk+=/ let prev = lh#ui#GetLikeCTRL_W() finally call cleanup.finalize() endtry let paths = lh#cpp#tags#get_included_paths(&path) let files = lh#path#glob_as_list(paths, [prev.'*']) " Keep headers files and directories call filter(files, 'v:val =~? "\\v\.(h|hpp|hxx|txx|h\\+\\+)$" || isdirectory(v:val)') call map(files, 'v:val . (isdirectory(v:val)?"/":"")') let files = lh#list#unique_sort(files) let entries = map(copy(files), '{"word": lh#path#strip_start(v:val, paths), "menu": v:val}') call lh#icomplete#new(col('.')-lh#encoding#strlen(prev)-1, entries, []).start_completion() return '' endfunction " Function: s:Open() {{{3 " built on top of SearchInRuntime function! s:Open() abort try let path = &path let paths = lh#cpp#tags#get_included_paths() exe 'set path+='.join(paths, ',') exe "normal \f" finally let &path = path endtry endfunction " }}}1 "------------------------------------------------------------------------ let &cpo=s:cpo_save "============================================================================= " vim600: set fdm=marker: ================================================ FILE: ftplugin/c/c_doc.vim ================================================ "============================================================================= " File: ftplugin/c/c_doc.vim {{{1 " Author: Luc Hermitte " " Version: v2.0.0 " Created: 22nd Jan 2004 " Last Update: $Date$ "------------------------------------------------------------------------ " Description: Open documentation for C & C++ code " "------------------------------------------------------------------------ " Installation: ?install details? " History: " v2.0.0 GPLv3 w/ exception + deprecation " TODO: " - config variables to tell where to search the documentation " - fix VAM dependencies if lh#path#fix is still used " }}}1 "============================================================================= " This plugin is deprecated for now. " I'll have to clean it up, and permit to tune where to find the documentation finish "============================================================================= " Local stuff {{{1 " Avoid buffer reinclusion {{{2 if exists('b:loaded_ftplug_c_doc') && !exists('g:force_reload_c_doc') finish endif let b:loaded_ftplug_c_doc = 1 let s:cpo_save=&cpo set cpo&vim " }}}2 "------------------------------------------------------------------------ " Commands and mappings {{{2 nnoremap :CHelp command! -buffer -nargs=1 CHelp :call s:CHelp() " Commands and mappings }}}2 " }}}1 "============================================================================= " Global stuff {{{1 " Avoid global reinclusion {{{2 if exists("g:loaded_c_doc") && !exists('g:force_reload_c_doc') let &cpo=s:cpo_save finish endif let g:loaded_c_doc = 1 " Avoid global reinclusion }}}2 "------------------------------------------------------------------------ " Functions {{{2 " " s:Error {{{3 function! s:Error(msg) if has('gui') call confirm(a:msg, '&Ok', 1, "Error") else echohl ErrorMsg echo a:msg echohl None endif endfunction " Definitions {{{3 let s:std_doc = 'F:/Users/Luc/Prog/C++/docs/ref & cours/SL/www.dinkumware.com/htm_cpl/' let s:boost_doc = 'F:/Users/Luc/Prog/C++/libs/boost_1_32_cvs/doc/html/' let s:boost_lib = 'F:/Users/Luc/Prog/C++/libs/boost_1_32_cvs/libs/' " s:Build_boost_url {{{3 function! s:Build_boost_url(class) return s:boost_lib . a:class . '/index.html' endfunction " s:Build_std_url {{{3 function! s:Build_std_url(class) " dinkumware doc exe 'sp '.s:std_doc.'_index.html' let l = 1 let urls = '' while 1 let l = search('.\{-}\<'.a:class.'', 'W') if l <= 0 | break | endif let url = matchstr(getline(l), '"\zs[^<>]\{-}\ze">[^<>]\{-}\<'.a:class) let urls = urls . "\n" . url endwhile bw! let g:urls = urls let nb = strlen(substitute(urls, "[^\n]", '', 'g')) if nb == 0 | return '' elseif nb == 1 | return s:std_doc . strpart(urls, 1) else let n = confirm('chose:', strpart(urls, 1), 1) if n > 0 let url = matchstr(urls, '\%('."[^\n]*\n".'\)\{'.n.'}\zs'."[^\n]*") return s:std_doc . url endif endif endfunction " s:CHelp {{{3 function! s:CHelp(WORD) let url = '' if a:WORD =~ 'boost' let class = matchstr(a:WORD, 'boost::\zs[^()[<>.?]*\>') let url = s:Build_boost_url(class) elseif a:WORD =~ 'std' let class = matchstr(a:WORD, 'std::\zs[^()[<>.?]*\>') let url = s:Build_std_url(class) else endif if strlen(url) call s:DisplayInBrowser(url) endif endfunction " s:DisplayInBrowser {{{3 function! s:DisplayInBrowser(url) if exists('g:html_browser') " ... into g:html_browser if specified call system(g:html_browser. " " . \ lh#path#fix(a:url,0,((&sh=~'sh')?"'":'"'))) elseif has('win32') " ... into Ms's Internet Explorer ; for MsWindows only " :exe ':!start explorer ' . escape(lh#path#fix(a:url,0), '#') call system("explorer file:///" . \ lh#path#fix(a:url,0,((&sh=~'sh')?"'":'"'))) else call s:Error('Please set <> ' \ . 'to the path of the browser you are using') endif endfunction " Functions }}}2 " }}}1 "------------------------------------------------------------------------ let &cpo=s:cpo_save "============================================================================= " vim600: set fdm=marker: ================================================ FILE: ftplugin/c/c_gcov.vim ================================================ "============================================================================= " File: ftplugin/c/c_gcov.vim {{{1 " Author: Luc Hermitte " " Version: 221 let s:k_version = 221 " Created: 30th Oct 2012 " Last Update: 16th Jan 2019 "------------------------------------------------------------------------ " Description: " ftplugin to swap between a .gcov file and its source " "------------------------------------------------------------------------ " Installation: " Drop this file into {rtp}/ftplugin/c " Requires Vim7+ " «install details» " History: «history» " TODO: «missing features» " }}}1 "============================================================================= " Buffer-local Definitions {{{1 " Avoid local reinclusion {{{2 let s:cpo_save=&cpo set cpo&vim if &cp || (exists("b:loaded_ftplug_c_gcov") \ && (b:loaded_ftplug_c_gcov >= s:k_version) \ && !exists('g:force_reload_ftplug_c_gcov')) let &cpo=s:cpo_save finish endif let b:loaded_ftplug_c_gcov = s:k_version " Avoid local reinclusion }}}2 "------------------------------------------------------------------------ " Local mappings {{{2 nnoremap g :call JumpOrToggleGCOVFile(expand('%:p'), 'e') "------------------------------------------------------------------------ " Local commands {{{2 "============================================================================= " Global Definitions {{{1 " Avoid global reinclusion {{{2 if exists("g:loaded_ftplug_c_gcov") \ && (g:loaded_ftplug_c_gcov >= s:k_version) \ && !exists('g:force_reload_ftplug_c_gcov') let &cpo=s:cpo_save finish endif let g:loaded_ftplug_c_gcov = s:k_version " Avoid global reinclusion }}}2 "------------------------------------------------------------------------ " Functions {{{2 " Note: most filetype-global functions are best placed into " autoload/«your-initials»/c/«c_gcov».vim " Keep here only the functions are are required when the ftplugin is " loaded, like functions that help building a vim-menu for this " ftplugin. " Function: s:FindGCOVFile(source_file) {{{3 let s:k_gcov_ext = '.gcov' function! s:FindGCOVFile(source_file) abort let current_file = fnamemodify(a:source_file, ':t') let current_path = fnamemodify(a:source_file,':p:h') let gcov_files_path = lh#ft#option#get('gcov_files_path', &ft, current_path) let files = lh#path#glob_as_list(gcov_files_path, current_file.s:k_gcov_ext) if empty(files) throw "Cannot find <".current_file.s:k_gcov_ext."> in ".string(files).". Please set b:[{ft}_]gcov_files_path" else let gcov_file = lh#path#select_one(files, "Which gcov file matches <".current_file."> ?") return gcov_file endif endfunction function! s:JumpOrToggleGCOVFile(source_file, cmd) abort let gcov_file = s:FindGCOVFile(a:source_file) call lh#buffer#jump(gcov_file, a:cmd) endfunction " Functions }}}2 " }}}1 "------------------------------------------------------------------------ let &cpo=s:cpo_save "============================================================================= " vim600: set fdm=marker: ================================================ FILE: ftplugin/c/c_menu.vim ================================================ "============================================================================= " File: ftplugin/c/c_menu.vim {{{1 " Author: Luc Hermitte " " License: GPLv3 with exceptions " " Version: 2.0.0 " Created: 14th Oct 2006 " Last Update: $Date$ "------------------------------------------------------------------------ " Description: " Various C++ menu definitions " }}}1 "============================================================================= "============================================================================= " Avoid buffer reinclusion {{{1 let s:cpo_save=&cpo set cpo&vim if exists('b:loaded_ftplug_c_menu') \ && !exists('g:force_reload_c_menu') let &cpo=s:cpo_save finish endif let b:loaded_ftplug_c_menu = 200 " }}}1 "------------------------------------------------------------------------ " Commands and mappings {{{1 " Commands and mappings }}}1 "============================================================================= " Avoid global reinclusion {{{1 if exists("g:loaded_c_menu") \ && !exists('g:force_reload_c_menu') let &cpo=s:cpo_save finish endif let g:loaded_c_menu = 200 " Avoid global reinclusion }}}1 "------------------------------------------------------------------------ " Menu {{{1 let s:menu_prio = lh#option#get('c_menu_priority', '50', 'g') let s:menu_name = lh#option#get('c_menu_name', '&C++', 'g') " 80 wizards " 90 options " " --------------------------------------------------[ 50 debug with pyclewn if exists(':Pyclewn') call lh#menu#make('n', s:menu_prio.'.50.1', s:menu_name.'.&Pyclewn.&Run', '', '', ':Crun') call lh#menu#make('n', s:menu_prio.'.50.2', s:menu_name.'.&Pyclewn.&Start', '', '', ':Cstart') call lh#menu#make('n', s:menu_prio.'.50.3', s:menu_name.'.&Pyclewn.&Stop', '', '', ':Cstop') exe 'amenu '.s:menu_prio.'.50.20 '.escape(s:menu_name.'.&Pyclewn.-20-', '\ '). ' ' call lh#menu#make('n', s:menu_prio.'.50.21', s:menu_name.'.&Pyclewn.Add &Breakpoint', '', '', ':Cbreak') call lh#menu#make('n', s:menu_prio.'.50.22', s:menu_name.'.&Pyclewn.Clear Breakpoint', '', '', ':Cclear') exe 'amenu '.s:menu_prio.'.50.30 '.escape(s:menu_name.'.&Pyclewn.-30-', '\ '). ' ' call lh#menu#make('n', s:menu_prio.'.50.31', s:menu_name.'.&Pyclewn.&Next', '', '', ':Cnext') call lh#menu#make('n', s:menu_prio.'.50.32', s:menu_name.'.&Pyclewn.&Step', '', '', ':Cstep') call lh#menu#make('n', s:menu_prio.'.50.33', s:menu_name.'.&Pyclewn.&Cont', '', '', ':Ccont') exe 'amenu '.s:menu_prio.'.50.98 '.escape(s:menu_name.'.&Pyclewn.-98-', '\ '). ' ' call lh#menu#make('n', s:menu_prio.'.50.99', s:menu_name.'.&Pyclewn.Help', '', '', ':Chelp') endif " --------------------------------------------------[ 100 help exe 'amenu '.s:menu_prio.'.100 '.escape(s:menu_name.'.-100-', '\ '). ' ' exe 'amenu '.s:menu_prio.'.100.1 '. \ escape(s:menu_name.'.&Help.&Contents', '\ '). \ ' :help lh-cpp-readme.txt' exe 'amenu '.s:menu_prio.'.100.2 '. \ escape(s:menu_name.'.&Help.&Features', '\ '). \ ' :help lh-cpp-features' exe 'amenu '.s:menu_prio.'.100.3 '. \ escape(s:menu_name.'.&Help.&First Steps', '\ '). \ ' :help lh-cpp-first-steps' exe 'amenu '.s:menu_prio.'.100.20.10 '. \ escape(s:menu_name.'.&Help.Code &snippets.&Brackets', '\ '). \ ' :help brackets-for-C' exe 'amenu '.s:menu_prio.'.100.20.20 '. \ escape(s:menu_name.'.&Help.Code &snippets.&C snippets', '\ '). \ ' :help C_control-statements' exe 'amenu '.s:menu_prio.'.100.20.20 '. \ escape(s:menu_name.'.&Help.Code &snippets.&C++ snippets', '\ '). \ ' :help C++_control-statements' exe 'amenu '.s:menu_prio.'.100.20.100 '. \ escape(s:menu_name.'.&Help.Code &snippets.-100-', '\ '). ' ' exe 'amenu '.s:menu_prio.'.100.20.100 '. \ escape(s:menu_name.'.&Help.Code &snippets.&Placeholders', '\ '). \ ' :help markers' exe 'amenu '.s:menu_prio.'.100.50.10 '. \ escape(s:menu_name.'.&Help.&Wizards.&Accessors', '\ '). \ ' :help C++_accessors' exe 'amenu '.s:menu_prio.'.100.50.20 '. \ escape(s:menu_name.'.&Help.&Wizards.&Goto Implementation', '\ '). \ ' :help C++_jump_implementation' exe 'amenu '.s:menu_prio.'.100.50.30 '. \ escape(s:menu_name.'.&Help.&Wizards.&Override function', '\ '). \ ' :help C++_Override' exe 'amenu '.s:menu_prio.'.100.50.40 '. \ escape(s:menu_name.'.&Help.&Wizards.&Doxygen function', '\ '). \ ' :help C++_function_doxygenation' exe 'amenu '.s:menu_prio.'.100.50.50 '. \ escape(s:menu_name.'.&Help.&Wizards.&C++ Templates', '\ '). \ ' :help C++_templates' " -> class " -> enum generator exe 'amenu '.s:menu_prio.'.100.50.100 '. \ escape(s:menu_name.'.&Help.&Wizards.-100-', '\ '). ' ' exe 'amenu '.s:menu_prio.'.100.50.100 '. \ escape(s:menu_name.'.&Help.&Wizards.mu&Template', '\ '). \ ' :help mu-template' exe 'amenu '.s:menu_prio.'.100.80 '. \ escape(s:menu_name.'.&Help.See &Unmatched functions', '\ '). \ ' :help C++_unmatched_functions' exe 'amenu '.s:menu_prio.'.100.90 '. \ escape(s:menu_name.'.&Help.-90-', '\ '). ' ' exe 'amenu '.s:menu_prio.'.100.90 '. \ escape(s:menu_name.'.&Help.&API', '\ '). \ ' :help lh-cpp-API' " Functions {{{1 " Functions }}}1 "------------------------------------------------------------------------ let &cpo=s:cpo_save "============================================================================= " vim600: set fdm=marker: ================================================ FILE: ftplugin/c/c_mu-template_api.vim ================================================ "============================================================================= " File: ftplugin/c/c_mu-template_api.vim {{{1 " Author: Luc Hermitte " " Version: 2.2.0 " Created: 14th Apr 2006 " Last Update: 16th Jan 2019 "------------------------------------------------------------------------ " Description: " Provides API functions used in mu-template's C template-files. " " - C_nl_before_bracket() that returns the text to insert before a " bracket according to the option |g:c_nl_before_bracket| " - C_nl_before_curlyB() that returns the text to insert before a " curly-bracket according to the option |g:c_nl_before_bracket| " "------------------------------------------------------------------------ " Installation: See |lh-cpp-readme.txt| " Dependancies: mu-template (=> lh-map-tools, searchInRuntime) " TODO: move to an autoload plugin " }}}1 "============================================================================= "============================================================================= " Avoid global reinclusion {{{1 let s:cpo_save=&cpo set cpo&vim if exists("g:loaded_c_mu_template_api") \ && !exists('g:force_reload_c_mu_template_api') let &cpo=s:cpo_save finish endif let g:loaded_c_mu_template_api = 1 " Avoid global reinclusion }}}1 "------------------------------------------------------------------------ " Functions {{{1 " note: The space is needed after the "\n" to avoid mu-template from joining " the two next lines. function! C_nl_before_bracket() abort return lh#cpp#option#nl_before_bracket() ? "\n " : " " endfunction function! C_nl_before_curlyB() abort return lh#cpp#option#nl_before_curlyB() ? "\n " : " " endfunction " Functions }}}1 "------------------------------------------------------------------------ let &cpo=s:cpo_save "============================================================================= " vim600: set fdm=marker: ================================================ FILE: ftplugin/c/c_navigate_functions.vim ================================================ "============================================================================= " File: ftplugin/c/c_navigate_functions.vim {{{1 " Author: Luc Hermitte " " Version: 221 let s:k_version = 221 " Created: 08th Jul 2011 " Last Update: 16th Jan 2019 "------------------------------------------------------------------------ " Description: " mappings ]m, ]M, [m and [M to navigate into functions begin/end " "------------------------------------------------------------------------ " Installation: " Drop this file into {rtp}/lh-cpp/ftplugin/c " Requires Vim7+, lh-dev " History: " 08th Jul 2011: first implementation " TODO: «missing features» " }}}1 "============================================================================= " Buffer-local Definitions {{{1 " Avoid local reinclusion {{{2 let s:cpo_save=&cpo set cpo&vim if &cp || (exists("b:loaded_ftplug_c_navigate_functions") \ && (b:loaded_ftplug_c_navigate_functions >= s:k_version) \ && !exists('g:force_reload_ftplug_c_navigate_functions')) let &cpo=s:cpo_save finish endif let b:loaded_ftplug_c_navigate_functions = s:k_version " Avoid local reinclusion }}}2 "------------------------------------------------------------------------ " Local mappings {{{2 nnoremap NextFunctionStart :call NextFunction('s') if !hasmapto('NextFunctionStart', 'n') \ || exists('g:force_reload_ftplug_c_navigate_functions') nmap ]m NextFunctionStart endif nnoremap PrevFunctionStart :call PrevFunction('s') if !hasmapto('PrevFunctionStart', 'n') \ || exists('g:force_reload_ftplug_c_navigate_functions') nmap [m PrevFunctionStart endif nnoremap NextFunctionEnd :call NextFunction('e') if !hasmapto('NextFunctionEnd', 'n') \ || exists('g:force_reload_ftplug_c_navigate_functions') nmap ]M NextFunctionEnd endif nnoremap PrevFunctionEnd :call PrevFunction('e') if !hasmapto('PrevFunctionEnd', 'n') \ || exists('g:force_reload_ftplug_c_navigate_functions') nmap [M PrevFunctionEnd endif "============================================================================= " Global Definitions {{{1 " Avoid global reinclusion {{{2 if exists("g:loaded_ftplug_c_navigate_functions") \ && (g:loaded_ftplug_c_navigate_functions >= s:k_version) \ && !exists('g:force_reload_ftplug_c_navigate_functions') let &cpo=s:cpo_save finish endif let g:loaded_ftplug_c_navigate_functions = s:k_version " Avoid global reinclusion }}}2 "------------------------------------------------------------------------ " Functions {{{2 " Note: most filetype-global functions are best placed into " autoload/«your-initials»/c/«navigate_functions».vim " Keep here only the functions are are required when the ftplugin is " loaded, like functions that help building a vim-menu for this " ftplugin. function! s:NextFunction(start_or_end) abort let line = line('.') let info = lh#dev#__FindFunctions(line) let crt_function = info.idx " function starting just after the current line let lFunctions = info.fn if crt_function == -1 throw "No known function after line ".line." in ctags base" endif let first_line = lFunctions[crt_function].line if a:start_or_end == 's' exe first_line else " we need to be sure the end of the previous function is < line let prev_end = lh#dev#__FindEndFunc(lFunctions[crt_function-1].line)[1] if prev_end <= line let last_line = lh#dev#__FindEndFunc(first_line) exe last_line[1] else exe prev_end endif endif endfunction function! s:PrevFunction(start_or_end) abort let line = line('.') let info = lh#dev#__FindFunctions(line) let crt_function = info.idx " function starting just after the current line let lFunctions = info.fn if crt_function == 0 throw "No known function before line ".line." in ctags base" endif let crt_function -= 1 let first_line = lFunctions[crt_function].line if a:start_or_end == 's' while first_line >= line let crt_function -= 1 let first_line = lFunctions[crt_function].line endwhile exe first_line else let last_line = lh#dev#__FindEndFunc(first_line) while last_line[1] >= line " "while" because sometimes tags are dedoubled let crt_function -= 1 let first_line = lFunctions[crt_function].line let last_line = lh#dev#__FindEndFunc(first_line) endwhile exe last_line[1] endif endfunction " Functions }}}2 "------------------------------------------------------------------------ let &cpo=s:cpo_save "============================================================================= " vim600: set fdm=marker: ================================================ FILE: ftplugin/c/c_pvs-2-qf.vim ================================================ "============================================================================= " File: ftplugin/c/c_pvs-2-qf.vim {{{1 " Author: Luc Hermitte " " Version: 221 let s:k_version = 221 " Created: 10th Jul 2012 " Last Update: 16th Jan 2019 "------------------------------------------------------------------------ " Description: " «description» " "------------------------------------------------------------------------ " Installation: " Drop this file into {rtp}/ftplugin/c " Requires Vim7+ " «install details» " History: «history» " TODO: «missing features» " }}}1 "============================================================================= " Buffer-local Definitions {{{1 " Avoid local reinclusion {{{2 let s:cpo_save=&cpo set cpo&vim if &cp || (exists("b:loaded_ftplug_c_pvs_2_qf") \ && (b:loaded_ftplug_c_pvs_2_qf >= s:k_version) \ && !exists('g:force_reload_ftplug_c_pvs_2_qf')) let &cpo=s:cpo_save finish endif let b:loaded_ftplug_c_pvs_2_qf = s:k_version " Avoid local reinclusion }}}2 "------------------------------------------------------------------------ " Local commands {{{2 command! -b -nargs=1 -complete=file PVSLoad call s:PVSLoad("") command! -b -nargs=* PVSIgnore call s:PVSAddFilters() command! -b -nargs=+ PVSShow call s:PVSDelFilters() command! -b -nargs=0 PVSRedraw call s:ReDisplay() "============================================================================= " Global Definitions {{{1 " Avoid global reinclusion {{{2 if exists("g:loaded_ftplug_c_pvs_2_qf") \ && (g:loaded_ftplug_c_pvs_2_qf >= s:k_version) \ && !exists('g:force_reload_ftplug_c_pvs_2_qf') let &cpo=s:cpo_save finish endif let g:loaded_ftplug_c_pvs_2_qf = s:k_version " Avoid global reinclusion }}}2 "------------------------------------------------------------------------ " Functions {{{2 " Note: most filetype-global functions are best placed into " autoload/«your-initials»/c/«c_pvs_2_qf».vim " Keep here only the functions are are required when the ftplugin is " loaded, like functions that help building a vim-menu for this " ftplugin. let s:xsl = lh#path#glob_as_list(&rtp, 'script/PVS2qf.xsl')[0] " Function: s:PVSLoad(plog) {{{3 function! s:PVSLoad(plog) abort let xsltproc = lh#option#get('xsltproc', 'xsltproc') if !executable(xsltproc) throw "Sorry <" . xsltproc . "> is not a valid executable. Please set g:xsltproc or $PATH" endif if !filereadable(a:plog) throw "PVS-Studio file <".a:plog."> cannot be read." endif let errors = system(xsltproc . ' ' . s:xsl . ' ' . a:plog) let errors = substitute(errors, '\n\|\r', '', 'g') silent! unlet s:qf let s:qf = eval(errors) call s:ReDisplay() endfunction if !exists('s:filters_nr') " filter for error numbers let s:filters_nr = [] endif if !exists('s:filters_mess') " filter for messages let s:filters_mess = [] endif " Function: s:PVSAddFilters(filters...) {{{3 function! s:PVSAddFilters(...) abort if len(a:000) == 0 echo "Errors ignored are: " . join(map(copy(s:filters_nr), '"V".v:val'), ', ') . ', and messages containing: ' . join(s:filters_mess, ', ') else for pat in a:000 if pat =~ '^\d\+$' let s:filters_nr += [pat] else let s:filters_mess += [pat] endif endfor call s:ReDisplay() endif endfunction " Function: s:PVSDelFilters(filters...) {{{3 function! s:PVSDelFilters(...) abort let to_remove_nr = [] let to_remove_mess = [] for pat in a:000 if pat =~ '^\d\+$' let to_remove_nr += [pat] else let to_remove_mess += [pat] endif call filter(s:filters_nr, 'match(to_remove_nr, v:val) < 0') call filter(s:filters_mess, 'match(to_remove_mess, v:val) < 0') endfor call s:ReDisplay() endfunction " Function: s:ReDisplay() {{{3 function! s:ReDisplay() abort let qf = filter(copy(s:qf), 'match(s:filters_nr, v:val.nr)<0') call filter(qf, 'lh#list#find_if(s:filters_mess, escape(string(v:val.text), "[") . "=~ v:1_")<0') call setqflist(qf) Copen " from BTW call lh#common#warning_msg(len(qf).'/'.len(s:qf).' warnings found') endfunction " }}}1 "------------------------------------------------------------------------ let &cpo=s:cpo_save "============================================================================= " vim600: set fdm=marker: ================================================ FILE: ftplugin/c/c_set.vim ================================================ " ======================================================================== " File: ftplugin/c/c_set.vim " Author: Luc Hermitte " " Version: 2.1.3 let s:k_version = 213 " Last Update: 28th Oct 2015 " " Purpose: ftplugin for C (-like) programming " "------------------------------------------------------------------------ " Installation: See |lh-cpp-readme.txt| " Dependencies: " LoadHeaderFile.vim " flist & flistmaps.vim -- Dr Chips " VIM >= 6.00 only " ======================================================================== " 4 log: " 14th Apr 2007: &isk-=- " for changelog: 02nd Jun 2006 -> suffixesadd " ======================================================================== " Buffer local definitions {{{1 " ======================================================================== if exists("b:loaded_c_set") && !exists('g:force_reload_c_set') finish endif let b:loaded_c_set = s:k_version let s:cpo_save = &cpo set cpo&vim " ------------------------------------------------------------------------ " Includes {{{ " ------------------------------------------------------------------------ source $VIMRUNTIME/ftplugin/c.vim let b:did_ftplugin = 1 " }}} " ------------------------------------------------------------------------ " Options to set {{{ " ------------------------------------------------------------------------ " Note: these options can be overrided into a ftplugin placed in an after/ " directory. " setlocal formatoptions=croql setlocal cindent setlocal cinoptions=g0,t0 setlocal define=^\(#\s*define\|[a-z]*\s*const\(expr\)\=\s*[a-z]*\) setlocal comments=sr:/*,mb:*,exl:*/,:///,:// " setlocal isk+=# " so #if is considered as a keyword, etc " setlocal isk-=- " so ptr- (in ptr->member) is not " setlocal isk-=< " setlocal isk-=> " setlocal isk-=: setlocal isk=#,a-z,A-Z,48-57,_ setlocal suffixesadd+=.h,.c setlocal cmdheight=3 setlocal nosmd " Dictionary from Dr.-Ing. Fritz Mehner let s:dictionary=expand(":p:h").'/word.list' if filereadable(s:dictionary) let &l:dictionary=s:dictionary setlocal complete+=k endif setlocal complete-=i " }}} " ------------------------------------------------------------------------ " File loading {{{ " ------------------------------------------------------------------------ " " Things on :A and :AS ""so $VIM/macros/a.vim " ""so :p:h/LoadHeaderFile.vim if exists("*LoadHeaderFile") nnoremap \ :call LoadHeaderFile(getline('.'),0) inoremap \ :call LoadHeaderFile(getline('.'),0) endif " flist (Dr Chips) ""so :p:h/flistmaps.vim if filereadable(expand("hints")) au BufNewFile,BufReadPost *.h,*.ti,*.inl,*.c,*.C,*.cpp,*.CPP,*.cxx \ so hints endif " }}} " ------------------------------------------------------------------------ "}}}1 " ======================================================================== let &cpo = s:cpo_save "============================================================================= " vim600: set fdm=marker: ================================================ FILE: ftplugin/c/c_show_scope.vim ================================================ "============================================================================= " File: ftplugin/c/c_show_scope.vim {{{1 " Author: Luc Hermitte " " Version: 2.2.1. let s:k_version = '221' " Created: 29th May 2017 " Last Update: 16th Jan 2019 "------------------------------------------------------------------------ " Description: " Display the context on the current function/namespace/class/... " "------------------------------------------------------------------------ " History: «history» " TODO: «missing features» " }}}1 "============================================================================= " Buffer-local Definitions {{{1 " Avoid local reinclusion {{{2 let s:cpo_save=&cpo set cpo&vim if &cp || (exists("b:loaded_ftplug_c_show_scope") \ && (b:loaded_ftplug_c_show_scope >= s:k_version) \ && !exists('g:force_reload_ftplug_c_show_scope')) let &cpo=s:cpo_save finish endif let b:loaded_ftplug_c_show_scope = s:k_version " Avoid local reinclusion }}}2 "------------------------------------------------------------------------ " Local mappings {{{2 nnoremap sc :echo lh#cpp#analyse#context() " }}}1 "------------------------------------------------------------------------ let &cpo=s:cpo_save "============================================================================= " vim600: set fdm=marker: ================================================ FILE: ftplugin/c/c_snippets.vim ================================================ "============================================================================= " File: ftplugin/c/c_snippets.vim {{{1 " Author: Luc Hermitte " " License: GPLv3 with exceptions " " Version: 2.2.0 let s:k_version = '220' " Created: 14th Apr 2008 " Last Update: 30th Apr 2019 "------------------------------------------------------------------------ " Description: Snippets of C Control Statements " "------------------------------------------------------------------------ " Dependencies: lh-vim-lib " a.vim -- alternate files " VIM >= 7.3 only " " History: " 06th,26th Mar 2006: InsertReturn() for smart insertion of return. " for changelog: 27th Jun 2006 -> C_SelectExpr4Surrounding used in " mappings " TODO: missing features " }}}1 "============================================================================= " Buffer-local Definitions {{{1 " Avoid local reinclusion {{{2 if (exists("b:loaded_ftplug_c_snippets") && !exists('g:force_reload_ftplug_c_snippets')) || get(g:, 'lh_cpp_snippets', 1) == 0 finish endif let s:cpo_save=&cpo set cpo&vim let b:loaded_ftplug_c_snippets = s:k_version " Avoid local reinclusion }}}2 "------------------------------------------------------------------------ " Local mappings {{{2 " Some C++ abbreviated Keywords {{{3 " ------------------------------------------------------------------------ " Are you also dyslexic ? inoreab ocnst const inoreab earse erase " C keywords {{{3 " ------------------------------------------------------------------------ " Pre-processor " "-- insert "#define" at start of line " iab =lh#map#no_context("\ ",'\0i#define') iab #d =lh#map#no_context("#d ",'\0i#define') "-- insert "#include" at start of line " iab =lh#map#no_context("\ ",'\0i#include') iab #n =lh#map#no_context("#n ",'\0i#include') "-- insert "#ifdef/endif" at start of line iab #i =lh#map#no_context('#i ','\0i#ifdef') iab #e =lh#map#no_context("#e ",'\0i#endif') "-- surrounds with "#if 0 ... endif" :Brackets #if\ 0 #endif -insert=0 -nl -trigger=0 xmap 0 nmap 0 :Brackets #if\ 0 #else!mark!\n#endif -insert=0 -nl -trigger=1 xmap 1 nmap 1 " ------------------------------------------------------------------------ " Control statements {{{3 " ------------------------------------------------------------------------ " nnoremap C_SelectExpr4Surrounding :call lh#cpp#snippets#select_expr_4_surrounding() " --- if ---------------------------------------------------------{{{4 "--if insert "if" statement {{{5 Inoreabbr if =lh#cpp#snippets#def_abbr('if ', \ '\if(!cursorhere!){!mark!}!mark!') "--,if insert "if" statement xnoremap if \ @=lh#style#surround('if(!cursorhere!){', '}!mark!', \ 0, 1, '', 1, 'if ') xnoremap if \ @=lh#style#surround('if(', '!cursorhere!) {!mark!}!mark!', \ 0, 1, '', 1, 'if ') nmap if Vif nmap if \ C_SelectExpr4Surroundingif "--elif insert else if () { ... } {{{5 Inoreabbr elif =lh#cpp#snippets#def_abbr('elif ', \ '\else if(!cursorhere!) {!mark!}!mark!') "--,elif insert else clause of if statement with following if statement xnoremap elif \ @=lh#style#surround('else if(!cursorhere!){', '}!mark!', \ 0, 1, '', 1, 'elif ') xnoremap elif \ @=lh#style#surround('else if(', '!cursorhere!){!mark!}!mark!', \ 0, 1, '', 1, 'elif ') nmap elif \ C_SelectExpr4Surroundingelif nmap elif Velif "--else insert else clause of if statement {{{5 Inoreabbr else =lh#cpp#snippets#insert_if_not_before('else ', \ '\else{!cursorhere!}!mark!', 'if') "--,else insert else clause of if statement xnoremap else \ @=lh#style#surround('else {', '}', \ 0, 1, '``l', 1, 'else ') nmap else Velse "--- for ---------------------------------------------------------{{{4 "--for insert "for" statement " TODO: pb when c_nl_before_bracket = 1, cursor is not placed correctly Inoreabbr for =lh#cpp#snippets#def_abbr('for ', \ { \ '! lh#cpp#use_cpp11()': '\for(!cursorhere!;!mark!;!mark!){!mark!}!mark!', \ ' lh#cpp#use_cpp11()': '\for(!cursorhere!){!mark!}!mark!' \ }) "--,for insert "for" statement xnoremap for \ @=lh#style#surround('for(!cursorhere!;!mark!;!mark!){', '}!mark!', \ 0, 1, '', 1, 'for ') nmap for Vfor "--- while -------------------------------------------------------{{{4 "--while insert "while" statement Inoreabbr while =lh#cpp#snippets#def_abbr('while ', \ '\while(!cursorhere!){!mark!}!mark!') "--,while insert "while" statement xnoremap wh \ @=lh#style#surround('while(!cursorhere!){', '}!mark!', \ 0, 1, '', 1, 'while ') xnoremap wh \ @=lh#style#surround('while(', \ '!cursorhere!){!mark!}!mark!', \ 0, 1, '', 1, 'while ') " Note: \lcw is used to strip every spaces at the beginning of the " selected-area nmap while Vwh nmap while \ C_SelectExpr4Surroundingwh "--- do ----------------------------------------------------------{{{4 "--do insert "do" statement Inoreabbr do =lh#cpp#snippets#def_abbr('do ', \ '\do{!cursorhere!}while(!mark!);!mark!') "--,do insert "do" statement xnoremap do \ @=lh#style#surround('do{', '!cursorhere!}while(!mark!);!mark!', \ 0, 1, '', 1, 'do ') xnoremap \ @=SurroundBySubstitute('do{', '!cursorhere!}while(!mark!);!mark!', \ 0, 1, '', 1, 'do ') " problem here with fix_indent !!! xnoremap do \ @=Surround('do{!cursorhere!}while(', \ ');!mark!', \ 0, 1, '', 1, 'do ') xnoremap d2 \ @=SurroundBySubstitute('do{!cursorhere!}while(', \ ');!mark!', \ 0, 1, '', 1, 'do ') " Note: \lcw is used to strip every spaces at the beginning of the " selected-area nmap do Vdo nmap do \ C_SelectExpr4Surroundingdo "--- switch ------------------------------------------------------{{{4 "--switch insert "switch" statement Inoreabbr switch =lh#cpp#snippets#def_abbr('switch ', \ '\switch(!cursorhere!){!mark!}!mark!') "--,switch insert "switch" statement xnoremap switch \ @=lh#style#surround('switch(!cursorhere!){case !mark!:', \ '}!mark!', 1, 1, '', 1, 'switch ') nmap switch Vswitch "--- {\n} --------------------------------------------------------{{{4 " xnoremap { " \ @=lh#style#surround('{!cursorhere!', '}!mark!', " \ 1, 1, '', 1, ',{ ') " nmap { V{ " --- return -----------------------------------------------------{{{4 "-- insert "return ;" inoremap =lh#cpp#snippets#insert_return() " --- ?: ---------------------------------------------------------{{{4 "-- ?: insert "? : ;" inoremap ?: =lh#map#build_map_seq('() ?!mark!:!mark!\F(a') "--- Commentaires automatiques -----------------------------------{{{4 "--/* insert /**/ Brackets /* */ -visual=0 Brackets /* */ -visual=0 -trigger= "--<*M-v>- Surrounds a selection (/word) with C comments. Brackets /* */ -insert=0 -trigger= "--/*- insert /*-----[ ]-------*/ inoreab /- 0/*75a-a*/45R[ "--/*= insert /*=====[ ]=======*/ inoreab /= 0/*75a=a*/45R[ " }}}1 "------------------------------------------------------------------------ let &cpo=s:cpo_save "============================================================================= " vim600: set fdm=marker: ================================================ FILE: ftplugin/c/c_stl.vim ================================================ "============================================================================= " File: ftplugin/c/c_stl.vim " Author: Luc Hermitte " " Version: 1.1.0 " Created: 24th oct 2002 " Last Update: $Date$ "------------------------------------------------------------------------ " Description: Show current the name of the current function, we are within, " on status line. " "------------------------------------------------------------------------ " Installation: See |lh-cpp-readme.txt| "============================================================================= " Local Definitions: {{{ " Avoid reinclusion finish " deactivated because it could be very, very slow in some cases if exists('b:loaded_ftplug_c_stl') | finish | endif let b:loaded_ftplug_c_stl = 1 " let s:cpo_save=&cpo set cpo&vim " "------------------------------------------------------------------------ " setlocal stl=%{C_ShowFuncName()} " setlocal statusline=%<%f%h%{1==&modified?'[+]':''}%r%=\ %-16(%l,%c%V\ %)\ %P " setlocal statusline=%-30(%<%f\ %h%{1==&modified?'[+]':''}%r%)%{C_ShowFuncName()}%=\ %-16(%l,%c%V\ %)\ %P setlocal statusline=%<%f\ %h%{1==&modified?'[+]':''}%r%{C_ShowFuncName()}%=\ %-16(%l,%c%V\ %)\ %P " }}} "============================================================================= " Global Definitions: {{{ if exists("g:loaded_c_stl") let &cpo=s:cpo_save finish endif let g:loaded_c_stl = 1 "------------------------------------------------------------------------ " Function: C_ShowFuncName() {{{ function! C_ShowFuncName() let s:type = '\<\I\i*\>' let s:name = '\%(::\)\=\<\I\i*\>\%(::\<\I\i*\>\)*' let s:param= '[^)]\+' " spaces, line-breaks, C comments or C++ comments let s:blan0='\%(//.*$\|\_s\|/\*.\{-}\*/\)*' let s:blank_ne0='\%(\_s\|/\*.\{-}\*/\|//.*$\)\+' " let s:blank0='\%(//.*$\|\_s\|/\*.\{-}\*/\)*' " let s:blank_ne0='\%(\_s\|/\*.\{-}\*/\|//.*$\)\+' " let s:blank = '\%('.s:blank0.'\)\@>' " let s:blank_ne = '\%('.s:blank_ne0.'\)\@>' let s:begin= '\%(\%^\|[;}]\)'.s:blank.'\zs' let s:function= s:type. s:blank_ne .s:name.s:blank \ .'(\%('.s:blank_ne.'\|'.s:param.'\)*)' \ .s:blank.'\%(\\)\='.s:blank " \ .'(\%('.s:param.'\)*)' let g:fn = s:function let l1 = 0 let l2 = line('.')+1 while 1 let l2 = searchpair( '{\_[^{]*\%<'.l2.'l', '', '}', 'bnW' ) if l2 <= 0 return '' | endif " let l1 = searchpair( s:function.'\%'.l2.'l{', '', '\%$', 'bnW' ) let l1 = searchpair( s:function.'\%'.l2.'l{', '', '}', 'bnW' ) if l1 > 0 | break | endif endwhile call confirm('l1='.l1, '&ok', 1) " \ what_is_good_to_skip_comments) " ... then getlines from line l (if > 0) to '{'. if l1 <= 0 | return '' | endif let l = exists('r') ? r : '' let ln=line('$') while l1 < ln let l = l. substitute(getline(l1), s:blank_ne, ' ', 'g') if -1 != match(l, '{') let l = substitute(l, '\s\+\|{.*$', ' ', 'g') return ' -> '.l endif let l1 = l1 + 1 endwhile endfunction " }}} "------------------------------------------------------------------------ let &cpo=s:cpo_save " }}} "============================================================================= " vim600: set fdm=marker: ================================================ FILE: ftplugin/c/c_switch-enum.vim ================================================ "============================================================================= " File: ftplugin/c/c_switch-enum.vim {{{1 " Author: Luc Hermitte " " License: GPLv3 with exceptions " " Version: 2.0.0 " Created: 24th Jun 2006 " Last Update: $Date$ "------------------------------------------------------------------------ " Description: " Builds a switch statement from all the possible values that define an " enum. " "------------------------------------------------------------------------ " Requirements: " Vim 7.0+ " lh-dev, mu-template, an up-to-date ctags database " word_tools.vim " " TODO: " - indirections with C typedef definitions " -> typedef enum { ... } ; " - Work with embedded C++ scopes " - Use libclang when available " Cannot manage: " - the order of enumerated values, try to see with libclang " " }}}1 "============================================================================= " Avoid buffer reinclusion {{{1 let s:cpo_save=&cpo set cpo&vim if exists('b:loaded_ftplug_switch_enum') \ && !exists('g:force_reload_c_switch_enum') let &cpo=s:cpo_save finish endif let b:loaded_ftplug_switch_enum = 200 " }}}1 "------------------------------------------------------------------------ " Commands and mappings {{{1 command! -b -nargs=0 SwitchEnum call lh#cpp#enum#expand_enum_to_switch() inoremap SwitchEnum :SwitchEnum if !hasmapto('SwitchEnum', 'i') imap se SwitchEnum endif " Commands and mappings }}}1 "============================================================================= "------------------------------------------------------------------------ let &cpo=s:cpo_save "============================================================================= " vim600: set fdm=marker: ================================================ FILE: ftplugin/c/flistmaps.vim ================================================ " flist.vim maps for Vim " Author : Charles E. Campbell, Jr. " Copyright: Charles E. Campbell, Jr. " License : refer to the file for flist " if !exists("g:loaded_flistmaps_vim") let g:loaded_flistmaps_vim = 1 " Make various lists of C/C++ functions " \p? prototypes : \[px]g: globals \pc: comment \pp: all prototypes " \x? externs : \[px]s: statics \xx: all externs nnoremap \pc :w:!${CECCMD}/flist -c % >tmp.vim:r tmp.vim:!rm tmp.vim nnoremap \pg :w:!${CECCMD}/flist -pg % >tmp.vim:r tmp.vim:!rm tmp.vim nnoremap \pp :w:!${CECCMD}/flist -p % >tmp.vim:r tmp.vim:!rm tmp.vim nnoremap \ps :w:!${CECCMD}/flist -ps % >tmp.vim:r tmp.vim:!rm tmp.vim nnoremap \xg :w:!${CECCMD}/flist -xg % >tmp.vim:r tmp.vim:!rm tmp.vim nnoremap \xs :w:!${CECCMD}/flist -xs % >tmp.vim:r tmp.vim:!rm tmp.vim nnoremap \xx :w:!${CECCMD}/flist -x % >tmp.vim:r tmp.vim:!rm tmp.vim endif ================================================ FILE: ftplugin/c/keep_pound_if_path.vim ================================================ "============================================================================= " File: ftplugin/c/keep_pound_if_path.vim {{{1 " Author: Luc Hermitte " " Version: 2.2.1. let s:k_version = '221' " Created: 30th Jun 2016 " Last Update: 16th Jan 2019 "------------------------------------------------------------------------ " Description: " Remove the true/false path into a `#if ... #else ... #endif` construct " "------------------------------------------------------------------------ " History: «history» " TODO: «missing features» " }}}1 "============================================================================= " Buffer-local Definitions {{{1 " Avoid local reinclusion {{{2 let s:cpo_save=&cpo set cpo&vim if &cp || (exists("b:loaded_ftplug_keep_pound_if_path") \ && (b:loaded_ftplug_keep_pound_if_path >= s:k_version) \ && !exists('g:force_reload_ftplug_keep_pound_if_path')) let &cpo=s:cpo_save finish endif let b:loaded_ftplug_keep_pound_if_path = s:k_version " Avoid local reinclusion }}}2 "------------------------------------------------------------------------ " Local commands {{{2 command! -b -nargs=1 KeepPoundIfPath call lh#cpp#macros#keep() "============================================================================= "------------------------------------------------------------------------ " }}}1 "------------------------------------------------------------------------ let &cpo=s:cpo_save "============================================================================= " vim600: set fdm=marker: ================================================ FILE: ftplugin/c/previewWord.vim ================================================ "============================================================================= " File: ftplugin/c/previewWord.vim " Author: Georgi Slavchev " From " Adapted by Luc Hermitte " " Version: 2.2.1 let s:k_version = '2.2.1' " Created: ? " Last Update: 16th Jan 2019 "------------------------------------------------------------------------ " Description: {{{ " Have you ever tried to call a function which parameters you have forgotten? " Especially those long named and with long parameter list GTK+ functions like " gtk_menu_item_image_from_stock_new(..........) !!! " By accident I saw a function in Vim help. It's name was PreviewWord and it " allowed one to jump in the preview window to the tag for the word cursor is " on. " I _slightly_ modified this function not to need tags file, but to search " included files instead. I wrote another function, which uses the above said " one, which triggers PreviewWord when you open the parenthesis after a " function name. " }}} "------------------------------------------------------------------------ " Installation: See |lh-cpp-readme.txt| "============================================================================= " Buffer-local Definitions {{{1 " Avoid local reinclusion {{{2 let s:cpo_save=&cpo set cpo&vim if &cp || (exists("b:loaded_ftplug_previewWord") \ && (b:loaded_ftplug_previewWord >= s:k_version) \ && !exists('g:force_reload_ftplug_previewWord')) let &cpo=s:cpo_save finish endif let b:loaded_ftplug_previewWord = s:k_version " Avoid local reinclusion }}}2 " Settings {{{2 setlocal previewheight=4 "------------------------------------------------------------------------ " Mappings {{{2 inoremap PreviewWord :call PreviewWord() nnoremap PreviewWord :call PreviewWord() call lh#mapping#plug({'lhs': 'pw', 'rhs': 'PreviewWord', 'buffer':1}, 'in') inoremap ClosePreviewWindow :call ClosePreviewWindow() nnoremap ClosePreviewWindow :call ClosePreviewWindow() call lh#mapping#plug({'lhs': 'cpw', 'rhs': 'ClosePreviewWindow', 'buffer':1}, 'in') " I've (LH) desactivated the '(' key because I use a bracketing system. " inoremap =PreviewFunctionSignature() " g:preview_if_hold {{{2 let g:preview_if_hold = get(g:, 'preview_if_hold', 0) let s:toggle_menu = { \ 'variable': 'preview_if_hold', \ 'values': [0, 1], \ 'texts': [ "No", "Yes" ], \ 'menu': {'priority': '50.10', 'name': 'C++.preview_if_hold'} \} call lh#menu#def_toggle_item(s:toggle_menu) nnoremap TogglePreviewIfHold :Toggle Cpreview_if_hold call lh#mapping#plug({'lhs': 'ctpw', 'rhs': 'TogglePreviewIfHold'}, 'n') " autocommands {{{2 augroup PreviewWord au! au! CursorHold *.[ch] nested :call DoPreviewWord() augroup END "============================================================================= " Global Definitions {{{1 " Avoid global reinclusion {{{2 if exists("g:loaded_ftplug_previewWord") \ && (g:loaded_ftplug_previewWord >= s:k_version) \ && !exists('g:force_reload_ftplug_previewWord') let &cpo=s:cpo_save finish endif let g:loaded_ftplug_previewWord = s:k_version " Avoid global reinclusion "------------------------------------------------------------------------ " Functions {{{2 "------------------------------------------------------------------------ " s:ClosePreviewWindow() {{{3 function! s:ClosePreviewWindow() abort silent! wincmd P " jump to preview window if &previewwindow " if we really get there... silent wincmd c " close the window endif endfunction "------------------------------------------------------------------------ " s:PreviewWord() {{{3 " Note: " This is literally stolen from Vim help (|CursorHold-example|). " The only changes are: " (1) if w != "" becomes if w =~ "\k" " (2) exe "silent! ptag " . w becomes exe "silent! psearch " . w " * The first change prevents PreviewWord of searching while cursor is on some " non-keyword characters, e.g. braces, asterisks, etc. function! s:PreviewWord() abort if &previewwindow " don't do this in the preview window return endif " let w = expand("") " get the word under cursor let w = GetNearestKeyword() " get the word under cursor if w =~ '\k\+' " if there is one ':ptag' to it " Delete any existing highlight before showing another tag silent! wincmd P " jump to preview window if &previewwindow " if we really get there... match none " delete existing highlight wincmd p " back to old window endif " Try previewing a matching tag for the word under the cursor let v:errmsg = "" " doing a search this way (ie, pattern ended by '\s*(') gives a better " chance to find a function prototype exe "silent! psearch /" . w .'\s*(/' " exe "silent! psearch " . w if v:errmsg =~ "tag not found" return endif silent! wincmd P " jump to preview window if &previewwindow " if we really get there... if has("folding") silent! .foldopen " don't want a closed fold endif call search("$", "b") " to end of previous line let w = substitute(w, '\', '\\\', "") call search('\<\V' . w . '\>') " position cursor on match " Add a match highlight to the word at this position hi previewWord term=bold ctermbg=green guibg=green exe 'match previewWord "\%' . line(".") . 'l\%' . col(".") . 'c\k*"' wincmd p " back to old window endif endif endfunction "------------------------------------------------------------------------ " s:PreviewFunctionSignature() {{{3 " Note: " When you open a parenthesis after a function name, and at the line end, that " function's definition is previewed through PreviewWord(). " This is inspired from Delphi's CodeInsight technology. " Something similar (PreviewClassMembers) could be written for the C++ users, " for previewing the class members when you type a dot after an object name. " If somebody decides to write it, please, mail it to me. function! s:PreviewFunctionSignature() abort " let CharOnCursor = strpart( getline('.'), col('.')-2, 1) if col(".") == col("$") call s:PreviewWord() endif return "(" endfunction "------------------------------------------------------------------------ " s:DoPreviewWord(), automatically called when the cursor is holded {{{3 function! s:DoPreviewWord() abort if g:preview_if_hold call s:PreviewWord() endif endfunction " }}}1 let &cpo = s:cpo_save "============================================================================= " vim600: set fdm=marker: ================================================ FILE: ftplugin/c/word.list ================================================ __cpp_aggregate_bases __cpp_aggregate_nsdmi __cpp_aggregate_paren_init __cpp_alias_templates __cpp_aligned_new __cpp_attributes __cpp_binary_literals __cpp_capture_star_this __cpp_char8_t __cpp_conditional_explicit __cpp_constexpr __cpp_coroutines __cpp_decltype __cpp_decltype_auto __cpp_deduction_guides __cpp_delegating_constructors __cpp_enumerator_attributes __cpp_fold_expressions __cpp_generic_lambdas __cpp_guaranteed_copy_elision __cpp_hex_float __cpp_if_constexpr __cpp_impl_destroying_delete __cpp_impl_three_way_comparison __cpp_inheriting_constructors __cpp_init_captures __cpp_initializer_lists __cpp_inline_variables __cpp_lambdas __cpp_lib_addressof_constexpr __cpp_lib_allocator_traits_is_always_equal __cpp_lib_any __cpp_lib_apply __cpp_lib_array_constexpr __cpp_lib_as_const __cpp_lib_atomic_is_always_lock_free __cpp_lib_atomic_ref __cpp_lib_bind_front __cpp_lib_bit_cast __cpp_lib_bool_constant __cpp_lib_bounded_array_traits __cpp_lib_boyer_moore_searcher __cpp_lib_byte __cpp_lib_char8_t __cpp_lib_chrono __cpp_lib_chrono_udls __cpp_lib_clamp __cpp_lib_complex_udls __cpp_lib_concepts __cpp_lib_constexpr __cpp_lib_constexpr_swap_algorithms __cpp_lib_destroying_delete __cpp_lib_enable_shared_from_this __cpp_lib_erase_if __cpp_lib_exchange_function __cpp_lib_execution __cpp_lib_filesystem __cpp_lib_gcd_lcm __cpp_lib_generic_associative_lookup __cpp_lib_generic_unordered_lookup __cpp_lib_hardware_interference_size __cpp_lib_has_unique_object_representations __cpp_lib_hypot __cpp_lib_incomplete_container_elements __cpp_lib_integer_sequence __cpp_lib_integral_constant_callable __cpp_lib_interpolate __cpp_lib_invoke __cpp_lib_is_aggregate __cpp_lib_is_constant_evaluated __cpp_lib_is_final __cpp_lib_is_invocable __cpp_lib_is_null_pointer __cpp_lib_is_swappable __cpp_lib_launder __cpp_lib_list_remove_return_type __cpp_lib_logical_traits __cpp_lib_make_from_tuple __cpp_lib_make_reverse_iterator __cpp_lib_make_unique __cpp_lib_map_try_emplace __cpp_lib_math_special_functions __cpp_lib_memory_resource __cpp_lib_node_extract __cpp_lib_nonmember_container_access __cpp_lib_not_fn __cpp_lib_null_iterators __cpp_lib_optional __cpp_lib_parallel_algorithm __cpp_lib_quoted_string_io __cpp_lib_ranges __cpp_lib_raw_memory_algorithms __cpp_lib_result_of_sfinae __cpp_lib_robust_nonmodifying_seq_ops __cpp_lib_sample __cpp_lib_scoped_lock __cpp_lib_shared_mutex __cpp_lib_shared_ptr_arrays __cpp_lib_shared_ptr_weak_type __cpp_lib_shared_timed_mutex __cpp_lib_string_udls __cpp_lib_string_view __cpp_lib_three_way_comparison __cpp_lib_to_chars __cpp_lib_transformation_trait_aliases __cpp_lib_transparent_operators __cpp_lib_tuple_element_t __cpp_lib_tuples_by_type __cpp_lib_type_trait_variable_templates __cpp_lib_uncaught_exceptions __cpp_lib_unordered_map_try_emplace __cpp_lib_variant __cpp_lib_void_t __cpp_namespace_attributes __cpp_noexcept_function_type __cpp_nontype_template_args __cpp_nontype_template_parameter_auto __cpp_nontype_template_parameter_class __cpp_nsdmi __cpp_range_based_for __cpp_raw_strings __cpp_ref_qualifiers __cpp_return_type_deduction __cpp_rvalue_references __cpp_sized_deallocation __cpp_static_assert __cpp_structured_bindings __cpp_template_template_args __cpp_threadsafe_static_init __cpp_unicode_characters __cpp_unicode_literals __cpp_user_defined_literals __cpp_variable_templates __cpp_variadic_templates __cpp_variadic_using _heap abort absolute accumulate add_const add_const_t add_cv add_cv_t add_lvalue_reference add_lvalue_reference_t add_pointer add_pointer_t add_rvalue_reference add_rvalue_reference_t add_volatile add_volatile_t address adjacent_difference adjacent_find advance alignas aligned_storage aligned_storage_t aligned_union aligned_union_t alignment_of alignment_of_v alignof all all_of all_view allocation allocator allocator_type and and_eq any any_cast append apply argument arithmetic array as_bytes as_const as_writable_bytes asm assign assignable_from assignement assoc_laguerre assoc_laguerref assoc_laguerrel assoc_legendre assoc_legendref assoc_legendrel async atexit atomic atomic_ref auto back back_insert_iterator back_inserter bad_any_cast bad_cast bad_optional_access bad_typeid bad_variant_access basic_filebuf basic_ios basic_iostream basic_istream basic_istream_view basic_istringstream basic_ostream basic_ostringstream basic_osyncstream basic_regex basic_streambuf basic_string basic_string_view basic_stringbuf basic_stringstream basic_syncbuf begin bernoulli_distribution beta betaf betal bidirectional_iterator bidirectional_iterator_tag bidirectional_range binary_compose binary_function binary_negate binary_search bind bind1st bind2nd binder1st binder2nd binomial_distribution bit_vector bitand bitor bitset bitwise block bool bool_constant boolean break bucket bucket_count bucket_size byte call_once canonical capacity carries_dependency case catch cauchy_distribution cbegin cdata cend cerr char char_8t char_producer char_traits character chars_format chi_squared_distribution chrono cin class clear clock clog co_await co_return co_yield code command common common_range common_reference_with common_type common_type_t common_view common_with comp_ellint_1 comp_ellint_1f comp_ellint_1l comp_ellint_2 comp_ellint_2f comp_ellint_2l comp_ellint_3 comp_ellint_3f comp_ellint_3l compare compare_exchange_strong compare_exchange_weak compare_partial_order_fallback compare_strong_order_fallback compare_three_way compare_three_way_category compare_three_way_result compare_weak_order_fallback compl concat concept condition condition_variable condition_variable_any conditional conditional_t conjuction conjuction_t const const_cast const_iterator const_pointer const_reference const_reverse_iterator constant consteval constexpr constinit construct constructible_from contiguous_range continue conversion convertible_to copy copy_backward copy_constructible copy_file copy_if copy_n copy_options copy_symlink copyable count count_if counted cout crbegin create_directories create_directory create_directory_symlink create_hard_link create_symlink cref crend current_path cv_status cyl_bessel_i cyl_bessel_if cyl_bessel_il cyl_bessel_j cyl_bessel_jf cyl_bessel_jl cyl_bessel_k cyl_bessel_kf cyl_bessel_kl cyl_neumann cyl_neumannf cyl_neumannl dangling data decay decay_t declaration decltype declval decrement default default_constructible default_random_engine defined definition delete denorm_absent denorm_indeterminate denorm_min denorm_present deprecated deque derived_from description descriptor destroy destroy_at destroy_n destructible difference_type digits digits10 dimension directory_entry directory_iterator directory_options disable_if disable_if_t disable_recursion_pending discard_block_engine discrete_distribution disjunction disjunction_t distance distance_type divides do double drop_view drop_while drop_while_view duration dynamic_cast dynamic_extent elements elements_view ellint_1 ellint_1f ellint_1l ellint_2 ellint_2f ellint_2l ellint_3 ellint_3f ellint_3l else emplace emplace_back emplace_hint emplace_insert empty empty_view enable_if enable_if_t end ends_with enum epsilon equal equal_range equal_to equality_comparableequality_comparable_with equivalent erase error_type evaluation exchange exists expint expintf expintl explicit exponential_distribution export expression extent extent_v extention extern external extreme_value_distribution fallthrough false false_type fetch_add fetch_and fetch_or fetch_sub fetch_xor file_size file_status file_time_type file_type filebuf filename filesystem_error fill fill_n filter_view final find find_end find_first_not_of find_first_of find_if find_if_not find_last_not_of find_last_of first fisher_f_distribution float float_denorm_style float_round_style floating_point follow_directory_symlink for for_each format format_to format_to_n formatted formatted_size forward forward_iterator forward_iterator_tag forward_list forward_range fpos friend from_chars front front_insert_iterator function future future_category future_errc future_error future_status gamma_distribution generate generate_canonical generate_n generic_string generic_u16string generic_u32string generic_u8string generic_wstring geometric_distribution get_allocator get_id get_if get_temporary_buffer global goto greater greater_equal group_all group_exec group_read group_write handling hard_link_count has_denorm has_denorm_loss has_extension has_filename has_infinity has_inifinity has_parent_path has_quiet_NaN has_relative_path has_root_directory has_root_name has_root_path has_signaling_NaN has_stem has_value has_virtual_destructor hash hash_function hash_map hash_multimap hash_multiset hash_set hermite hermitef hermitel high_resolution_clock holds_alternative identifier identity if if_floatting_point ignore implementation import in_place in_place_index in_place_index_t in_place_t in_place_type in_place_type_t includes increment independent_bits_engine index indirect_relation indirect_result_t indirect_strict_weak_order indirect_unary_predicate indirectly_comparable indirectly_copyable indirectly_copyable_storable indirectly_movable indirectly_movable_storable indirectly_regular_unary_invocable indirectly_swappable indirectly_unary_invocable infinity initialization initializer_list inline inner_product inplace_merge input input_iterator input_iterator_tag input_range insert insert_iterator insert_or_assign inserter int int16_t int32_t int64_t int8_t int_fast16_t int_fast32_t int_fast64_t int_fast8_t int_least16_t int_least32_t int_least64_t int_least8_t integer_sequence integral integral_constant interface interger_sequence invocable io_errc ios iostream iostream_category iota iota_view is_absolute is_abstract is_abstract_v is_always_lock_free is_arithmetic is_arithmetic_v is_array is_array_v is_assignable is_assignable_v is_baseof is_baseof_v is_block_file is_bounded is_character_file is_class is_class_v is_compound is_compound_v is_const is_const_v is_constructible is_constructible_v is_convertible is_convertible_v is_copy_assignable is_copy_assignable_v is_copy_constructible is_copy_constructible_v is_default_constructible is_default_constructible_v is_destructible is_destructible_v is_directory is_ed is_ed_until is_empty is_empty_v is_enum is_enum_v is_eq is_exact is_fifo is_final is_final_v is_function is_function_v is_fundamental is_fundamental_v is_gt is_gteq is_heap is_heap_until is_heap_until_v is_heap_v is_iec559 is_integer is_integral is_integral_v is_literal_type is_lock_free is_lt is_lteq is_lvalue_reference is_member_function_pointer is_member_object_pointer is_member_pointer is_modulo is_move_assignable is_move_constructible is_neq is_nothrow_assignable is_nothrow_constructible is_nothrow_copy_assignable is_nothrow_copy_constructible is_nothrow_default_constructible is_nothrow_destructible is_nothrow_move_assignable is_nothrow_move_constructible is_null_pointer is_object is_other is_partioned is_permutation is_placeholder is_pod is_pointer is_polymorphic is_reference is_regular_file is_relative is_rvalue_reference is_same is_scalar is_signed is_socket is_specialized is_standard_layout is_symlink is_trivial is_trivially_assignable is_trivially_constructible is_trivially_copy_assignable is_trivially_copy_constructible is_trivially_copyable is_trivially_default_constructible is_trivially_destructible is_trivially_move_assignable is_trivially_move_constructible is_union is_unsigned is_void is_volatile istream istream_iterator istream_view istringstream iter_swap iterator iterator_category iterator_t iterator_traits join join_view key_comp key_eq keys keys_view knuth_b label laguerre laguerref laguerrel last last_write_time launch launder legendre legendref legendrel less less_equal lexical lexical_normal lexical_proximate lexical_relative lexicographical_compare lexicographical_compare_3way likely linear_congruential_engine list load load_factor local lock lock_guard logical logical_and logical_not logical_or lognormal_distribution long lookup loop lower_bound lowest lvalue make_any make_from_tuple make_heap make_iterator make_move_iterator make_pair make_preferred make_reverse_iterator make_shared make_signed make_signed_t make_tuple make_unique make_unsigned make_unsigned_t map mask match_flag_type match_results max max_align_t max_bucket_count max_digits10 max_element max_exponent max_exponent10 max_load_factor max_size maybe_unused mem_fun mem_fun1_ref_t mem_fun1_t mem_fun_ref mem_fun_ref_t mem_fun_t merge mergeable mersenne_twister_engine min min_element min_exponent min_exponent10 minmax minmax_element minstd_rand minstd_rand0 minus miscellaneous mismatch module modulus monostate movable move move_backward move_constructible move_if_noexcept move_iterator mt19937 mt19937_64 multimap multiplies multiset mutable mutex namespace native negate negation negation_t negative_binomial_distribution new next next_permutation no_unique_address nodiscard noexcept nofollow noncopyable none none_of noreturn normal_distribution not not_eq not_equal_to notation notify_all notify_all_at_thread_exit notify_one npos nth_element nullopt nullopt_t nullptr nullptr_t numeric_limits numerical offsetof once_flag operation operator optional or or_eq ostream ostream_iterator ostringstream osyncstream others_all others_exec others_read others_write output output_iterator output_iterator_tag output_range override owner_all owner_exec owner_read owner_write packaged_task pair parent_path partial partial_copy partial_order partial_ordering partial_sum partition partition_copy partition_point path perm_options permissions perms permutable piecewise_constant_distribution piecewise_construct piecewise_construct_t piecewise_linear_distribution placeholders plus pointer pointer_to_binary_function pointer_to_unary_function poisson_distribution pop pop_back pop_front pop_heap power precedence predicate preprocessing preprocessor prev prev_permutation priority_queue private program project1st project2nd projected promise protected proximate ptr_fun ptr_list ptr_map ptr_set ptr_vector ptrdiff_t public push_back push_heap queue quiet_NaN radix random random_access_iterator random_access_iterator_tag random_access_range random_device random_sample random_sample_n random_shuffle range range_difference_t range_reference_t range_rvalue_reference_t range_value_t ranges rank rank_v ranlux24 ranlux24_base ranlux48 ranlux48_base raw_storage_iterator rbegin read_symlink recursion recursive recursive_directory_iterator recursive_mutex ref ref_view reference reference_wrapper referential refresh regex regex_error regex_iterator regex_match regex_replace regex_search regex_token_iterator regex_traits register regular regular_invocable rehash reinterpret_cast relation relational relative relative_path remove remove_all remove_all_extents remove_all_extents_t remove_const remove_const_t remove_copy remove_copy_if remove_copy_if_t remove_copy_t remove_cv remove_cv_t remove_extent remove_extent_t remove_filename remove_if remove_if_t remove_pointer remove_pointer_t remove_prefix remove_reference remove_reference_t remove_suffix remove_t remove_volatile remove_volatile_t rename rend replace replace_copy replace_copy_if replace_extension replace_filename replace_if required_alignment requires reserve reset resize resize_file result_of result_of_t return return_temporary_buffer reverse reverse_bidirectional_iterator reverse_copy reverse_iterator reverse_view rfind riemann_zeta riemann_zetaf riemann_zetal root_directory root_name root_path rope rotate rotate_copy round_error round_indeterminate round_style round_to_nearest round_toward_infinity round_toward_neg_infinity round_toward_zero runtime_error safe_iterator_t safe_subrange_t same_as scope search search_n seed_seq select1st select2nd semiregular sentinel_t sequence_buffer set set_difference set_gid set_intersection set_symmetric_difference set_uid set_union shared_future shared_lock shared_mutex shared_ptr shared_timed_mutex short shrink_to_fit shuffle shuffle_order_engine signaling_NaN signed signed_integral single single_view size size_bytes size_t size_type sized_range sizeof skip_permission_denied sleep_for sleep_until slist sortable space space_info span sph_bessel sph_besself sph_bessell sph_legendre sph_legendref sph_legendrel sph_neumann sph_neumannf sph_neumannl split split_view stable_ stable_partition stack standard starts_with statement static static_assert static_cast status status_known steady_clock stem sticky_bit store streambuf streamoff streampos streamsize strict_weak_order string string_view stringbuf stringstream strong_order strong_ordering struct structure student_t_distribution sub_match subrange subspan substr subtract_with_carry_engine subtractive_rng swap swap_ranges swappableswappable_with switch symlink_status syncbuf syntax_option_type system system_clock system_error take take_view take_while take_while_view temp_directory_path template temporary_buffer this thread three_way_comparable three_way_comparable_with throw tie time time_point timed_mutex timed_recursive_mutex tinyness_before to_chars totally_orderedtotally_ordered_with transform transform_view traps true true_type try try_emplace try_lock tuple tuple_element tuple_size type_index type_info type_traits typedef typeid typename u16string u16string_view u32string u32string_view u8path u8string u8string_view uint16_t uint32_t uint64_t uint8_t uint_fast16_t uint_fast32_t uint_fast64_t uint_fast8_t uint_least16_t uint_least32_t uint_least64_t uint_least8_t uintmax_t unary_compose unary_function unary_negate undefined underlying_type underlying_type_t uniform_int_distribution uniform_real_distribution uninitialized_copy uninitialized_copy_n uninitialized_default_construct uninitialized_default_construct_n uninitialized_fill uninitialized_fill_n uninitialized_move uninitialized_move_n uninitialized_value_construct uninitialized_value_construct_n union unique unique_copy unique_lock unique_ptr unlikely unordered_map unordered_multimap unordered_multiset unordered_set unsigned unsigned_integral upper_bound using value value_comp value_or value_type valueless_by_exception values values_view variable variant variant_alternative variant_alternative_t variant_npos variant_size variant_size_v vector view view_interface viewable_range views virtual visit void void_t volatile wait wcerr wchar_t wcin wclog wcout weak_order weak_ordering weak_ptr weakly_canonical weibull_distribution wfilebuf what while wios wiostream wistream wistringstream wostream wostringstream wosyncstream wstreambuf wstreampos wstring_view wstringbuf wstringstream wsyncbuf xor xor_eq yield ================================================ FILE: ftplugin/cpp/changelog ================================================ [08 Dec 2005] {{{1 (*) cpp_set.vim {{{2 (*) mapping to => insert "typename" (after a '<', or after "typedef"), or "typedef" [26 Aug 2005] {{{1 (*) cpp_set.vim {{{2 (*) New visual mode mappings to convert C-style casts into C++ style casts => ,,sc ,,rc ,,cc ,,dc (*) todo {{{2 (*) Merge ,sc and ,,sc => auto detect a C-style cast to apply translation ; hint: looks like (.*).* [14th Apr 2005] {{{1 (*) common_brackets.vim (*) Triggers.vim can be installed into {rtp}/macros [02nd Feb 2005] {{{1 (*) ftplugin/cpp/cpp_set.vim (*) Does not expand `namespace' if there is a `using' on the same line (*) New vmappings for the vaious C++ castings -> ,dc ,sc ,rc ,sc ,,dc ,,sc ,,rc ,,sc (*) ftplugin/c/c_set.vim (*) New N&V mappings, on , that surround a selection (/word) with a C-comment (/*...*/) [31st Jan 2005] {{{1 (*) after/ftplugin/c/c_brackets.vim (*) `<' expands into `!mark!' after a `#include', `template', `typename', or a `xxxx_cast' [16th Jan 2005] {{{1 (*) ftplugin/c/c_set.vim (*) Don't expand #if anymore [22nd Nov 2004] {{{1 (*) plugin/bracketing_base.vim (*) New behaviour for !mark! in visual mode: If a marker is selected, then the marker is replaced by its contents. Otherwise the visual slection is wrapped into a marker. (*) New mappings !mark! and MarkersMark added to the normal mode. [25th Jul 2004] {{{1 (*) macros/options.vim {{{2 (*) New plugin: Fatorizes a very common function: LHOption() (*) ftplugin/c/c_compile.vim {{{2 (*) Requires: macros/options.vim (*) New Options: [bg]:key_make, key_execute and key_config -> override the default keybindings to , , (*) ftplugin/c/c_set.vim {{{2 (*) while: changed into wh (*) ftplugin/cpp/cpp_set.vim {{{2 (*) New mapping: "rbe" : reverse version of "be" (*) New abbreviation: "namespace" that expands into "namespace | {\n\n}" (*) Bug fix: namespace is correctly expanded when we select a marker. (*) Bug Fix: "try" is correctly expanded when c_nl_before_curlyB == 1 (*) Behaviour change: c_nl_before_curlyB also applies with '}' Modification noticeable with the abbreviation "try". [16th Jun 2004] {{{1 (*) ftpugin/c/c_compile.vim {{{2 (*) New ftplugin: Defines helper mappings to compile, execute and configure projects (*) Requires: ui-functions.vim (*) Takes advantage of: let-modeline.vim (not shipped) (*) mu-template {{{2 (*) Little improvements: with the function s:Include() (*) New templates: C++'s operators >> and << (*) misc_map.vim {{{2 (*) Bug fix in BuildMapSeq: the function was not compatible with LaTeX-Suite ; as LS mapped '!' in order to protect ``!, \`! and "`! => s/mapcheck/maparg/ [07th May 2004] {{{1 (*) misc_map.vim {{{2 (*) New function: Map4TheseContexts() (*) The default value for: the parameter {default_value} of MapContext() is now {key} (*) New function: Surround() Aimed to replace InsertAroundVisual() in the definition of mappings. This new function emulates :smap-pings : - when a marker/placeholder is selected, an insert mode mapping/abbreviation is used, - otherwise, a visual-mode mapping (that inserts text arround the selection) is used. (*) common_brackets.vim {{{2 (*) now compatible with Srinath Avadhanula's IMAP.vim (*) smarter: The behaviour of '\(' and '\%(' for Vim buffers has been changed. (*) c_set.vim & cpp_set.vim {{{2 (*) Rewritten: to use Surround() instead of InsertAroundVisual() [16th Mar 2004] {{{1 (*) cpp_set {{{2 (*) imap: -> boost:: (*) imap: -> luc_lib:: (*) n/vmap: ns -> "namespace{\n}" around bloc/line [13th Jan 2004] {{{1 (*) c_sep, cpp_set {{{2 (*) Def_Abbr_C() simplified => only two parameters now => Bug happening when loading the control-structure abbreviations fixed (*) Using InsertAroundVisual() instead of the old MapAroundVisualLine (*) cpp_set {{{2 (*) the abbreviations (try, catch) don't mess the search history anymore. [25th Sep 2003] {{{1 (*) c_set {{{2 (*) the abbreviations (if, for, switch, while) don't mess the search history anymore. [26th Aug 2003] {{{1 (*) c_set, cpp_set {{{2 (*) visual mappings behave correctly, even in select-mode (:h gV) (*) bracketing.base.vim {{{2 (*) New option: [bg]:marker_center (*) New mappings: !jump-and-del! !bjump-and-del! -> Always jump and delete the next/previous markers, whatever the options are. [28th Jul 2003] {{{1 (*) cpp_options, c_set {{{2 (*) b:nl_before_xxx changed into g:c_nl_before_xxx (*) cpp_InsertAccessors {{{2 (*) respects g:c_nl_before_curlyB But the definition of g:c_nl_before_curlyB must be done into ./cpp_options.vim. (*) new option: g:accessorCap that enables to tune the capitalization of the first letter of the attribute within accessor-names. -1 (lowcase), 0 (no change), 1 (upcase) (*) new options: g:accessor_comment_{get,set,ref}, g:accessor_comment_proxy_{get,set,ref} => customize the comments written for the various accessors. Note: the comment may be an empty string (*) cpp_InsertAccessors, cpp_BuildTemplate, cpp_GotoFunctionImpl {{{2 (*) bug fixed regarding automatic !jump! and Template [20th Jul 2003] {{{1 (*) misc_map.vim {{{2 (*) doxygen comments are correctly recognized as comments. [12th Jul 2003] {{{1 (*) doxygen.vim {{{2 (*) Michael Geddes's syntax file has been move to: {rtp}/syntax/ (*) c_set.vim {{{2 (*) Loads: doxygen.vim (*) cpp_options.vim {{{2 (*) comments added regarding b:nl_before_bracket [I know, it is not unique to C++ but concerns C as well] [03rd Jul 2003 -- 04th Jul 2003] {{{1 (*) c_set {{{2 (*) fix: the documentation wasn't find-able anymore (*) Two new boolean options : b:nl_before_bracket and b:nl_before_curlyB that specify wheither we require a newline character before the '(' and the '{' of the various control statements (if, for, while, ...) default values: false (0) (*) cpp_set {{{2 (*) Small changes in consequence (*) common_brackets.vim 4.0: {{{2 (*) New option: b:cb_jump_on_close that specify weither the mappings for the closing brackets are defined or not ; [default: true (1)] (*) Documentation {{{2 (*) Updated and minor changes. (*) todo {{{2 (*) "imap }" does not work correctly (*) the control statements should not mess up the search history (*) mutemplate... utf-8 & doc [... -- 09th Apr 2003] {{{1 (*) Mu-template 0.31 {{{2 (*) Documentation {{{2 (*) Little changes [10th oct 2002 -- 18th oct 2002] {{{1 (*) cpp_FindContextClass.vim {{{2 (*) Cpp_CurrentScope(l,'class') supports: - inheritance -> 'class A : xx B, xx C ... {' - and declaration on several lines of the previous inheritance text. (*) Cpp_SearchClassDefinition becomes obsolete. Instead, use Cpp_CurrentScope(lineNo, scope_type) to search for a namespace::class scope. (*) Functions that will return the list of the direct base classes of the current class. (*) Able to handle C-definitions like: "typedef struct foo{...} *PFoo,Foo;" (*) An inversion problem, with nested classes, fixed. (*) cpp_GotoFunctionImpl 0.6 {{{2 (*) Supports destructors (*) Supports namespaces: + If the zone where the function implementation is going to be inserted is within a namespace, then the scope of the function will be corrected. + The |search-implementation| feature is able to differentiate functions according to the namespace they are within, and thus it is able to jump to the right function. For instance: int NS::CL::FN(int i) {} // is NS::CL::FN namespace NS0 { int NS::CL::FN(int i) {} // is NS0::NS::CL:FN } (*) Checks whether the function is a pure virtual method and refuse to define an implementation in such cases ... (*) When searching for the implementation of a function within the .cpp file, comments before the signature will be ignored ; i.e. the cursor will move to the return-type. The difference is noticeable on virtual or static functions. (*) cpp_GotoFunctionImpl 0.5 {{{2 (*) The management of cpp_options.vim has been moved to another file. (*) Comments are completly ignored when searching for the implementation of a function. Actually, the match is done according to the list of type only -- even parameter names will be ignored. (*) Inlines functions (within the class def) (ie not prototypes) will be ignored (*) Enhancements and little bug corrections regaring default parameters (*) We can specify where we want the default implementation code to be written ; cf cpp_options.vim and g:cpp_FunctionPosition. (*) cpp_InsertAccessors.vim {{{2 (*) The management of cpp_options.vim has been moved to another file. (*) cpp_options-commands.vim 1.0 {{{2 (*) New file that will centralize options management (*) Mu-template 0.23 {{{2 (*) New global boolean ([0]/1) option: g:mt_IDontWantTemplatesAutomaticallyInserted that forbids mu-template to automatically insert templates when opening new files. Must be set once before mu-template.vim is sourced -> .vimrc (*) Documentation {{{2 (*) Updated (*) New sections: first steps, C++-options, ... }}}1 ================================================================== vim600: set fdm=marker: ================================================ FILE: ftplugin/cpp/cpp_AddMissingScope.vim ================================================ "============================================================================= " File: ftplugin/cpp/cpp_AddMissingScope.vim {{{1 " Author: Luc Hermitte " " Version: 2.2.1 let s:k_version = 221 " Created: 25th Jun 2014 " Last Update: 16th Jan 2019 "------------------------------------------------------------------------ " Description: " Given an identifier under the cursor, search for its scope (namespace, " ...) and insert it. " "------------------------------------------------------------------------ " }}}1 "============================================================================= " Buffer-local Definitions {{{1 " Avoid local reinclusion {{{2 let s:cpo_save=&cpo set cpo&vim if &cp || (exists("b:loaded_ftplug_cpp_AddMissingScope") \ && (b:loaded_ftplug_cpp_AddMissingScope >= s:k_version) \ && !exists('g:force_reload_ftplug_cpp_AddMissingScope')) let &cpo=s:cpo_save finish endif let b:loaded_ftplug_cpp_AddMissingScope = s:k_version " Avoid local reinclusion }}}2 "------------------------------------------------------------------------ " Local mappings {{{2 nnoremap AddMissingScope :call lh#cpp#scope#_add_missing() if !hasmapto('AddMissingScope', 'n') nmap AddMissingScope endif " }}}1 "------------------------------------------------------------------------ let &cpo=s:cpo_save "============================================================================= " vim600: set fdm=marker: ================================================ FILE: ftplugin/cpp/cpp_BuildTemplates.vim ================================================ " ======================================================================== " File: ftplugin/cpp/cpp_BuildTemplates.vim {{{1 " Author: Luc Hermitte " " License: GPLv3 with exceptions " " Version: 2.1.6 " Last Update: 03rd Nov 2015 "------------------------------------------------------------------------ " Description: description " "------------------------------------------------------------------------ " Installation: See |lh-cpp-readme.txt| " Dependencies: a.vim (Alternate files) " TODO: " * Correct the ftplugin to be VIM 6 fully compliant " * Delete what's redundant with Template's templates " }}}1 " ======================================================================== " ======================================================================== " Buffer local definitions {{{1 " ======================================================================== if exists("b:loaded_cpp_BuildTemplates_local_settings") && !exists('g:force_reload_cpp_BuildTemplates') finish endif let b:loaded_cpp_BuildTemplates_local_settings = 1 let s:cpo_save = &cpo set cpo&vim " ------------------------------------------------------------------------ " Commands {{{2 " ------------------------------------------------------------------------ " Command: :HEADER " Map shortcut: ;HE " Purpose: Insert the template for a header file (.h) plus a class " Parameter: <1> == Name of the main class of the file " Note: Use the same function than :CLASS for inserting the class " template. command! -buffer -nargs=1 HEADER :call Cpp_newHeaderFile() nnoremap ;HE :HEADER " " Command: :CLASS " Map shortcut: ;CL " Purpose: Insert the template for a class " Parameter: <1> == Name of the class command! -buffer -nargs=1 CLASS :call Cpp_newClass() nnoremap ;CL :CLASS " " Command: :BLINE " Map shortcut: ;BL " Purpose: Insert a 3 lines separator " Parameter: <1> == Title of the separation command! -buffer -nargs=1 BLINE :call Cpp_bigLine() nnoremap ;BL :BLINE " " Command: :MGROUP " Map shortcut: ;MGR " Purpose: Insert a group plus a separator line " Parameter: <1> == Name of the group command! -buffer -nargs=1 MGROUP :call Cpp_megagroup() nnoremap ;MGR :MGROUP " " Command: :GROUP " Map shortcut: ;GR " Purpose: Insert a group " Parameter: <1> == Name of the group command! -buffer -nargs=1 GROUP :call Cpp_group() nnoremap ;GR :GROUP " " Command: :ADDATTRIBUTE " Map shortcut: ;AA " Purpose: Insert an attribute plus its accessors to the current class command! -buffer -nargs=0 ADDATTRIBUTE :call Cpp_AddAttribute() nnoremap ;AA :ADDATTRIBUTE " " Command: :REACHINLINE " Map shortcut: ;RI " Purpose: Reach the location of inlines for the specified class command! -buffer -nargs=1 REACHINLINE :call Cpp_ReachInlinePart() nnoremap ;RI :REACHINLINE " ========================================================================== " Mappings {{{2 " ;GR inserts /**@name " */ " //@{ " //@} " suppose so=coqlr inoremap //@{ lh#map#insert_seq('//@{', \ '//@{\ !cursorhere!\@}') " \ '//@{\@}\O\\') " ======================================================================== " General Definitions {{{1 " ======================================================================== if exists("g:loaded_cpp_BuildTemplates") && !exists('g:force_reload_cpp_BuildTemplates') let &cpo = s:cpo_save finish endif let g:loaded_cpp_BuildTemplates = 1 " Constants {{{2 let s:header_includes_text = 'Includes' let s:header_inlines_text = 'Inlines' let s:header_inlines_type = '=' let s:header_inlining_text = 'Inlinings for ' let s:header_inlining_type = '=' let s:EqLine= '/*===========================================================================*/' let s:MnLine= '/*---------------------------------------------------------------------------*/' " Functions {{{2 inoremap /*1 0/*75a=a*/ function! s:Cpp_group(name) abort " {{{3 " TODO: use indent() silent put = ' /**'. lh#dox#tag('name') silent put = ' */' silent put = ' //@{' silent put = ' //@}' endfunction function! s:Cpp_bigLine(title) abort " {{{3 silent put = s:EqLine let pos = (79-lh#encoding#strlen(a:title)-4)/2 silent put = substitute(s:EqLine, \ '\(.\{'.pos.'}\).\{'.(lh#encoding#strlen(a:title)+4).'}\(.*\)$', \ '\1[ '.a:title.' ]\2', '') silent put = s:EqLine endfunction function! s:Cpp_littleLine(title) abort " {{{3 let pos = (79-lh#encoding#strlen(a:title)-4)/2 silent put = substitute(s:MnLine, \ '\(.\{'.pos.'}\).\{'.(lh#encoding#strlen(a:title)+4).'}\(.*\)$', \ '\1[ '.a:title.' ]\2', '') endfunction function! s:Cpp_megagroup(name) abort " {{{3 call s:Cpp_littleLine(a:name) call s:Cpp_group(a:name) endfunction function! s:Cpp_emptyLine(nb) abort " {{{3 let fo = &fo | set fo-=o exe "normal! ".a:nb."o\\" let &fo = fo endfunction function! s:Cpp_addGroup(emptyLine, name, access) abort " {{{3 if a:emptyLine != 0 call s:Cpp_emptyLine( a:emptyLine ) endif call s:Cpp_megagroup( a:name ) let fo = &fo | set fo-=o exe "normal! O".a:access."\" let &fo = fo endfunction function! s:Cpp_addMethod(name, sig) abort " {{{3 silent put = ' /* '.a:name.' */' silent put = ' '.a:sig endfunction " ========================================================================== " Search for parts {{{3 " ========================================================================== " Function: Cpp_search4line " Returns: line of the found pattern function! s:Cpp_search4line(title,type) abort " let v:errmsg = '' let str = '\/\*' . a:type . '*\[\s*' . a:title . '\s*\]' . a:type . '*\*\/' return search(str) " exe '/'.str ""let str = '/\*' . a:type . '*\[\s*' . a:title . '\s*\]' . a:type . '*\*/' ""exe '?'.str " return strlen(v:errmsg) != 0 endfunction " ========================================================================== " Add classes {{{3 " ========================================================================== function! s:Cpp_newClass(name) abort " if lh#brackets#usemarks() " let bg:usemarks = 0 " let recall_usemarks = 1 " else " let recall_usemarks = 0 " endif " class let old_foldenable = &foldenable set nofoldenable call s:Cpp_bigLine( "Class ".a:name ) silent put = 'class ' . a:name silent put = '{' " contructions , added after every other group because of reindentation call s:Cpp_addGroup(0, "Construction", "public:") call s:Cpp_addMethod("Argument-less constructor", a:name."();") call s:Cpp_addMethod("Copy constructor", a:name."(const ".a:name." & rhs);") call s:Cpp_addMethod("Copy operator", a:name."& operator=(const ".a:name." & rhs);") call s:Cpp_addMethod("Destructor", "virtual ~".a:name."();") " public methods call search('}') call s:Cpp_addGroup(1, "Public methods", "public:") " internal methods call search('}') call s:Cpp_addGroup(1, "Internal methods", "protected:") " Data call search('}') call s:Cpp_addGroup(1, "Data", "private:") " End of class call search('}') call s:Cpp_emptyLine( 1 ) call s:Cpp_littleLine( "End of class" ) silent put = '};' " if recall_usemarks == 1 | let gb:usemarks = 1 | endif let &foldenable = old_foldenable endfunction " ========================================================================== function! s:Cpp_newHeaderFile(name) abort " {{{3 " reinclusion call s:Cpp_bigLine( "Avoid re-inclusion") silent put = '#ifndef __'.toupper(a:name).'_H__' silent put = '#define __'.toupper(a:name).'_H__' call s:Cpp_emptyLine( 2 ) " Includes call s:Cpp_bigLine( s:header_includes_text ) if exists('*Marker_Txt') silent put = '// ' . Marker_Txt('Includes') endif call s:Cpp_emptyLine( 2 ) " Class call s:Cpp_newClass(a:name) " reinclusion normal! G call s:Cpp_emptyLine( 2 ) call s:Cpp_bigLine( "Avoid re-inclusion") silent $ put = '#endif' endfunction " ========================================================================== " Inlines {{{3 " ========================================================================== " Function: Cpp_fileType(name) {{{4 " Returns: A number indicating the kind of C++ file involved " 0 : header file ; 1 : inlines file ; 2 : other (.cpp & co) function! s:Cpp_fileType(name) abort if a:name =~'\.hh\=$' | return 0 elseif a:name =~ Cpp_FileExtension4Inlines() . '$' | return 1 else | return 2 endif endfunction " Function: Cpp_fileExtension(type) {{{4 function! s:Cpp_fileExtension(type) abort if a:type == 0 | return 'h' elseif a:type == 1 | let ret = Cpp_FileExtension4Inlines() else | let ret = Cpp_FileExtension4Implementation() endif return strpart(ret,1,strlen(ret)-1) endfunction " Function: Cpp_fileName(name0,type) {{{4 " Purpose: Substitute the file extension regarding the final type " expected. " Returns: A filename built on the basename from and of type " (cf. Cpp_fileType for the value of ) function! s:Cpp_fileName(name0,type) abort return expand(a:name0.":r") . '.' .s:Cpp_fileExtension(a:type) endfunction " Function: Cpp_TestInlineFile(filename,type,class) {{{4 " Purpose: Looks for inlining section of the class in the file " of type " Returns: The line of the section / -1 if no found function! s:Cpp_TestInlineFile(filename,type,class) abort if exists('g:mu_template') && \ (!exists('g:mt_jump_to_first_markers') || g:mt_jump_to_first_markers) " NB: g:mt_jump_to_first_markers is true by default let mt = g:mt_jump_to_first_markers let g:mt_jump_to_first_markers = 0 endif let fn = s:Cpp_fileName(a:filename,a:type) ""if filereadable(fn) || y a buffer du meme nom... call FindOrCreateBuffer(fn,1) if exists('mt') let g:mt_jump_to_first_markers = mt endif if s:Cpp_search4line(s:header_inlining_text.a:class,s:header_inlining_type) return line('.') else bdelete endif ""endif return -1 endfunction function! s:Cpp_addInlinesInHeader(name) abort " Internal use {{{4 normal! G call s:Cpp_emptyLine( 3 ) call s:Cpp_bigLine( "Inlines") call s:Cpp_littleLine( "Check whether inlines required" ) " exe "normal! i#ifdef __".a:name."_INL__\viwU" silent put = '#ifdef __'.toupper(a:name).'_INL__' call s:Cpp_emptyLine( 3 ) call s:Cpp_littleLine( s:header_includes_text ) " reinclusion call s:Cpp_emptyLine( 2 ) call s:Cpp_bigLine( "End of Inlinings") silent put = '#endif // Check if asked : __'.toupper(a:name).'_INL__' exe "normal! 4\" endfunction function! s:Cpp_newInlineFile(name) abort " Internal use {{{4 normal! G call s:Cpp_bigLine( "Inlines") call s:Cpp_littleLine( "Avoid re-inclusion") silent put = '#ifndef __'.toupper(a:name).'_AvR_INL__' silent put = '#define __'.toupper(a:name).'_AvR_INL__' call s:Cpp_emptyLine( 2 ) call s:Cpp_bigLine( s:header_includes_text ) silent put = '#include \"'.a:name.'.h\"' call s:Cpp_emptyLine( 2 ) call s:Cpp_littleLine( "Avoid re-inclusion") silent put ='#endif //Avoid re-inclusion : __'.toupper(a:name).'_AvR_INL__' exe "normal! 2\" endfunction " Function: ReachInlinesZone(type) {{{4 " Purpose: Reach the inlines zone of a file, if the file does not " exist, create it ; if the zone does not exist, create it. function! s:ReachInlinesZone(type) abort if s:Cpp_search4line(s:header_inlines_text, s:header_inlines_type) call s:Cpp_search4line(s:header_includes_text, '[-=]') exe "normal! 2\" return else if exists('g:mu_template') && \(!exists('g:mt_jump_to_first_markers') || g:mt_jump_to_first_markers) " NB: g:mt_jump_to_first_markers is true by default let mt = g:mt_jump_to_first_markers let g:mt_jump_to_first_markers = 0 endif " !!! expand("%:r:t") does not work. "%:t:r" does. if a:type == 0 | call s:Cpp_addInlinesInHeader(expand("%:t:r")) elseif a:type == 1 | call s:Cpp_newInlineFile(expand("%:t:r")) endif if exists('mt') let g:mt_jump_to_first_markers = mt endif endif endfunction function! s:WriteInlinePart(name) abort " Internal use {{{4 " Class call s:Cpp_emptyLine( 1 ) if s:header_inlining_type == '=' call s:Cpp_bigLine( s:header_inlining_text. a:name) else call s:Cpp_littleLine( s:header_inlining_text. a:name) endif call s:Cpp_emptyLine( 1 ) endfunction " ========================================================================= " Function: AddInlinePart(class,type) {{{4 " Purpose: Main function for accessing the inline zone of a class function! s:AddInlinePart(class,type) call s:ReachInlinesZone(a:type) call s:WriteInlinePart(a:class) endfunction function! s:TabSet(name,i,value) "{{{4 exe 'let beg = strpart('.a:name.',0,'.a:i.')' let b = a:i+1 let e = strlen(a:name) exe 'let end = strpart('.a:name.',b,e)' exe "let " . a:name . "= beg . a:value . end " endfunction " Function: Cpp_ReachInlinePart(class) {{{4 " Purpose: Reach the inlining part for the specifed class. " Use the different options and already pre-existant " structures. function! Cpp_ReachInlinePart(class) abort " 1- look whether the part already exists let g:lookedin = 'nnn' " a- current file let i = s:Cpp_fileType(expand("%")) call s:TabSet('g:lookedin',i,'y') if s:Cpp_search4line(s:header_inlining_text.a:class, s:header_inlining_type) exe "normal! 2\" return endif " b- prefered file (regarding options) (.inl / .h) let i = Cpp_fileTypeRegardingOption() if g:lookedin[i] == 'n' if s:Cpp_TestInlineFile("%", i, a:class) != -1 exe "normal! 2\" return endif endif " c- last possible location (.h / .inl), but never .cpp let i = 1 - i if g:lookedin[i] == 'n' if s:Cpp_TestInlineFile("%", i, a:class) != -1 exe "normal! 2\" return endif endif "--- " 2- Othewise, build/add the part in the correct file exe ':silent AS ' . s:Cpp_fileExtension(1-i) " :CheckOptions call s:AddInlinePart(a:class, 1-i) endfunction " }}}1 " ========================================================================= let &cpo = s:cpo_save " ========================================================================= " vim60: set fdm=marker: ================================================ FILE: ftplugin/cpp/cpp_Constructor.vim ================================================ "============================================================================= " File: ftplugin/cpp/cpp_Constructor.vim {{{1 " Author: Luc Hermitte " " License: GPLv3 with exceptions " " Version: 2.2.1 " Created: 09th Feb 2009 " Last Update: 16th Jan 2019 "------------------------------------------------------------------------ " Description: " Helper MMIs to generate constructors " "------------------------------------------------------------------------ " Installation: install details " History: " v1.1.0: creation " v.2.0.0b4 " New commands: :ConstructorCopy, :ConstructorDefault, " :ConstructorInit, :AssignmentOperator " }}}1 "============================================================================= " Buffer-local Definitions {{{1 " Avoid local reinclusion {{{2 let s:cpo_save=&cpo set cpo&vim if &cp || (exists("b:loaded_ftplug_cpp_Constructor") \ && !exists('g:force_reload_ftplug_cpp_Constructor')) let &cpo=s:cpo_save finish endif let b:loaded_ftplug_cpp_Constructor = 221 " Avoid local reinclusion }}}2 "------------------------------------------------------------------------ " Local commands {{{2 command! -b -nargs=? -complete=customlist,lh#cpp#constructors#_complete \ Constructor :call lh#cpp#constructors#Main() command! -b -nargs=0 ConstructorInit :call lh#cpp#constructors#InitConstructor() command! -b -nargs=0 ConstructorCopy :call lh#cpp#constructors#GenericConstructor('copy') command! -b -nargs=0 ConstructorDefault :call lh#cpp#constructors#GenericConstructor('default') command! -b -nargs=0 AssignmentOperator :call lh#cpp#constructors#AssignmentOperator() "============================================================================= "}}}1 "------------------------------------------------------------------------ let &cpo=s:cpo_save "============================================================================= " vim600: set fdm=marker: ================================================ FILE: ftplugin/cpp/cpp_Enum.vim ================================================ "============================================================================= " File: ftplugin/cpp/cpp_Enum.vim {{{1 " Author: Luc Hermitte " " License: GPLv3 with exceptions " " Version: 2.2.1 let s:k_version = 221 " Created: 30th Apr 2014 " Last Update: 16th Jan 2019 "------------------------------------------------------------------------ " Description: " Defines the command " :InsertEnum [] [Enum Values...] " which insert a smart enum (the one defined in cpp/enum2) " }}}1 "============================================================================= " Buffer-local Definitions {{{1 " Avoid local reinclusion {{{2 let s:cpo_save=&cpo set cpo&vim if &cp || (exists("b:loaded_ftplug_cpp_Enum") \ && (b:loaded_ftplug_cpp_Enum >= s:k_version) \ && !exists('g:force_reload_ftplug_cpp_Enum')) let &cpo=s:cpo_save finish endif let b:loaded_ftplug_cpp_Enum = s:k_version " Avoid local reinclusion }}}2 "------------------------------------------------------------------------ " Local commands {{{2 command! -b -nargs=* InsertEnum call lh#cpp#enum#_new() " }}}1 "------------------------------------------------------------------------ let &cpo=s:cpo_save "============================================================================= " vim600: set fdm=marker: ================================================ FILE: ftplugin/cpp/cpp_FindContextClass.vim ================================================ " ======================================================================== " File: ftplugin/cpp/cpp_FindContextClass.vim {{{1 " Author: Luc Hermitte " " Version: 1.1.0 " Last Update: $Date$ (16th May 2006) "------------------------------------------------------------------------ " 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: Cpp_CurrentScope(lineNo, scope_type) " Returns the scope (class name or namespace name) at line lineNo. " scope_type can value: "any", "class" or "namespace". " (*) Function: Cpp_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 Cpp_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 6.0+ " History: {{{2 " 16th May 2006 " (*) Bug fix: "using namespace" was misdirecting Cpp_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 " Cpp_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::B, etc " (*) Find the list of every base class ; aim: be able to retrieve the list of " every virtual function available to the class. " (*) Must we differentiate anonymous namespaces from the global namespace ? " }}}1 " ========================================================================== " No reinclusion {{{1 if exists("g:loaded_cpp_FindContextClass_vim") \ && !exists('g:force_load_cpp_FindContextClass') finish endif let g:loaded_cpp_FindContextClass_vim = 1 "" line continuation used here ?? let s:cpo_save = &cpo set cpo&vim " }}}1 " ========================================================================== " 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 = '\<\(class\|struct\|enum\|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 if exists('g:force_load_cpp_FindContextClass') command! -nargs=1 CppFCCEcho :echo s: endi " Search for current and most nested namespace/class {{{ let s:skip_comments = 'synIDattr(synID(line("."), col("."), 0), "name") =~?' \ . '"string\\|comment\\|doxygen"' function! s:SearchBracket() let flag = 'bW' return searchpair('{', '', '}', flag, s:skip_comments) endfunction function! s:CurrentScope(bMove, scope_type) let flag = a:bMove ? 'bW' : 'bnW' let pos = 'call cursor(' . line('.') . ',' . col('.') . ')' let result = line('.') while 1 let result = s:SearchBracket() if result <= 0 exe pos break endif let skip_comments = '(synIDattr(synID(line("."), col("."), 0), "name") ' \ . '!~? "c\\%(pp\\)\\=Structure")' let skip_using_ns = '(getline(".") =~ "using\s*namespace")' " let result = searchpair( " \ substitute(s:{a:scope_type}_part, '(', '%(', 'g') " \ . s:{a:scope_type}_open, '', '{', flag, " \ skip_comments) let result = searchpair( \ substitute(s:both_part, '(', '%(', 'g') \ . s:{a:scope_type}_open, '', '{', flag, \ skip_comments.'&&'.skip_using_ns) if result > 0 if getline(result) !~ '.*'.s:{a:scope_type}_token.'.*' exe pos let result = 0 endif break endif endwhile return result endfunction " obsolete function! s:CurrentScope000(bMove,scope_type) 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) let pos = 1 let scope = '' while pos > 0 let pos = s:CurrentScope(1, a:class_or_ns) if pos > 0 let current_scope = substitute(getline(pos), \ '^.*'.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! Cpp_SearchClassDefinition(lineNo,...) " 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! Cpp_CurrentScope(lineNo, scope_type) 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 'cpp_FindContextClass.vim::Cpp_CurrentScope(): the only ' . \ 'scope-types accepted are {class}, {namespace} and {any}!' return '' endif exe a:lineNo return scope endfunction " }}} " ========================================================================== " Search for templates specs {{{ function! s:TemplateSpecs() endfunction " }}} " ========================================================================== " Search for the direct base classes {{{ function! s:BaseClasses(pos) " 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 " }}} " ========================================================================== " Search for the direct base classes {{{ function! Cpp_BaseClasses(lineNo) exe a:lineNo let pos = s:CurrentScope(1, 'class') exe a:lineNo return (pos > 0) ? s:BaseClasses(pos) : '' endfunction " }}} " ========================================================================== let &cpo = s:cpo_save " ======================================================================== " vim60: set fdm=marker: ================================================ FILE: ftplugin/cpp/cpp_GotoFunctionImpl.vim ================================================ " ======================================================================== " File: ftplugin/cpp/cpp_GotoFunctionImpl.vim {{{1 " Authors: {{{2 " From an original mapping by Leif Wickland (VIM-TIP#335) " See: http://vim.sourceforge.net/tip_view.php?tip_id=335 " Firstly changed into a plugin (Mangled by) Robert KellyIV " " Rewritten by Luc Hermitte , but features " and fixes still mainly coming from Robert's ideas. " " License: GPLv3 with exceptions " " }}}2 " Last Change: 16th Jan 2019 " Version: 2.2.1 "------------------------------------------------------------------------ " Description: " Defines mappings and commands to jumps to the implementation of a " function prototype. If the implementation cannot be found, then " it provides a default one. " " Definitions: {{{2 " Commands: " - :GOTOIMPL " - :PASTEIMPL " - :MOVETOIMPL " Mappings: " - ;GI " - ;PI " - ;MI " }}}2 "------------------------------------------------------------------------ " Installation: See |lh-cpp-readme.txt| " Requirements: " vim7+ " {rtp}/autoload/lh/cpp/CodeAnalysisLib.vim " History: {{{2 " Note: for simplicity reasons, this ftplugin may accept illegal C++ " code. If you find such a broken C++-rule, send me an email to see if I " can fix it. " " [Luc: 12th Apr 2012] v2.0.0: {{{3 " (*) GPLv3 w/ extension " (*) facultative option: extension of the file where to put the " definition of the function. " [Luc: 06th Oct 2006] v0.8.6: {{{3 " (*) Code refactorized and moved to " {rtp}/autoload/lh/cpp/CodeAnalysisLib.vim " todo: search definition of operators " todo: support the ellipsis -> "..." " [Luc: 13th Sep 2006] v0.8.5: {{{3 " (*) :GOTOIMPL supports: " - parameters with default value being a function (vim 7+ only) " - C++ operators ; there is still a little issue with operator* " - exceptions specifications are unsupported " - pointer return types " [Luc: 16th May 2006] v0.8.4: {{{3 " (*) :GOTOIMPL inserts code at the line _after_ the matching pattern " [Luc: 05th May 2006] v0.8.3: {{{3 " (*) The alternate-file search has been patched for vim7. " [Luc: 18th Apr 2006] v0.8.2: {{{3 " (*) "explicit" is handled like "static" and "virtual". " Todo: " (*) escape() the return type pointers (and reference as well probably) " of functions. " [Luc: 27th Feb 2006] v0.8.1: {{{3 " (*) New command (and related mappings) :MOVETOIMPL " [Luc: 22nd Nov 2005] v0.8.0: {{{3 " (*) Cpp_GetFunctionPrototype() can declarations from pure signatures " only, or from definitions as well. " (*) Cpp_GetListOfParams() " " [Luc: 29th Apr 2005] v0.7.0: {{{3 " (*) Use g:alternateSearchPath (from a.vim) to check if the " implementation file (.cpp) exists in another directory from the list " (*) New option: g:cpp_Split which tells where the implementation file " should be opened. Possible values are "h\%[orizontal]", " "v\%[ertical]" or anything which will be interpreted as "no-split". " By default if g:cpp_Split is not set, "vertical" is assumed. " Todo: " (*) for PASTEIMPL and GOTOIMPL, same behavior than the one " of :put-! " " [Luc: 17th oct 2002] v0.6.0: {{{3 " (*) Supports destructors " (*) Supports namespaces: " + If the zone where the function implementation is going to be " inserted is within a namespace, then the scope of the function " will be corrected. " + The |search-implementation| feature is able to differentiate " functions according to the namespace they are within, and thus " it is able jump to the right function. For instance: " int NS::CL::FN(int i) {} // is NS::CL::FN " namespace NS0 { " int NS::CL::FN(int i) {} // is NS0::NS::CL:FN " } " (*) Checks whether the function is a pure virtual method and refuse to " define an implementation in such cases ... " (*) When searching for the implementation of a function within the " .cpp file, comments before the signature will be ignored ; i.e. " the cursor will move to the return-type. The difference is " noticeable on virtual or static functions. " (*) s/GIMPL/GOTOIMPL " Todo: " (*) Pb (now hanging) when searching/building/checking when GOTOIMPL is " invoked on a non function " (*) Pb when GOTOIMPL invoked on a function call within an " implementation -- searching/checking for {} may do the trick " (*) Skip comments with searchpair() " " [Luc: 15th oct 2002] v0.5.0: {{{3 " (*) The management of cpp_options.vim has been moved to another file. " (*) Comments are completely ignored when searching for the " implementation of a function. Actually, the match is done " according to the list of types only -- even parameter names will " be ignored. " Hence: the programmer can change the name of the parameters and/or " add comments wherever she want within the function's header. " Parameters-types Supported: " - simple types (int, unsigned short int, signed double, etc) " - pointers, references and const modifiers usable " - arrays "T p[][xx]" " - arrays of pointers and pointers of arrays: " "T (*p)[][N]", "T* p[][N]" " - complex types with scopes : "T1::T2::T3" " (*) Inlines functions (within the class def) (ie not prototypes) will " be ignored " (*) Enhancements and little bugs corrections regarding default " parameters " (*) We can specify where we want the default implementation code to be " written ; cf cpp_options.vim and g:cpp_FunctionPosition. " Todo: " (*) Check about declared exceptions : 'throws' " (*) Possibility to extend the list of simple types (__int64, long " long, UINT, etc) on user request/conf. " (*) Support very complex types : function types, template types. " Must we consider that p for "T p[10]", "T p[]" and "T p[N]" have " the same type ? " Don't differentiate: " "T * p$" and "T (*p)$" ; "const T" and "T const" " " [Luc: 08th oct 2002] v0.4.0: {{{3 " (*) Accepts comments within the signature and trim them. " (*) If something is written between the ')' and the ';', even on " new line, it will be understood as part of the prototype " (typically 'const' and '=0'). " But: We can not put the cursor on this particular line and then " invoke the command ; the last line accepted is the one of the " closing parenthesis. " " [Luc: 08th oct 2002] v0.3.0: {{{3 " (*) No more parameters don't require anymore to be on the same line " But, the return type and the possible const modifier on the " function must. " (*) No more registers, " (*) Works with member and non-member functions. " (*) Requires some other files of mine. " => Can handle nested class. " (*) If an implementation already exists for the function, we go to " this implementation, otherwise we add it at once. " (*) The command accept optional arguments " (*) Add two default mappings for normal and insert modes, can be " easily remapped to anything we want. " (*) Divergence in the versionning from now " Todo: " (*) Enable multi-lines prototypes " Status: Half implemented in 0.4 " (*) Memorize the current cursor position ? -> option " (*) Use tags to achieve a more accurate search " (*) Check whether the function is a pure virtual method and refuse to " define an implementation ... " Status: done in 0.6 " " [Feral:274/02@20:42] v0.2.0: {{{3 " Improvements: from Leif's Tip (#335): " (*) can handle any number of default params (as long as they are all " on the same line!) " Status: 2/3 fixed with ver 0.4 " (*) Options on how to format default params, virtual and static. " (see below) TextLink:||@|Prototype:| " (*) placed commands into a function (at least I think it's an " improvement ;) ) " (*) Improved clarity of the code, at least I hope. " (*) Preserves registers/marks. (rather does not use marks), Should not " dirty anything. " (*) All normal operations do not use mappings i.e. :normal! " (I have Y mapped to y$ so Leif's mappings could fail.) " " Limitations: " (*) fails on multi line declarations. All params must be on the same " line. " Status: 2/3 fixed with ver 0.4 " (*) fails for non member functions. (though not horribly, just have to " remove the IncorectClass:: text... " Status: fixed with 0.3. " " [Leif:] v0.1 {{{3 " Leif's original VIM-Tip #335 " " Requirements: {{{2 " VIM 6.0, " cpp_FindContextClass.vim, cpp_options-commands.vim, " a.vim " }}}1 "############################################################################# " Buffer Relative stuff {{{1 let s:cpo_save=&cpo set cpo&vim if &cp || (exists("b:loaded_ftplug_cpp_GotoFunctionImpl") \ && !exists('g:force_load_cpp_GotoFunctionImpl')) let &cpo=s:cpo_save finish endif let b:loaded_ftplug_cpp_GotoFunctionImpl = 221 " ========================================================================== " Commands: {{{2 " Possible Arguments: " 'ShowVirtualon', 'ShowVirtualoff', 'ShowVirtual0', 'ShowVirtual1', " 'ShowStaticon', '..off', '..0' or '..1' " 'ShowExplicitcon', '..off', '..0' or '..1' " 'ShowDefaultParamson', '..off', '..0', '..1', or '..2' " {extension} -> cpp,txx,cxx, etc when there can be a choice where to have the " function definition command! -buffer -nargs=* GOTOIMPL call lh#cpp#GotoFunctionImpl#GrabFromHeaderPasteInSource() " In order to insert the default implementation when the user want it (with " the option g:cpp_FunctionPosition set to 3 ; Robert's approach) or after a " positioning error (ie: if a searched pattern is not found, them :PASTEIMPL " will be usable). command! -buffer -nargs=0 PASTEIMPL call lh#cpp#GotoFunctionImpl#InsertCodeAtLine() " Like GOTOIMPL, but instead move an inlined function to a separate .cpp file command! -buffer -nargs=* MOVETOIMPL call lh#cpp#GotoFunctionImpl#MoveImpl() " Mappings: {{{2 " normal mode mapping ; still possible to set parameters nnoremap GotoImpl :GOTOIMPL nnoremap PasteImpl :PASTEIMPL nnoremap MoveToImpl :MOVETOIMPL if !hasmapto('GotoImpl', 'n') nmap ;GI GotoImpl " is used to position the cursor first nmap GotoImpl endif if !hasmapto('PasteImpl', 'n') nmap ;PI PasteImpl nmap PasteImpl endif if !hasmapto('MoveToImpl', 'n') nmap ;MI MoveToImpl " is used to position the cursor first " nmap MoveToImpl endif " insert mode mapping ; use global parameters inoremap GotoImpl :GOTOIMPL inoremap PasteImpl :PASTEIMPL if !hasmapto('GotoImpl', 'i') imap GI GotoImpl imap GotoImpl endif if !hasmapto('PasteImpl', 'i') imap PI PasteImpl imap PasteImpl endif if !hasmapto('MoveToImpl', 'i') imap MI MoveToImpl endif " }}}1 "============================================================================= " Global definitions {{{1 if exists("g:loaded_cpp_GotoFunctionImpl") \ && !exists('g:force_load_cpp_GotoFunctionImpl') let &cpo=s:cpo_save finish endif let g:loaded_cpp_GotoFunctionImpl = 1 "------------------------------------------------------------------------ " Menus {{{2 " if 0 let s:menu_prio = lh#option#get('cpp_menu_priority', '50', 'g') let s:menu_name = lh#option#get('cpp_menu_name', '&C++', 'g') let s:FunctionPositionMenu = { \ "variable": "cpp_FunctionPosition", \ "idx_crt_value": 0, \ "texts": [ 'end-of-file', 'pattern', 'function', 'other' ], \ "values": [ 0, 1, 2, 3 ], \ "menu": { \ "priority": s:menu_prio.'.90.10', \ "name": s:menu_name.'.&Options.&New-function-position'} \} call lh#menu#def_toggle_item(s:FunctionPositionMenu) endif "------------------------------------------------------------------------ " }}}2 "------------------------------------------------------------------------ let &cpo=s:cpo_save " }}} "============================================================================= " Documentation {{{1 "***************************************************************** " given: " virtual void Test_Member_Function_B3(int _iSomeNum2 = 5, char * _cpStr = "Yea buddy!"); " Prototype: "GrabFromHeaderPasteInSource(VirtualFlag, StaticFlag, DefaultParamsFlag) " VirtualFlag: " 1: if you want virtual commented in the implementation: " /*virtual*/ void Test_Member_Function_B3(int _iSomeNum2 = 5, char * _cpStr = "Yea buddy!"); " else: remove virtual and any spaces/tabs after it. " void Test_Member_Function_B3(int _iSomeNum2 = 5, char * _cpStr = "Yea buddy!"); " StaticFlag: " 1: if you want static commented in the implementation: " Same as virtual, save deal with static " else: remove static and any spaces/tabs after it. " Same as virtual, save deal with static " ExplicitFlag: " 1: if you want explicit commented in the implementation: " Same as virtual, save deal with explicit " else: remove explicit and any spaces/tabs after it. " Same as virtual, save deal with explicit " DefaultParamsFlag: " 1: If you want to remove default param reminders, i.e. " Test_Member_Function_B3(int _iSomeNum2, char * _cpStr); " 2: If you want to comment default param assignments, i.e. " Test_Member_Function_B3(int _iSomeNum2/*= 5*/, char * _cpStr/*= "Yea buddy!"*/); " 3: Like 2 but, If you do not want the = in the comment, i.e. " Test_Member_Function_B3(int _iSomeNum2/*5*/, char * _cpStr/*"Yea buddy!"*/); " " Examples: " smallest implementation: " void Test_Member_Function_B3(int _iSomeNum2, char * _cpStr); ":command! -nargs=0 GHPH call GrabFromHeaderPasteInSource(0,0,1) " Verbose...: " /*virtual*/ void Test_Member_Function_B3(int _iSomeNum2/*5*/, char * _cpStr/*"Yea buddy!"*/); ":command! -nargs=0 GHPH call GrabFromHeaderPasteInSource(1,1,3) " What I like: " void Test_Member_Function_B3(int _iSomeNum2/*5*/, char * _cpStr/*"Yea buddy!"*/); " }}}1 "============================================================================= " vim60:fdm=marker ================================================ FILE: ftplugin/cpp/cpp_InsertAccessors.vim ================================================ " ======================================================================== " File: ftplugin/cpp/cpp_InsertAccessors.vim {{{1 " Author: Luc Hermitte " " License: GPLv3 with exceptions " " Version: 2.2.1 let s:k_version = 221 " Last Change: $Date$ (28th July 2003) " "------------------------------------------------------------------------ " Description: " Defines a function to insert const-correct accessors and mutators. " " Used in cpp_BuildTemplates.vim " "------------------------------------------------------------------------ " Installation: See |lh-cpp-readme.txt| " Requires Vim7+, lh-dev, lh-brackets v2.2.0 " Options: cf. lh_dev " " TODO: {{{2 " * Clean up the inline file generated when mu-template is installed. " * Better place the members in respect of the different options. " * Extend the accessors feature to any member, and jump from a definition to " an implementation, and vice-versa. " * Use Cpp_FileExtensionXXX() " * Understand const, mutable, volatile as particular type specifiers ; and " then adapt the accessors : for instance, a const data can't have a " reference accessor ; a reference attribute must be defined in the " constructor (no parameter-less constructor), ... " * Do something about the pimpl idiom. " * g:BooleanAccessorPrefix -> "is" or "" " }}}1 " ========================================================================== " Buffer-local Definitions {{{1 " Avoid local reinclusion {{{2 let s:cpo_save=&cpo set cpo&vim if &cp || (exists("b:loaded_ftplug_cpp_InsertAccessors") \ && (b:loaded_ftplug_cpp_InsertAccessors >= s:k_version) \ && !exists('g:force_reload_ftplug_cpp_InsertAccessors')) let &cpo=s:cpo_save finish endif let b:loaded_ftplug_cpp_InsertAccessors = s:k_version " Avoid local reinclusion }}}2 "============================================================================= " Global Definitions {{{1 " Avoid global reinclusion {{{2 if exists("g:loaded_ftplug_cpp_InsertAccessors") \ && (g:loaded_ftplug_cpp_InsertAccessors >= s:k_version) \ && !exists('g:force_reload_ftplug_cpp_InsertAccessors') let &cpo=s:cpo_save finish endif let g:loaded_ftplug_cpp_InsertAccessors = s:k_version " Avoid global reinclusion }}}2 "------------------------------------------------------------------------ " Constants {{{2 let s:k_accessor_comment_attribute = '/** %a ... */' let s:k_accessor_comment_get = '/** Get accessor to %a */' let s:k_accessor_comment_set = '/** Set accessor to %a */' let s:k_accessor_comment_proxy_get = '/** Proxy-Get accessor to %a */' let s:k_accessor_comment_proxy_set = '/** Proxy-Set accessor to %a */' let s:k_accessor_comment_ref = '/** Ref. accessor to %a */' let s:k_accessor_comment_proxy_ref = '/** Proxy-Ref. accessor to %a */' "------------------------------------------------------------------------ " Functions {{{2 " Note: most filetype-global functions are best placed into " autoload/your-initials/cpp/cpp_InsertAccessors.vim " Keep here only the functions are are required when the ftplugin is " loaded, like functions that help building a vim-menu for this " ftplugin. " Insertion of accessors {{{3 " Function: s:InsertLines(lines) "{{{4 function! s:InsertLines(lines) abort silent put = a:lines silent '[,']normal! == endfunction " Function: s:WriteAccessor {{{4 function! s:WriteAccessor(returnType, signature, instruction, comment) abort try let old_foldenable = &foldenable set nofoldenable let lines = [] let lines += [a:comment] if '' != a:instruction let curly = lh#cpp#option#nl_before_curlyB() ? "" : "\{" if a:returnType =~ "^inline" let lines += ['inline'] let lines += [ substitute(a:returnType,"inline.",'','') \ . "\" . a:signature . curly] else let lines += [ a:returnType . "\" . a:signature . curly ] endif if '' == curly let lines += [ '{' ] endif let lines += [ a:instruction ] let lines += [ '}' ] else " normal! ==<< let lines += [ a:returnType . "\" . a:signature .";" ] endif call s:InsertLines(lines) finally let &foldenable = old_foldenable endtry endfunction " Function: s:InsertAccessor {{{4 function! s:InsertAccessor(className, returnType, signature, instruction, comment) abort try let old_foldenable = &foldenable set nofoldenable if exists('g:mu_template') && \ ( !exists('g:mt_jump_to_first_markers') \ || g:mt_jump_to_first_markers) " NB: g:mt_jump_to_first_markers is true by default let mt_jump = 1 let g:mt_jump_to_first_markers = 0 endif let implPlace = lh#ft#option#get('implPlace', 'cpp', 0) let in_place = implPlace == 0 \ || expand('%:e') =~? 'c\|cpp\|c++' if in_place " within the class definition / la/ Java call s:WriteAccessor(a:returnType, a:signature, a:instruction, a:comment) else let returnType = a:returnType let instruction = a:instruction " 1- Insert the prototype call s:WriteAccessor(a:returnType, a:signature, '', a:comment) let fn = expand("%") let l_line = line('.') " 2- Find the right place if implPlace == 1 " Inline section of the right file {{{ let returnType = "inline\n" . returnType call Cpp_ReachInlinePart(a:className) " }}} elseif implPlace == 2 " Within implementation file {{{ silent AS cpp normal! G " }}} elseif implPlace == 3 " use the pimpl idiom {{{ silent AS cpp normal! G if exists('*Marker_Txt') && lh#brackets#usemarks() let instruction = Marker_Txt(';;') else let instruction = ';;' endif " does nothing !!! " }}} endif " 3- Insert the implementation let signature = a:className."::".a:signature call s:WriteAccessor(returnType, signature, instruction, a:comment) " 4- go back after the last prototype inserted call FindOrCreateBuffer(fn,1) exe ":".(l_line) endif finally let &foldenable = old_foldenable if exists('mt_jump') let g:mt_jump_to_first_markers = mt_jump unlet mt_jump endif endtry endfunction " Nb: the mt_jump stuff is required in order to not mess things up with " automatically (by the mean of mu-template) built .cpp files. function! s:Comment(attribute, accessor_type) abort "{{{4 let template = lh#option#get('accessor_comment_'.a:accessor_type, \ s:k_accessor_comment_{a:accessor_type}) return substitute(template, '%a',a:attribute,'g') endfunction " Function: AddAttribute {{{4 " Options: g:getPrefix (default = "get_") " g:setPrefix (default = "set_") " g:refPrefix (default = "ref_") function! Cpp_AddAttribute() abort :CheckOptions " Todo: factorize and move this elsewhere " GUI : request name and type {{{ echo "--------------------------------------------" echo "Adding an attribute to the current class ..." echo "--------------------------------------------" let type = input("Type of the new attribute : ") echo "\n" if strlen(type)==0 | call input("Aborting...") | return | endif let name = input("Name of the new attribute : ") echo "\n" if strlen(name)==0 | call input("Aborting...") | return | endif " }}} " " TODO: Place the cursor where the attribute must be defined " Insert the attribute itself let attrName = lh#naming#member(name) let lines=[ s:Comment(name, 'attribute'), \ type . "\" . attrName . ';' \ ] call s:InsertLines(lines) " TODO: Place the cursor where accessors must be defined let l_line = line('.') let c_col = col('.') let className = lh#cpp#AnalysisLib_Class#CurrentScope(l_line, 'any') " const correct type let ccType = lh#dev#cpp#types#ConstCorrectType(type) " Insert the get accessor {{{ let proxyType = 0 let choice = confirm('Do you want a get accessor ?', "&Yes\n&No\n&Proxy", 1) if choice == 1 let comment = s:Comment(name, 'get') let signature = lh#naming#getter(name) . "()\const" let instruction = 'return ' . attrName . ';' call s:InsertAccessor(className, ccType, signature, instruction, comment) elseif choice == 3 let proxyType = input( 'Proxy type : ') | echo "\n" let comment = s:Comment(name, 'proxy_get') let signature = lh#naming#getter(name) . "()\const" let instruction = 'return ' . proxyType.'('.attrName . ' /*,this*/);' call s:InsertAccessor(className, 'const '.proxyType, signature, instruction, comment) endif " }}} " Insert the set accessor {{{ if confirm('Do you want a set accessor ?', "&Yes\n&No", 1) == 1 let comment = s:Comment(name, 'set') let signature = lh#naming#setter(name) \ . '('. ccType .' '. lh#naming#param(name) .')' let instruction = attrName . ' = '.name.';' call s:InsertAccessor(className, 'void', signature, instruction, comment) if proxyType != "" let comment = s:Comment(name, 'proxy_set') let signature = lh#naming#setter(name) . '('. proxyType .'& '. name .')' let instruction = attrName . ' = '.name.';' call s:InsertAccessor(className, 'void', signature, instruction, comment) endif endif " }}} " Insert the ref accessor {{{ if confirm('Do you want a reference accessor ?', "&Yes\n&No", 1) == 1 if proxyType == "" let comment = s:Comment(name, 'ref') let signature = lh#naming#ref_getter(name) . "()\" let instruction = 'return ' . attrName . ';' call s:InsertAccessor(className, type.'&', signature, instruction, comment) else let comment = s:Comment(name, 'proxy_ref') let signature = lh#naming#proxy_getter(name) . "()\" let instruction = 'return ' . proxyType.'('.attrName . ' /*,this*/);' call s:InsertAccessor(className, proxyType, signature, instruction, comment) endif endif " }}} " TODO: Go back to the class initial cursor's position " -> l_line, l_col... exe ":" . l_line endfunction " Functions }}}2 " }}}1 "------------------------------------------------------------------------ let &cpo=s:cpo_save "============================================================================= " vim600: set fdm=marker: ================================================ FILE: ftplugin/cpp/cpp_Inspect.vim ================================================ "============================================================================= " File: ftplugin/cpp/cpp_Inspect.vim {{{1 " Author: Luc Hermitte " " License: GPLv3 with exceptions " " Version: 2.2.1 let s:k_version = 221 " Created: 11th Sep 2008 " Last Update: 28th Nov 2019 "------------------------------------------------------------------------ " Description: " C++ ftplugin that provides command to inpect various information: " - ancestor of a class " - children of a class " }}}1 "============================================================================= " Buffer-local Definitions {{{1 " Avoid local reinclusion {{{2 let s:cpo_save=&cpo set cpo&vim if &cp || (exists("b:loaded_ftplug_cpp_Inspect") && !exists('g:force_reload_ftplug_cpp_Inspect')) let &cpo=s:cpo_save finish endif let b:loaded_ftplug_cpp_Inspect = s:k_version " Avoid local reinclusion }}}2 "------------------------------------------------------------------------ " Local commands {{{2 if lh#has#plugin('autoload/clang.vim') && clang#can_plugin_be_used() command! -b -nargs=? Ancestors \ call lh#cpp#libclang#show_ancestors() else command! -b -nargs=? Ancestors \ echo lh#dev#option#call('class#ancestors', &ft, lh#cpp#ftplugin#OptionalClass()) endif command! -b -nargs=? -bang Children call s:Children("", ) "============================================================================= " Global Definitions {{{1 " Avoid global reinclusion {{{2 if exists("g:loaded_ftplug_cpp_Inspect") && !exists('g:force_reload_ftplug_cpp_Inspect') let &cpo=s:cpo_save finish endif let g:loaded_ftplug_cpp_Inspect = s:k_version " Avoid global reinclusion }}}2 "------------------------------------------------------------------------ " Functions {{{2 " Note: most filetype-global functions are best placed into " autoload/your-initials/cpp/cpp_Inspect.vim " Keep here only the functions are are required when the ftplugin is " loaded, like functions that help building a vim-menu for this " ftplugin. " s:Children(bang [, namespace [,classname]] function! s:Children(bang, ...) abort let reset_namespace_cache = a:bang == "!" let namespace = a:0 > 0 ? (a:1) : '' let classname = lh#cpp#ftplugin#OptionalClass(a:000[1:]) let children = lh#dev#option#call('class#fetch_direct_children', &ft, \ classname, namespace, reset_namespace_cache) " lh#cpp#AnalysisLib_Class#FetchDirectChildren(classname, a:namespace, reset_namespace_cache) echo children endfunction " Functions }}}2 " }}}1 "------------------------------------------------------------------------ let &cpo=s:cpo_save "============================================================================= " vim600: set fdm=marker: ================================================ FILE: ftplugin/cpp/cpp_Override.vim ================================================ "============================================================================= " File: ftplugin/cpp/cpp_Override.vim {{{1 " Author: Luc Hermitte " " Version: 1.1.0 " Created: 15th Apr 2008 " Last Update: $Date$ "------------------------------------------------------------------------ " Description: Helper MMI to overide functions " "------------------------------------------------------------------------ " Installation: install details " History: history " TODO: missing features " }}}1 "============================================================================= " Buffer-local Definitions {{{1 " Avoid local reinclusion {{{2 if exists("b:loaded_ftplug_cpp_Override") && !exists('g:force_reload_ftplug_cpp_Override') finish endif let b:loaded_ftplug_cpp_Override = 100 let s:cpo_save=&cpo set cpo&vim " Avoid local reinclusion }}}2 "------------------------------------------------------------------------ " Local commands {{{2 command! -b -nargs=? Override :call lh#cpp#override#Main() "============================================================================= "------------------------------------------------------------------------ let &cpo=s:cpo_save "============================================================================= " vim600: set fdm=marker: ================================================ FILE: ftplugin/cpp/cpp_options-commands.vim ================================================ "============================================================================= " File: ftplugin/cpp/cpp_options-commands.vim {{{1 " Author: Luc Hermitte " " Version: 1.1.0 " Created: 10th oct 2002 " Last Update: $Date$ (10th oct 2002) "------------------------------------------------------------------------ " Description: " Some commands used to handle the local files cpp_options.vim " " To define options for a project in a hierarchy tree, use |local_vimrc| " instead. " "------------------------------------------------------------------------ " Installation: Drop this files into $$/ftplugin/cpp/ " History: {{{ " Version 1.0.0 " (*) Commands come from cpp_GotoFunctionImpl.vim " }}} " TODO: Find a way to define options for a project or a hierarchy " tree. "============================================================================= " Avoid reinclusion {{{ if exists('b:loaded_ftplug_cpp_options_commands_vim') | finish | endif let b:loaded_ftplug_cpp_options_commands_vim = 1 " let s:cpo_save=&cpo set cpo&vim " }}} "------------------------------------------------------------------------ command! -buffer -nargs=0 CheckOptions :call CheckOptions() "============================================================================= " No reinclusion {{{ if exists("g:loaded_cpp_options_commands_vim") let &cpo=s:cpo_save finish endif let g:loaded_cpp_options_commands_vim = 1 " }}} "------------------------------------------------------------------------ let s:esc_pwd = '' " Function: s:CheckOptions() {{{ " Role: Checks whether we must reload the options file to match the current " project. function! s:CheckOptions() if s:esc_pwd != escape(getcwd(), '\') let s:pwd = getcwd() let s:esc_pwd = escape(s:pwd, '\') let g:do_load_cpp_options = 1 if filereadable("./cpp_options.vim") so ./cpp_options.vim " elseif filereadable("$VIM/ftplugin/cpp/cpp_options.vim") " so $VIM/ftplugin/cpp/cpp_options.vim else " so :p:h/cpp_options.vim runtime ftplugin/cpp/cpp_options.vim endif endif endfunction " }}} "------------------------------------------------------------------------ let &cpo=s:cpo_save "============================================================================= " vim600: set fdm=marker: ================================================ FILE: ftplugin/cpp/cpp_options.vim ================================================ " ======================================================================== " File: ftplugin/cpp/cpp_InsertAccessors.vim {{{1 " Author: Luc Hermitte " " Last Change: $Date$ (28th July 2003) " Version: 2.0.0 " "------------------------------------------------------------------------ " Description: " Options for C & C++ editing. " "------------------------------------------------------------------------ " Installation: See |lh-cpp-readme.txt| " Override these definitions in each C|C++ project. " TODO: move these definitions to autoload/lh/cpp/option.vim as the approach " used in this file is now deprecated " }}}1 " ========================================================================== if !exists("g:do_load_cpp_options") | finish | endif unlet g:do_load_cpp_options " exe 'command! -nargs=0 CppEditOptions :sp '.expand(':p') exe 'command! -nargs=0 CppReloadOptions :so '.expand(':p') " ==================================================================== " Preferences for the names of classes' attributes and their accessors {{{ " ==================================================================== " let g:accessorCap = -1 " g:accessorCap = -1 (lowcase), 0 (no change), 1 (upcase) let g:accessor_comment_attribute = '/** %a ... */' let g:accessor_comment_get = '/** Get accessor to %a */' let g:accessor_comment_set = '/** Set accessor to %a */' let g:accessor_comment_proxy_get = '/** Proxy-Get accessor to %a */' let g:accessor_comment_proxy_set = '/** Proxy-Set accessor to %a */' let g:accessor_comment_ref = '/** Ref. accessor to %a */' let g:accessor_comment_proxy_ref = '/** Proxy-Ref. accessor to %a */' " To use markers/placeholders, use Marker_Txt() " let g:accessor_comment_get = Marker_Txt('/** Get accessor to %a */') " Luc's Preferences: let g:setPrefix = 'set_' let g:getPrefix = 'get_' let g:refPrefix = 'ref_' let g:dataPrefix = 'm_' let g:dataSuffix = '' let g:paramPrefix = '' let g:paramSuffix = '' """ Very Short Style: ""let g:setPrefix = '' ""let g:getPrefix = '' ""let g:refPrefix = '' ""let g:dataPrefix = '' ""let g:dataSuffix = '_' ""let g:paramPrefix = '' ""let g:paramSuffix = '' " """ Herb Sutter's Style: ""let g:setPrefix = 'Set' ""let g:getPrefix = 'Get' ""let g:refPrefix = 'Get' ""let g:dataPrefix = '' ""let g:dataSuffix = '_' ""let g:paramPrefix = '' ""let g:paramSuffix = '' " }}} " ==================================================================== " Preference regarding where accessors' definitions occur {{{ " ==================================================================== " " Possible Values: " 0: Near the prototype/definition (Java's way) " 1: Within the inline section of the header/inline/current file " 2: Within the implementation file (.cpp) " 3: Use the pimpl idiom let g:implPlace = 1 " }}} " ==================================================================== " Preference regarding where inlines are written {{{ " ==================================================================== " Possible values: " 0: In the inline section of the header/current file " 1: In the inline section of a dedicated inline file let g:inlinesPlace = 1 " Function used by Cpp_reachInlinePart() function! Cpp_fileTypeRegardingOption() return g:inlinesPlace endfunction " }}} " ==================================================================== " Preferences regarding what is shown in functions signatures {{{ " IE.: Should every element from the signature of a function be reminded along " with the implementationof the function ? " " ShowVirtual = 0 -> '' ; 1 -> '/*virtual*/' let g:cpp_ShowVirtual = 1 " ShowStatic = 0 -> '' ; 1 -> '/*static*/' let g:cpp_ShowStatic = 1 " ShowExplicit= 0 -> '' ; 1 -> '/*explicit*/' let g:cpp_ShowExplicit = 1 " ShowDefaultParam = 0 -> '' ; " 1 -> default value for params within comments ; " 2 -> within comment as well, but spaces are trimmed ; " 3 -> like 2, but the equal sign is not displayed. let g:cpp_ShowDefaultParams = 1 " }}} " ==================================================================== " Preference regarding where functions definitions are written {{{ " ==================================================================== " " Possible Values: " 0: At the end of the file plus offset g:cpp_FunctionPosArg " 1: Search for a specific pattern g:cpp_FunctionPosArg " Useful if you use template skeletons " 2: Call a user specified function : g:cpp_FunctionPosArg " Beware! This is a (security) back door. " 3: Store the value in a temporary variable ; to be used in conjunction " with :PASTEIMPL -- Robert Kelly IV's approach let g:cpp_FunctionPosition = 2 if exists('g:cpp_FunctionPosArg') | unlet g:cpp_FunctionPosArg | endif function! s:GroupPattern(group) " {{{ " Yes the pattern is very, very complex. " It searches for "/*===[ groupname ]===*/\n/*=======*/" followed by : " - either the end of the file " - or a line not made of one and only one comment " Todo: Support "//" comments return '/\*=*\[ '.a:group.' \]=*\*/\_s*/\*=*\*/\zs'. \ '\%(\%$\|\_s\%(^/\*\%(\*[^/]\|[^*]\)*\*/\s*$\)\@!\)' endfunction " }}} " Some default definitions of g:cpp_FunctionPosArg regarding the chosen value " of g:cpp_FunctionPosition. Use them as examples for your code preferences. if g:cpp_FunctionPosition == 0 " {{{ let g:cpp_FunctionPosArg = -1 " }}} elseif g:cpp_FunctionPosition == 1 " {{{ " That one fit my own needs. Find your owns let g:cpp_FunctionPosArg = s:GroupPattern('') " }}} elseif g:cpp_FunctionPosition == 2 " {{{ let g:cpp_FunctionPosArg = 'Cpp_SearchForGroup' function! Cpp_SearchForGroup() " Cf cpp_BuildTemplate.vim::BLINE for groups definitions: " /*=================*/ (80 characters) " /*====[ title ]====*/ " /*=================*/ " Todo: Move this function into cpp_BuildTemplate.vim let g = inputdialog('Which group do you want to search for ?') if "" == g | return -1 else let s = search(s:GroupPattern(g)) if 0 == s echoerr "Can't find group [ ".g." ]!!!" return -1 else | return s endif endif endfunction " }}} endif " }}} " ==================================================================== " File extensions {{{ " ==================================================================== function! Cpp_FileExtension4Inlines() return '.inl' endfunction function! Cpp_FileExtension4Implementation() return '.cpp' endfunction " }}} " ==================================================================== " vim600: set fdm=marker: ================================================ FILE: ftplugin/cpp/cpp_refactor.vim ================================================ "============================================================================= " File: ftplugin/cpp/cpp_refactor.vim {{{1 " Author: Luc Hermitte " " License: GPLv3 with exceptions " " Version: 2.2.1 " Created: 10th Feb 2005 " Last Update: 21st Feb 2019 "------------------------------------------------------------------------ " Description: Some refactoring oriented mappings and commands " " Definitions: " - :ToInitList " - :AddBrief " "------------------------------------------------------------------------ " Installation: See |lh-cpp-readme.txt| " " History: " v0.1: 10th Feb 2005 " Initial version " }}}1 "============================================================================= "============================================================================= " Avoid buffer reinclusion {{{1 let s:cpo_save=&cpo set cpo&vim if &cp || (exists('b:loaded_ftplug_cpp_refactor') \ && !exists('g:force_reload_cpp_refactor')) let &cpo=s:cpo_save finish endif let b:loaded_ftplug_cpp_refactor = 1 " }}}1 "------------------------------------------------------------------------ " Commands and mappings {{{1 " Adds Doxygen's keyword @brief into headers where it is missing. command! -buffer -range=% AddBrief \ ,s#\(/\*\*\%(\s*\n\s*\*\)*\)\s*\([^@ ]\)#\1 @brief \u\2 " Changes a list of affectations (instruction) into an initialisation list. " This is meant to be used into poorly-written constructors. " How To use it: " - Move first the '{' after the instructions you want to transform " - Select (visual mode) the lines where the instructions are " - Type ``:ToInitList'' " - Enjoy " - You may have to change the leading ':' inserted into a ','. " NB: " - The initialisation list is reindented at the end of the operation. command! -buffer -range ToInitList \ ,s#^\s*\(.\{-}\)\s*=\s*\(.\{-}\);#, \1( \2 )# \ |s#^,#:# \ |,normal! == command! -buffer -nargs=* Parents :call ShowParents() command! -buffer -range -nargs=0 Modernize :call lh#cpp#refactor#_modernize() " Commands and mappings }}}1 "============================================================================= " Avoid global reinclusion {{{1 if exists("g:loaded_cpp_refactor") \ && !exists('g:force_reload_cpp_refactor') let &cpo=s:cpo_save finish endif let g:loaded_cpp_refactor = 1 " Avoid global reinclusion }}}1 "------------------------------------------------------------------------ " Functions {{{1 function! s:ShowParents(...) abort let classname = (a:0 == 0) \ ? lh#cpp#AnalysisLib_Class#CurrentScope(line('.'),'any') \ : a:1 let ancestors = lh#cpp#AnalysisLib_Class#Ancestors(classname) echo string(ancestors) endfunction " Functions }}}1 "------------------------------------------------------------------------ let &cpo=s:cpo_save "============================================================================= " vim600: set fdm=marker: ================================================ FILE: ftplugin/cpp/cpp_set.vim ================================================ " ======================================================================== " File: ftplugin/cpp/cpp_set.vim {{{1 " Author: Luc Hermitte " " Version: 2.2.0 " Last Update: 07th Mar 2017 " "------------------------------------------------------------------------ " Description: " Defines vim options for C++ programming. " }}}1 " ======================================================================== " for changelog: 02nd Jun 2006 -> suffixesadd " ======================================================================== " Buffer local definitions {{{1 " ======================================================================== if exists("b:loaded_local_cpp_settings") && !exists('g:force_reload_cpp_set') finish endif let b:loaded_local_cpp_settings = 1 "" line continuation used here ?? let s:cpo_save = &cpo set cpo&vim " ------------------------------------------------------------------------ " Commands {{{2 " ------------------------------------------------------------------------ " Cf. cpp_BuildTemplates.vim " " ------------------------------------------------------------------------ " VIM Includes {{{2 " ------------------------------------------------------------------------ if exists("b:did_ftplugin") unlet b:did_ftplugin endif source $VIMRUNTIME/ftplugin/cpp.vim let b:did_ftplugin = 1 " " ------------------------------------------------------------------------ " Options to set {{{2 " ------------------------------------------------------------------------ " setlocal formatoptions=croql " setlocal cindent " setlocal cinoptions=g0,t0,h1s,i0 if has('patch-7.3-202') setlocal cinoptions+=N-s endif setlocal suffixesadd+=.hpp,.cpp,.C,.h++,.c++,.hh " Emulate [[ and ]] in C++ nnoremap [[ :call lh#dev#_goto_function_begin() onoremap [[ :call lh#dev#_goto_function_begin() nnoremap ][ :call lh#dev#_goto_function_end() onoremap ][ :call lh#dev#_goto_function_end() " browse filter if has("gui_win32") let b:browsefilter = \ "C++ Header Files (*.hpp *.h++ *hh)\t*.hpp;*.h++;*.hh\n" . \ "C++ Source Files (*.cpp *.c++)\t*.cpp;*.c++\n" . \ "C Header Files (*.h)\t*.h\n" . \ "C Source Files (*.c)\t*.c\n" . \ "All Files (*.*)\t*.*\n" endif " }}}2 " ======================================================================== " General definitions {{{1 " ======================================================================== if exists("g:loaded_cpp_set") && !exists('g:force_reload_cpp_ftp') let &cpo = s:cpo_save finish endif let g:loaded_cpp_set = 1 let &cpo = s:cpo_save "============================================================================= " vim600: set fdm=marker: ================================================ FILE: ftplugin/cpp/cpp_snippets.vim ================================================ "============================================================================= " File: ftplugin/cpp/cpp_snippets.vim {{{1 " Author: Luc Hermitte " " License: GPLv3 with exceptions " " Version: 2.2.0 let s:k_version = '220' " Created: 15th Apr 2008 " Last Update: 08th Mar 2018 "------------------------------------------------------------------------ " Description: Snippets of C++ Control Statements " "------------------------------------------------------------------------ " History: " for changelog: 13th Dec 2005 -> little bug in vmaps for ,,sc ,,rc ,,dc ,,cc " for changelog: 15th Feb 2006 -> abbr for firend -> friend " for changelog: 10th Apr 2006 -> "typename" after commas as well " for changelog: 12th Jun 2006 -> is not expanded in comments/string " }}}1 "============================================================================= " Buffer-local Definitions {{{1 " Avoid local reinclusion {{{2 if (exists("b:loaded_ftplug_cpp_snippets") && !exists('g:force_reload_ftplug_cpp_snippets')) || get(g:, 'lh_cpp_snippets', 1) == 0 finish endif let s:cpo_save=&cpo set cpo&vim let b:loaded_ftplug_cpp_snippets = s:k_version " Avoid local reinclusion }}}2 "------------------------------------------------------------------------ " This must be loaded before continuing runtime! ftplugin/c/c_snippets.vim " Local mappings {{{2 " "------------------------------------------------------------------------ " Some C++ abbreviated Keywords {{{3 " ------------------------------------------------------------------------ " TODO: check whether the line is empty Inoreab pub ='public'.lh#cpp#snippets#insert_if_not_after(' ', ':\', '[:,]') Inoreab pro ='protected'.lh#cpp#snippets#insert_if_not_after(' ', ':\', '[:,]') Inoreab pri ='private'.lh#cpp#snippets#insert_if_not_after(' ', ':\', '[:,]') Iabbr tpl template < inoreab vir virtual cnoreab firend friend inoreab firend friend inoreab delate delta inoremap std:: inoremap (getline('.')=~'#\s*include') ? 'boost/' : 'boost::' inoremap lh#cpp#snippets#current_namespace("\") " We don't want ? (\hat o) to be expanded in comments) inoremap =lh#map#insert_seq('', '\=lh#cpp#snippets#typedef_typename()\') "------------------------------------------------------------------------ " Control statements {{{3 "------------------------------------------------------------------------ "--- namespace ---------------------------------------------------{{{4 "--,ns insert "namespace" statement Inoreabbr namespace =lh#cpp#snippets#insert_if_not_after('namespace ', \ '\namespace <+namespace+>{<++>}// namespace <+namespace+>', 'using') " Inoreabbr namespace =lh#cpp#snippets#insert_if_not_after('namespace ', " \ '\namespace !cursorhere! {!mark!}!mark!', 'using') vnoremap ns \ @=lh#style#surround('namespace !cursorhere!{', '!mark!}!mark!', \ 0, 1, '', 1, 'namespace ') nmap ns Vns "--- try ---------------------------------------------------------{{{4 "--try insert "try" statement command! -nargs=0 PrivateCppSearchTry :call search('try\_s*{\_s*\zs$', 'b') " Inoreabbr try =lh#cpp#snippets#def_abbr('try ', " \ '\try{!cursorhere!}catch(!mark!){!mark!}!mark!\') Inoreabbr try =lh#cpp#snippets#def_abbr('try ', \ '\try{}catch(!mark!){!mark!}!mark!\' \ .':PrivateCppSearchTry\a\') " " \ .'?try\\_s*\\zs{\:PopSearch\o') " pb with prev. line: { is replaced by \n when c_nl_before_curlyB=1 " " pb with next line: !cursorhere! is badly indented " \ '\try {!cursorhere!} catch (!mark!) {!mark!}!mark!') "--,try insert "try - catch" statement vnoremap try \ @=lh#style#surround('try{!cursorhere!', '!mark!}catch(!mark!){!mark!}', \ 0, 1, '', 1, 'try ') nmap try Vtry "--- catch -------------------------------------------------------{{{4 "--catch insert "catch" statement Inoreabbr catch =lh#cpp#snippets#def_abbr('catch ', \ '\catch(!cursorhere!){!mark!}!mark!') vnoremap catch \ @=lh#style#surround('catch(!cursorhere!){', '!mark!}', \ 0, 1, '', 1, 'catch ') nmap catch Vcatch vnoremap catch \ @=lh#style#surround('catch(', '!cursorhere!){!mark!}', \ 0, 1, '', 1, 'catch ') nmap catch Vcatch "------------------------------------------------------------------------ " Castings {{{3 "------------------------------------------------------------------------ " TODO: have s:k_cast_fmt be a [bg]:({ft}_) option. let s:k_cast = { \ 'sc': 'static_cast', \ 'dc': 'dynamic_cast', \ 'cc': 'const_cast', \ 'rc': 'reinterpret_cast', \ 'lc': 'boost::lexical_cast' \ } " ,*c -> surround selection/current with "cast<«cursor»>(«selection»)>" " 2,*c -> surround selection/current with "cast<«selection»>(«cursor»)>" for cast in ['sc', 'cc', 'rc', 'dc', 'lc'] exe 'vnoremap '.cast \ ." @=lh#style#surround('".s:k_cast[cast]."(', '!mark!)'," \ ."0, 0, '', 1, '".s:k_cast[cast]."<')" exe ' nmap '.cast.' viw'.cast endfor " ,*c -> change the C cast selected into the C++ cast for cast in ['sc', 'cc', 'rc', 'dc'] exe 'vnoremap '.cast \ ." :'<,'>call lh#cpp#snippets#_convert_to_cpp_cast('".cast."')" exe ' nmap '.cast.' viw'.cast endfor " "------------------------------------------------------------------------ " Misc {{{3 "------------------------------------------------------------------------ "--- Std oriented stuff-------------------------------------------{{{4 " In std::foreach and std::find algorithms, ..., expand 'algo(container?)' " into: " TODO: support begin(container) (std:: or boost::) as well " - 'algo(container.begin(),container.end()?)', " imap be .ci,"begin(),"end() imap be =lh#cpp#snippets#_begin_end('begin') xmap be ci,".begin(),".end() nmap be viwbe " - 'algo(container.rbegin(),container.rend()?)', imap rbe =lh#cpp#snippets#_begin_end('rbegin') xmap rbe ci,".rbegin(),".rend() nmap rbe viwrbe " - 'algo(container.cbegin(),container.cend()?)', imap cbe =lh#cpp#snippets#_begin_end('cbegin') xmap cbe ci,".cbegin(),".cend() nmap cbe viwcbe " }}}1 "------------------------------------------------------------------------ let &cpo=s:cpo_save "============================================================================= " vim600: set fdm=marker: ================================================ FILE: ftplugin/idl_set.vim ================================================ "============================================================================= " File: ftplugin/cpp/idl_set.vim {{{1 " Author: Luc Hermitte " " Version: 1.1.0 " Created: 09th Mar 2005 " Last Update: 30th Apr 2019 "------------------------------------------------------------------------ " Description: Few definitions for IDL editing. " "------------------------------------------------------------------------ " Installation: Drop the file into {rtp}/ftplugin/ " History: " v1.0: first version " inspired from ftplugin/c/c_set.vim and ftplugin/cpp/cpp_set.vim " TODO: " * Ensure Def_MapC from c_set.vim is loaded " }}}1 "============================================================================= "============================================================================= " Avoid buffer reinclusion {{{1 let s:cpo_save=&cpo set cpo&vim if exists('b:loaded_ftplug_idl_set_vim') \ && !exists('g:force_reload_idl_set_vim') let &cpo=s:cpo_save finish endif let b:loaded_ftplug_idl_set_vim = 1 " ------------------------------------------------------------------------ " VIM Includes {{{2 " ------------------------------------------------------------------------ if exists("b:did_ftplugin") unlet b:did_ftplugin endif " }}}1 "------------------------------------------------------------------------ " Commands and mappings {{{1 " ------------------------------------------------------------------------ " Options to set {{{2 " ------------------------------------------------------------------------ setlocal formatoptions=croql setlocal cindent setlocal comments=sr:/*,mb:*,exl:*/,:// setlocal isk+=# " so #if is considered as a keyword, etc setlocal ch=2 setlocal nosmd setlocal cinoptions=g0,t0,h1s runtime syntax/doxygen.vim runtime ftplugin/c/c_brackets.vim " ------------------------------------------------------------------------ " Comments ; Javadoc/DOC++/Doxygen style {{{2 " ------------------------------------------------------------------------ " /** inserts /** " */ " but only outside the scope of C++ comments and strings inoremap /** =Def_MapC('/**', \ '/**\\/\\ ', \ '/**\\/!mark!\\ ') " /* inserts /** */ inoremap /* =Def_MapC('/* ', \ '/** */\\', \ '/** */!mark!\F*i') " Commands and mappings }}}1 "============================================================================= " Avoid global reinclusion {{{1 if exists("g:loaded_idl_set_vim") \ && !exists('g:force_reload_idl_set_vim') let &cpo=s:cpo_save finish endif let g:loaded_idl_set_vim = 1 " Avoid global reinclusion }}}1 "------------------------------------------------------------------------ " Functions {{{1 " Functions }}}1 "------------------------------------------------------------------------ let &cpo=s:cpo_save "============================================================================= " vim600: set fdm=marker: ================================================ FILE: mkVba/mk-lh-cpp.vim ================================================ "============================================================================= " File: mkVba/mk-lh-cpp.vim " Author: Luc Hermitte " " License: GPLv3 with exceptions " " Version: 2.2.1 " Created: 06th Nov 2007 " Last Update: 28th Nov 2019 "------------------------------------------------------------------------ let s:version = '2.2.1' let s:project = 'lh-cpp' cd :p:h try let save_rtp = &rtp let &rtp = expand(':p:h:h').','.&rtp exe '24,$MkVimball! '.s:project.'-'.s:version set modifiable set buftype= finally let &rtp = save_rtp endtry finish VimFlavor addon-info.json after/plugin/a.vim after/template/c/assert.template after/template/c/comment.template after/template/c/internals/c-header-content.template after/template/c/rand_init.template after/template/c/realloc.template after/template/cpp/abs-rel.template after/template/cpp/abstract-class.template after/template/cpp/array_size.template after/template/cpp/assignment-operator.template after/template/cpp/auto_ptr-instance.template after/template/cpp/auto_ptr.template after/template/cpp/b-e.template after/template/cpp/base-class-non-virtual.template after/template/cpp/base-class.template after/template/cpp/benchmark.template after/template/cpp/bool-operator.template after/template/cpp/catch.template after/template/cpp/cerr.template after/template/cpp/chrono-how-long.template after/template/cpp/cin.template after/template/cpp/class.template after/template/cpp/clonable-class.template after/template/cpp/copy-and-swap.template after/template/cpp/copy-back_inserter.template after/template/cpp/copy-constructor.template after/template/cpp/copy.template after/template/cpp/cout.template after/template/cpp/default-constructor.template after/template/cpp/destructor.template after/template/cpp/empty-exception-class.template after/template/cpp/ends_with.template after/template/cpp/entity-class.template after/template/cpp/enum.template after/template/cpp/enum2-impl.template after/template/cpp/enum2.template after/template/cpp/erase-remove.template after/template/cpp/exception-class.template after/template/cpp/file.template after/template/cpp/for-enum.template after/template/cpp/for-iterator.template after/template/cpp/for-range.template after/template/cpp/fori.template after/template/cpp/foriN.template after/template/cpp/forward.template after/template/cpp/getter.template after/template/cpp/init-constructor.template after/template/cpp/interface.template after/template/cpp/internals/abs-rel-shared.template after/template/cpp/internals/attribute.template after/template/cpp/internals/class-skeleton.template after/template/cpp/internals/formatted-comment.template after/template/cpp/internals/function-comment.template after/template/cpp/internals/function.template after/template/cpp/internals/get-b-e.template after/template/cpp/internals/get-class-name.template after/template/cpp/internals/includes.template after/template/cpp/internals/list-constructors.template after/template/cpp/internals/namespace-name.template after/template/cpp/internals/shall_explicit_defaults.template after/template/cpp/internals/stream-common.template after/template/cpp/internals/stream-implementation.template after/template/cpp/internals/stream-signature.template after/template/cpp/iss.template after/template/cpp/list.template after/template/cpp/map.template after/template/cpp/namespace.template after/template/cpp/noncopyable.template after/template/cpp/operator-binary.template after/template/cpp/oss.template after/template/cpp/otb-sug-latex.template after/template/cpp/otb-sug-snippet.template after/template/cpp/path.template after/template/cpp/ptr_vector.template after/template/cpp/ref_setter.template after/template/cpp/scoped_ptr.template after/template/cpp/set.template after/template/cpp/setter.template after/template/cpp/shared_ptr.template after/template/cpp/singleton.template after/template/cpp/sort.template after/template/cpp/starts_with.template after/template/cpp/static_assert.template after/template/cpp/stream-extractor.template after/template/cpp/stream-inserter.template after/template/cpp/string.template after/template/cpp/swap-function.template after/template/cpp/throw.template after/template/cpp/traits.template after/template/cpp/try.template after/template/cpp/typeid.template after/template/cpp/unique_ptr.template after/template/cpp/unordered_map.template after/template/cpp/unordered_set.template after/template/cpp/utf8.template after/template/cpp/value-class.template after/template/cpp/vector.template after/template/cpp/weak_ptr.template after/template/cpp/while-getline.template after/template/dox/author.template after/template/dox/code.template after/template/dox/em.template after/template/dox/file.template after/template/dox/function.template after/template/dox/group.template after/template/dox/html.template after/template/dox/ingroup.template after/template/dox/since.template after/template/dox/tt.template autoload/lh/cpp.vim autoload/lh/cpp/AnalysisLib_Class.vim autoload/lh/cpp/AnalysisLib_Function.vim autoload/lh/cpp/GotoFunctionImpl.vim autoload/lh/cpp/UnmatchedFunctions.vim autoload/lh/cpp/abs_rel.vim autoload/lh/cpp/constructors.vim autoload/lh/cpp/enum.vim autoload/lh/cpp/ftplugin.vim autoload/lh/cpp/include.vim autoload/lh/cpp/libclang.vim autoload/lh/cpp/macros.vim autoload/lh/cpp/option.vim autoload/lh/cpp/override.vim autoload/lh/cpp/refactor.vim autoload/lh/cpp/scope.vim autoload/lh/cpp/snippets.vim autoload/lh/cpp/style.vim autoload/lh/cpp/tags.vim autoload/lh/cpp/types.vim autoload/lh/dox.vim doc/API.md doc/Doxygen.md doc/Enums.md doc/TODO.md doc/c.html doc/lh-cpp-readme.txt doc/options.md doc/snippets.md ftplugin/c/LoadHeaderFile.vim ftplugin/c/c_AddInclude.vim ftplugin/c/c_Doxygen.vim ftplugin/c/c_UnmatchedFunctions.vim ftplugin/c/c_complete_include.vim ftplugin/c/c_doc.vim ftplugin/c/c_gcov.vim ftplugin/c/c_menu.vim ftplugin/c/c_mu-template_api.vim ftplugin/c/c_navigate_functions.vim ftplugin/c/c_pvs-2-qf.vim ftplugin/c/c_set.vim ftplugin/c/c_snippets.vim ftplugin/c/c_stl.vim ftplugin/c/c_switch-enum.vim ftplugin/c/flistmaps.vim ftplugin/c/keep_pound_if_path.vim ftplugin/c/previewWord.vim ftplugin/c/word.list ftplugin/cpp/cpp_AddMissingScope.vim ftplugin/cpp/cpp_BuildTemplates.vim ftplugin/cpp/cpp_Constructor.vim ftplugin/cpp/cpp_Doxygen_class_stuff.vim ftplugin/cpp/cpp_Enum.vim ftplugin/cpp/cpp_FindContextClass.vim ftplugin/cpp/cpp_GotoFunctionImpl.vim ftplugin/cpp/cpp_InsertAccessors.vim ftplugin/cpp/cpp_Inspect.vim ftplugin/cpp/cpp_Override.vim ftplugin/cpp/cpp_options-commands.vim ftplugin/cpp/cpp_options.vim ftplugin/cpp/cpp_refactor.vim ftplugin/cpp/cpp_set.vim ftplugin/cpp/cpp_snippets.vim ftplugin/idl_set.vim mkVba/mk-lh-cpp.vim plugin/a-old.vim plugin/homeLikeVC++.vim plugin/omap-param.vim syntax/c-assign-in-condition.vim syntax/c-fallthrough-case.vim syntax/c.vim syntax/cpp-badcatch.vim syntax/cpp-c-cast.vim syntax/cpp-cxxtest.vim syntax/cpp-funcdef.vim syntax/cpp-throw-spec.vim syntax/cpp.vim tests/lh/analysis.vim tests/lh/omap-param.vim tests/lh/snippets.vim tests/lh/test-flavours.vim tests/lh/test-types.vim ================================================ FILE: plugin/homeLikeVC++.vim ================================================ "============================================================================= " File: plugin/homeLikeVC++.vim " Author: Luc Hermitte " " Version: 2.0.1 " Created: 23rd mar 2002 " Last Update: $Date$ "------------------------------------------------------------------------ " Description: Makes behaves like it does with Ms-VC++. " -> Hitting once moves the cursor to the first non blank character of " the line, twice: to the first column of the line. " -> once moves the cursor at the last non blank character, then at the " last character (if different), ... " "------------------------------------------------------------------------ " Installation: Drop it into one of your plugin directories " " This plugin does not propose, on purpose, windows-like keybindings " combining with , nor . " These keybinding are more generic, and may need to be implemented " differently according to one's taste. If you come from a MsWindows " background you may be interrested in " :imap gh " :nmap gh " :vmap " " :imap gh " :nmap gh " :vmap " " Personnally, I'd rather never end-up in SELECT-mode unless I " explicitly say so, or unless I jumped to a |marker| (aka " |placeholder|). For instance, I often need to (visually) select text " and then surround it with a pair of brackets, while I expect '(' to " expand into '()' when I am in INSERT- or SELECT-mode. " " Thus, In my .vimrc, I define the following mappings: " :imap vo " :nmap v " :vmap " :imap v " :nmap v " :vmap " " Note: I use here :*map and not :*noremap. " " History: " v1.0: initial version " v1.1: VISUAL-mode mapping added. " v2.0.0: is supported as well " v2.0.1: silent mappings "============================================================================= " " Avoid reinclusion if exists("g:loaded_homeLikeVC") && !exists('g:force_reload_homelikeVC') finish endif let g:loaded_homeLikeVC = '2.0.1' "------------------------------------------------------------------------ inoremap @=HomeLikeVCpp() nnoremap @=HomeLikeVCpp() vnoremap @=HomeLikeVCpp() inoremap @=EndLikeVCpp()a nnoremap @=EndLikeVCpp() vnoremap @=EndLikeVCpp() function! s:HomeLikeVCpp() let ll = strpart(getline('.'), -1, col('.')) if ll =~ '^\s\+$' | return '0' else | return '^' endif endfunction function! s:EndLikeVCpp() let l = strpart(getline('.'), col('.')-1) let ll = match(l, '^\S\s*$') if getline('.') =~ '^\s*$' if col('.') + (mode()!='v') == col('$') | return 'g_' else | return '$' endif else if ll >= 0 | return '$' else | return 'g_' endif endif endfunction ================================================ FILE: plugin/omap-param.vim ================================================ "============================================================================= " File: plugin/omap-param.vim {{{1 " Maintainer: Luc Hermitte " " Other Contributors: A.Politz " Version: 1.1.0 " Created: 03rd Sep 2007 " Last Update: $Date$ (05th Sep 2007) "------------------------------------------------------------------------ " Description: " Mappings for selecting functions parameters in various programming " langages where parameters are passed within braces, separated by " commas. " " See: " :h objet-select " "------------------------------------------------------------------------ " Installation: " Drop this file into {rtp}/plugin/ " Requires " - Vim 7+, " - {rtp}/autoload/lh/position.vim " - {rtp}/autoload/lh/syntax.vim " History: " v0.9.0 first version " Credits: " " A.Politz " TODO: " Move this into lh-vim-lib or a plugin. " Notes: " * "i," can't be used to select several parameters with several uses of " "i," ; use "a," instead (-> "va,a,a,"). This is because of simple " letter parameters. " However, "v2i," works perfectly. " * The following should be resistant to &magic, and other mappings " * select-mode is not parasited by this plugin " }}}1 "============================================================================= "============================================================================= " Avoid global reinclusion {{{1 let s:cpo_save=&cpo set cpo&vim if exists("g:loaded_omap_param_vim") \ && !exists('g:force_reload_omap_param_vim') let &cpo=s:cpo_save finish endif let g:loaded_omap_param_vim = 1 " Avoid global reinclusion }}}1 "------------------------------------------------------------------------ " Public Mappings {{{1 onoremap i, :call SelectParam(1,0) xnoremap i, :call SelectParam(1,1)gv onoremap a, :call SelectParam(0,0) xnoremap a, :call SelectParam(0,1)gv " Private Functions {{{1 function! s:SelectParam(inner, visual) abort let saved_pos = getpos('.') if a:visual ==1 && lh#position#char_at_mark("'>") =~ '[(,]' \ && !lh#syntax#skip_at_mark("'>") normal! gv elseif searchpair('(',',',')','bcW','lh#syntax#skip()') > 0 || \ searchpair('(',',',')','bW','lh#syntax#skip()') > 0 " Test necessary because 'c' flag and Skip() don't always work well together call search('.') normal! v else throw "Not on a parameter" endif let cnt = v:count <= 0 ? 1 : v:count while cnt > 0 let cnt -= 1 if 0 == searchpair('(', ',',')', 'W','lh#syntax#skip()') if lh#position#is_before(getpos('.'), saved_pos) " no "vi," when starting from the last parameter exe "normal! \" call setpos('.', saved_pos) throw (a:visual?'v':'').(a:inner?'i':'a').",: Cursor not on a parameter" else echomsg (a:visual?'v':'').(a:inner?'i':'a').",: No more parameters" " 999di, silently deletes everything till the end break endif endif endwhile " Don't include the last closing paren if a:inner == 1 || searchpair('(',',',')','n','lh#syntax#skip()') <= 0 call search('.','b') endif endfunction " Private Functions }}}1 if 0 finish call Un(Null,fun2(fun3(a,b,g(NULL))),t, titi, r , zzz call Un(Null,fun2(fun3(a,b,g(NULL))),t, titi, , zzz) endif "------------------------------------------------------------------------ let &cpo=s:cpo_save "============================================================================= " vim600: set fdm=marker: ================================================ FILE: script/PVS2qf.xsl ================================================ '" [ { 'filename': '', 'lnum': , 'nr' : '', 'text': ' ', 'type': } , ] ================================================ FILE: spec/abstract-class_spec.rb ================================================ # encoding: UTF-8 require 'spec_helper' require 'pp' RSpec.describe "C++ abstract class wizard", :abstract, :cpp, :class do let (:filename) { "test.cpp" } # ====[ Executed once before all test {{{2 before :all do if !defined? vim.runtime vim.define_singleton_method(:runtime) do |path| self.command("runtime #{path}") end end vim.runtime('spec/support/input-mock.vim') expect(vim.command('verbose function lh#ui#input')).to match(/input-mock.vim/) expect(vim.echo('lh#mut#dirs#get_templates_for("cpp/abstract-class")')).to match(/abstract-class.template/) end # ====[ Always executed before each test {{{2 before :each do expect(vim.echo('&enc')).to eq 'utf-8' vim.command('filetype plugin on') vim.command("file #{filename}") vim.set('ft=cpp') vim.command('set fenc=utf-8') vim.set('expandtab') vim.set('sw=4') vim.command('silent! unlet g:cpp_explicit_default') vim.command('silent! unlet g:cpp_std_flavour') clear_buffer set_buffer_contents <<-EOF /** File Header line to trick auto-inclusion */ EOF vim.command(%Q{call append(1, ['', ''])}) expect(vim.echo('line("$")')).to eq '3' expect(vim.echo('setpos(".", [1,3,1,0])')).to eq '0' expect(vim.echo('line(".")')).to eq '3' end specify "abstract-class noncopyable, with implicit definitions", :cpp98, :cpp11, :noncopyable do vim.command('silent! unlet g:cpp_noncopyable_class') expect(vim.command('MuTemplate cpp/abstract-class')).to match(/^$|#include added/) assert_buffer_contents <<-EOF /** File Header line to trick auto-inclusion */ #include /** * «Test». * @invariant «» *

    Semantics
    * - Abstract * - Entity * - Non-copyable * @author «author-name», creation * @since Version «1.0» */ class «Test» : private boost::noncopyable { public: /** * Virtual destructor. * @throw Nothing */ virtual ~«Test»() = 0; protected: /** * Default constructor. * «@throw » */ «Test»(); }; EOF end specify "abstract-class noncopyable, no implicit definitions", :cpp11, :noncopyable, :defaulted do vim.command('silent! unlet g:cpp_noncopyable_class') vim.command("let g:cpp_std_flavour = 11") vim.command("let g:cpp_explicit_default = 1") expect(vim.command('MuTemplate cpp/abstract-class')).to match(/^$|#include added/) assert_buffer_contents <<-EOF /** File Header line to trick auto-inclusion */ #include /** * «Test». * @invariant «» *

    Semantics
    * - Abstract * - Entity * - Non-copyable * @author «author-name», creation * @since Version «1.0» */ class «Test» : private boost::noncopyable { public: /** * Virtual destructor. * @throw Nothing */ virtual ~«Test»() = 0; protected: «Test»() = default; private: «Test»(«Test» const&) = delete; «Test»& operator=(«Test» const&) = delete; }; EOF end specify "abstract-class C++98 alone", :cpp98, :deleted do vim.command('let g:cpp_noncopyable_class=""') vim.command('let g:cpp_std_flavour = 03') expect(vim.command('MuTemplate cpp/abstract-class')).to eq "" assert_buffer_contents <<-EOF /** File Header line to trick auto-inclusion */ /** * «Test». * @invariant «» *

    Semantics
    * - Abstract * - Entity * - Non-copyable * @author «author-name», creation * @since Version «1.0» */ class «Test» { public: /** * Virtual destructor. * @throw Nothing */ virtual ~«Test»() = 0; protected: /** * Default constructor. * «@throw » */ «Test»(); private: «Test»(«Test» const&) /* = delete */; «Test»& operator=(«Test» const&) /* = delete */; }; EOF end specify "abstract-class C++11 alone, w/ implicit definition", :cpp11, :deleted do vim.command('let g:cpp_noncopyable_class = ""') vim.command('let g:cpp_std_flavour = 11') expect(vim.command('MuTemplate cpp/abstract-class')).to eq "" assert_buffer_contents <<-EOF /** File Header line to trick auto-inclusion */ /** * «Test». * @invariant «» *

    Semantics
    * - Abstract * - Entity * - Non-copyable * @author «author-name», creation * @since Version «1.0» */ class «Test» { public: /** * Virtual destructor. * @throw Nothing */ virtual ~«Test»() = 0; protected: /** * Default constructor. * «@throw » */ «Test»(); private: «Test»(«Test» const&) = delete; «Test»& operator=(«Test» const&) = delete; }; EOF end specify "abstract-class C++11 alone, no implicit definitions", :cpp11, :deleted, :defaulted do vim.command('let g:cpp_noncopyable_class = ""') vim.command('let g:cpp_std_flavour = 11') vim.command("let g:cpp_explicit_default = 1") expect(vim.command('MuTemplate cpp/abstract-class')).to eq "" assert_buffer_contents <<-EOF /** File Header line to trick auto-inclusion */ /** * «Test». * @invariant «» *

    Semantics
    * - Abstract * - Entity * - Non-copyable * @author «author-name», creation * @since Version «1.0» */ class «Test» { public: /** * Virtual destructor. * @throw Nothing */ virtual ~«Test»() = 0; protected: «Test»() = default; private: «Test»(«Test» const&) = delete; «Test»& operator=(«Test» const&) = delete; }; EOF end end # vim:set sw=2: ================================================ FILE: spec/base-class-NV_spec.rb ================================================ # encoding: UTF-8 require 'spec_helper' require 'pp' RSpec.describe "C++ non virtual base class wizard", :base_nv, :cpp, :class do let (:filename) { "test.cpp" } # ====[ Executed once before all test {{{2 before :all do if !defined? vim.runtime vim.define_singleton_method(:runtime) do |path| self.command("runtime #{path}") end end vim.runtime('spec/support/input-mock.vim') expect(vim.command('verbose function lh#ui#input')).to match(/input-mock.vim/) expect(vim.echo('lh#mut#dirs#get_templates_for("cpp/base-class-non-virtual")')).to match(/base-class-non-virtual.template/) end # ====[ Always executed before each test {{{2 before :each do vim.command('filetype plugin on') vim.command("file #{filename}") vim.set('ft=cpp') vim.set('expandtab') vim.set('sw=4') vim.command('silent! unlet g:cpp_explicit_default') vim.command('silent! unlet g:cpp_std_flavour') clear_buffer set_buffer_contents <<-EOF /** File Header line to trick auto-inclusion */ EOF vim.command(%Q{call append(1, ['', ''])}) expect(vim.echo('line("$")')).to eq '3' expect(vim.echo('setpos(".", [1,3,1,0])')).to eq '0' expect(vim.echo('line(".")')).to eq '3' end specify "base-class-non-virtual noncopyable, with implicit definitions", :cpp98, :cpp11, :noncopyable do vim.command('silent! unlet g:cpp_noncopyable_class') expect(vim.command('MuTemplate cpp/base-class-non-virtual')).to match(/^$|#include added/) assert_buffer_contents <<-EOF /** File Header line to trick auto-inclusion */ #include /** * «Test». * @invariant «» *

    Semantics
    * - Entity * - Non-copyable * @author «author-name», creation * @since Version «1.0» */ class «Test» : private boost::noncopyable { public: protected: /** * Default constructor. * «@throw » */ «Test»(); /** * Destructor. * @throw Nothing * @note This class is not meant to be destroyed polymorphically */ ~«Test»(); }; EOF end specify "base-class-non-virtual noncopyable, no implicit definitions", :cpp11, :noncopyable, :defaulted do vim.command('silent! unlet g:cpp_noncopyable_class') vim.command("let g:cpp_std_flavour = 11") vim.command("let g:cpp_explicit_default = 1") expect(vim.command('MuTemplate cpp/base-class-non-virtual')).to match(/^$|#include added/) assert_buffer_contents <<-EOF /** File Header line to trick auto-inclusion */ #include /** * «Test». * @invariant «» *

    Semantics
    * - Entity * - Non-copyable * @author «author-name», creation * @since Version «1.0» */ class «Test» : private boost::noncopyable { public: protected: «Test»() = default; /** * Destructor. * @throw Nothing * @note This class is not meant to be destroyed polymorphically */ ~«Test»() = default; private: «Test»(«Test» const&) = delete; «Test»& operator=(«Test» const&) = delete; }; EOF end specify "base-class-non-virtual C++98 alone", :cpp98, :deleted do vim.command('let g:cpp_noncopyable_class=""') vim.command('let g:cpp_std_flavour = 03') expect(vim.command('MuTemplate cpp/base-class-non-virtual')).to eq "" assert_buffer_contents <<-EOF /** File Header line to trick auto-inclusion */ /** * «Test». * @invariant «» *

    Semantics
    * - Entity * - Non-copyable * @author «author-name», creation * @since Version «1.0» */ class «Test» { public: protected: /** * Default constructor. * «@throw » */ «Test»(); /** * Destructor. * @throw Nothing * @note This class is not meant to be destroyed polymorphically */ ~«Test»(); private: «Test»(«Test» const&) /* = delete */; «Test»& operator=(«Test» const&) /* = delete */; }; EOF end specify "base-class-non-virtual C++11 alone, w/ implicit definition", :cpp11, :deleted do vim.command('let g:cpp_noncopyable_class = ""') vim.command('let g:cpp_std_flavour = 11') expect(vim.command('MuTemplate cpp/base-class-non-virtual')).to eq "" assert_buffer_contents <<-EOF /** File Header line to trick auto-inclusion */ /** * «Test». * @invariant «» *

    Semantics
    * - Entity * - Non-copyable * @author «author-name», creation * @since Version «1.0» */ class «Test» { public: protected: /** * Default constructor. * «@throw » */ «Test»(); /** * Destructor. * @throw Nothing * @note This class is not meant to be destroyed polymorphically */ ~«Test»(); private: «Test»(«Test» const&) = delete; «Test»& operator=(«Test» const&) = delete; }; EOF end specify "base-class-non-virtual C++11 alone, no implicit definition", :cpp11, :deleted, :defaulted do vim.command('let g:cpp_noncopyable_class = ""') vim.command('let g:cpp_std_flavour = 11') vim.command("let g:cpp_explicit_default = 1") expect(vim.command('MuTemplate cpp/base-class-non-virtual')).to eq "" assert_buffer_contents <<-EOF /** File Header line to trick auto-inclusion */ /** * «Test». * @invariant «» *

    Semantics
    * - Entity * - Non-copyable * @author «author-name», creation * @since Version «1.0» */ class «Test» { public: protected: «Test»() = default; /** * Destructor. * @throw Nothing * @note This class is not meant to be destroyed polymorphically */ ~«Test»() = default; private: «Test»(«Test» const&) = delete; «Test»& operator=(«Test» const&) = delete; }; EOF end end # vim:set sw=2: ================================================ FILE: spec/base-class_spec.rb ================================================ # encoding: UTF-8 require 'spec_helper' require 'pp' RSpec.describe "C++ base class wizard", :base, :cpp, :class do let (:filename) { "test.cpp" } # ====[ Executed once before all test {{{2 before :all do if !defined? vim.runtime vim.define_singleton_method(:runtime) do |path| self.command("runtime #{path}") end end vim.runtime('spec/support/input-mock.vim') expect(vim.command('verbose function lh#ui#input')).to match(/input-mock.vim/) expect(vim.echo('lh#mut#dirs#get_templates_for("cpp/base-class")')).to match(/base-class.template/) end # ====[ Always executed before each test {{{2 before :each do vim.command('filetype plugin on') vim.command("file #{filename}") vim.set('ft=cpp') vim.set('expandtab') vim.set('sw=4') vim.command('silent! unlet g:cpp_explicit_default') vim.command('silent! unlet g:cpp_std_flavour') clear_buffer set_buffer_contents <<-EOF /** File Header line to trick auto-inclusion */ EOF vim.command(%Q{call append(1, ['', ''])}) expect(vim.echo('line("$")')).to eq '3' expect(vim.echo('setpos(".", [1,3,1,0])')).to eq '0' expect(vim.echo('line(".")')).to eq '3' end specify "base_class noncopyable, with implicit definitions", :cpp98, :cpp11, :noncopyable do vim.command('silent! unlet g:cpp_noncopyable_class') expect(vim.command('MuTemplate cpp/base-class')).to match(/^$|#include added/) assert_buffer_contents <<-EOF /** File Header line to trick auto-inclusion */ #include /** * «Test». * @invariant «» *

    Semantics
    * - Entity * - Non-copyable * @author «author-name», creation * @since Version «1.0» */ class «Test» : private boost::noncopyable { public: /** * Virtual destructor. * @throw Nothing */ virtual ~«Test»(); protected: /** * Default constructor. * «@throw » */ «Test»(); }; EOF end specify "base_class noncopyable, no implicit definitions", :cpp11, :noncopyable, :defaulted do vim.command('silent! unlet g:cpp_noncopyable_class') vim.command("let g:cpp_std_flavour = 11") vim.command("let g:cpp_explicit_default = 1") expect(vim.command('MuTemplate cpp/base-class')).to match(/^$|#include added/) assert_buffer_contents <<-EOF /** File Header line to trick auto-inclusion */ #include /** * «Test». * @invariant «» *

    Semantics
    * - Entity * - Non-copyable * @author «author-name», creation * @since Version «1.0» */ class «Test» : private boost::noncopyable { public: /** * Virtual destructor. * @throw Nothing */ virtual ~«Test»(); protected: «Test»() = default; private: «Test»(«Test» const&) = delete; «Test»& operator=(«Test» const&) = delete; }; EOF end specify "base_class C++98 alone", :cpp98, :deleted do vim.command('let g:cpp_noncopyable_class=""') vim.command('let g:cpp_std_flavour = 03') expect(vim.command('MuTemplate cpp/base-class')).to eq "" assert_buffer_contents <<-EOF /** File Header line to trick auto-inclusion */ /** * «Test». * @invariant «» *

    Semantics
    * - Entity * - Non-copyable * @author «author-name», creation * @since Version «1.0» */ class «Test» { public: /** * Virtual destructor. * @throw Nothing */ virtual ~«Test»(); protected: /** * Default constructor. * «@throw » */ «Test»(); private: «Test»(«Test» const&) /* = delete */; «Test»& operator=(«Test» const&) /* = delete */; }; EOF end specify "base_class C++11 alone, w/ implicit definition", :cpp11, :deleted do vim.command('let g:cpp_noncopyable_class = ""') vim.command('let g:cpp_std_flavour = 11') expect(vim.command('MuTemplate cpp/base-class')).to eq "" assert_buffer_contents <<-EOF /** File Header line to trick auto-inclusion */ /** * «Test». * @invariant «» *

    Semantics
    * - Entity * - Non-copyable * @author «author-name», creation * @since Version «1.0» */ class «Test» { public: /** * Virtual destructor. * @throw Nothing */ virtual ~«Test»(); protected: /** * Default constructor. * «@throw » */ «Test»(); private: «Test»(«Test» const&) = delete; «Test»& operator=(«Test» const&) = delete; }; EOF end specify "base_class C++11 alone, no implicit definition", :cpp11, :deleted, :defaulted do vim.command('let g:cpp_noncopyable_class = ""') vim.command('let g:cpp_std_flavour = 11') vim.command("let g:cpp_explicit_default = 1") expect(vim.command('MuTemplate cpp/base-class')).to eq "" assert_buffer_contents <<-EOF /** File Header line to trick auto-inclusion */ /** * «Test». * @invariant «» *

    Semantics
    * - Entity * - Non-copyable * @author «author-name», creation * @since Version «1.0» */ class «Test» { public: /** * Virtual destructor. * @throw Nothing */ virtual ~«Test»(); protected: «Test»() = default; private: «Test»(«Test» const&) = delete; «Test»& operator=(«Test» const&) = delete; }; EOF end end # vim:set sw=2: ================================================ FILE: spec/class-with-attributes_spec.rb ================================================ # encoding: UTF-8 require 'spec_helper' require 'pp' RSpec.describe "C++ class w/ attributes wizard", :cpp, :class, :with_attributes do let (:filename) { "test.cpp" } # ====[ Executed once before all test {{{2 before :all do if !defined? vim.runtime vim.define_singleton_method(:runtime) do |path| self.command("runtime #{path}") end end vim.runtime('spec/support/input-mock.vim') expect(vim.command('verbose function lh#ui#input')).to match(/input-mock.vim/) expect(vim.echo('lh#mut#dirs#get_templates_for("cpp/value-class")')).to match(/value-class.template/) expect(vim.echo('lh#style#clear()')).to eq '0' vim.command('UseStyle breakbeforebraces=stroustrup -ft=c') vim.command('UseStyle spacesbeforeparens=control-statements -ft=c') vim.command('UseStyle empty_braces=nl -ft=c') end # ====[ Always executed before each test {{{2 before :each do vim.command('filetype plugin on') vim.command("file #{filename}") vim.set('ft=cpp') vim.set('expandtab') vim.set('sw=4') vim.command('silent! unlet g:cpp_explicit_default') vim.command('silent! unlet g:cpp_std_flavour') clear_buffer set_buffer_contents <<-EOF /** File Header line to trick auto-inclusion */ EOF vim.command(%Q{call append(1, ['', ''])}) expect(vim.echo('line("$")')).to eq '3' expect(vim.echo('setpos(".", [1,3,1,0])')).to eq '0' expect(vim.echo('line(".")')).to eq '3' end specify "attribute-class copy-neutral, C++98", :cpp98 do expect(vim.command('call lh#mut#expand_and_jump(0, "cpp/internals/class-skeleton", {"attributes": [{"name": "foo", "type": "int"}, {"name": "str", "type": "string", "functions": ["set", "get"]}, {"name": "bar", "type": "Bar", "includes":"bar.h"}]})')).to match(/^$|#include added/) vim.feedkeys('\\:silent! $call append("$", ["",""])\G') assert_buffer_contents <<-EOF /** File Header line to trick auto-inclusion */ #include #include "bar.h" /** * «Test». * @invariant «» * @author «author-name», creation * @since Version «1.0» */ class «Test» { public: /** * Init constructor. * @param[in] foo «foo-explanations» * @param[in] str «str-explanations» * @param[in] bar «bar-explanations» * «@throw » */ «Test»(int foo, std::string const& str, Bar const& bar) : m_foo(foo) , m_str(str) , m_bar(bar) { } void setStr(std::string const& str) { m_str = str; } std::string const& getStr() const { return m_str; } private: int m_foo; std::string m_str; Bar m_bar; }; EOF end specify "attribute-class copy-neutral, C++11", :cpp11 do vim.command('silent! let g:cpp_std_flavour=11') expect(vim.command('call lh#mut#expand_and_jump(0, "cpp/internals/class-skeleton", {"attributes": [{"name": "foo", "type": "int"}, {"name": "bar", "type": "string", "functions": ["set", "get"]}]})')).to match(/^$|#include added/) vim.feedkeys('\\:silent! $call append("$", ["",""])\G') assert_buffer_contents <<-EOF /** File Header line to trick auto-inclusion */ #include /** * «Test». * @invariant «» * @author «author-name», creation * @since Version «1.0» */ class «Test» { public: /** * Init constructor. * @param[in] foo «foo-explanations» * @param[in] bar «bar-explanations» * «@throw » */ «Test»(int foo, std::string const& bar) : m_foo(foo) , m_bar(bar) { } void setBar(std::string const& bar) { m_bar = bar; } std::string const& getBar() const { return m_bar; } private: int m_foo; std::string m_bar; }; EOF end end # vim:set sw=2: ================================================ FILE: spec/clonable-class_spec.rb ================================================ # encoding: UTF-8 require 'spec_helper' require 'pp' RSpec.describe "C++ clonable class wizard", :clonable, :cpp, :class do let (:filename) { "test.cpp" } # ====[ Executed once before all test {{{2 before :all do if !defined? vim.runtime vim.define_singleton_method(:runtime) do |path| self.command("runtime #{path}") end end vim.runtime('spec/support/input-mock.vim') expect(vim.command('verbose function lh#ui#input')).to match(/input-mock.vim/) expect(vim.echo('lh#mut#dirs#get_templates_for("cpp/clonable-class")')).to match(/clonable-class.template/) expect(vim.echo('lh#style#clear()')).to eq '0' vim.command('UseStyle breakbeforebraces=stroustrup -ft=c') vim.command('UseStyle spacesbeforeparens=control-statements -ft=c') vim.command('UseStyle empty_braces=nl -ft=c') end # ====[ Always executed before each test {{{2 before :each do vim.command('filetype plugin on') vim.command("file #{filename}") vim.set('ft=cpp') vim.set('expandtab') vim.set('sw=4') vim.command('silent! unlet g:cpp_explicit_default') vim.command('silent! unlet g:cpp_std_flavour') clear_buffer set_buffer_contents <<-EOF /** File Header line to trick auto-inclusion */ EOF vim.command(%Q{call append(1, ['', ''])}) expect(vim.echo('line("$")')).to eq '3' expect(vim.echo('setpos(".", [1,3,1,0])')).to eq '0' expect(vim.echo('line(".")')).to eq '3' end # ===============[ The base class ]============= specify "clonable_class noncopyable, with implicit definitions", :cpp98, :cpp11, :noncopyable do vim.command('silent! unlet g:cpp_noncopyable_class') expect(vim.command('MuTemplate cpp/clonable-class')).to match(/^$|#include added/) assert_buffer_contents <<-EOF /** File Header line to trick auto-inclusion */ #include #include /** * «Test». * @invariant «» *

    Semantics
    * - Clonable (but not assignable) * @author «author-name», creation * @since Version «1.0» */ class «Test» : private boost::noncopyable { public: /** * Virtual destructor. * @throw Nothing */ virtual ~«Test»(); virtual std::auto_ptr<«Test»> clone() const { return std::auto_ptr<«Test»>(new «Test»(*this)); } protected: /** * Default constructor. * «@throw » */ «Test»(); «Test»(«Test» const&) /* = default */; }; EOF end specify "clonable_class noncopyable, no implicit definitions, C++11", :cpp11, :noncopyable, :defaulted do vim.command('silent! unlet g:cpp_noncopyable_class') vim.command("let g:cpp_std_flavour = 11") vim.command("let g:cpp_explicit_default = 1") expect(vim.command('MuTemplate cpp/clonable-class')).to match(/^$|#include added/) assert_buffer_contents <<-EOF /** File Header line to trick auto-inclusion */ #include #include /** * «Test». * @invariant «» *

    Semantics
    * - Clonable (but not assignable) * @author «author-name», creation * @since Version «1.0» */ class «Test» : private boost::noncopyable { public: /** * Virtual destructor. * @throw Nothing */ virtual ~«Test»(); virtual std::unique_ptr<«Test»> clone() const { return std::unique_ptr<«Test»>(new «Test»(*this)); } protected: «Test»() = default; «Test»(«Test» const&) = default; private: «Test»& operator=(«Test» const&) = delete; }; EOF end specify "clonable_class noncopyable, no implicit definitions, C++14", :cpp14, :noncopyable, :defaulted do vim.command('silent! unlet g:cpp_noncopyable_class') vim.command("let g:cpp_std_flavour = 14") vim.command("let g:cpp_explicit_default = 1") expect(vim.command('MuTemplate cpp/clonable-class')).to match(/^$|#include added/) assert_buffer_contents <<-EOF /** File Header line to trick auto-inclusion */ #include #include /** * «Test». * @invariant «» *

    Semantics
    * - Clonable (but not assignable) * @author «author-name», creation * @since Version «1.0» */ class «Test» : private boost::noncopyable { public: /** * Virtual destructor. * @throw Nothing */ virtual ~«Test»(); virtual std::unique_ptr<«Test»> clone() const { return std::make_unique(*this); } protected: «Test»() = default; «Test»(«Test» const&) = default; private: «Test»& operator=(«Test» const&) = delete; }; EOF end specify "clonable_class C++98 alone", :cpp98, :deleted do vim.command('let g:cpp_noncopyable_class=""') vim.command('let g:cpp_std_flavour = 03') expect(vim.command('MuTemplate cpp/clonable-class')).to match(/^$|#include added/) assert_buffer_contents <<-EOF /** File Header line to trick auto-inclusion */ #include /** * «Test». * @invariant «» *

    Semantics
    * - Clonable (but not assignable) * @author «author-name», creation * @since Version «1.0» */ class «Test» { public: /** * Virtual destructor. * @throw Nothing */ virtual ~«Test»(); virtual std::auto_ptr<«Test»> clone() const { return std::auto_ptr<«Test»>(new «Test»(*this)); } protected: /** * Default constructor. * «@throw » */ «Test»(); «Test»(«Test» const&) /* = default */; private: «Test»& operator=(«Test» const&) /* = delete */; }; EOF end specify "clonable_class C++11 alone, w/ implicit definition", :cpp11, :deleted do vim.command('let g:cpp_noncopyable_class = ""') vim.command('let g:cpp_std_flavour = 11') expect(vim.command('MuTemplate cpp/clonable-class')).to match(/^$|#include added/) assert_buffer_contents <<-EOF /** File Header line to trick auto-inclusion */ #include /** * «Test». * @invariant «» *

    Semantics
    * - Clonable (but not assignable) * @author «author-name», creation * @since Version «1.0» */ class «Test» { public: /** * Virtual destructor. * @throw Nothing */ virtual ~«Test»(); virtual std::unique_ptr<«Test»> clone() const { return std::unique_ptr<«Test»>(new «Test»(*this)); } protected: /** * Default constructor. * «@throw » */ «Test»(); «Test»(«Test» const&) = default; private: «Test»& operator=(«Test» const&) = delete; }; EOF end specify "clonable_class C++11 alone, no implicit definition", :cpp11, :deleted, :defaulted do vim.command('let g:cpp_noncopyable_class = ""') vim.command('let g:cpp_std_flavour = 11') vim.command("let g:cpp_explicit_default = 1") expect(vim.command('MuTemplate cpp/clonable-class')).to match(/^$|#include added/) assert_buffer_contents <<-EOF /** File Header line to trick auto-inclusion */ #include /** * «Test». * @invariant «» *

    Semantics
    * - Clonable (but not assignable) * @author «author-name», creation * @since Version «1.0» */ class «Test» { public: /** * Virtual destructor. * @throw Nothing */ virtual ~«Test»(); virtual std::unique_ptr<«Test»> clone() const { return std::unique_ptr<«Test»>(new «Test»(*this)); } protected: «Test»() = default; «Test»(«Test» const&) = default; private: «Test»& operator=(«Test» const&) = delete; }; EOF end # ===============[ base class + cloable child ]============= specify "clonable_class base noncopyable, with implicit definitions + child", :cpp98, :cpp11, :noncopyable, :clonable_child do vim.command('silent! unlet g:cpp_noncopyable_class') # expect(vim.command('MuTemplate cpp/clonable-class')).to match(/^$|#include added/) expect(vim.command('call lh#mut#expand_and_jump(0, "cpp/clonable-class", {"clsname": "base"})')).to match(/^$|#include added/) # vim.feedkeys('\G') # vim.type('$:put=""$:put=""G') vim.feedkeys('\\:silent! $call append("$", ["",""])\G') vim.write() # pp vim.echo('expand("%:p")') # pp system('pwd') expect(system("ctags --c++-kinds=+p --fields=+imaS --extras=+q --language-force=C++ -f tags #{filename}")).to be true vim.command("let b:tags_dirname = expand('%:p:h')") expect(vim.command('call lh#mut#expand_and_jump(0, "cpp/clonable-class", {"clsname": "child", "parents": [{"base": {}}]})')).to match(/^$|memory is already included/) # pp vim.echo('g:root_clones') assert_buffer_contents <<-EOF /** File Header line to trick auto-inclusion */ #include #include /** * base. * @invariant «» *

    Semantics
    * - Clonable (but not assignable) * @author «author-name», creation * @since Version «1.0» */ class base : private boost::noncopyable { public: /** * Virtual destructor. * @throw Nothing */ virtual ~base(); virtual std::auto_ptr clone() const { return std::auto_ptr(new base(*this)); } protected: /** * Default constructor. * «@throw » */ base(); base(base const&) /* = default */; }; /** * child. * @invariant «» *

    Semantics
    * - Clonable (but not assignable) * @author «author-name», creation * @since Version «1.0» */ class child : public base { public: /** * Virtual destructor. * @throw Nothing */ virtual ~child(); /** * Init constructor. * @param «ctr-parameters» «» * «@throw » */ child(«ctr-parameters»); virtual std::auto_ptr clone() const /* override */ { return std::auto_ptr(new child(*this)); } protected: child(child const&) /* = default */; }; EOF end end # vim:set sw=2: ================================================ FILE: spec/constructor-command_spec.rb ================================================ # encoding: UTF-8 require 'spec_helper' require 'pp' # ======[ :Constructor {{{1 # Tests with parameters are done in *-class_spec.rb tests # Test expanding with MuT_ckword don't seem to work correctly # TODO: C++11 RSpec.describe ":Constructor command", :cpp, :ctr_cmd do let (:filename) { "test.cpp" } # ====[ Executed once before all test {{{2 before :all do if !defined? vim.runtime vim.define_singleton_method(:runtime) do |path| self.command("runtime #{path}") end end vim.runtime('spec/support/input-mock.vim') expect(vim.command('verbose function lh#ui#input')).to match(/input-mock.vim/) vim.set('report=9999') expect(vim.echo('lh#mut#dirs#get_templates_for("cpp/value-class")')).to match(/value-class.template/) expect(vim.echo('lh#style#clear()')).to eq '0' vim.command('UseStyle breakbeforebraces=stroustrup -ft=c') vim.command('UseStyle spacesbeforeparens=control-statements -ft=c') vim.command('UseStyle empty_braces=empty -ft=c') end # ====[ Always executed before each test {{{2 before :each do vim.command('filetype plugin on') vim.command("file #{filename}") vim.set('ft=cpp') vim.set('expandtab') vim.set('sw=4') vim.command('silent! unlet g:cpp_explicit_default') vim.command('silent! unlet g:cpp_std_flavour') vim.command('silent! unlet g:mocked_input') vim.command('silent! unlet g:mocked_confirm') vim.command('silent! unlet g:cpp_use_copy_and_swap') clear_buffer set_buffer_contents <<-EOF class Foo { public: private: std::string m_bar; int * m_foo; }; EOF vim.write() vim.feedkeys('a\') # pause # expect(system("ctags --c++-kinds=+p --fields=+imaS --extras=+q --language-force=C++ -f tags #{filename}")).to be true # system('less tags') vim.command("let b:tags_dirname = expand('%:p:h')") vim.command("let &l:tags.=','.b:tags_dirname.'/tags'") # system('echo "'+vim.echo('lh#dev#class#attributes("Foo")')+'"') assert_buffer_contents <<-EOF class Foo { public: private: std::string m_bar; int * m_foo; }; EOF expect(vim.echo('line("$")')).to eq '7' expect(vim.echo('setpos(".", [1,3,1,0])')).to eq '0' expect(vim.echo('line(".")')).to eq '3' end # ====[ default constructor {{{2 context "when expanding default-constructor", :default_ctr do it "has a pointer attribute" do # {{{3 # TODO: In C++11, no need for m_bar() if there is a default # initialisation at class scope # expect(vim.echo('lh#dev#class#attributes("Foo")')).to eq('m_bar') # expect(vim.echo('lh#cpp#constructors#debug("s:Attributes(\"Foo\")")')).to eq('m_bar') # vim.command('Constructor default') vim.echo('lh#cpp#constructors#Main("default")') # expect(vim.echo('g:step."--".string(g:implproto)')).to eq('42') # expect(vim.echo('g:step')).to eq('42') vim.feedkeys('a\') # pause assert_buffer_contents <<-EOF class Foo { public: /** * Default constructor. * «@throw » */ Foo(); private: std::string m_bar; int * m_foo; }; Foo::Foo() : m_bar() , m_foo() {} EOF end end # }}}3 # ====[ copy-constructor {{{2 context "when expanding copy-constructor", :copy_ctr do it "has a pointer attribute" do # {{{3 # vim.command('Constructor copy') vim.echo('lh#cpp#constructors#Main("copy")') vim.feedkeys('a\') # pause assert_buffer_contents <<-EOF class Foo { public: /** * Copy constructor. * @param[in] rhs source data to be copied. * «@throw » */ Foo(Foo const& rhs); private: std::string m_bar; int * m_foo; }; Foo::Foo(Foo const& rhs) : m_bar(rhs.m_bar) , m_foo(«duplicate(rhs.m_foo)») {} EOF end end # }}}3 # ====[ assignment-operator {{{2 context "when expanding assignment-operator", :assign_copy do it "has a pointer attribute" do # {{{3 vim.command('let g:mocked_confirm = 0') # expect(vim.echo('lh#dev#class#attributes("Foo")')).to eq('m_bar') # expect(vim.echo('lh#cpp#constructors#debug("s:Attributes(\"Foo\")")')).to eq('m_bar') vim.echo('lh#cpp#constructors#Main("assign")') # expect(vim.echo('lh#cpp#constructors#Main("assign")')).to eq '0' # vim.command('Constructor assign') # expect(vim.echo('string(g:implproto)')).to eq('42') # expect(vim.echo('g:step')).to eq('42') vim.feedkeys('a\') # pause assert_buffer_contents <<-EOF class Foo { public: /** * Assignment operator. * @param[in] rhs source data to be copied. * «@throw » */ Foo& operator=(Foo const& rhs); private: std::string m_bar; int * m_foo; }; Foo& Foo::operator=(Foo const& rhs) { m_bar = rhs.m_bar; m_foo = «duplicate(rhs.m_foo)»; } EOF end end # }}}3 # ====[ copy'n'swap {{{2 context "when expanding copy-and-swap", :copy_n_swap do it "has a pointer attribute" do # {{{3 vim.command('let g:mocked_confirm = 1') # vim.command('Constructor assign') vim.echo('lh#cpp#constructors#Main("assign")') vim.feedkeys('a\') # pause assert_buffer_contents <<-EOF class Foo { public: /** * Assignment operator. * @param[in] rhs source data to be copied. * «@throw » * * @note based on copy-and-swap idiom, with copy-elision exploited * @note exception-safe */ Foo& operator=(Foo rhs) { this->swap(rhs); return *this; } /** * Swap operation. * @param[in,out] other data with which content is swapped * @throw None */ void swap(Foo & other) throw(); private: std::string m_bar; int * m_foo; }; void Foo::swap(Foo & other) throw() { using std::swap; swap(m_bar, other.m_bar); swap(m_foo, other.m_foo); } EOF end end # }}}3 # ====[ init constructor {{{2 # No test for init-constructor as it requires a user-interaction and # vimrunner+vim client-server architecture doesn't work very-well together # }}}2 end # }}}1 # vim:set sw=2:fdm=marker: ================================================ FILE: spec/deps_spec.rb ================================================ # encoding: UTF-8 require 'spec_helper' require 'pp' RSpec.describe "C++ check dependencies are loaded", :cpp, :deps do let (:filename) { "test.cpp" } before :each do # expect(vim.echo('&enc')).to eq 'utf-8' # vim.command('let b:marker_open = "\u00AB"') # vim.command('let b:marker_close = "\u00BB"') # expect(vim.echo('b:marker_open')).to eq '«' # expect(vim.echo('lh#marker#open()')).to eq '«' vim.command('filetype plugin on') vim.command("file #{filename}") vim.set('ft=cpp') vim.set('expandtab') vim.set('sw=4') vim.command('silent! unlet g:cpp_explicit_default') vim.command('silent! unlet g:cpp_std_flavour') clear_buffer end it "has loaded C++ ftplugin" do # pp vim.echo('&rtp') # pp vim.command(':scriptnames') expect(/plugin.mu-template\.vim/).to be_sourced # expect(/ftplugin.cpp.cpp_snippets\.vim/).to be_sourced vim.command('call lh#mut#dirs#update()') expect(vim.echo('g:lh#mut#dirs#cache')).to match(/cpp/) # pp vim.echo('g:lh#mut#dirs#cache') expect(vim.echo('lh#naming#type("toto")')).to eq "Toto" end end ================================================ FILE: spec/empty-exception-class_spec.rb ================================================ # encoding: UTF-8 require 'spec_helper' require 'pp' RSpec.describe "C++ empty-exception class wizard", :empty_exception, :cpp, :class do let (:filename) { "test.cpp" } # ====[ Executed once before all test {{{2 before :all do if !defined? vim.runtime vim.define_singleton_method(:runtime) do |path| self.command("runtime #{path}") end end vim.runtime('spec/support/input-mock.vim') expect(vim.command('verbose function lh#ui#input')).to match(/input-mock.vim/) expect(vim.echo('lh#mut#dirs#get_templates_for("cpp/empty-exception-class")')).to match(/empty-exception-class.template/) end # ====[ Always executed before each test {{{2 before :each do vim.command('filetype plugin on') vim.command("file #{filename}") vim.set('ft=cpp') vim.set('expandtab') vim.set('sw=4') vim.command('silent! unlet g:cpp_explicit_default') vim.command('silent! unlet g:cpp_std_flavour') clear_buffer set_buffer_contents <<-EOF /** File Header line to trick auto-inclusion */ EOF vim.command(%Q{call append(1, ['', ''])}) expect(vim.echo('line("$")')).to eq '3' expect(vim.echo('setpos(".", [1,3,1,0])')).to eq '0' expect(vim.echo('line(".")')).to eq '3' end specify "empty_exception_class noncopyable, with implicit definitions, C++98", :cpp98 do expect(vim.command('MuTemplate cpp/empty-exception-class')).to match(/^$|#include added/) assert_buffer_contents <<-EOF /** File Header line to trick auto-inclusion */ #include /** * «Test». * @invariant «» *

    Semantics
    * - Exception class * - Copyable * @author «author-name», creation * @since Version «1.0» */ class «Test» : public std::runtime_error { public: /** * Init constructor. * @param «ctr-parameters» «» * «@throw » */ «Test»(«ctr-parameters»); }; EOF end specify "empty_exception_class noncopyable, with implicit definitions, C++11", :cpp11 do vim.command('let g:cpp_std_flavour = 11') expect(vim.command('MuTemplate cpp/empty-exception-class')).to match(/^$|#include added/) assert_buffer_contents <<-EOF /** File Header line to trick auto-inclusion */ #include /** * «Test». * @invariant «» *

    Semantics
    * - Exception class * - Copyable * @author «author-name», creation * @since Version «1.0» */ class «Test» : public std::runtime_error { public: using std::runtime_error::runtime_error; }; EOF end specify "empty_exception_class noncopyable, no implicit definitions, C++11", :cpp11, :defaulted do vim.command('let g:cpp_std_flavour = 11') vim.command("let g:cpp_explicit_default = 1") expect(vim.command('MuTemplate cpp/empty-exception-class')).to match(/^$|#include added/) assert_buffer_contents <<-EOF /** File Header line to trick auto-inclusion */ #include /** * «Test». * @invariant «» *

    Semantics
    * - Exception class * - Copyable * @author «author-name», creation * @since Version «1.0» */ class «Test» : public std::runtime_error { public: «Test»(«Test» const&) = default; «Test»& operator=(«Test» const&) = default; /** * Virtual destructor. * @throw Nothing */ virtual ~«Test»() = default; using std::runtime_error::runtime_error; }; EOF end end # vim:set sw=2: ================================================ FILE: spec/exception-class_spec.rb ================================================ # encoding: UTF-8 require 'spec_helper' require 'pp' RSpec.describe "C++ exception class wizard", :exception, :cpp, :class do let (:filename) { "test.cpp" } # ====[ Executed once before all test {{{2 before :all do if !defined? vim.runtime vim.define_singleton_method(:runtime) do |path| self.command("runtime #{path}") end end vim.runtime('spec/support/input-mock.vim') expect(vim.command('verbose function lh#ui#input')).to match(/input-mock.vim/) expect(vim.echo('lh#mut#dirs#get_templates_for("cpp/exception-class")')).to match(/exception-class.template/) end # ====[ Always executed before each test {{{2 before :each do vim.command('filetype plugin on') vim.command("file #{filename}") vim.set('ft=cpp') vim.set('expandtab') vim.set('sw=4') vim.command('silent! unlet g:cpp_explicit_default') vim.command('silent! unlet g:cpp_std_flavour') vim.command('silent! unlet g:cpp_root_exception') clear_buffer set_buffer_contents <<-EOF /** File Header line to trick auto-inclusion */ EOF vim.command(%Q{call append(1, ['', ''])}) expect(vim.echo('line("$")')).to eq '3' expect(vim.echo('setpos(".", [1,3,1,0])')).to eq '0' expect(vim.echo('line(".")')).to eq '3' end specify "exception_class, with implicit definitions, C++98", :cpp98 do expect(vim.command('MuTemplate cpp/exception-class')).to match(/^$|#include added/) assert_buffer_contents <<-EOF /** File Header line to trick auto-inclusion */ #include /** * «Test». * @invariant «» *

    Semantics
    * - Exception class * - Copyable * @author «author-name», creation * @since Version «1.0» */ class «Test» : public std::runtime_error { public: /** * Init constructor. * @param «ctr-parameters» «» * «@throw » */ «Test»(«ctr-parameters»); virtual char const* what() const throw() /* override */; }; EOF end specify "exception_class, with implicit definitions, C++11", :cpp11 do vim.command('let g:cpp_std_flavour = 11') expect(vim.command('MuTemplate cpp/exception-class')).to match(/^$|#include added/) assert_buffer_contents <<-EOF /** File Header line to trick auto-inclusion */ #include /** * «Test». * @invariant «» *

    Semantics
    * - Exception class * - Copyable * @author «author-name», creation * @since Version «1.0» */ class «Test» : public std::runtime_error { public: using std::runtime_error::runtime_error; virtual char const* what() const noexcept override; }; EOF end specify "exception_class, no implicit definitions, C++11", :cpp11, :defaulted do vim.command('let g:cpp_std_flavour = 11') vim.command("let g:cpp_explicit_default = 1") expect(vim.command('MuTemplate cpp/exception-class')).to match(/^$|#include added/) assert_buffer_contents <<-EOF /** File Header line to trick auto-inclusion */ #include /** * «Test». * @invariant «» *

    Semantics
    * - Exception class * - Copyable * @author «author-name», creation * @since Version «1.0» */ class «Test» : public std::runtime_error { public: «Test»(«Test» const&) = default; «Test»& operator=(«Test» const&) = default; /** * Virtual destructor. * @throw Nothing */ virtual ~«Test»() = default; using std::runtime_error::runtime_error; virtual char const* what() const noexcept override; }; EOF end # ---------------------------------------------------------------------- specify "domain (param) exception_class, with implicit definitions, C++98", :cpp98 do expect(vim.command('call lh#mut#expand_and_jump(0, "cpp/exception-class", {"root-exception": {"std::logic_error": {"includes": ""}}})')).to match(/^$|#include added/) assert_buffer_contents <<-EOF /** File Header line to trick auto-inclusion */ #include /** * «Test». * @invariant «» *

    Semantics
    * - Exception class * - Copyable * @author «author-name», creation * @since Version «1.0» */ class «Test» : public std::logic_error { public: /** * Init constructor. * @param «ctr-parameters» «» * «@throw » */ «Test»(«ctr-parameters»); virtual char const* what() const throw() /* override */; }; EOF end specify "domain (option) exception_class, with implicit definitions, C++98", :cpp98 do vim.command('let g:cpp_root_exception = {"std::logic_error": {"includes": ""}}') expect(vim.command('MuTemplate cpp/exception-class')).to match(/^$|#include added/) assert_buffer_contents <<-EOF /** File Header line to trick auto-inclusion */ #include /** * «Test». * @invariant «» *

    Semantics
    * - Exception class * - Copyable * @author «author-name», creation * @since Version «1.0» */ class «Test» : public std::logic_error { public: /** * Init constructor. * @param «ctr-parameters» «» * «@throw » */ «Test»(«ctr-parameters»); virtual char const* what() const throw() /* override */; }; EOF end end # vim:set sw=2: ================================================ FILE: spec/spe_func_spec.rb ================================================ # encoding: UTF-8 require 'spec_helper' require 'pp' # ======[ Special functions {{{1 # Tests with parameters are done in *-class_spec.rb tests # Test expanding with MuT_ckword don't seem to work correctly # TODO: C++11 RSpec.describe "Special functions", :cpp, :spe_func do let (:filename) { "test.cpp" } before :all do if !defined? vim.runtime vim.define_singleton_method(:runtime) do |path| self.command("runtime #{path}") end end vim.runtime('spec/support/input-mock.vim') expect(vim.command('verbose function lh#ui#input')).to match(/input-mock.vim/) expect(vim.echo('lh#style#clear()')).to eq '0' vim.command('UseStyle breakbeforebraces=stroustrup -ft=c') vim.command('UseStyle spacesbeforeparens=control-statements -ft=c') vim.command('UseStyle empty_braces=nl -ft=c') end # ====[ Always executed before each test {{{2 before :each do vim.command('filetype plugin on') vim.command("file #{filename}") vim.set('ft=cpp') vim.set('expandtab') vim.set('sw=4') vim.command('silent! unlet g:cpp_explicit_default') vim.command('silent! unlet g:cpp_std_flavour') vim.command('silent! unlet g:mocked_input') vim.command('silent! unlet g:mocked_confirm') vim.command('silent! unlet g:cpp_use_copy_and_swap') clear_buffer end # ====[ default constructor {{{2 context "when expanding default-constructor", :default_ctr do it "asks the user, when the only context is the filename" do expect(vim.command('MuTemplate cpp/default-constructor')).to match(/^$/) assert_buffer_contents <<-EOF /** * Default constructor. * «@throw » */ «Test»(); EOF end it "takes the class name as a parameter" do expect(vim.command('MuTemplate cpp/default-constructor FooBar')).to match(/^$/) assert_buffer_contents <<-EOF /** * Default constructor. * «@throw » */ FooBar(); EOF end it "recognizes it's within a class definition" do set_buffer_contents <<-EOF class Foo { }; EOF assert_buffer_contents <<-EOF class Foo { }; EOF expect(vim.echo('line("$")')).to eq '3' expect(vim.echo('setpos(".", [1,2,1,0])')).to eq '0' expect(vim.echo('line(".")')).to eq '2' expect(vim.command('MuTemplate cpp/default-constructor')).to match(/^$/) assert_buffer_contents <<-EOF class Foo { /** * Default constructor. * «@throw » */ Foo(); }; EOF end end # ====[ copy-constructor {{{2 context "when expanding copy-constructor", :copy_ctr do it "asks the user, when the only context is the filename" do expect(vim.command('MuTemplate cpp/copy-constructor')).to match(/^$/) assert_buffer_contents <<-EOF /** * Copy constructor. * @param[in] rhs source data to be copied. * «@throw » */ «Test»(«Test» const& rhs); EOF end it "takes the class name as a parameter" do expect(vim.command('MuTemplate cpp/copy-constructor FooBar')).to match(/^$/) assert_buffer_contents <<-EOF /** * Copy constructor. * @param[in] rhs source data to be copied. * «@throw » */ FooBar(FooBar const& rhs); EOF end it "recognizes it's within a class definition" do set_buffer_contents <<-EOF class Foo { }; EOF assert_buffer_contents <<-EOF class Foo { }; EOF expect(vim.echo('line("$")')).to eq '3' expect(vim.echo('setpos(".", [1,2,1,0])')).to eq '0' expect(vim.echo('line(".")')).to eq '2' expect(vim.command('MuTemplate cpp/copy-constructor')).to match(/^$/) assert_buffer_contents <<-EOF class Foo { /** * Copy constructor. * @param[in] rhs source data to be copied. * «@throw » */ Foo(Foo const& rhs); }; EOF end end # ====[ assignment-operator {{{2 context "when expanding assignment-operator", :assign_copy do it "asks the user, when the only context is the filename (copy'n'swap choice made by user)" do vim.command('let g:mocked_confirm = 0') expect(vim.command('MuTemplate cpp/assignment-operator')).to match(/^$/) assert_buffer_contents <<-EOF /** * Assignment operator. * @param[in] rhs source data to be copied. * «@throw » */ «Test»& operator=(«Test» const& rhs); EOF end it "asks the user, when the only context is the filename" do vim.command('let g:cpp_use_copy_and_swap = 0') expect(vim.command('MuTemplate cpp/assignment-operator')).to match(/^$/) assert_buffer_contents <<-EOF /** * Assignment operator. * @param[in] rhs source data to be copied. * «@throw » */ «Test»& operator=(«Test» const& rhs); EOF end it "takes the class name as a parameter (copy'n'swap choice made by user)" do vim.command('let g:mocked_confirm = 0') expect(vim.command('MuTemplate cpp/assignment-operator FooBar')).to match(/^$/) assert_buffer_contents <<-EOF /** * Assignment operator. * @param[in] rhs source data to be copied. * «@throw » */ FooBar& operator=(FooBar const& rhs); EOF end it "recognizes it's within a class definition (copy'n'swap choice made by user)" do vim.command('let g:mocked_confirm = 0') set_buffer_contents <<-EOF class Foo { }; EOF assert_buffer_contents <<-EOF class Foo { }; EOF expect(vim.echo('line("$")')).to eq '3' expect(vim.echo('setpos(".", [1,2,1,0])')).to eq '0' expect(vim.echo('line(".")')).to eq '2' expect(vim.command('MuTemplate cpp/assignment-operator')).to match(/^$/) assert_buffer_contents <<-EOF class Foo { /** * Assignment operator. * @param[in] rhs source data to be copied. * «@throw » */ Foo& operator=(Foo const& rhs); }; EOF end end # ====[ copy'n'swap {{{2 context "when expanding copy-and-swap", :copy_n_swap do it "asks the user, when the only context is the filename (copy'n'swap choice made by user)" do vim.command('let g:mocked_confirm = 1') expect(vim.command('MuTemplate cpp/assignment-operator')).to match(/^$/) assert_buffer_contents <<-EOF /** * Assignment operator. * @param[in] rhs source data to be copied. * «@throw » * * @note based on copy-and-swap idiom, with copy-elision exploited * @note exception-safe */ «Test»& operator=(«Test» rhs) { this->swap(rhs); return *this; } /** * Swap operation. * @param[in,out] other data with which content is swapped * @throw None */ void swap(«Test» & other) throw(); EOF end it "asks the user, when the only context is the filename" do vim.command('let g:cpp_use_copy_and_swap = 1') expect(vim.command('MuTemplate cpp/assignment-operator')).to match(/^$/) assert_buffer_contents <<-EOF /** * Assignment operator. * @param[in] rhs source data to be copied. * «@throw » * * @note based on copy-and-swap idiom, with copy-elision exploited * @note exception-safe */ «Test»& operator=(«Test» rhs) { this->swap(rhs); return *this; } /** * Swap operation. * @param[in,out] other data with which content is swapped * @throw None */ void swap(«Test» & other) throw(); EOF end it "takes the class name as a parameter (copy'n'swap choice made by user)" do vim.command('let g:mocked_confirm = 1') expect(vim.command('MuTemplate cpp/assignment-operator FooBar')).to match(/^$/) assert_buffer_contents <<-EOF /** * Assignment operator. * @param[in] rhs source data to be copied. * «@throw » * * @note based on copy-and-swap idiom, with copy-elision exploited * @note exception-safe */ FooBar& operator=(FooBar rhs) { this->swap(rhs); return *this; } /** * Swap operation. * @param[in,out] other data with which content is swapped * @throw None */ void swap(FooBar & other) throw(); EOF end it "recognizes it's within a class definition (copy'n'swap choice made by user)" do vim.command('let g:mocked_confirm = 1') set_buffer_contents <<-EOF class Foo { }; EOF assert_buffer_contents <<-EOF class Foo { }; EOF expect(vim.echo('line("$")')).to eq '3' expect(vim.echo('setpos(".", [1,2,1,0])')).to eq '0' expect(vim.echo('line(".")')).to eq '2' expect(vim.command('MuTemplate cpp/assignment-operator')).to match(/^$/) assert_buffer_contents <<-EOF class Foo { /** * Assignment operator. * @param[in] rhs source data to be copied. * «@throw » * * @note based on copy-and-swap idiom, with copy-elision exploited * @note exception-safe */ Foo& operator=(Foo rhs) { this->swap(rhs); return *this; } /** * Swap operation. * @param[in,out] other data with which content is swapped * @throw None */ void swap(Foo & other) throw(); }; EOF end end # ====[ destructor {{{2 context "when expanding destructor", :destructor do it "asks the user, when the only context is the filename" do expect(vim.command('MuTemplate cpp/destructor')).to match(/^$/) assert_buffer_contents <<-EOF /** * «virtual »destructor. * @throw Nothing */ «virtual »~«Test»(); EOF end it "takes the class name as a parameter" do expect(vim.command('MuTemplate cpp/destructor FooBar')).to match(/^$/) assert_buffer_contents <<-EOF /** * «virtual »destructor. * @throw Nothing */ «virtual »~FooBar(); EOF end it "recognizes it's within a class definition" do set_buffer_contents <<-EOF class Foo { }; EOF assert_buffer_contents <<-EOF class Foo { }; EOF expect(vim.echo('line("$")')).to eq '3' expect(vim.echo('setpos(".", [1,2,1,0])')).to eq '0' expect(vim.echo('line(".")')).to eq '2' expect(vim.command('MuTemplate cpp/destructor')).to match(/^$/) assert_buffer_contents <<-EOF class Foo { /** * «virtual »destructor. * @throw Nothing */ «virtual »~Foo(); }; EOF end end # ====[ init constructor {{{2 context "when expanding init-constructor", :init_ctr do it "asks the user, when the only context is the filename" do expect(vim.command('MuTemplate cpp/init-constructor')).to match(/^$/) assert_buffer_contents <<-EOF /** * Init constructor. * @param «ctr-parameters» «» * «@throw » */ «Test»(«ctr-parameters»); EOF end it "takes the class name as a parameter" do expect(vim.command('MuTemplate cpp/init-constructor FooBar')).to match(/^$/) assert_buffer_contents <<-EOF /** * Init constructor. * @param «ctr-parameters» «» * «@throw » */ FooBar(«ctr-parameters»); EOF end it "recognizes it's within a class definition" do set_buffer_contents <<-EOF class Foo { }; EOF assert_buffer_contents <<-EOF class Foo { }; EOF expect(vim.echo('line("$")')).to eq '3' expect(vim.echo('setpos(".", [1,2,1,0])')).to eq '0' expect(vim.echo('line(".")')).to eq '2' expect(vim.command('MuTemplate cpp/init-constructor')).to match(/^$/) assert_buffer_contents <<-EOF class Foo { /** * Init constructor. * @param «ctr-parameters» «» * «@throw » */ Foo(«ctr-parameters»); }; EOF end end # }}}2 end # }}}1 # vim:set sw=2:fdm=marker: ================================================ FILE: spec/spec_helper.rb ================================================ require 'tmpdir' require 'vimrunner' require 'vimrunner/rspec' require 'support/vim' require 'rspec/expectations' require 'support/vim_matchers' # require 'simplecov' # SimpleCov.start module Vimrunner class Client def runtime(script) script_path = Path.new(script) command("runtime #{script_path}") end end end Vimrunner::RSpec.configure do |config| config.reuse_server = true vim_plugin_path = File.expand_path('.') vim_flavor_path = ENV['HOME']+'/.vim/flavors' config.start_vim do vim = Vimrunner.start_gvim # vim = Vimrunner.start vim.add_plugin(vim_flavor_path, 'bootstrap.vim') vim.prepend_runtimepath(vim_plugin_path+'/after') vim.prepend_runtimepath(vim_plugin_path) # lh-UT vim_UT_path = File.expand_path('../../../vim-UT', __FILE__) vim.prepend_runtimepath(vim_UT_path) vim.runtime('plugin/UT.vim') # pp vim_flavor_path # lh-vim-lib vim_lib_path = File.expand_path('../../../lh-vim-lib', __FILE__) vim.prepend_runtimepath(vim_lib_path) vim.runtime('plugin/let.vim') # LetIfUndef # vim.runtime('plugin/ui-functions.vim') # lh#ui#confirm # vim.command(':messages') # lh-tags vim_tags_path = File.expand_path('../../../lh-tags', __FILE__) vim.prepend_runtimepath(vim_tags_path) vim.runtime('plugin/lh-tags.vim') # AddStyle # lh-style vim_style_path = File.expand_path('../../../lh-style', __FILE__) vim.prepend_runtimepath(vim_style_path) vim.runtime('plugin/lh-style.vim') # AddStyle # lh-dev vim_dev_path = File.expand_path('../../../lh-dev', __FILE__) vim.prepend_runtimepath(vim_dev_path) # lh-brackets vim_brackets_path = File.expand_path('../../../lh-brackets', __FILE__) vim.prepend_runtimepath(vim_brackets_path) vim.runtime('plugin/misc_map.vim') # Inoreab vim.runtime('plugin/common_brackets.vim') # Brackets vim.runtime('plugin/bracketing.base.vim') # !mark! vim.command('set enc=utf-8') #vim.command('SetMarker <+ +>') # mu-template mu_template_path = File.expand_path('../../../mu-template@lh', __FILE__) vim.prepend_runtimepath(mu_template_path+'/after') vim.prepend_runtimepath(mu_template_path) vim.runtime('plugin/mu-template.vim') # !mark! # pp vim.echo('&rtp') vim.command('set shm=') has_redo = vim.echo('has("patch-7.4.849")') if has_redo != "1" puts "WARNING: this flavor of vim won't permit to support redo" end vim end end RSpec.configure do |config| config.include Support::Vim def write_file(filename, contents) dirname = File.dirname(filename) FileUtils.mkdir_p dirname if not File.directory?(dirname) File.open(filename, 'w') { |f| f.write(contents) } end end # vim:set sw=2: ================================================ FILE: spec/value-class-with-attributes_spec.rb ================================================ # encoding: UTF-8 require 'spec_helper' require 'pp' # ======[ Value class w/ attributes {{{1 RSpec.describe "C++ Value class w/ attributes wizard", :cpp, :class, :value, :with_attributes, :value_attributes do let (:filename) { "test.cpp" } # ====[ Executed once before all test {{{2 before :all do if !defined? vim.runtime vim.define_singleton_method(:runtime) do |path| self.command("runtime #{path}") end end vim.runtime('spec/support/input-mock.vim') expect(vim.command('verbose function lh#ui#input')).to match(/input-mock.vim/) expect(vim.echo('lh#style#clear()')).to eq '0' vim.command('UseStyle breakbeforebraces=stroustrup -ft=c') vim.command('UseStyle spacesbeforeparens=control-statements -ft=c') vim.command('UseStyle empty_braces=nl -ft=c') end # ====[ Always executed before each test {{{2 before :each do vim.command('filetype plugin on') vim.command("file #{filename}") vim.set('ft=cpp') vim.set('expandtab') vim.set('sw=4') vim.command('silent! unlet g:cpp_explicit_default') vim.command('silent! unlet g:cpp_std_flavour') vim.command('silent! unlet g:mocked_input') vim.command('silent! unlet g:mocked_confirm') vim.command('silent! unlet g:cpp_use_copy_and_swap') clear_buffer set_buffer_contents <<-EOF /** File Header line to trick auto-inclusion */ EOF vim.command(%Q{call append(1, ['', ''])}) expect(vim.echo('line("$")')).to eq '3' expect(vim.echo('setpos(".", [1,3,1,0])')).to eq '0' expect(vim.echo('line(".")')).to eq '3' end # ====[ implictly copyable, explicit definitions, C++98 {{{2 specify "value-attribute-class copyable", :cpp98, :cpp11, :copyable do expect(vim.echo('lh#mut#dirs#get_templates_for("cpp/value-class")')).to match(/value-class.template/) expect(vim.command('call lh#mut#expand_and_jump(0, "cpp/value-class", {"attributes": [{"name": "foo", "type": "int"}, {"name": "bar", "type": "string", "functions": ["set", "get"]}]})')).to match(/^$|#include added/) vim.feedkeys('\\:silent! $call append("$", ["",""])\G') assert_buffer_contents <<-EOF /** File Header line to trick auto-inclusion */ #include /** * «Test». * @invariant «» *

    Semantics
    * - Value object * - «Regular object» * - «Comparable» * @author «author-name», creation * @since Version «1.0» */ class «Test» { public: /** * Init constructor. * @param[in] foo «foo-explanations» * @param[in] bar «bar-explanations» * «@throw » */ «Test»(int foo, std::string const& bar) : m_foo(foo) , m_bar(bar) { } void setBar(std::string const& bar) { m_bar = bar; } std::string const& getBar() const { return m_bar; } private: int m_foo; std::string m_bar; }; EOF end # ====[ implictly copyable, NO explicit definitions, C++11 {{{2 specify "value-attribute-class copyable, no explicit definition, C++11", :cpp11, :copyable, :defaulted do expect(vim.echo('lh#mut#dirs#get_templates_for("cpp/value-class")')).to match(/value-class.template/) vim.command('let g:cpp_std_flavour=11') vim.command("let g:cpp_explicit_default = 1") expect(vim.command('call lh#mut#expand_and_jump(0, "cpp/value-class", {"attributes": [{"name": "foo", "type": "int"}, {"name": "bar", "type": "string", "functions": ["set", "get"]}]})')).to match(/^$|#include added/) vim.feedkeys('\\:silent! $call append("$", ["",""])\G') assert_buffer_contents <<-EOF /** File Header line to trick auto-inclusion */ #include /** * «Test». * @invariant «» *

    Semantics
    * - Value object * - «Regular object» * - «Comparable» * @author «author-name», creation * @since Version «1.0» */ class «Test» { public: «Test»(«Test» const&) = default; «Test»& operator=(«Test» const&) = default; /** * Destructor. * @throw Nothing * @warning this class is not meant to be publicly inherited */ ~«Test»() = default; /** * Init constructor. * @param[in] foo «foo-explanations» * @param[in] bar «bar-explanations» * «@throw » */ «Test»(int foo, std::string const& bar) : m_foo(foo) , m_bar(bar) { } void setBar(std::string const& bar) { m_bar = bar; } std::string const& getBar() const { return m_bar; } private: int m_foo; std::string m_bar; }; EOF end # ====[ explicit copy, implicit definitions, no-swap, C++98 {{{2 #====================================================================== # The same with pointer attributes that imply ... copy operations to be # explicited specify "value-attribute-class copyable, with ptr attributes", :cpp98, :cpp11, :copyable do expect(vim.echo('lh#mut#dirs#get_templates_for("cpp/value-class")')).to match(/value-class.template/) expect(vim.command('call lh#mut#expand_and_jump(0, "cpp/value-class", {"use_copy_and_swap": 0, "attributes": [{"name": "foo", "type": "int"}, {"name": "bar", "type": "std::auto_ptr", "includes":["", ""], "functions": ["ref_set", "set", "get"]}]})')).to match(/^$|#include added/) vim.feedkeys('\\:silent! $call append("$", ["",""])\G') # T* will require a destructor in current class # auto_ptr<> will require a destructor in current class, even empty # unique_ptr<>, doesn't require anything # Let's suppose other types to follow RAII # # Regarding getters: # - pointers are best avoided, IMO => references, # - or may be non_null<>. # - Only shared_ptr<> would deserved to be returned. I don't know... # Regarding setters: # 1- one that takes a pointer that'll change the current one # 2- one that takes a value to assign in the pointer (if we're in a value # class, somehow this means that the value behind the pointer could be # duplicated) assert_buffer_contents <<-EOF /** File Header line to trick auto-inclusion */ #include #include /** * «Test». * @invariant «» *

    Semantics
    * - Value object * - «Regular object» * - «Comparable» * @author «author-name», creation * @since Version «1.0» */ class «Test» { public: /** * Copy constructor. * @param[in] rhs source data to be copied. * «@throw » */ «Test»(«Test» const& rhs) : m_foo(rhs.m_foo) , m_bar(«duplicate(rhs.m_bar)») { } /** * Assignment operator. * @param[in] rhs source data to be copied. * «@throw » */ «Test»& operator=(«Test» const& rhs) { m_foo = rhs.m_foo; m_bar = «duplicate(rhs.m_bar)»; } /** * Destructor. * @throw Nothing * @warning this class is not meant to be publicly inherited */ ~«Test»(); /** * Init constructor. * @param[in] foo «foo-explanations» * @param«[in]» bar «bar-explanations» * «@throw » * @pre `bar != NULL`«» */ «Test»(int foo, std::auto_ptr bar) : m_foo(foo) , m_bar(bar) { } void setBar(std::string const& bar) { *m_bar = bar; } void setBar(std::auto_ptr bar) { m_bar = bar; } std::string const& getBar() const { return *m_bar; } private: int m_foo; std::auto_ptr m_bar; }; EOF end # ====[ explicit copy, implicit definitions, copy-n-swap, C++98 {{{2 specify "value-attribute-class copyable, with ptr attributes", :cpp98, :cpp11, :copyable, :copy_n_swap do expect(vim.echo('lh#mut#dirs#get_templates_for("cpp/value-class")')).to match(/value-class.template/) expect(vim.command('call lh#mut#expand_and_jump(0, "cpp/value-class", {"use_copy_and_swap": 1, "attributes": [{"name": "foo", "type": "int"}, {"name": "bar", "type": "std::auto_ptr", "includes":["", ""], "functions": ["ref_set", "set", "get"]}]})')).to match(/^$|#include added/) vim.feedkeys('\\:silent! $call append("$", ["",""])\G') # T* will require a destructor in current class # auto_ptr<> will require a destructor in current class, even empty # unique_ptr<>, doesn't require anything # Let's suppose other types to follow RAII # # Regarding getters: # - pointers are best avoided, IMO => references, # - or may be non_null<>. # - Only shared_ptr<> would deserved to be returned. I don't know... # Regarding setters: # 1- one that takes a pointer that'll change the current one # 2- one that takes a value to assign in the pointer (if we're in a value # class, somehow this means that the value behind the pointer could be # duplicated) assert_buffer_contents <<-EOF /** File Header line to trick auto-inclusion */ #include #include /** * «Test». * @invariant «» *

    Semantics
    * - Value object * - «Regular object» * - «Comparable» * @author «author-name», creation * @since Version «1.0» */ class «Test» { public: /** * Copy constructor. * @param[in] rhs source data to be copied. * «@throw » */ «Test»(«Test» const& rhs) : m_foo(rhs.m_foo) , m_bar(«duplicate(rhs.m_bar)») { } /** * Assignment operator. * @param[in] rhs source data to be copied. * «@throw » * * @note based on copy-and-swap idiom, with copy-elision exploited * @note exception-safe */ «Test»& operator=(«Test» rhs) { this->swap(rhs); return *this; } /** * Swap operation. * @param[in,out] other data with which content is swapped * @throw None */ void swap(«Test» & other) throw() { using std::swap; swap(m_foo, other.m_foo); swap(m_bar, other.m_bar); } /** * Destructor. * @throw Nothing * @warning this class is not meant to be publicly inherited */ ~«Test»(); /** * Init constructor. * @param[in] foo «foo-explanations» * @param«[in]» bar «bar-explanations» * «@throw » * @pre `bar != NULL`«» */ «Test»(int foo, std::auto_ptr bar) : m_foo(foo) , m_bar(bar) { } void setBar(std::string const& bar) { *m_bar = bar; } void setBar(std::auto_ptr bar) { m_bar = bar; } std::string const& getBar() const { return *m_bar; } private: int m_foo; std::auto_ptr m_bar; }; EOF end # }}}2 end # }}}1 # vim:set sw=2: ================================================ FILE: spec/value-class_spec.rb ================================================ # encoding: UTF-8 require 'spec_helper' require 'pp' RSpec.describe "C++ Value class wizard", :cpp, :class, :value do let (:filename) { "test.cpp" } # ====[ Executed once before all test {{{2 before :all do if !defined? vim.runtime vim.define_singleton_method(:runtime) do |path| self.command("runtime #{path}") end end vim.runtime('spec/support/input-mock.vim') expect(vim.command('verbose function lh#ui#input')).to match(/input-mock.vim/) expect(vim.echo('lh#mut#dirs#get_templates_for("cpp/value-class")')).to match(/value-class.template/) end # ====[ Always executed before each test {{{2 before :each do vim.command('filetype plugin on') vim.command("file #{filename}") vim.set('ft=cpp') vim.set('expandtab') vim.set('sw=4') vim.command('silent! unlet g:cpp_explicit_default') vim.command('silent! unlet g:cpp_std_flavour') clear_buffer set_buffer_contents <<-EOF /** File Header line to trick auto-inclusion */ EOF vim.command(%Q{call append(1, ['', ''])}) expect(vim.echo('line("$")')).to eq '3' expect(vim.echo('setpos(".", [1,3,1,0])')).to eq '0' expect(vim.echo('line(".")')).to eq '3' end specify "value-class copyable", :cpp98, :cpp11, :copyable do expect(vim.command('MuTemplate cpp/value-class')).to eq "" assert_buffer_contents <<-EOF /** File Header line to trick auto-inclusion */ /** * «Test». * @invariant «» *

    Semantics
    * - Value object * - «Regular object» * - «Comparable» * @author «author-name», creation * @since Version «1.0» */ class «Test» { public: }; EOF end specify "value-class copyable, no implicit definition", :cpp11, :copyable, :defaulted do vim.command("let g:cpp_std_flavour = 11") vim.command("let g:cpp_explicit_default = 1") expect(vim.command('MuTemplate cpp/value-class')).to eq "" assert_buffer_contents <<-EOF /** File Header line to trick auto-inclusion */ /** * «Test». * @invariant «» *

    Semantics
    * - Value object * - «Regular object» * - «Comparable» * @author «author-name», creation * @since Version «1.0» */ class «Test» { public: «Test»() = default; «Test»(«Test» const&) = default; «Test»& operator=(«Test» const&) = default; /** * Destructor. * @throw Nothing * @warning this class is not meant to be publicly inherited */ ~«Test»() = default; }; EOF end end # vim:set sw=2: ================================================ FILE: syntax/c-assign-in-condition.vim ================================================ "============================================================================= " File: syntax/c-assign-in-condition.vim {{{1 " Author: Luc Hermitte " " Version: 2.2.0 " Created: 08th Oct 2007 " Last Update: 16th Dec 2015 "------------------------------------------------------------------------ " Purpose: C syntax enhancements " (*) Hightlights assignements in if(), while(), ..., conditions " "------------------------------------------------------------------------ " Requirements: " None " " Option: " - |c_no_assign_in_condition| to disable the check that assignments are " done in conditions. " }}}1 " ======================================================================== " {{{1 Syntax definitions " " {{{2 Don't assign in conditions if !get(g:, "c_no_assign_in_condition", 0) syn match cAssignInConditionBad '\(\]*\)\@<==[^=][^,)]*' syn match cAssignInConditionRare '\(\]*\)\@<==[^=][^,)]*' hi def link cAssignInConditionBad SpellBad hi def link cAssignInConditionRare SpellRare endif " ======================================================================== " {{{1 Some mappings " }}}1 " ======================================================================== " vim: set foldmethod=marker: ================================================ FILE: syntax/c-fallthrough-case.vim ================================================ "============================================================================= " File: syntax/c-fallthrough-case.vim {{{1 " Author: Luc Hermitte " " Version: 2.2.0. let s:k_version = '217' " Created: 16th Dec 2015 " Last Update: 16th Dec 2015 "------------------------------------------------------------------------ " Description: C syntax enhancements " (*) Hightlights cases that fall through other cases " " Option: " - |c_no_hl_fallthrough_case| to disable the check " Disabled by default " }}}1 "============================================================================= let s:cpo_save=&cpo set cpo&vim "------------------------------------------------------------------------ if !get(g:, 'c_no_hl_fallthrough_case', 1) silent! syn clear cFallthroughCase " These are usually defined as keywords, but we don't want their " |:syn-priority| to be higher => we redefine them as |:syn-match| syn clear cLabel silent! syn clear cBadLabel syn match cBadLabel /\v/ containedin=cFallthroughCase syn match cBadLabel /\v/ containedin=cFallthroughCase syn match cLabel /\v/ syn match cLabel /\v/ " FIXME: "break;} case" is incorrectly recognized " FIXME: "default:" is not recognized syn match cFallthroughCase /\v(((||\_s+\w+|return.*)\_s*;(\_s*})*|\{|\[\[fallthrough]])\_s*)@\_s+\w+|)\s*:/ contains=cBadLabel hi def link cFallthroughCase spellBad hi def link cBadLabel badLabel hi badLabel term=reverse,bold ctermfg=3 ctermbg=9 gui=undercurl,bold guisp=Red guifg=Brown endif "------------------------------------------------------------------------ let &cpo=s:cpo_save "============================================================================= " vim600: set fdm=marker: ================================================ FILE: syntax/c.vim ================================================ " ======================================================================== " File: syntax/c.vim " Author: Luc Hermitte " " Version: 1.1.0 " Last Update: $Date$ " " Purpose: C syntax enhancements " Option: " ======================================================================== " This is the only valid way to load the C++ and C default syntax file. so $VIMRUNTIME/syntax/c.vim " Source syntax hooks for C runtime! syntax/c-*.vim syntax/c_*.vim ================================================ FILE: syntax/cpp-badcatch.vim ================================================ "============================================================================= " File: syntax/cpp-badcatch.vim {{{1 " Author: Luc Hermitte " " Version: 2.2.0 " Created: 29th Jun 2006 " Last Update: 16th Dec 2015 "------------------------------------------------------------------------ " Purpose: C++ syntax enhancements " (*) Hightlights catches made by-value instead of by-reference. " (*) Defines the two mappings [b (/resp. ]b) to jump to the previous " (/resp. next) catch made by value. " "------------------------------------------------------------------------ " Requirements: " word_tools.vim::GetCurrentKeyword() -- unchecked " " Option: " - |cpp_no_bad_by_reference| to disable the check that catches are done " by reference. " TODO: " - "typename" should be supported like "const" " - bug fix: do not highlight "catch ([[:space:]] const foo)" " }}}1 " ======================================================================== " {{{1 Syntax definitions " " {{{2 Enforce catch by reference if !get(g:, "cpp_no_catch_by_reference", 0) " In C++, we should always catch by reference (and throw by value) " " - "constains=cStorageClass" is used to accept and highlight "const" " - "\(regex\)\@<=" is used to exclude a (required) leading context, optional " closing spaces are better outside the context " "\(regex\)\@=" is used to exclude a (required) closing context " - The complex BadCatch regex tells to match an expression without "&" except "...". " " @todo " - catch ([[:space:]]const foo <+cursor+>) is not recognized as a " cppEditedCatch, but a cppBadCatch " syn match cppBadCatch /\(catch\s*(\s*\(const\)\=\)\@<=\(\s*\.\.\.\s*\)\@![^&)]*\()\)\@=/ contains=cStorageClass syn match cppBadCatch /\(catch\s*(\)\@<=\(\s*\.\.\.\s*\)\@![^&)]*\()\)\@=/ contains=cStorageClass " syn match cppBadCatch /\(catch\s*(\s*const\)\@<=\(\s*\.\.\.\s*\)\@![^&)]*\()\)\@=/ contains=cStorageClass " Accept what is currently typed " catch(foo^) catch(foobar ^) catch(foobar con^) catch(foobar const ^) ... syn match cppEditedCatch /\(catch\s*(\)\@<=\s*[a-zA-Z:_]\+\s*\(\%[const]\|const\s*\)\=\%#\(\s*)\)\@=/ contains=cStorageClass " syn match cppEditedCatch /\(catch\s*(\)\@<=\s*[a-zA-Z:_]*\s*\%#\(\s*)\)\@=/ syn match cppEditedCatch /\(catch\s*(\s*const\)\@<=\s*[a-zA-Z:_]*\s*\%#\(\s*)\)\@=/ contains=cStorageClass " syn match cppEditedCatch /\(catch\s*(\s*\(const\s*\)\=\)\@<=\(\%[const]\s*\|const\s*[a-zA-Z:_]\+\s*\)\%#\(\s*)\)\@=/ " syn match cppEditedCatch /\(catch\s*(\s*\(const\s*\)\=\)\@<=[a-zA-Z:_]\+\s*\(\%[const]\|const\s*\)\=\%#\(\s*)\)\@=/ hi def link cppBadCatch SpellBad hi def link cppEditedCatch SpellRare endif " ======================================================================== " {{{1 Some mappings if exists('b:cpp_bad_catch_loaded') && !exists('g:force_reload_cpp_bad_catch') finish endif let b:cpp_bad_catch_loaded = 1 nnoremap ]b :call NextBadCatch() nnoremap [b :call PrevBadCatch() " ======================================================================== " {{{1 Some functions if exists('g:cpp_bad_catch_loaded') && !exists('g:force_reload_cpp_bad_catch') finish endif let g:cpp_bad_catch_loaded = 1 " {{{2 Constants let s:k_badCatch = "cppBadCatch" let s:k_badCatchGID = hlID(s:k_badCatch) let s:k_trans = 1 " {{{2 Tells if the cursor in on a bad catch function! s:IsInBadCatch() let res = synID(line("."),col("."),s:k_trans) == s:k_badCatchGID return res endfunction " {{{2 Find next or previous bad catch " @param {direction} = "" => next " = "b" => previous function! s:FindNextOrPrev(direction) let r = 0 while r != 1 let r = search('\ fail! if r == 0 | return 0 | endif let r = s:IsInBadCatch() endwhile " assert r == 1 return 1 endfunction " {{{2 Next bad catch function! s:NextPrevBadCatchImpl(moveWhenOnBadCatch, moveWhenNotOnBadCatch, searchDirection) " Remember where the search started let pos = line('.').'normal! '.virtcol('.').'|' " if the cursor is on a bad catch, go out of the catch declaration " or if the current keyword is "const" (as s:IsInBadCatch() won't work " correctly on "const" ; expand('') doesn't return anything useful if s:IsInBadCatch() || GetCurrentKeyword() == "const" " goto end of line if the cursor is on a badcatch silent! exe "normal! ".a:moveWhenOnBadCatch else " else goto next word silent! exe "normal! ".a:moveWhenNotOnBadCatch endif if !s:FindNextOrPrev(a:searchDirection) exe pos call s:ErrorMsg ('No other catch() by value found') return 0 else call s:GotoWhereAmpersandIsMissing() return 1 endif endfunction function! s:NextBadCatch() return s:NextPrevBadCatchImpl('$', 'w', '') endfunction function! s:PrevBadCatch() return s:NextPrevBadCatchImpl('0', 'b', 'b') endfunction " {{{2 Error Message function! s:ErrorMsg(msg) if has('gui') call confirm(a:msg, '&Ok', 1, 'Error') else echohl ErrorMsg echo a:msg echohl None endif endfunction " {{{2 GotoWhereAmpersandIsMissing function! s:GotoWhereAmpersandIsMissing() " Move the cursor where the ampersand ("&") should be inserted let last_line = line('.') let pos = last_line.'normal! '.virtcol('.').'|' " move to start of line normal! 0 " if const, move after the const if search('(\s*[A-Za-z_:]\+\s*const\zs') == last_line " found! " do nothing, it ok else " reset position exe last_line normal! 0 if search('(\s*\(const\s*\)\=[A-Za-z_:]\+\zs') == last_line " found! " do nothing, it ok else " reset position exe pos endif endif endfunction " {{{2 Old implementations " {{{3 Next bad catch function! s:NextBadCatch0() " if the cursor is on a bad catch, go out of the catch declaration if synID(line("."),col("."),1) == s:k_badCatchGID " goto next line if the cursor is on a badcatch silent normal! j else " else goto next word silent! norm! w endif if LHNextHighlight(s:k_badCatch, 1) == 0 call s:ErrorMsg ('No other catch() by value found') return 0 else call s:GotoWhereAmpersandIsMissing() return 1 endif endfunction " {{{3 Previous bad catch function! s:PrevBadCatch0() " if the cursor is on a bad catch, go out of the catch declaration if synID(line("."),col("."),1) == hlID(s:k_badCatch) " goto start of line if the cursor is on a badcatch silent normal! 0 else " else goto prev word silent! norm! b endif if LHPrevHighlight(s:k_badCatch, 1) == 0 call s:ErrorMsg ('No other catch() by value found') return 0 else call s:GotoWhereAmpersandIsMissing() return 1 endif endfunction " ======================================================================== " vim: set foldmethod=marker: ================================================ FILE: syntax/cpp-c-cast.vim ================================================ "============================================================================= " File: syntax/cpp-c-cast.vim {{{1 " Author: Luc Hermitte " " Version: 2.2.0 let s:k_version = '220' " Created: 16th Dec 2015 " Last Update: 20th Apr 2016 "------------------------------------------------------------------------ " Description: C++ syntax enhancements " (*) detect C casts in C++ " " Options: " - |cpp_no_hl_c_cast| to disable the check " " Known bugs: " - `decltype(auto) foo;` " - `f(12)(13)(14)` " }}}1 "============================================================================= " {{{1 Syntax definitions if get(g:, 'cpp_no_hl_c_cast', 0) finish endif silent! syn clear cCast " (int*)v " but exclude some operators like "and", "or", "xor", "not" with "@!" " and function specifiers: "const", "volatile", "final", "override", "throw", "noexcept" syn match cCast '\v\(.{-}\)\s*(|||||||||)@!\w+' " (int*)(expr) " "\w@!" is used to ignore double chained calls to operator() " -> f(12)(13) and f (12)(13) are ignored " -> (int*)(expr) is matched syn match cCast '\v(\w\s*)@ " " Version: 2.2.0. " Created: 23rd Apr 2009 " Last Update: 16th Dec 2015 "------------------------------------------------------------------------ " Description: C++ syntax enhancements for CxxTest " assertions. " "------------------------------------------------------------------------ " Option: " History: «history» " TODO: «missing features» " }}}1 "============================================================================= let s:cpo_save=&cpo set cpo&vim "------------------------------------------------------------------------ syn keyword cppCxxTest TS_FAIL syn keyword cppCxxTest TS_ASSERT syn keyword cppCxxTest TS_ASSERT_EQUALS syn keyword cppCxxTest TS_ASSERT_SAME_DELTA syn keyword cppCxxTest TS_ASSERT_DIFFERS syn keyword cppCxxTest TS_ASSERT_LESS_THAN syn keyword cppCxxTest TS_ASSERT_LESS_THAN_EQUALS syn keyword cppCxxTest TS_ASSERT_PREDICATE syn keyword cppCxxTest TS_ASSERT_RELATION syn keyword cppCxxTest TS_ASSERT_THROWS syn keyword cppCxxTest TS_ASSERT_THROWS_EQUALS syn keyword cppCxxTest TS_ASSERT_THROWS_ASSERT syn keyword cppCxxTest TS_ASSERT_THROWS_ANYTHING syn keyword cppCxxTest TS_ASSERT_THROWS_NOTHING syn keyword cppCxxTest TS_WARN syn keyword cppCxxTest TS_TRACE syn keyword cppCxxTest TSM_FAIL syn keyword cppCxxTest TSM_ASSERT syn keyword cppCxxTest TSM_ASSERT_EQUALS syn keyword cppCxxTest TSM_ASSERT_SAME_DELTA syn keyword cppCxxTest TSM_ASSERT_DIFFERS syn keyword cppCxxTest TSM_ASSERT_LESS_THAN syn keyword cppCxxTest TSM_ASSERT_LESS_THAN_EQUALS syn keyword cppCxxTest TSM_ASSERT_PREDICATE syn keyword cppCxxTest TSM_ASSERT_RELATION syn keyword cppCxxTest TSM_ASSERT_THROWS syn keyword cppCxxTest TSM_ASSERT_THROWS_EQUALS syn keyword cppCxxTest TSM_ASSERT_THROWS_ASSERT syn keyword cppCxxTest TSM_ASSERT_THROWS_ANYTHING syn keyword cppCxxTest TSM_ASSERT_THROWS_NOTHING syn keyword cppCxxTest TSM_WARN syn keyword cppCxxTest TSM_TRACE hi def link cppCxxTest Special "------------------------------------------------------------------------ let &cpo=s:cpo_save "============================================================================= " vim600: set fdm=marker: ================================================ FILE: syntax/cpp-funcdef.vim ================================================ "============================================================================= " File: syntax/cpp-funcdef.vim {{{1 " Author: Olivier Teuliere " " Maintainer: Luc Hermitte " " Version: 2.2.0. " Created: 23rd Jul 2007 " Last Update: 16th Dec 2015 "------------------------------------------------------------------------ " Purpose: C++ syntax enhancements " (*) Hightlights member-function definitions " "------------------------------------------------------------------------ " Option: " - |cpp_no_hl_funcdef| to disable the highlight " }}}1 " ======================================================================== " {{{1 Syntax definitions " " {{{2 Enforce catch by reference if !get(g:, "cpp_no_hl_funcdef", 0) syn match cppFuncDef "::\~\?\zs\h\w*\ze([^)]*\()\s*\(const\)\?\)\?$" hi def link cppFuncDef Special endif " ======================================================================== " ======================================================================== " vim: set foldmethod=marker: ================================================ FILE: syntax/cpp-throw-spec.vim ================================================ "============================================================================= " File: syntax/cpp-throw-spec.vim {{{1 " Author: Luc Hermitte " " Version: 2.2.0. " Created: 06th Sep 2007 " Last Update: 18th May 2016 "------------------------------------------------------------------------ " Purpose: C++ syntax enhancements " (*) Hightlights throw specifications " (*) Defines the two mappings [t (/resp. ]t) to jump to the previous " (/resp. next) throw specification. " "------------------------------------------------------------------------ " Requirements: " word_tools.vim::GetCurrentKeyword() -- unchecked " " Option: " - |cpp_no_bad_by_reference| to disable the check that catches are done " by reference. " TODO: " }}}1 "============================================================================= " ======================================================================== " {{{1 Syntax definitions " " {{{2 Enforce no throw specifications if !get(g:, "cpp_no_hl_throw_spec", 0) " In C++, throw specifications does not do what most C++ developpers think " they do. Instead of enforcing a static verification on exceptions flows, " they embed in the result binary some code that checks that the exceptions " thrown from a function match the authorized exceptions. If not, the " application will crash (if the exception handler has not been overriden). " In all cases the application can't do anything but halt very soon. They can " be seen as some kind of assertions, except they are always active, even in " "release" binaries. " Considered this is a tricky feature of C++, and considered they are hardly " useful, here is this script that highlight them as "misspellings". " As nevetheless some framework require them, it will be possible to " configure a list of authorized familly of exception specifications. if ! exists('g:cpp_throw_spec_ignore') let g:cpp_throw_spec_ignore = [ 'CORBA' ] endif silent! syn clear cppThrowSpec silent! syn clear cppThrowSpecIgnored " Method 2, that has the same result... (throw is not underlined) syn match cppThrowSpec /\(\ ]t :call NextThrowSpec() nnoremap [t :call PrevThrowSpec() " {{{1 Some functions if exists('g:cpp_throw_spec_loaded') && !exists('g:force_reload_cpp_throw_spec') finish endif let g:cpp_throw_spec_loaded = 1 " {{{2 Constants let s:k_throwSpec = "cppThrowSpec" let s:k_throwSpecGID = hlID(s:k_throwSpec) let s:k_trans = 1 " {{{2 Tells if the cursor in on a bad catch function! s:IsInThrowSpec() let res = synID(line("."),col("."),s:k_trans) == s:k_throwSpecGID return res endfunction " {{{2 Find next or previous bad catch " @param {direction} = "" => next " = "b" => previous function! s:FindNextOrPrev(direction) let r = 0 while r != 1 let r = search('\ fail! if r == 0 | return 0 | endif let r = s:IsInThrowSpec() if r == 1 call search('\') doesn't return anything useful " if s:IsInThrowSpec() || GetCurrentKeyword() == "throw" if s:IsInThrowSpec() || expand('') == "throw" " goto end of line if the cursor is on a throwspec silent! exe "normal! ".a:moveWhenOnThrowSpec else " else goto next word silent! exe "normal! ".a:moveWhenNotOnThrowSpec endif endif if !s:FindNextOrPrev(a:searchDirection) exe pos call s:ErrorMsg ('No other throw-specification found') return 0 else return 1 endif endfunction function! s:NextThrowSpec() return s:NextPrevThrowSpecImpl("/)/\", 'w', '') endfunction function! s:PrevThrowSpec() return s:NextPrevThrowSpecImpl('0', 'b', 'b') endfunction " {{{2 Error Message function! s:ErrorMsg(msg) if has('gui') call confirm(a:msg, '&Ok', 1, 'Error') else echohl ErrorMsg echo a:msg echohl None endif endfunction "------------------------------------------------------------------------ "============================================================================= " vim600: set fdm=marker: ================================================ FILE: syntax/cpp.vim ================================================ " ======================================================================== " File: syntax/cpp.vim " Author: Luc Hermitte " " Version: 1.1.0 " Last Update: $Date$ " " Purpose: C++ syntax enhancements " " Option: " ======================================================================== " This is the only valid way to load the C++ and C default syntax file. so $VIMRUNTIME/syntax/cpp.vim " Source syntax hooks for C++ runtime! syntax/cpp-*.vim syntax/cpp_*.vim " Load syntax enhancements for Doxygen, if installed " runtime syntax/doxygen.vim " see :h doxygen " .vimrc => :let g:load_doxygen_syntax=1 " Load syntax enhancements for wxWindows, if installed runtime syntax/wxwin.vim ================================================ FILE: tests/VimFlavor ================================================ flavor 'LucHermitte/vim-UT', '>= 0.6.0' ================================================ FILE: tests/lh/analysis.vim ================================================ "============================================================================= " File: tests/lh/analysis.vim {{{1 " Author: Luc Hermitte " " Version: 2.0.0.b15 let s:k_version = '2.0.0b15' " Created: 17th Feb 2015 " Last Update: $Date$ "------------------------------------------------------------------------ " Description: " Unit Tests for AnalysisLic " }}}1 "============================================================================= UTSuite [lh-cpp] Testing lh/cpp/AnalysisLib_Class runtime autoload/lh/cpp/AnalysisLib_Class.vim let s:cpo_save=&cpo set cpo&vim "------------------------------------------------------------------------ function! s:Test_simplify_id() " Partial Match up to last ns Assert lh#cpp#AnalysisLib_Class#simplify_id('a::b::C', ['', 'a', 'a::b'] ) == 'C' Assert lh#cpp#AnalysisLib_Class#simplify_id('a::b::C', ['::', 'a::', 'a::b::']) == 'C' Assert lh#cpp#AnalysisLib_Class#simplify_id('a::b::C', ['a', 'a::b'] ) == 'C' Assert lh#cpp#AnalysisLib_Class#simplify_id('a::b::C', ['a::', 'a::b::'] ) == 'C' " Partial Match (of first ns) Assert lh#cpp#AnalysisLib_Class#simplify_id('a::b::C', ['a', 'a::z'] ) == 'b::C' Assert lh#cpp#AnalysisLib_Class#simplify_id('a::b::C', ['a::', 'a::z::'] ) == 'b::C' " No Match Assert lh#cpp#AnalysisLib_Class#simplify_id('a::b::C', ['z', 'a::z'] ) == 'a::b::C' Assert lh#cpp#AnalysisLib_Class#simplify_id('a::b::C', ['z::', 'a::z::'] ) == 'a::b::C' Assert lh#cpp#AnalysisLib_Class#simplify_id('a::b::C', ['', 'z', 'a::z'] ) == 'a::b::C' Assert lh#cpp#AnalysisLib_Class#simplify_id('a::b::C', ['::', 'z::', 'a::z::']) == 'a::b::C' " Full Match Assert lh#cpp#AnalysisLib_Class#simplify_id('a::b::C', ['a', 'a::b::C'] ) == '' Assert lh#cpp#AnalysisLib_Class#simplify_id('a::b::C', ['a::', 'a::b::C::'] ) == '' Assert lh#cpp#AnalysisLib_Class#simplify_id('a::b::C', ['', 'b', 'a::b::C'] ) == '' Assert lh#cpp#AnalysisLib_Class#simplify_id('a::b::C', ['::', 'b::', 'a::b::C::']) == '' endfunction function! s:Test_simplify_id_and_show_ns() Assert lh#cpp#AnalysisLib_Class#simplify_id('a::b::C', ['', 'a', 'a::b'] , 1) == ['a::b::', 'C'] Assert lh#cpp#AnalysisLib_Class#simplify_id('a::b::C', ['::', 'a::', 'a::b::'], 1) == ['a::b::', 'C'] Assert lh#cpp#AnalysisLib_Class#simplify_id('a::b::C', ['a', 'a::b'] , 1) == ['a::b::', 'C'] Assert lh#cpp#AnalysisLib_Class#simplify_id('a::b::C', ['a::', 'a::b::'] , 1) == ['a::b::', 'C'] Assert lh#cpp#AnalysisLib_Class#simplify_id('a::b::C', ['a', 'a::z'] , 1) == ['a::', 'b::C'] Assert lh#cpp#AnalysisLib_Class#simplify_id('a::b::C', ['a::', 'a::z::'] , 1) == ['a::', 'b::C'] Assert lh#cpp#AnalysisLib_Class#simplify_id('a::b::C', ['z', 'a::z'] , 1) == ['', 'a::b::C'] Assert lh#cpp#AnalysisLib_Class#simplify_id('a::b::C', ['z::', 'a::z::'] , 1) == ['', 'a::b::C'] Assert lh#cpp#AnalysisLib_Class#simplify_id('a::b::C', ['', 'z', 'a::z'] , 1) == ['', 'a::b::C'] Assert lh#cpp#AnalysisLib_Class#simplify_id('a::b::C', ['::', 'z::', 'a::z::'], 1) == ['', 'a::b::C'] endfunction "------------------------------------------------------------------------ let &cpo=s:cpo_save "============================================================================= " vim600: set fdm=marker: ================================================ FILE: tests/lh/cpp-TU-override.cpp ================================================ // Vim: let b:tags_dirname = '.' // namespace nZ { class B {}; } // nZ namespace namespace foo { class A0 { virtual ~A0() = 0; virtual void a0(); }; class A1 { virtual ~A1(); virtual void f1(std::string const& s) = 0; virtual void f2() { f1("foo"); } void f2(int); [] }; class A2 : virtual A0 { virtual ~A2() {} virtual void g(); virtual void a0(); ['A0'] } class A3 : virtual A0 { void a0(); ['A0'] } class C1 : A1, A2 { virtual ~C1(); void f2(); ['A0', 'A1', 'A2'] }; class D : C1, virtual A0 { virtual void g(); ['A0', 'A1', 'A2', 'C1'] }; class B : A0{}; } // foo namespace namespace bar { using namespace nZ; struct V {}; struct Z {}; struct C1 : virtual V {}; struct C2 : virtual V, Z {}; struct C3 : C2{}; struct D : C1, C3, B {}; // echo lh#cpp#AnalysisLib_Class#Ancestors('bar::D') } // bar namespace ================================================ FILE: tests/lh/cpp-TU.cpp ================================================ // nnoremap :echo lh#cpp#AnalysisLib_Function#AnalysePrototype(lh#cpp#AnalysisLib_Function#GetFunctionPrototype(line('.'), 0)) // nnoremap :echo lh#cpp#AnalysisLib_Function#GetFunctionPrototype(line('.'), 0) enum Ee { E_a, E_b}; enum class Ec {a, c}; // test refactorinng void f(int z) { int i = 42 + z; printf("ttoto %d\n", i); int j = i / 2 ; Ee ee; } Ec ec; int ec; struct MyEnum { enum type { E1, E2, MAX__}; }; void f(int) { printf(toto); } class Toto { typedef tutu; Toto(Toto const& rhs); Toto(Ttiti const& rhs, int z=42, T t=T()); Toto(Ttiti const& rhs, float z=42); ~Toto(); virtual ~Toto(); Toto& operator=(Toto const& rhs); Toto& operator*(Toto const& rhs); Toto* operator*(Toto const& rhs); void operator*(Toto const& rhs); void operator+(Toto const& rhs); std::ostream & operator<<(std::ostream &os, const Toto& toto); operator int() const; operator const T*() const; Titi * f(); Titi & g(); virtual void f(Titi * titi) const; static void f(Titi const* titi); static s(); void foo(toto t=42, titi r, tutu z=f()) throw(); void foo(toto t=42, titi r, tutu z=f()) throw(foo); void foo(toto t=42, titi r, tutu z=f()) throw(foo, bar); void foo(toto t=42, std::string const& s, char * p, int[] i, titi r, tutu z=f()) const throw(foo, bar); int foo(toto t=42, std::string const&, char * p, int[] i, std::vector, titi r, tutu z=f()) const throw(foo, bar); int bar(/*c1*/T/*c2*/ v/*c3*/); // c-eol }; namespace NS1 { namespace NS2 { int foo; // -> echo lh#cpp#AnalysisLib_Class#CurrentScope(line('.'), '##') class Bar { }; } } void NS1::NS2::foo(toto t=42, int, std::string const& s, char * p, int[] i, titi r, tutu z=f()) const throw(foo, bar); /*===========================================================================*/ /*===================================[ t ]===================================*/ /*===========================================================================*/ Toto::~Toto() { } void Toto::operator+(Toto const& rhs) { } Toto* Toto::operator*(Toto const& rhs) { } Titi & Toto::g() { } Titi * Toto::f() { } Toto& Toto::operator=(Toto const& rhs) { while (toto = 42) { if (toto = 42) foo == 42; } } /*===========================================================================*/ /*===========================[ :Constructor test ]===========================*/ /*===========================================================================*/ class Titi { public: private: int m_int; std::string m_str; Ptr* m_ptr; Ref& m_ref; Tab[N] m_tab; std::vector m_vector; }; ================================================ FILE: tests/lh/omap-param.vim ================================================ " ====================================================================== " $Id$ " File: tests/lh/omap-param.vim " Maintainer: Luc Hermitte " " Last Update: $Date$ " Version: 1.1.0 " " " Author: Luc Hermitte " Notes: " * "i," can't be used to select several parameters with several uses of " "i," ; use "a," instead (-> "va,a,a,"). This is because of simple letter " parameters. " However, "v2i," works perfectly. " * Requires Vim 7+ " * The following should be resistant to &magic, and other mappings " * select-mode is not parasited by this plugin " ====================================================================== onoremap i, :call SelectParam(1,0) xnoremap i, :call SelectParam(1,1)gv onoremap a, :call SelectParam(0,0) xnoremap a, :call SelectParam(0,1)gv if 0 call Un(Null,fun2(fun3(a,b,g(NULL))),t, titi, r , zzz call Un(Null,fun2(fun3(a,b,g(NULL))),t, titi, r , zzz) endif function! s:SelectParam(inner, visual) let saved_pos = getpos('.') if a:visual ==1 && s:CharAtMark("'>") =~ '[(,]' \ && !s:SkipAtMark("'>") normal! gv elseif searchpair('(',',',')','bcW','s:Skip()') > 0 || \ searchpair('(',',',')','bW','s:Skip()') > 0 " Test necessary because 'c' flag and Skip() don't always work well together call search('.') normal! v else throw "Not on a parameter" endif let cnt = v:count <= 0 ? 1 : v:count while cnt > 0 let cnt -= 1 if 0 == searchpair('(', ',',')', 'W','s:Skip()') if s:IsBefore(getpos('.'), saved_pos) " no "vi," when starting from the last parameter exe "normal! \" call setpos('.', saved_pos) throw (a:visual?'v':'').(a:inner?'i':'a').",: Cursor not on a parameter" else echomsg (a:visual?'v':'').(a:inner?'i':'a').",: No more parameters" " 999di, silently deletes everything till the end break endif endif endwhile " Don't include the last closing paren if a:inner == 1 || searchpair('(',',',')','n','s:Skip()') <= 0 call search('.','b') endif endfunction function! s:CharAtMark(char) let c = getline(a:char)[col(a:char)-1] return c endfunction func! s:SkipAt(l,c) return synIDattr(synID(a:l, a:c, 0),'name') =~? \ 'string\|comment\|character\|doxygen' endfun func! s:Skip() return s:SkipAt(line('.'), col('.')) endfun func! s:SkipAtMark(mark) return s:SkipAt(line(a:mark), col(a:mark)) endfun function! s:IsBefore(lhs_pos, rhs_pos) if a:lhs_pos[0] != a:rhs_pos[0] throw "Postions from incompatible buffers can't be ordered" endif "1 test lines "2 test cols let before \ = (a:lhs_pos[1] == a:rhs_pos[1]) \ ? (a:lhs_pos[2] < a:rhs_pos[2]) \ : (a:lhs_pos[1] < a:rhs_pos[1]) return before endfunction function! SelectParam(i,v) call s:SelectParam(a:i, a:v) endfunction " by A.Politz "assert("cursor at or in front of opening paren") func! FargsPos() let res = [] let p0 = getpos('.') "find first paren if !search('(','Wc') return [] endif call add(res,getpos('.')) "goto closing paren if searchpair('(','',')','W','Skip()') <= 0 call setpos('.',p0) return [] endif let end = getpos('.') "go back to opening paren call setpos('.',res[0]) "search for ',' , while not at the closing paren while searchpair('(',',',')','W','Skip()') > 0 && getpos('.') != end call add(res,getpos('.')) endwhile call add( res , end) call setpos('.',p0) return res " = positions of '(' ',' ... ')' endfun finish function! s:t(a, b, c, d e,, f ) endfunction fun(Null,fun2(fun3(a,b,g(NULL))), zzz) ================================================ FILE: tests/lh/snippets.vim ================================================ "============================================================================= " File: tests/lh/snippets.vim {{{1 " Author: Luc Hermitte " " Version: 2.2.0. let s:k_version = '220' " Created: 25th Nov 2015 " Last Update: 15th Dec 2015 "------------------------------------------------------------------------ " Description: " Test autoload/lh/snippets.vim functions " }}}1 "============================================================================= UTSuite [lh-cpp] Testing lh/cpp/snippets.vim runtime autoload/lh/cpp/on.vim runtime autoload/lh/cpp/snippets.vim let s:cpo_save=&cpo set cpo&vim " ## Tests {{{1 "------------------------------------------------------------------------ function! s:Test_noexcept() " {{{2 let cleanup = lh#on#exit() \.restore_option('cpp_noexcept') \.restore_option('cpp_std_flavour') \.restore('$CXXFLAGS') silent! unlet g:cpp_std_flavour silent! unlet b:cpp_std_flavour silent! unlet g:cpp_noexcept silent! unlet b:cpp_noexcept let $CXXFLAGS = '' try AssertEquals(lh#cpp#snippets#noexcept(), 'throw()') AssertEquals(lh#cpp#snippets#noexcept('false'), 'throw()') let b:cpp_std_flavour = 11 AssertEquals(lh#cpp#snippets#noexcept(), 'noexcept') AssertEquals(lh#cpp#snippets#noexcept('false'), 'noexcept(false)') let g:cpp_noexcept = 'ITK_NOEXCEPT%1' AssertEquals(lh#cpp#snippets#noexcept(), 'ITK_NOEXCEPT') AssertEquals(lh#cpp#snippets#noexcept('false'), 'ITK_NOEXCEPT(false)') unlet b:cpp_std_flavour AssertEquals(lh#cpp#snippets#noexcept(), 'ITK_NOEXCEPT') AssertEquals(lh#cpp#snippets#noexcept('false'), 'ITK_NOEXCEPT(false)') finally call cleanup.finalize() endtry endfunction "------------------------------------------------------------------------ function! s:Test_deleted() " {{{2 let cleanup = lh#on#exit() \.restore_option('cpp_deleted') \.restore_option('cpp_std_flavour') \.restore('$CXXFLAGS') silent! unlet g:cpp_std_flavour silent! unlet b:cpp_std_flavour silent! unlet g:cpp_deleted silent! unlet b:cpp_deleted let $CXXFLAGS = '' try AssertEquals(lh#cpp#snippets#deleted(), '/* = delete */') let b:cpp_std_flavour = 11 AssertEquals(lh#cpp#snippets#deleted(), '= delete') let g:cpp_deleted = 'ITK_DELETE' AssertEquals(lh#cpp#snippets#deleted(), 'ITK_DELETE') unlet b:cpp_std_flavour AssertEquals(lh#cpp#snippets#deleted(), 'ITK_DELETE') finally call cleanup.finalize() endtry endfunction "------------------------------------------------------------------------ function! s:Test_defaulted() " {{{2 let cleanup = lh#on#exit() \.restore_option('cpp_defaulted') \.restore_option('cpp_std_flavour') \.restore('$CXXFLAGS') silent! unlet g:cpp_std_flavour silent! unlet b:cpp_std_flavour silent! unlet g:cpp_defaulted silent! unlet b:cpp_defaulted let $CXXFLAGS = '' try AssertEquals(lh#cpp#snippets#defaulted(), '/* = default */') let b:cpp_std_flavour = 11 AssertEquals(lh#cpp#snippets#defaulted(), '= default') let g:cpp_defaulted = 'ITK_DEFAULT' AssertEquals(lh#cpp#snippets#defaulted(), 'ITK_DEFAULT') unlet b:cpp_std_flavour AssertEquals(lh#cpp#snippets#defaulted(), 'ITK_DEFAULT') finally call cleanup.finalize() endtry endfunction "------------------------------------------------------------------------ " Function: s:Test_parents() {{{2 function! s:Test_parents() abort let parents = [] AssertEquals(lh#cpp#snippets#parents(parents), ['', []]) let parents += [ {"boost::noncopyable" : {"how": "include", "visibility": "private"}}] AssertEquals(lh#cpp#snippets#parents(parents), [" : private boost::noncopyable", []]) let parents += [ {"SomeBase" : {}}] AssertEquals(lh#cpp#snippets#parents(parents), ["\n: private boost::noncopyable\n, public SomeBase", []]) let parents += [ {"Base2" : {"virtual": 1}}] AssertEquals(lh#cpp#snippets#parents(parents), ["\n: private boost::noncopyable\n, public SomeBase\n, public virtual Base2", []]) " Start from new, uses lh#cpp#types let parents = [ {"noncopyable" : {"how": "include", "visibility": "private"}}] AssertEquals(lh#cpp#snippets#parents(parents), [" : private boost::noncopyable", ['']]) endfunction " }}}1 "------------------------------------------------------------------------ let &cpo=s:cpo_save "============================================================================= " vim600: set fdm=marker: ================================================ FILE: tests/lh/test-flavours.vim ================================================ "============================================================================= " File: tests/lh/test-flavours.vim {{{1 " Author: Luc Hermitte " " License: GPLv3 with exceptions " " Version: 2.1.7. let s:k_version = '217' " Created: 23rd Nov 2015 " Last Update: "------------------------------------------------------------------------ " Description: " Test C++ flavour detection " " - Test all flavours " - Test priorities "------------------------------------------------------------------------ " Todo: " - Test CMakeCache decoding " }}}1 "============================================================================= UTSuite [lh-cpp] Testing lh#cpp#get_flavour() runtime autoload/lh/cpp.vim let s:cpo_save=&cpo set cpo&vim "------------------------------------------------------------------------ function! s:Setup() let s:cleanup = lh#on#exit() \.restore_option('cpp_std_flavour') \.restore('$CXXFLAGS') silent! let $CXXFLAGS='' silent! unlet g:cpp_std_flavour silent! unlet b:cpp_std_flavour endfunction function! s:Teardown() call s:cleanup.finalize() endfunction "------------------------------------------------------------------------ function! s:Expect98() AssertEquals!(lh#cpp#get_flavour(), 03) Assert !lh#cpp#use_cpp11() Assert !lh#cpp#use_cpp14() Assert !lh#cpp#use_cpp17() endfunction function! s:Expect11() AssertEquals(lh#cpp#get_flavour(), 11) Assert lh#cpp#use_cpp11() Assert !lh#cpp#use_cpp14() Assert !lh#cpp#use_cpp17() endfunction function! s:Expect14() AssertEquals(lh#cpp#get_flavour(), 14) Assert lh#cpp#use_cpp11() Assert lh#cpp#use_cpp14() Assert !lh#cpp#use_cpp17() endfunction function! s:Expect17() AssertEquals(lh#cpp#get_flavour(), 17) Assert lh#cpp#use_cpp11() Assert lh#cpp#use_cpp14() Assert lh#cpp#use_cpp17() endfunction "------------------------------------------------------------------------ "------------------------------------------------------------------------ function! s:Test_cpp98() call s:Expect98() let $CXXFLAGS = '-Wall -O3 -DNDEBUG' call s:Expect98() endfunction "------------------------------------------------------------------------ function! s:Test_cpp0x() let $CXXFLAGS = '-O3 -std=c++0x -Wall' call s:Expect11() let $CXXFLAGS = '-Wall -O3 -DNDEBUG' AssertEquals(lh#cpp#get_flavour(), 03) call s:Expect98() endfunction function! s:Test_cpp11() let b:cpp_std_flavour = '11' call s:Expect11() unlet b:cpp_std_flavour let $CXXFLAGS = '-O3 -std=c++11 -Wall' call s:Expect11() let $CXXFLAGS = '-Wall -O3 -DNDEBUG' AssertEquals(lh#cpp#get_flavour(), 03) call s:Expect98() endfunction "------------------------------------------------------------------------ function! s:Test_cpp1y() let $CXXFLAGS = '-O3 -std=c++1y -Wall' call s:Expect14() let $CXXFLAGS = '-Wall -O3 -DNDEBUG' AssertEquals(lh#cpp#get_flavour(), 03) call s:Expect98() endfunction function! s:Test_cpp14() let b:cpp_std_flavour = '14' call s:Expect14() unlet b:cpp_std_flavour let $CXXFLAGS = '-O3 -std=c++14 -Wall' call s:Expect14() let $CXXFLAGS = '-Wall -O3 -DNDEBUG' AssertEquals(lh#cpp#get_flavour(), 03) call s:Expect98() endfunction "------------------------------------------------------------------------ function! s:Test_cpp1z() let $CXXFLAGS = '-O3 -std=c++1z -Wall' call s:Expect17() let $CXXFLAGS = '-Wall -O3 -DNDEBUG' AssertEquals(lh#cpp#get_flavour(), 03) call s:Expect98() endfunction function! s:Test_cpp17() let b:cpp_std_flavour = '17' call s:Expect17() unlet b:cpp_std_flavour let $CXXFLAGS = '-O3 -std=c++17 -Wall' call s:Expect17() let $CXXFLAGS = '-Wall -O3 -DNDEBUG' AssertEquals(lh#cpp#get_flavour(), 03) call s:Expect98() endfunction "------------------------------------------------------------------------ "------------------------------------------------------------------------ function! s:Test_prio() call s:Expect98() let $CXXFLAGS = '-O3 -std=c++17 -Wall' call s:Expect17() let g:cpp_std_flavour = '11' call s:Expect11() let b:cpp_std_flavour = '03' call s:Expect98() endfunction "------------------------------------------------------------------------ let &cpo=s:cpo_save "============================================================================= " vim600: set fdm=marker: ================================================ FILE: tests/lh/test-types.vim ================================================ "============================================================================= " File: tests/lh/test-types.vim {{{1 " Author: Luc Hermitte " " Version: 2.2.0. let s:k_version = '220' " Created: 15th Dec 2015 " Last Update: 15th Dec 2015 "------------------------------------------------------------------------ " Description: " Test lh#cpp#types#... " "------------------------------------------------------------------------ " History: «history» " TODO: «missing features» " }}}1 "============================================================================= UTSuite [lh-cpp] Testing lh/cpp/types.vim runtime autoload/lh/cpp/types.vim let s:cpo_save=&cpo set cpo&vim " SetUp {{{1 " Function: s:Setup() {{{3 function! s:Setup() abort " SetMarker <+ +> " it seems that playing with encodings messes vim execution through rspec let b:marker_open = '<+' let b:marker_close = '+>' let b:last_encoding_used = &enc AssertEquals( b:marker_open, '<+') AssertRelation( lh#marker#version(), '>=' , 310) AssertEquals(lh#marker#open(), '<+') endfunction " Tests {{{1 "------------------------------------------------------------------------ function! s:Test_none() " {{{2 let info = lh#cpp#types#get_info('invalid_type') Assert get(info, 'unknown', 0) AssertEquals(lh#cpp#types#get_includes(''), []) endfunction "------------------------------------------------------------------------ function! s:Test_vector() " {{{2 let vector = lh#cpp#types#get_info('vector') AssertEquals(vector.includes , ['']) AssertEquals(vector.name , 'vector') AssertEquals(vector.type , 'vector<%1>') AssertEquals(vector.namespace , 'std') AssertEquals(vector.typename_for_header('T'), 'std::vector') AssertEquals(vector.typename_for_header() , 'std::vector<<+T1+>>') endfunction "------------------------------------------------------------------------ function! s:Test_map() " {{{2 let map = lh#cpp#types#get_info('map') AssertEquals(map.includes , ['']) AssertEquals(map.name , 'map') AssertEquals(map.type , 'map<%1,%2>') AssertEquals(map.namespace , 'std') AssertEquals(map.typename_for_header('T', 'V'), 'std::map') AssertEquals(map.typename_for_header('T') , 'std::map>') AssertEquals(map.typename_for_header() , 'std::map<<+T1+>,<+T2+>>') endfunction "------------------------------------------------------------------------ function! s:Test_string() " {{{2 let string = lh#cpp#types#get_info('string') AssertEquals(string.includes , ['']) AssertEquals(string.name , 'string') AssertEquals(string.type , 'string') AssertEquals(string.namespace , 'std') AssertEquals(string.typename_for_header(), 'std::string') endfunction "------------------------------------------------------------------------ function! s:Test_chrono() " {{{2 let chrono_time_point = lh#cpp#types#get_info('chrono::time_point') AssertEquals(chrono_time_point.includes , ['']) AssertEquals(chrono_time_point.name , 'chrono::time_point') AssertEquals(chrono_time_point.type , 'chrono::time_point<%1>') AssertEquals(chrono_time_point.namespace, 'std') endfunction "------------------------------------------------------------------------ function! s:Test_size_t() " {{{2 let size_t = lh#cpp#types#get_info('size_t') AssertEquals(size_t.includes , ['', '', '', '', '', '']) AssertEquals(size_t.name , 'size_t') AssertEquals(size_t.type , 'size_t') AssertEquals(size_t.namespace, 'std') endfunction "------------------------------------------------------------------------ function! s:Test_noncopyable() " {{{2 let noncopyable = lh#cpp#types#get_info('noncopyable') AssertEquals(noncopyable.includes , ['']) AssertEquals(noncopyable.name , 'noncopyable') AssertEquals(noncopyable.type , 'noncopyable') AssertEquals(noncopyable.namespace, 'boost') endfunction "------------------------------------------------------------------------ function! s:Test_ptr_vector() " {{{2 let ptr_vector = lh#cpp#types#get_info('ptr_vector') AssertEquals(ptr_vector.includes , ['', '']) AssertEquals(ptr_vector.name , 'ptr_vector') AssertEquals(ptr_vector.type , 'ptr_vector<%1>') AssertEquals(ptr_vector.namespace, 'boost') endfunction "------------------------------------------------------------------------ " }}}1 "------------------------------------------------------------------------ let &cpo=s:cpo_save "============================================================================= " vim600: set fdm=marker: