Vim Create File(s) Using Template(s) - vim

I'm tending to rely on vim more than a full IDE for working on projects, and one of the things I find myself doing on a regular basis is creating a new file(s) with derived values.
For example, creating a new c++ class involves creating a .hpp file and a .cpp file, adding file comments, the license, the author, ctor/dtor, copy, assign, move, etc...
.hpp
class %Object% {
public:
explicit %Object%() = default;
~%Object%() = default;
%Object%(%Object%&& rhs) = default;
%Object%(const %Object%& rhs) = default;
%Object%& operator=(%Object%&& rhs) = default;
%Object%& operator=(const %Object%& rhs) = default;
protected:
private:
}
.cpp
#include "%Object%.hpp"
Another example would be a .h and a .c file in c.
I'm a little familiar with UltiSnips and muTemplate, which both seem to cut down on boilerplate a lot. However, I'm not clear if there's a way to use these, or something else, outside of a file scope. I wrote a really quick and dirty set of bash scripts to do it, and I'm getting ready to re-implement it in python, but I'd rather use an existing plugin.
Is there a way to do this with UltiSnips, muTemplate, or something else? If not, is there a good way to extend an existing plugin?

Discl. I'm the maintainer of mu-template and lh-cpp. Unfortunately I'm just seeing your question now -- I would say that you shouldn't have hesitated to drop me an email/an issue/... I'm not sure the question is still opened. I'm not even sure to have exactly grasped what you were looking for.
Since the version you've experimented with, I've added many templates/snippets/wizards in lh-cpp to generate classes according to their semantics. You can now either:
expand things like value-class, base-class, etc
or call a function to expand the same wizard/snippet/template and give it parameters. For instance, expanding a value class with a pointer-like parameter will trigger the generation of the copy constructor and assignment operator (otherwise, they would be defaulted, explicitly or implicitly depending on options and on the C++ flavour detected (C++98/03, C++11 or more -- rule of all or nothing still has to be enforced). Alas this approach is not very ergonomic at the moment. I have to find a way to simplify this task. You can find example of use in the test/spec directory of lh-cpp.
Note that the c++ template for C++ files are also highly customizable -- on a per project basis. Usual licence texts are ready to include. A new C++ file knows how to include its associated header file (if detected).

Add this to one of your start up file:
" Function to substitute the class names in a file
function! SubstituteClassName()
execute "1,$s/%Object%/" . expand("%:t:r") . "/g"
endfunction
" Function to create the skeleton of a header file
function! CreateHeaderFile()
1
insert
#pragma once
#ifndef %Object%_H
#define %Object%_H
class %Object% {
public:
explicit %Object%() = default;
~%Object%() = default;
%Object%(%Object%&& rhs) = default;
%Object%(const %Object%& rhs) = default;
%Object%& operator=(%Object%&& rhs) = default;
%Object%& operator=(const %Object%& rhs) = default;
protected:
private:
}
.
call SubstituteClassName()
endfunction
" Function to create the skeleton of a source file
function! CreateSourceFile()
1
insert
#include "%Object%.hpp"
.
call SubstituteClassName()
endfunction
function! CreateClassFiles(name)
" Open the header file.
execute "edit " . a:name . ".hpp"
" Create the skeleton of the header file
call CreateHeaderFile()
" Write the file
wa
" Open the source file.
execute "edit " . a:name . ".cpp"
" Create the skeleton of the header file
call CreateSourceFile()
" Write the file
wa
endfunction
Now you can create the skeleton .hpp and .cpp files using
call CreateClassFiles("myclassname")

Related

How do I apply syntax highlighting to a string literal in Code Mirror?

I'm writing a python library that operates on C++ code stored in string literals. The normal use case is to create a code object like so:
code(r"""
void* foo() {
return NULL;
}
""")
The library is meant to work in Jupyter Lab which uses Code Mirror for syntax highlighting/editing, so I'd like to extend Code Mirror to identify calls to code() and apply C++ syntax highlighting to its argument, so it'd look something like this:
code(r""" # python highlighting
void* foo() { // C++ higlighting
return NULL;
}
""")
I know how to do something similar in Pygments, but I'm not sure where to get started with Code Mirror.

Vim Quickfix prefixes double-bar "||" — explain?

I use the Quickfix view in Vim often.
The text in there always has a prefix of || added to it.
So, for instance, when I copy/paste out of that buffer, etc. I get those characters included by default.
Is there a way to disable this?
I haven't had luck finding any documentation or configuration for this...
Quickfix buffer is supposed to be used for parsing specially formatted strings (like compiler messages). This is done with the help of :h 'errorformat' option. And those "bars" are output separators between "filename", "line number" and "the message body".
If you have only "double bars" at the beginning of a line then you either have errorformat set wrong, or you misuse the quickfix buffer.
UPD. If you're interested, "Bars" are hardcoded in Vim's source (src/quickfix.c):
static int
qf_buf_add_line(buf_T *buf, linenr_T lnum, qfline_T *qfp, char_u *dirname)
{
...
if (qfp->qf_module != NULL)
...
if (len < IOSIZE - 1)
IObuff[len++] = '|';
if (qfp->qf_lnum > 0)
...
if (len < IOSIZE - 2)
{
IObuff[len++] = '|';
IObuff[len++] = ' ';
}
...
}
It is now possible to customize the display of the quickfix window.
vim has introduced the quickfixtextfunc (:h qftf).
It allows exactly to customize the rendering of the quickfix window. The documentation includes an example, you can also see an example in the nvim-bqf README, although it's neovim/lua based.
You can see an example in the vim documentation in :h quickfix-window-function.
To implement a general-purpose qftf (not a specific one as in the vim documentation), you should start similarly than in the nvim-bqf readme, meaning, check if the info parameter quickfix field is 1, you should display items from getqflist, otherwise items from getloclist

Vim cindent after scope declartion not working

I would like to indent my C++ code to have 1 shiftwidth after the scope specifier (private, public, protected) like the following code (assuming shiftwidth=3)
class blah
{
public:
blah();
private:
m_bl;
};
I'm currently using set cino=g0,h1.
However, vim always indents the lines after scope specifier to be as if gs was used, i.e, vim always adds 6 spaces instead of 3. The result looks like below:
class blah
{
public:
blah();
private:
m_b1;
};
I have tried several different options like:
set cino=g0,h0
set cino=g0,h-1
set cino=g0,h0.5s
None of them seem to be working. Vim always indents by 6 spaces (shiftwidth=3).
How do I achieve the indent results to get 1 shiftwidth after scope specifier?
I'm using Vim version 8.0.69 if that helps.

Vim - Overwrite Plugin Scoped Function

I've a plugin in Vim and I don't like the behavior of a single function within it. But it isn't rly a case to open a pull request, but more an extension for it.
I know that overwriting a function ist possible by using a bang as postfix, as soon as the new definition comes after the previous one. But how can I do such thing, if this method is scoped to a script within a plugin?
I wasn't able to find a hint in _Vim_s help, nor by request a search engine. Anybody aware of this topic, at least if he can say that it is simply not possible.
A short example:
plugin/autoload/plugin.vim
...
function! s:foo() {
// behavior I would like to adjust
}
...
~/.vimrc
function! foo() {
// the "correct" behavior
}
Thanks for any help!
Actually it is possible. But as #romainl said, you'd better suggest your patch to the plugin maintainer or ask for a variation point.
Regarding the how.
First, you'll need to identify the script number of this autoload plugin. Let's say that :scriptname says it's 210. In order to do that automatically I have a lh#askvim#scriptid() function in my library plugin that does the job -- see the current definition at the end of the answer.
Then, to override the s:foo() function, you'll need to provide a new definition for
function! <SNR>210_Foo()
new definition
endfunction
(I've just tested it with vim 8.0-1157)
IOW, we can override a script-local function. However, I haven't found how to override a script-local variable directly without a reference to its s: dictionary. We could inject setter/getter functions to a specific variable or a function that returns the local s: dictionary.
lh#askvim#scriptid() current definition is the following
" Function: lh#askvim#execute(command) {{{3
" #since Version 4.0.0
if exists('*execute')
function! lh#askvim#execute(command) abort
return split(execute(a:command), "\n")
endfunction
else
function! lh#askvim#execute(command) abort
return s:beware_running_through_client_server ? [] : split(lh#askvim#exe(a:command), "\n")
endfunction
endif
" Function: lh#askvim#scriptnames() {{{3
function! lh#askvim#scriptnames() abort
let scripts = lh#askvim#execute('scriptnames')
let s:scripts = map(copy(scripts), 'split(v:val, "\\v:=\\s+")')
call lh#list#map_on(s:scripts, 1, 'fnamemodify(v:val, ":p")')
return s:scripts
endfunction
" Function: lh#askvim#scriptid(name) {{{3
function! lh#askvim#scriptid(name, ...) abort
let last_change = get(a:, 1, 0)
if last_change || !exists('s:scripts')
call lh#askvim#scriptnames()
endif
let matches = filter(copy(s:scripts), 'v:val[1] =~ a:name')
if len(matches) > 1
throw "Too many scripts match `".a:name."`: ".string(matches)
elseif empty(matches)
if last_change
throw "No script match `".a:name."`"
else
return lh#askvim#scriptid(a:name, 1)
endif
endif
return matches[0][0]
endfunction
That is not possible.
s:foo() is scoped to the script it belongs to (see :help s:) so it can't be accessed from anywhere else.
Fork it.
Make the desired changes to your fork.
Use your fork instead of the original.
Consider submitting a pull request.

Testing vim plugin private functions

I'm creating a vim plugin which has a couple of private functions and I'm trying to add unitary testing to it using vim-vspec.
What is the best way to invoke these private functions in the test file?
For now, I created a public function that invokes the private one, but I don't think that's a good approach because I'm loosing the point of having a private function. Here's some of the code
" File foo.vim (the plugin)
" Private function
fu! s:foo(arg)
...
endfu
" Public function
fu! InvokeFoo(arg)
call <SID>foo(a:arg)
endfu
" File foo-unittest.vim (the test file)
runtime! plugin/foo.vim
describe 'foo function'
it 'should have some behavior'
call InvokeFoo(...)
" Some expectations ...
end
end
I tried creating maps to the private functions but when I call exe map_combination it doesn't have any effect on the testing buffer.
I found a solution to my question here, and it gives one approach for variables and another for functions.
Variables
For the variables, I used vim's scopes. Calling :help internal-variables:
The scope name by itself can be used as a Dictionary. For example, to
delete all script-local variables:
:for k in keys(s:)
: unlet s:[k]
:endfor
So I access the :s scope by making a getter function to its dictionary:
fun! SScope()
return s:
endfu
And finally an variable s:variable will be accessed by:
let l:scope = SScope()
echom l:scope['variable']
Functions
The functions are a bit more complicated due the <SID> string. If you read the manual you'll get
When executing the map command, Vim will replace <SID> with the
special key code , followed
by a number that's unique for the script, and an underscore. Example:
:map <SID>Add could define a mapping "23_Add".
So, we need to access this unique number and one way to do it is to define a map that will serve as an accesor using maparg inside a function:
fu! SID()
return maparg('<SID>', 'n')
endfu
nnoremap <SID> <SID>
Then, to call the function we will make a little hack:
call call(substitute('s:my_function', '^s:', SID(), ''), [arg1, arg2, ...])

Resources