Latest commit

History

21 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

cpptags

Vim plugin that customizes 'tagfunc' for C++ files.

Index

Motivation

The default builtin 'tagfunc' is not suitable for modern C++, lacks support for: namespaces and classes, function and methods signatures, template parameters and specialization.

The new ctags releases provide support for the above features and more.

This filetype plugin will automatically set up a new 'tagfunc' that will profit from the new ctags fields.

Installation

An obvious precondition is having ctags installed. Is available on the most popular package managers:

  • Ubuntu:
 $ sudo apt install universal-ctags
  • Windows:
> winget install UniversalCtags.Ctags 
  • MacOs:
 $ brew install universal-ctags

This plugin can be installed using any popular plugin manager (vim-plug, Vundle, etc...) but vim plugin integration is extremely easy in later releases (version8.0 introduced package support):

  • A vimball is distributed by www.vim.org. Installation is as easy as sourcing the vimball file:

    :source cpptags.vba

    so is uninstall:

    :RmVimball cpptags.vba
  • The github repo can be cloned direcly into the $VIMRUNTIME/pack directory as explained in matchit-install. Though using this approach many useless files in this repo will be installed too.

  • Use getscript plugin to automatically download an update it. Update the local $VIMRUNTIME/GetLatest/GetLatestVimScripts.dat adding a line associated with this plugin.

Once installed the vim's filetype plugins must be enabled:

:filetypepluginon

is adviceable to introduce this into the .vimrc if not there already.

Usage

For proper operation the plugin requires:

  • set up a tag file suitable for modern C/C++ navigation.
  • learn how to prompt the :tag and :tselect commands.

Required tag generation options

In order to profit from the new ctags output several non-default options must be used:

$ ctags --extras=+f -R --languages=c++ --langmap=c++:+.c. --c++-kinds=+pl --fields=+iaeSK --fields-c++=*
--options=<option-file-path> -f <output-tags-file><source-dirs>

The options file allows simplifying the command line by including there lenghtly parameters. It is usual to include there options devoted to resolve preprocessor macros that ctags cannot understand by itself.

Old C/C++ libraries relied heavily on preprocessor magic and require tedious composition of option files to generate a useful ctags output. For example, the microsoft version of the STL requires the following options:

 -D _STD_BEGIN= namespace std {
-D _STD_END=}
-D _STD= ::std::
-D _CHRONO= ::std::chrono::
-D _RANGES= ::std::ranges::
-D _STDEXT_BEGIN= namespace stdext {
-D _STDEXT_END=}
-D _STDEXT= ::stdext::
-D _CSTD=::
-I _NODISCARD
-I _EXPORT_STD
-I _CRT_GUARDOVERFLOW
-I _Out_writes_all_+
-I _In_reads_+
-I _CONSTEXPR20 -I _CONSTEXPR17
-I __PURE_APPDOMAIN_GLOBAL
-I _CRTDATA2_IMPORT
-I _CRTIMP2_PURE_IMPORT
-I __thiscall
-I _STL_RESTORE_CLANG_WARNINGS
-I _STL_DISABLE_CLANG_WARNINGS

fortunately new C/C++ libraries favor the new template capabilities and discourage preprocessor usage. For example, C++/WinRT projection sources can be parsed completely with only two options:

 -D WINRT_IMPL_AUTO(B)=B
-I WINRT_EXPORT

Once the tag file is generated it must be appended to the 'tags' option which contains patterns to locate tag files. For example if the output file is in ~/mytagfiles/stl.tags we must do:

:settags+=~/mytagfiles/stl.tags

For convenience, this can be included in the source files using a modeline. For example ending the sources with:

/* vim: set tags+=~/mytagfiles/stl.tags: */

New tag syntax

The syntax follows the natural semantics of C++. The basics are simple:

  • namespaces/classes. The use of qualified identifiers restricts the tag choices. For example:

    voidf(); // case anamespaceA {
    voidf(); // case bnamespaceB {
    voidf(); // case c
    }}

    Doing:

    • :tsel f will show all 3 cases (a,b & c).
    • :tsel A::f will show 2 cases (b & c) and prioritize b.
    • :tsel A::B will show only case c.
  • template syntax:

    template <typename A, typename B> classA; // forward declaration, case atemplate <typename A, typename B> classA {}; // declaration, case btemplate <> classA<int, double> {}; // specialization, case c

    Case a is ignore by ctags. Doing:

    • :tsel A or :tsel A<> will show case b only (specializations are ignored).
    • :tsel A<int> or :tsel A<int,double> will show case c only.
  • signature syntax:

    classa {}; // case avoida(); // declaration, case bvoida() {} // definition, case cvoida(int e, int f); // declaration, case d voida(int e, int f) {} // definition, case e 

    Doing:

    • :tsel a will show all cases.
    • :tsel a() will show c, b, e & d. It:
      • ignores non-functions.
      • prioritizes definitions over declarations.
      • prioritizes functions without arguments.
    • :tsel a(int) or :tsel a(int, int) will show e, d because matches the signature.
  • operator syntax:

    structO {
    operatorint() { return0; } // case aoperatorA::cB() { return {}; } // case b
    };
    structP {
    operatorint() { return0; } // case c
    };

    Doing:

    • :tsel operator int will show case a and c
    • :tsel O::operator int will show case a
    • :tsel operator cB will show case b
    • :tsel O::operator cB will show case b
    • :tsel O::operator A::cB will show case b

All the above rules can be combined together, for example in:

namespaceA {
classB {
template<bool> voidm(int) {} // case atemplate<> void m<true>(int) {} // case b
};}

the command:

:tagA::B::m<true>(int)

will match case b which is the result of combining the rules above.

About

Vim plugin that customizes 'tagfunc' for cpp files

Resources

Stars

3 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Latest commit

History

21 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

cpptags

Vim plugin that customizes 'tagfunc' for C++ files.

Index

Motivation

The default builtin 'tagfunc' is not suitable for modern C++, lacks support for: namespaces and classes, function and methods signatures, template parameters and specialization.

The new ctags releases provide support for the above features and more.

This filetype plugin will automatically set up a new 'tagfunc' that will profit from the new ctags fields.

Installation

An obvious precondition is having ctags installed. Is available on the most popular package managers:

  • Ubuntu:
 $ sudo apt install universal-ctags
  • Windows:
> winget install UniversalCtags.Ctags 
  • MacOs:
 $ brew install universal-ctags

This plugin can be installed using any popular plugin manager (vim-plug, Vundle, etc...) but vim plugin integration is extremely easy in later releases (version8.0 introduced package support):

  • A vimball is distributed by www.vim.org. Installation is as easy as sourcing the vimball file:

    :source cpptags.vba

    so is uninstall:

    :RmVimball cpptags.vba
  • The github repo can be cloned direcly into the $VIMRUNTIME/pack directory as explained in matchit-install. Though using this approach many useless files in this repo will be installed too.

  • Use getscript plugin to automatically download an update it. Update the local $VIMRUNTIME/GetLatest/GetLatestVimScripts.dat adding a line associated with this plugin.

Once installed the vim's filetype plugins must be enabled:

:filetypepluginon

is adviceable to introduce this into the .vimrc if not there already.

Usage

For proper operation the plugin requires:

  • set up a tag file suitable for modern C/C++ navigation.
  • learn how to prompt the :tag and :tselect commands.

Required tag generation options

In order to profit from the new ctags output several non-default options must be used:

$ ctags --extras=+f -R --languages=c++ --langmap=c++:+.c. --c++-kinds=+pl --fields=+iaeSK --fields-c++=*
--options=<option-file-path> -f <output-tags-file><source-dirs>

The options file allows simplifying the command line by including there lenghtly parameters. It is usual to include there options devoted to resolve preprocessor macros that ctags cannot understand by itself.

Old C/C++ libraries relied heavily on preprocessor magic and require tedious composition of option files to generate a useful ctags output. For example, the microsoft version of the STL requires the following options:

 -D _STD_BEGIN= namespace std {
-D _STD_END=}
-D _STD= ::std::
-D _CHRONO= ::std::chrono::
-D _RANGES= ::std::ranges::
-D _STDEXT_BEGIN= namespace stdext {
-D _STDEXT_END=}
-D _STDEXT= ::stdext::
-D _CSTD=::
-I _NODISCARD
-I _EXPORT_STD
-I _CRT_GUARDOVERFLOW
-I _Out_writes_all_+
-I _In_reads_+
-I _CONSTEXPR20 -I _CONSTEXPR17
-I __PURE_APPDOMAIN_GLOBAL
-I _CRTDATA2_IMPORT
-I _CRTIMP2_PURE_IMPORT
-I __thiscall
-I _STL_RESTORE_CLANG_WARNINGS
-I _STL_DISABLE_CLANG_WARNINGS

fortunately new C/C++ libraries favor the new template capabilities and discourage preprocessor usage. For example, C++/WinRT projection sources can be parsed completely with only two options:

 -D WINRT_IMPL_AUTO(B)=B
-I WINRT_EXPORT

Once the tag file is generated it must be appended to the 'tags' option which contains patterns to locate tag files. For example if the output file is in ~/mytagfiles/stl.tags we must do:

:settags+=~/mytagfiles/stl.tags

For convenience, this can be included in the source files using a modeline. For example ending the sources with:

/* vim: set tags+=~/mytagfiles/stl.tags: */

New tag syntax

The syntax follows the natural semantics of C++. The basics are simple:

  • namespaces/classes. The use of qualified identifiers restricts the tag choices. For example:

    voidf(); // case anamespaceA {
    voidf(); // case bnamespaceB {
    voidf(); // case c
    }}

    Doing:

    • :tsel f will show all 3 cases (a,b & c).
    • :tsel A::f will show 2 cases (b & c) and prioritize b.
    • :tsel A::B will show only case c.
  • template syntax:

    template <typename A, typename B> classA; // forward declaration, case atemplate <typename A, typename B> classA {}; // declaration, case btemplate <> classA<int, double> {}; // specialization, case c

    Case a is ignore by ctags. Doing:

    • :tsel A or :tsel A<> will show case b only (specializations are ignored).
    • :tsel A<int> or :tsel A<int,double> will show case c only.
  • signature syntax:

    classa {}; // case avoida(); // declaration, case bvoida() {} // definition, case cvoida(int e, int f); // declaration, case d voida(int e, int f) {} // definition, case e 

    Doing:

    • :tsel a will show all cases.
    • :tsel a() will show c, b, e & d. It:
      • ignores non-functions.
      • prioritizes definitions over declarations.
      • prioritizes functions without arguments.
    • :tsel a(int) or :tsel a(int, int) will show e, d because matches the signature.
  • operator syntax:

    structO {
    operatorint() { return0; } // case aoperatorA::cB() { return {}; } // case b
    };
    structP {
    operatorint() { return0; } // case c
    };

    Doing:

    • :tsel operator int will show case a and c
    • :tsel O::operator int will show case a
    • :tsel operator cB will show case b
    • :tsel O::operator cB will show case b
    • :tsel O::operator A::cB will show case b

All the above rules can be combined together, for example in:

namespaceA {
classB {
template<bool> voidm(int) {} // case atemplate<> void m<true>(int) {} // case b
};}

the command:

:tagA::B::m<true>(int)

will match case b which is the result of combining the rules above.

About

Vim plugin that customizes 'tagfunc' for cpp files

Resources

Stars

3 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Latest commit

History

21 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

cpptags

Vim plugin that customizes 'tagfunc' for C++ files.

Index

Motivation

The default builtin 'tagfunc' is not suitable for modern C++, lacks support for: namespaces and classes, function and methods signatures, template parameters and specialization.

The new ctags releases provide support for the above features and more.

This filetype plugin will automatically set up a new 'tagfunc' that will profit from the new ctags fields.

Installation

An obvious precondition is having ctags installed. Is available on the most popular package managers:

  • Ubuntu:
 $ sudo apt install universal-ctags
  • Windows:
> winget install UniversalCtags.Ctags 
  • MacOs:
 $ brew install universal-ctags

This plugin can be installed using any popular plugin manager (vim-plug, Vundle, etc...) but vim plugin integration is extremely easy in later releases (version8.0 introduced package support):

  • A vimball is distributed by www.vim.org. Installation is as easy as sourcing the vimball file:

    :source cpptags.vba

    so is uninstall:

    :RmVimball cpptags.vba
  • The github repo can be cloned direcly into the $VIMRUNTIME/pack directory as explained in matchit-install. Though using this approach many useless files in this repo will be installed too.

  • Use getscript plugin to automatically download an update it. Update the local $VIMRUNTIME/GetLatest/GetLatestVimScripts.dat adding a line associated with this plugin.

Once installed the vim's filetype plugins must be enabled:

:filetypepluginon

is adviceable to introduce this into the .vimrc if not there already.

Usage

For proper operation the plugin requires:

  • set up a tag file suitable for modern C/C++ navigation.
  • learn how to prompt the :tag and :tselect commands.

Required tag generation options

In order to profit from the new ctags output several non-default options must be used:

$ ctags --extras=+f -R --languages=c++ --langmap=c++:+.c. --c++-kinds=+pl --fields=+iaeSK --fields-c++=*
--options=<option-file-path> -f <output-tags-file><source-dirs>

The options file allows simplifying the command line by including there lenghtly parameters. It is usual to include there options devoted to resolve preprocessor macros that ctags cannot understand by itself.

Old C/C++ libraries relied heavily on preprocessor magic and require tedious composition of option files to generate a useful ctags output. For example, the microsoft version of the STL requires the following options:

 -D _STD_BEGIN= namespace std {
-D _STD_END=}
-D _STD= ::std::
-D _CHRONO= ::std::chrono::
-D _RANGES= ::std::ranges::
-D _STDEXT_BEGIN= namespace stdext {
-D _STDEXT_END=}
-D _STDEXT= ::stdext::
-D _CSTD=::
-I _NODISCARD
-I _EXPORT_STD
-I _CRT_GUARDOVERFLOW
-I _Out_writes_all_+
-I _In_reads_+
-I _CONSTEXPR20 -I _CONSTEXPR17
-I __PURE_APPDOMAIN_GLOBAL
-I _CRTDATA2_IMPORT
-I _CRTIMP2_PURE_IMPORT
-I __thiscall
-I _STL_RESTORE_CLANG_WARNINGS
-I _STL_DISABLE_CLANG_WARNINGS

fortunately new C/C++ libraries favor the new template capabilities and discourage preprocessor usage. For example, C++/WinRT projection sources can be parsed completely with only two options:

 -D WINRT_IMPL_AUTO(B)=B
-I WINRT_EXPORT

Once the tag file is generated it must be appended to the 'tags' option which contains patterns to locate tag files. For example if the output file is in ~/mytagfiles/stl.tags we must do:

:settags+=~/mytagfiles/stl.tags

For convenience, this can be included in the source files using a modeline. For example ending the sources with:

/* vim: set tags+=~/mytagfiles/stl.tags: */

New tag syntax

The syntax follows the natural semantics of C++. The basics are simple:

  • namespaces/classes. The use of qualified identifiers restricts the tag choices. For example:

    voidf(); // case anamespaceA {
    voidf(); // case bnamespaceB {
    voidf(); // case c
    }}

    Doing:

    • :tsel f will show all 3 cases (a,b & c).
    • :tsel A::f will show 2 cases (b & c) and prioritize b.
    • :tsel A::B will show only case c.
  • template syntax:

    template <typename A, typename B> classA; // forward declaration, case atemplate <typename A, typename B> classA {}; // declaration, case btemplate <> classA<int, double> {}; // specialization, case c

    Case a is ignore by ctags. Doing:

    • :tsel A or :tsel A<> will show case b only (specializations are ignored).
    • :tsel A<int> or :tsel A<int,double> will show case c only.
  • signature syntax:

    classa {}; // case avoida(); // declaration, case bvoida() {} // definition, case cvoida(int e, int f); // declaration, case d voida(int e, int f) {} // definition, case e 

    Doing:

    • :tsel a will show all cases.
    • :tsel a() will show c, b, e & d. It:
      • ignores non-functions.
      • prioritizes definitions over declarations.
      • prioritizes functions without arguments.
    • :tsel a(int) or :tsel a(int, int) will show e, d because matches the signature.
  • operator syntax:

    structO {
    operatorint() { return0; } // case aoperatorA::cB() { return {}; } // case b
    };
    structP {
    operatorint() { return0; } // case c
    };

    Doing:

    • :tsel operator int will show case a and c
    • :tsel O::operator int will show case a
    • :tsel operator cB will show case b
    • :tsel O::operator cB will show case b
    • :tsel O::operator A::cB will show case b

All the above rules can be combined together, for example in:

namespaceA {
classB {
template<bool> voidm(int) {} // case atemplate<> void m<true>(int) {} // case b
};}

the command:

:tagA::B::m<true>(int)

will match case b which is the result of combining the rules above.

About

Vim plugin that customizes 'tagfunc' for cpp files

Resources

Stars

3 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Latest commit

History

21 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

cpptags

Vim plugin that customizes 'tagfunc' for C++ files.

Index

Motivation

The default builtin 'tagfunc' is not suitable for modern C++, lacks support for: namespaces and classes, function and methods signatures, template parameters and specialization.

The new ctags releases provide support for the above features and more.

This filetype plugin will automatically set up a new 'tagfunc' that will profit from the new ctags fields.

Installation

An obvious precondition is having ctags installed. Is available on the most popular package managers:

  • Ubuntu:
 $ sudo apt install universal-ctags
  • Windows:
> winget install UniversalCtags.Ctags 
  • MacOs:
 $ brew install universal-ctags

This plugin can be installed using any popular plugin manager (vim-plug, Vundle, etc...) but vim plugin integration is extremely easy in later releases (version8.0 introduced package support):

  • A vimball is distributed by www.vim.org. Installation is as easy as sourcing the vimball file:

    :source cpptags.vba

    so is uninstall:

    :RmVimball cpptags.vba
  • The github repo can be cloned direcly into the $VIMRUNTIME/pack directory as explained in matchit-install. Though using this approach many useless files in this repo will be installed too.

  • Use getscript plugin to automatically download an update it. Update the local $VIMRUNTIME/GetLatest/GetLatestVimScripts.dat adding a line associated with this plugin.

Once installed the vim's filetype plugins must be enabled:

:filetypepluginon

is adviceable to introduce this into the .vimrc if not there already.

Usage

For proper operation the plugin requires:

  • set up a tag file suitable for modern C/C++ navigation.
  • learn how to prompt the :tag and :tselect commands.

Required tag generation options

In order to profit from the new ctags output several non-default options must be used:

$ ctags --extras=+f -R --languages=c++ --langmap=c++:+.c. --c++-kinds=+pl --fields=+iaeSK --fields-c++=*
--options=<option-file-path> -f <output-tags-file><source-dirs>

The options file allows simplifying the command line by including there lenghtly parameters. It is usual to include there options devoted to resolve preprocessor macros that ctags cannot understand by itself.

Old C/C++ libraries relied heavily on preprocessor magic and require tedious composition of option files to generate a useful ctags output. For example, the microsoft version of the STL requires the following options:

 -D _STD_BEGIN= namespace std {
-D _STD_END=}
-D _STD= ::std::
-D _CHRONO= ::std::chrono::
-D _RANGES= ::std::ranges::
-D _STDEXT_BEGIN= namespace stdext {
-D _STDEXT_END=}
-D _STDEXT= ::stdext::
-D _CSTD=::
-I _NODISCARD
-I _EXPORT_STD
-I _CRT_GUARDOVERFLOW
-I _Out_writes_all_+
-I _In_reads_+
-I _CONSTEXPR20 -I _CONSTEXPR17
-I __PURE_APPDOMAIN_GLOBAL
-I _CRTDATA2_IMPORT
-I _CRTIMP2_PURE_IMPORT
-I __thiscall
-I _STL_RESTORE_CLANG_WARNINGS
-I _STL_DISABLE_CLANG_WARNINGS

fortunately new C/C++ libraries favor the new template capabilities and discourage preprocessor usage. For example, C++/WinRT projection sources can be parsed completely with only two options:

 -D WINRT_IMPL_AUTO(B)=B
-I WINRT_EXPORT

Once the tag file is generated it must be appended to the 'tags' option which contains patterns to locate tag files. For example if the output file is in ~/mytagfiles/stl.tags we must do:

:settags+=~/mytagfiles/stl.tags

For convenience, this can be included in the source files using a modeline. For example ending the sources with:

/* vim: set tags+=~/mytagfiles/stl.tags: */

New tag syntax

The syntax follows the natural semantics of C++. The basics are simple:

  • namespaces/classes. The use of qualified identifiers restricts the tag choices. For example:

    voidf(); // case anamespaceA {
    voidf(); // case bnamespaceB {
    voidf(); // case c
    }}

    Doing:

    • :tsel f will show all 3 cases (a,b & c).
    • :tsel A::f will show 2 cases (b & c) and prioritize b.
    • :tsel A::B will show only case c.
  • template syntax:

    template <typename A, typename B> classA; // forward declaration, case atemplate <typename A, typename B> classA {}; // declaration, case btemplate <> classA<int, double> {}; // specialization, case c

    Case a is ignore by ctags. Doing:

    • :tsel A or :tsel A<> will show case b only (specializations are ignored).
    • :tsel A<int> or :tsel A<int,double> will show case c only.
  • signature syntax:

    classa {}; // case avoida(); // declaration, case bvoida() {} // definition, case cvoida(int e, int f); // declaration, case d voida(int e, int f) {} // definition, case e 

    Doing:

    • :tsel a will show all cases.
    • :tsel a() will show c, b, e & d. It:
      • ignores non-functions.
      • prioritizes definitions over declarations.
      • prioritizes functions without arguments.
    • :tsel a(int) or :tsel a(int, int) will show e, d because matches the signature.
  • operator syntax:

    structO {
    operatorint() { return0; } // case aoperatorA::cB() { return {}; } // case b
    };
    structP {
    operatorint() { return0; } // case c
    };

    Doing:

    • :tsel operator int will show case a and c
    • :tsel O::operator int will show case a
    • :tsel operator cB will show case b
    • :tsel O::operator cB will show case b
    • :tsel O::operator A::cB will show case b

All the above rules can be combined together, for example in:

namespaceA {
classB {
template<bool> voidm(int) {} // case atemplate<> void m<true>(int) {} // case b
};}

the command:

:tagA::B::m<true>(int)

will match case b which is the result of combining the rules above.

About

Vim plugin that customizes 'tagfunc' for cpp files

Resources

Stars

3 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Latest commit

History

21 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

cpptags

Vim plugin that customizes 'tagfunc' for C++ files.

Index

Motivation

The default builtin 'tagfunc' is not suitable for modern C++, lacks support for: namespaces and classes, function and methods signatures, template parameters and specialization.

The new ctags releases provide support for the above features and more.

This filetype plugin will automatically set up a new 'tagfunc' that will profit from the new ctags fields.

Installation

An obvious precondition is having ctags installed. Is available on the most popular package managers:

  • Ubuntu:
 $ sudo apt install universal-ctags
  • Windows:
> winget install UniversalCtags.Ctags 
  • MacOs:
 $ brew install universal-ctags

This plugin can be installed using any popular plugin manager (vim-plug, Vundle, etc...) but vim plugin integration is extremely easy in later releases (version8.0 introduced package support):

  • A vimball is distributed by www.vim.org. Installation is as easy as sourcing the vimball file:

    :source cpptags.vba

    so is uninstall:

    :RmVimball cpptags.vba
  • The github repo can be cloned direcly into the $VIMRUNTIME/pack directory as explained in matchit-install. Though using this approach many useless files in this repo will be installed too.

  • Use getscript plugin to automatically download an update it. Update the local $VIMRUNTIME/GetLatest/GetLatestVimScripts.dat adding a line associated with this plugin.

Once installed the vim's filetype plugins must be enabled:

:filetypepluginon

is adviceable to introduce this into the .vimrc if not there already.

Usage

For proper operation the plugin requires:

  • set up a tag file suitable for modern C/C++ navigation.
  • learn how to prompt the :tag and :tselect commands.

Required tag generation options

In order to profit from the new ctags output several non-default options must be used:

$ ctags --extras=+f -R --languages=c++ --langmap=c++:+.c. --c++-kinds=+pl --fields=+iaeSK --fields-c++=*
--options=<option-file-path> -f <output-tags-file><source-dirs>

The options file allows simplifying the command line by including there lenghtly parameters. It is usual to include there options devoted to resolve preprocessor macros that ctags cannot understand by itself.

Old C/C++ libraries relied heavily on preprocessor magic and require tedious composition of option files to generate a useful ctags output. For example, the microsoft version of the STL requires the following options:

 -D _STD_BEGIN= namespace std {
-D _STD_END=}
-D _STD= ::std::
-D _CHRONO= ::std::chrono::
-D _RANGES= ::std::ranges::
-D _STDEXT_BEGIN= namespace stdext {
-D _STDEXT_END=}
-D _STDEXT= ::stdext::
-D _CSTD=::
-I _NODISCARD
-I _EXPORT_STD
-I _CRT_GUARDOVERFLOW
-I _Out_writes_all_+
-I _In_reads_+
-I _CONSTEXPR20 -I _CONSTEXPR17
-I __PURE_APPDOMAIN_GLOBAL
-I _CRTDATA2_IMPORT
-I _CRTIMP2_PURE_IMPORT
-I __thiscall
-I _STL_RESTORE_CLANG_WARNINGS
-I _STL_DISABLE_CLANG_WARNINGS

fortunately new C/C++ libraries favor the new template capabilities and discourage preprocessor usage. For example, C++/WinRT projection sources can be parsed completely with only two options:

 -D WINRT_IMPL_AUTO(B)=B
-I WINRT_EXPORT

Once the tag file is generated it must be appended to the 'tags' option which contains patterns to locate tag files. For example if the output file is in ~/mytagfiles/stl.tags we must do:

:settags+=~/mytagfiles/stl.tags

For convenience, this can be included in the source files using a modeline. For example ending the sources with:

/* vim: set tags+=~/mytagfiles/stl.tags: */

New tag syntax

The syntax follows the natural semantics of C++. The basics are simple:

  • namespaces/classes. The use of qualified identifiers restricts the tag choices. For example:

    voidf(); // case anamespaceA {
    voidf(); // case bnamespaceB {
    voidf(); // case c
    }}

    Doing:

    • :tsel f will show all 3 cases (a,b & c).
    • :tsel A::f will show 2 cases (b & c) and prioritize b.
    • :tsel A::B will show only case c.
  • template syntax:

    template <typename A, typename B> classA; // forward declaration, case atemplate <typename A, typename B> classA {}; // declaration, case btemplate <> classA<int, double> {}; // specialization, case c

    Case a is ignore by ctags. Doing:

    • :tsel A or :tsel A<> will show case b only (specializations are ignored).
    • :tsel A<int> or :tsel A<int,double> will show case c only.
  • signature syntax:

    classa {}; // case avoida(); // declaration, case bvoida() {} // definition, case cvoida(int e, int f); // declaration, case d voida(int e, int f) {} // definition, case e 

    Doing:

    • :tsel a will show all cases.
    • :tsel a() will show c, b, e & d. It:
      • ignores non-functions.
      • prioritizes definitions over declarations.
      • prioritizes functions without arguments.
    • :tsel a(int) or :tsel a(int, int) will show e, d because matches the signature.
  • operator syntax:

    structO {
    operatorint() { return0; } // case aoperatorA::cB() { return {}; } // case b
    };
    structP {
    operatorint() { return0; } // case c
    };

    Doing:

    • :tsel operator int will show case a and c
    • :tsel O::operator int will show case a
    • :tsel operator cB will show case b
    • :tsel O::operator cB will show case b
    • :tsel O::operator A::cB will show case b

All the above rules can be combined together, for example in:

namespaceA {
classB {
template<bool> voidm(int) {} // case atemplate<> void m<true>(int) {} // case b
};}

the command:

:tagA::B::m<true>(int)

will match case b which is the result of combining the rules above.

About

Vim plugin that customizes 'tagfunc' for cpp files

Resources

Stars

3 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Latest commit

History

21 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

cpptags

Vim plugin that customizes 'tagfunc' for C++ files.

Index

Motivation

The default builtin 'tagfunc' is not suitable for modern C++, lacks support for: namespaces and classes, function and methods signatures, template parameters and specialization.

The new ctags releases provide support for the above features and more.

This filetype plugin will automatically set up a new 'tagfunc' that will profit from the new ctags fields.

Installation

An obvious precondition is having ctags installed. Is available on the most popular package managers:

  • Ubuntu:
 $ sudo apt install universal-ctags
  • Windows:
> winget install UniversalCtags.Ctags 
  • MacOs:
 $ brew install universal-ctags

This plugin can be installed using any popular plugin manager (vim-plug, Vundle, etc...) but vim plugin integration is extremely easy in later releases (version8.0 introduced package support):

  • A vimball is distributed by www.vim.org. Installation is as easy as sourcing the vimball file:

    :source cpptags.vba

    so is uninstall:

    :RmVimball cpptags.vba
  • The github repo can be cloned direcly into the $VIMRUNTIME/pack directory as explained in matchit-install. Though using this approach many useless files in this repo will be installed too.

  • Use getscript plugin to automatically download an update it. Update the local $VIMRUNTIME/GetLatest/GetLatestVimScripts.dat adding a line associated with this plugin.

Once installed the vim's filetype plugins must be enabled:

:filetypepluginon

is adviceable to introduce this into the .vimrc if not there already.

Usage

For proper operation the plugin requires:

  • set up a tag file suitable for modern C/C++ navigation.
  • learn how to prompt the :tag and :tselect commands.

Required tag generation options

In order to profit from the new ctags output several non-default options must be used:

$ ctags --extras=+f -R --languages=c++ --langmap=c++:+.c. --c++-kinds=+pl --fields=+iaeSK --fields-c++=*
--options=<option-file-path> -f <output-tags-file><source-dirs>

The options file allows simplifying the command line by including there lenghtly parameters. It is usual to include there options devoted to resolve preprocessor macros that ctags cannot understand by itself.

Old C/C++ libraries relied heavily on preprocessor magic and require tedious composition of option files to generate a useful ctags output. For example, the microsoft version of the STL requires the following options:

 -D _STD_BEGIN= namespace std {
-D _STD_END=}
-D _STD= ::std::
-D _CHRONO= ::std::chrono::
-D _RANGES= ::std::ranges::
-D _STDEXT_BEGIN= namespace stdext {
-D _STDEXT_END=}
-D _STDEXT= ::stdext::
-D _CSTD=::
-I _NODISCARD
-I _EXPORT_STD
-I _CRT_GUARDOVERFLOW
-I _Out_writes_all_+
-I _In_reads_+
-I _CONSTEXPR20 -I _CONSTEXPR17
-I __PURE_APPDOMAIN_GLOBAL
-I _CRTDATA2_IMPORT
-I _CRTIMP2_PURE_IMPORT
-I __thiscall
-I _STL_RESTORE_CLANG_WARNINGS
-I _STL_DISABLE_CLANG_WARNINGS

fortunately new C/C++ libraries favor the new template capabilities and discourage preprocessor usage. For example, C++/WinRT projection sources can be parsed completely with only two options:

 -D WINRT_IMPL_AUTO(B)=B
-I WINRT_EXPORT

Once the tag file is generated it must be appended to the 'tags' option which contains patterns to locate tag files. For example if the output file is in ~/mytagfiles/stl.tags we must do:

:settags+=~/mytagfiles/stl.tags

For convenience, this can be included in the source files using a modeline. For example ending the sources with:

/* vim: set tags+=~/mytagfiles/stl.tags: */

New tag syntax

The syntax follows the natural semantics of C++. The basics are simple:

  • namespaces/classes. The use of qualified identifiers restricts the tag choices. For example:

    voidf(); // case anamespaceA {
    voidf(); // case bnamespaceB {
    voidf(); // case c
    }}

    Doing:

    • :tsel f will show all 3 cases (a,b & c).
    • :tsel A::f will show 2 cases (b & c) and prioritize b.
    • :tsel A::B will show only case c.
  • template syntax:

    template <typename A, typename B> classA; // forward declaration, case atemplate <typename A, typename B> classA {}; // declaration, case btemplate <> classA<int, double> {}; // specialization, case c

    Case a is ignore by ctags. Doing:

    • :tsel A or :tsel A<> will show case b only (specializations are ignored).
    • :tsel A<int> or :tsel A<int,double> will show case c only.
  • signature syntax:

    classa {}; // case avoida(); // declaration, case bvoida() {} // definition, case cvoida(int e, int f); // declaration, case d voida(int e, int f) {} // definition, case e 

    Doing:

    • :tsel a will show all cases.
    • :tsel a() will show c, b, e & d. It:
      • ignores non-functions.
      • prioritizes definitions over declarations.
      • prioritizes functions without arguments.
    • :tsel a(int) or :tsel a(int, int) will show e, d because matches the signature.
  • operator syntax:

    structO {
    operatorint() { return0; } // case aoperatorA::cB() { return {}; } // case b
    };
    structP {
    operatorint() { return0; } // case c
    };

    Doing:

    • :tsel operator int will show case a and c
    • :tsel O::operator int will show case a
    • :tsel operator cB will show case b
    • :tsel O::operator cB will show case b
    • :tsel O::operator A::cB will show case b

All the above rules can be combined together, for example in:

namespaceA {
classB {
template<bool> voidm(int) {} // case atemplate<> void m<true>(int) {} // case b
};}

the command:

:tagA::B::m<true>(int)

will match case b which is the result of combining the rules above.

About

Vim plugin that customizes 'tagfunc' for cpp files

Resources

Stars

3 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Latest commit

History

21 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

cpptags

Vim plugin that customizes 'tagfunc' for C++ files.

Index

Motivation

The default builtin 'tagfunc' is not suitable for modern C++, lacks support for: namespaces and classes, function and methods signatures, template parameters and specialization.

The new ctags releases provide support for the above features and more.

This filetype plugin will automatically set up a new 'tagfunc' that will profit from the new ctags fields.

Installation

An obvious precondition is having ctags installed. Is available on the most popular package managers:

  • Ubuntu:
 $ sudo apt install universal-ctags
  • Windows:
> winget install UniversalCtags.Ctags 
  • MacOs:
 $ brew install universal-ctags

This plugin can be installed using any popular plugin manager (vim-plug, Vundle, etc...) but vim plugin integration is extremely easy in later releases (version8.0 introduced package support):

  • A vimball is distributed by www.vim.org. Installation is as easy as sourcing the vimball file:

    :source cpptags.vba

    so is uninstall:

    :RmVimball cpptags.vba
  • The github repo can be cloned direcly into the $VIMRUNTIME/pack directory as explained in matchit-install. Though using this approach many useless files in this repo will be installed too.

  • Use getscript plugin to automatically download an update it. Update the local $VIMRUNTIME/GetLatest/GetLatestVimScripts.dat adding a line associated with this plugin.

Once installed the vim's filetype plugins must be enabled:

:filetypepluginon

is adviceable to introduce this into the .vimrc if not there already.

Usage

For proper operation the plugin requires:

  • set up a tag file suitable for modern C/C++ navigation.
  • learn how to prompt the :tag and :tselect commands.

Required tag generation options

In order to profit from the new ctags output several non-default options must be used:

$ ctags --extras=+f -R --languages=c++ --langmap=c++:+.c. --c++-kinds=+pl --fields=+iaeSK --fields-c++=*
--options=<option-file-path> -f <output-tags-file><source-dirs>

The options file allows simplifying the command line by including there lenghtly parameters. It is usual to include there options devoted to resolve preprocessor macros that ctags cannot understand by itself.

Old C/C++ libraries relied heavily on preprocessor magic and require tedious composition of option files to generate a useful ctags output. For example, the microsoft version of the STL requires the following options:

 -D _STD_BEGIN= namespace std {
-D _STD_END=}
-D _STD= ::std::
-D _CHRONO= ::std::chrono::
-D _RANGES= ::std::ranges::
-D _STDEXT_BEGIN= namespace stdext {
-D _STDEXT_END=}
-D _STDEXT= ::stdext::
-D _CSTD=::
-I _NODISCARD
-I _EXPORT_STD
-I _CRT_GUARDOVERFLOW
-I _Out_writes_all_+
-I _In_reads_+
-I _CONSTEXPR20 -I _CONSTEXPR17
-I __PURE_APPDOMAIN_GLOBAL
-I _CRTDATA2_IMPORT
-I _CRTIMP2_PURE_IMPORT
-I __thiscall
-I _STL_RESTORE_CLANG_WARNINGS
-I _STL_DISABLE_CLANG_WARNINGS

fortunately new C/C++ libraries favor the new template capabilities and discourage preprocessor usage. For example, C++/WinRT projection sources can be parsed completely with only two options:

 -D WINRT_IMPL_AUTO(B)=B
-I WINRT_EXPORT

Once the tag file is generated it must be appended to the 'tags' option which contains patterns to locate tag files. For example if the output file is in ~/mytagfiles/stl.tags we must do:

:settags+=~/mytagfiles/stl.tags

For convenience, this can be included in the source files using a modeline. For example ending the sources with:

/* vim: set tags+=~/mytagfiles/stl.tags: */

New tag syntax

The syntax follows the natural semantics of C++. The basics are simple:

  • namespaces/classes. The use of qualified identifiers restricts the tag choices. For example:

    voidf(); // case anamespaceA {
    voidf(); // case bnamespaceB {
    voidf(); // case c
    }}

    Doing:

    • :tsel f will show all 3 cases (a,b & c).
    • :tsel A::f will show 2 cases (b & c) and prioritize b.
    • :tsel A::B will show only case c.
  • template syntax:

    template <typename A, typename B> classA; // forward declaration, case atemplate <typename A, typename B> classA {}; // declaration, case btemplate <> classA<int, double> {}; // specialization, case c

    Case a is ignore by ctags. Doing:

    • :tsel A or :tsel A<> will show case b only (specializations are ignored).
    • :tsel A<int> or :tsel A<int,double> will show case c only.
  • signature syntax:

    classa {}; // case avoida(); // declaration, case bvoida() {} // definition, case cvoida(int e, int f); // declaration, case d voida(int e, int f) {} // definition, case e 

    Doing:

    • :tsel a will show all cases.
    • :tsel a() will show c, b, e & d. It:
      • ignores non-functions.
      • prioritizes definitions over declarations.
      • prioritizes functions without arguments.
    • :tsel a(int) or :tsel a(int, int) will show e, d because matches the signature.
  • operator syntax:

    structO {
    operatorint() { return0; } // case aoperatorA::cB() { return {}; } // case b
    };
    structP {
    operatorint() { return0; } // case c
    };

    Doing:

    • :tsel operator int will show case a and c
    • :tsel O::operator int will show case a
    • :tsel operator cB will show case b
    • :tsel O::operator cB will show case b
    • :tsel O::operator A::cB will show case b

All the above rules can be combined together, for example in:

namespaceA {
classB {
template<bool> voidm(int) {} // case atemplate<> void m<true>(int) {} // case b
};}

the command:

:tagA::B::m<true>(int)

will match case b which is the result of combining the rules above.

About

Vim plugin that customizes 'tagfunc' for cpp files

Resources

Stars

3 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Latest commit

History

21 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

cpptags

Vim plugin that customizes 'tagfunc' for C++ files.

Index

Motivation

The default builtin 'tagfunc' is not suitable for modern C++, lacks support for: namespaces and classes, function and methods signatures, template parameters and specialization.

The new ctags releases provide support for the above features and more.

This filetype plugin will automatically set up a new 'tagfunc' that will profit from the new ctags fields.

Installation

An obvious precondition is having ctags installed. Is available on the most popular package managers:

  • Ubuntu:
 $ sudo apt install universal-ctags
  • Windows:
> winget install UniversalCtags.Ctags 
  • MacOs:
 $ brew install universal-ctags

This plugin can be installed using any popular plugin manager (vim-plug, Vundle, etc...) but vim plugin integration is extremely easy in later releases (version8.0 introduced package support):

  • A vimball is distributed by www.vim.org. Installation is as easy as sourcing the vimball file:

    :source cpptags.vba

    so is uninstall:

    :RmVimball cpptags.vba
  • The github repo can be cloned direcly into the $VIMRUNTIME/pack directory as explained in matchit-install. Though using this approach many useless files in this repo will be installed too.

  • Use getscript plugin to automatically download an update it. Update the local $VIMRUNTIME/GetLatest/GetLatestVimScripts.dat adding a line associated with this plugin.

Once installed the vim's filetype plugins must be enabled:

:filetypepluginon

is adviceable to introduce this into the .vimrc if not there already.

Usage

For proper operation the plugin requires:

  • set up a tag file suitable for modern C/C++ navigation.
  • learn how to prompt the :tag and :tselect commands.

Required tag generation options

In order to profit from the new ctags output several non-default options must be used:

$ ctags --extras=+f -R --languages=c++ --langmap=c++:+.c. --c++-kinds=+pl --fields=+iaeSK --fields-c++=*
--options=<option-file-path> -f <output-tags-file><source-dirs>

The options file allows simplifying the command line by including there lenghtly parameters. It is usual to include there options devoted to resolve preprocessor macros that ctags cannot understand by itself.

Old C/C++ libraries relied heavily on preprocessor magic and require tedious composition of option files to generate a useful ctags output. For example, the microsoft version of the STL requires the following options:

 -D _STD_BEGIN= namespace std {
-D _STD_END=}
-D _STD= ::std::
-D _CHRONO= ::std::chrono::
-D _RANGES= ::std::ranges::
-D _STDEXT_BEGIN= namespace stdext {
-D _STDEXT_END=}
-D _STDEXT= ::stdext::
-D _CSTD=::
-I _NODISCARD
-I _EXPORT_STD
-I _CRT_GUARDOVERFLOW
-I _Out_writes_all_+
-I _In_reads_+
-I _CONSTEXPR20 -I _CONSTEXPR17
-I __PURE_APPDOMAIN_GLOBAL
-I _CRTDATA2_IMPORT
-I _CRTIMP2_PURE_IMPORT
-I __thiscall
-I _STL_RESTORE_CLANG_WARNINGS
-I _STL_DISABLE_CLANG_WARNINGS

fortunately new C/C++ libraries favor the new template capabilities and discourage preprocessor usage. For example, C++/WinRT projection sources can be parsed completely with only two options:

 -D WINRT_IMPL_AUTO(B)=B
-I WINRT_EXPORT

Once the tag file is generated it must be appended to the 'tags' option which contains patterns to locate tag files. For example if the output file is in ~/mytagfiles/stl.tags we must do:

:settags+=~/mytagfiles/stl.tags

For convenience, this can be included in the source files using a modeline. For example ending the sources with:

/* vim: set tags+=~/mytagfiles/stl.tags: */

New tag syntax

The syntax follows the natural semantics of C++. The basics are simple:

  • namespaces/classes. The use of qualified identifiers restricts the tag choices. For example:

    voidf(); // case anamespaceA {
    voidf(); // case bnamespaceB {
    voidf(); // case c
    }}

    Doing:

    • :tsel f will show all 3 cases (a,b & c).
    • :tsel A::f will show 2 cases (b & c) and prioritize b.
    • :tsel A::B will show only case c.
  • template syntax:

    template <typename A, typename B> classA; // forward declaration, case atemplate <typename A, typename B> classA {}; // declaration, case btemplate <> classA<int, double> {}; // specialization, case c

    Case a is ignore by ctags. Doing:

    • :tsel A or :tsel A<> will show case b only (specializations are ignored).
    • :tsel A<int> or :tsel A<int,double> will show case c only.
  • signature syntax:

    classa {}; // case avoida(); // declaration, case bvoida() {} // definition, case cvoida(int e, int f); // declaration, case d voida(int e, int f) {} // definition, case e 

    Doing:

    • :tsel a will show all cases.
    • :tsel a() will show c, b, e & d. It:
      • ignores non-functions.
      • prioritizes definitions over declarations.
      • prioritizes functions without arguments.
    • :tsel a(int) or :tsel a(int, int) will show e, d because matches the signature.
  • operator syntax:

    structO {
    operatorint() { return0; } // case aoperatorA::cB() { return {}; } // case b
    };
    structP {
    operatorint() { return0; } // case c
    };

    Doing:

    • :tsel operator int will show case a and c
    • :tsel O::operator int will show case a
    • :tsel operator cB will show case b
    • :tsel O::operator cB will show case b
    • :tsel O::operator A::cB will show case b

All the above rules can be combined together, for example in:

namespaceA {
classB {
template<bool> voidm(int) {} // case atemplate<> void m<true>(int) {} // case b
};}

the command:

:tagA::B::m<true>(int)

will match case b which is the result of combining the rules above.

About

Vim plugin that customizes 'tagfunc' for cpp files

Resources

Stars

3 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages