Own simple template system in vim - include file - vim

I've read vim-wiki about dynamic templates and I want similar, simple "template-system". I've created a function:
function! Read_template(file)
execute '0r /home/zsolt/.vim/skeletons/'.a:file
%substitute#\[:EVAL:\]\(.\{-\}\)\[:END:\]#\=eval(submatch(1))#ge
%substitute#\[:READ:\]\(.\{-\}\)\[:END:\]#??????#ge
endfunction
I want to include a file from a template. The EVAL works well but how can I solve the READ function? It isn't important to eval the included file.
An example:
main.tex:
\documentclass[a4paper]{article}
....
exam.tex:
% Created [:EVAL:]strftime('%Y. %B. %d.')[:END:]
[:READ:]/path/of/main/main.tex[:READ:]
I exec Read_template("exam.tex") and want that exam.tex includes main.tex.
How can I do this?

You'll need to read the file and insert its contents. As you cannot use :read (it will read entire lines and cannot be called from within a substitution), you have to use the lower-level readfile() Vimscript function, like this:
%substitute#\[:READ:\]\(.\{-\}\)\[:END:\]#\=join(readfile(submatch(1)),"\n")/#ge

You'll have to parse each line imported and apply what needs be :
- expression substitution
- inclusion of other templates, etc. (which will mean that you'll have to remove and add lines on the fly. In the last version of mu-template template expansion engine, the expansion is done in-memory)
FYI, my work of mu-template already has this feature: http://code.google.com/p/lh-vim/wiki/muTemplate#Completely_useless_recursive_example

Related

How to create a centralized syntax file that be able to recognize multiple parts with different syntaxes?

For i.e: I'd like to have a custom syntax file, may be called sugar.vim that includes multiple other syntax files(?) to have the ability to highlight, maybe a paragraph as python.vim and another paragraph as javascript.vim, may be separated by newline (paragraphs often distinct by newline)
The real case that I often catch myself writing a document (non-extension file) other than real config a specific filetype (specific extension file), but for clear readability in the document filetype (we called sugar above). I'm thinking about a mechanism to recognize and highlight different parts of a filetype as different syntaxes.
To narrow down this case. How would it be to have a syntax file called sugar.vim that would be able to recognize python syntax and javascript syntax in files that have an extension of .sugar then the recognized python text should have highlights applied as a normal python file, same for javascript part. All recognized text must be separated by newline (at least one before and one after that text)
Sample:
# this is a sample text for this question
# i'm writing a document that has an extension of `.sugar`
def py_func1(arg1, arg2) # python.vim and its highlights applied here.
print("bello world!")
square = function(x) { # javascript.vim and its highlights applied here.
return x * x;
};
System: gvim 8.1 / windows10
Thanks in advances.
Vim supports that with the :help :syn-include command. As it's intended for syntax script writers leveraging other syntaxes, its use is somewhat complicated, and it's not really suited for interactive, on-demand use.
My SyntaxRange plugin provides commands and functions to set up regions in the current buffer that either use a syntax different from the buffer's 'filetype', or completely ignore the syntax. With it, it's trivial to dynamically add a particular syntax highlighting for a range of lines, and public API functions also make the programmatic definition easier.
You're looking for :help :syn-include.
Excerpt from vim help :
If top-level syntax items in the included syntax file are to be
contained within a region in the including syntax, you can use the
":syntax include" command:
:sy[ntax] include [#{grouplist-name}] {file-name}
All syntax items declared in the included file will have the
"contained" flag added. In addition, if a group list is specified,
all top-level syntax items in the included file will be added to
that list. >
" In perl.vim:
:syntax include #Pod :p:h/pod.vim
:syntax region perlPOD start="^=head" end="^=cut" contains=#Pod
When {file-name} is an absolute path (starts with "/", "c:", "$VAR"
or "") that file is sourced. When it is a relative path
(e.g., "syntax/pod.vim") the file is searched for in 'runtimepath'.
All matching files are loaded. Using a relative path is
recommended, because it allows a user to replace the included file
with his own version, without replacing the file that does the ":syn
include".
As long as you can clearly define boundaries for your embedded language regions it is fairly straight forward to achieve this.
You can also refer to https://github.com/tpope/vim-markdown/blob/master/syntax/markdown.vim for reference on how tpope embeds other syntax definitions within the markdown syntax, driven by configuration to minimise the number of language syntax's that need embedding for optimal performance.

In Vim how to know if function is defined

I am using Vim editor v7.4 .
I have a huge C Code library , and i make constant changes to it.
Is there a way ( before compilation) to know if a function i am adding to some file is defined for this file.
Thanks
I'm not sure to correctly understand your need. In my definition, when I add a function to a file, I add its definition, so it's defined. But when I'm using a function in a file, I only need its declaration. Then there is also the problem of being sure that a function defined in a translation unit is declared somewhere (privately in the same TU as a static function, or in a header file).
For the latter, I have a solution (that checks functions definitions and declarations are balanced in lh-cpp). For the case of being sure a function is declared in the UT it's used, it won't be that simple: we need to do the preprocessor work (and recursively follow includes) and search whether a function is indeed declared. It's not impossible, but it's best to have vim know the paths where header files are in order to look for them.
Look at a tool like exuberant ctags. It parses C-style files to find any identifier and store them in a tag file, so that each of them can be accessed quickly, inside Vim for example.
Once installed, in the shell command line, you have to create a tag file with this kind of command:
$ ctags *.c *.h
This will create an new file called tags, where all the c files and header files in the current directory are parsed. Please note that there are many options for this tool (like recursively include all lib headers, which can lead to a huge file, though), you may look at the doc for more details.
Once done, in Vim, there are several commands to use transparently the infos in this file. First check your current directory is the same as the tag file; then, to check if an identifier (like a function name) is already present in the tag file, you can use:
:ts myFunctionName
I don't think tag is a good enough solution to check whether function is defined. The flexibility of C syntax make it worse, because most tag tool is syntax-based other than semantics-based.
For example, at present, the most powerful code-completion plug-in for vim is
YouCompleteMe, which is semantic-based by virtue of Clang.
So IMHO, the answer to your question is: compile it!
In order to do compiling more convenience, you can add the following configuration in your .vimrc.
map <F6> :make install<CR>
After this, when you press F6, compiler will be launched to check your code.

<SID> with foldexpr

I am reading Learn Vim Script the Hard Way and hit something that confused me whilst doing the exercise to convert the folding functions to script local ones.
I tried to go this:
setlocal foldexpr=<SID>GetPotionFold(v:lnum)
and renamed all the functions to start with s:
To my surprise this didn't work and every line had a fold level of 0? It works if I put GetPotionFold into the global scope. Do you have to use a globally scoped function when assigning it to a option? Why?
The <SID> can be used in a mapping or menu, unfortunately not in an option. (This is a shortcoming in the implementation.)
You'd either have to translate it into the actual <SNR>NNN_ prefix (there's an s:SID() example function at :help <SID>), or use a different scope that is accessible from outside the script that defines the function. It's commendable that you want to avoid clobbering the global function namespace, as this is prone to name clashes.
A nice trick is using the autoload function prefix; it doesn't just work in autoload scripts, but can also be used elsewhere, e.g. in plugin scripts. Just prepend the script's name, and you'll have a function that can be invoked from anywhere, but scoped to the script's name:
:function! MyScriptName#GetPotionFold(lnum)
...
:setlocal foldexpr=MyScriptName#GetPotionFold(v:lnum)
Adding to the previous answer, you could define the function s:SID() to determine the script number as in the help documentation and then use execute to set the fold expression as following:
exe "setlocal foldexpr=<SNR>" . s:SID() . "_GetPotionFold(v:lnum)"

Apply a set of lines to a template

I want to process a set of lines and apply a template to each line. Let's say I have the following block of lines:
CASE
ESAC
IF
FI
And I would like to get the following output:
<YYINITIAL> {CASE} {
return new Symbol(sym.CASE);
}
...
<YYINITIAL> {FI} {
return new Symbol(sym.FI);
}
So, I thought of having a template with the body to apply for each line, something like this:
<YYINITIAL> {###PLACE_HOLDER###} {
return new Symbol(sym.###PLACE_HOLDER###);
}
And apply it to each line.
What I thought was of selecting the lines, putting then in a register ("a, for instance), then selecting the template putting it in a register ("b) and call an external script that generates the output. However no luck (don't know how to pass the contents of a register to an external script).
Any other approach is welcome.
this command will do that job:
:%s/.*/<YYINITIAL> {&} {\r\treturn new Symbol(sym.&);\r}/
you could remove the %, if you visual selected lines. Also you could create a mapping or user command for it, if it is used often.
Your suggested approach seems overly complex, especially because you still have to implement the template expansion logic as the external script.
Why don't you simply define your templates as :substitute commands?! You can pattern-match your PLACEHOLDER via /\({pattern}\)/ and insert it in the replacement text as \1, \2, etc. (I hope you know about the power of Vim's :substitute command; otherwise, read :help :s.
You can keep and persist your templates in several ways, depending on how often / long you need them:
Just in the command-line history (:s<Up>)
Save in named registers (:let #a = #:), execute with :#a
Save in a Vim script and :source it
Write a custom plugin with :commands

How do I actually use the value of an argument to a Vim function?

I'm trying to write a simple Vim function that takes the name of a file as an argument and reads the contents of that file into the current document (related to this question).
Here's my first stab at it:
fun! Tpl(tplfile)
r c:\tpl\a:tplfile
endfun
That just gives me the following error:
E484: Can't open file c:\tpl\a:tplfile
How do I make the function actually use the value of the tplfile argument?
Replace the line with:
exe 'r c:\tpl\' . a:tplfile
The a:tplfile is a string variable, so to include it in a command, you have to combine the whole lot into one string (with the '.' operator) and then use exe to run the command
:help exe
On a related note (and a shameless plug), if you're trying to add templates (as implied by the post you linked to), my file templates plugin has a command AddTemplate to add a template from your vimfiles/templates directory at the current cursor location. However, the documentation is currently rather poor, so if you decide to use it and have any difficulties, feel free to drop me an email at the address on my website.

Resources