GitLab Commit is coming up on August 3-4. Learn how to innovate together using GitLab, the DevOps platform. Register for free: gitlabcommitvirtual2021.com

Commit a9367337 authored by HiPhish's avatar HiPhish
Browse files

Initial commit

parents
# Tags are generated by Vim automatically
doc/tags
###########################
Contributing to jinja.vim
###########################
.. default-role:: code
The main repository is on GitLab_, there is a mirror on GitHub_.
Bug reports
Bugs can be submitted to either GitLab or GitHub, but GitLab is preferred.
Make sure you describe how to reproduce the issue, ideally you should
provide a minimum example that reproduces the issue.
Merge requests
Please submit merge request (pull request) to GitLab only. If you are fixing
a bug go ahead and make your submissions, but if you intend a new feature
please file an issue first so we can discuss it.
See also the `HACKING` file for finding your way around the code.
.. _GitLab: https://gitlab.com/HiPhish/jinja.vim/
.. _GitHub: https://github.com/HiPhish/jinja.vim/
.. default-role:: code
######################
Working on jinja.vim
######################
This document is intended for those who want to work on jinja.vim, improve it,
fix bugs, or add new features.
Overview of the plugin design
#############################
Jinja.vim is intentionally a very minimal plugin. It provides the basics of
file type support of Jinja files: syntax highlighting and file type detection.
This does not mean that we cannot add more features, but the goal is to make
Jinja a first-class citizen to Vim, not to provide a Jinja IDE.
About Jinja
===========
Jinja is a template engine: you write your files in a format of you choice
(e.g. HTML) with pieces of Jinja syntax added in. Then you invoke the Jinja API
from within your Python program. Here is what a piece of Jinja code in HTML
looks like:
.. code-block:: jinja
{% extends "layout.html" %}
{% block body %}
<ul>
{% for user in users %}
<li><a href="{{ user.url }}">{{ user.username }}</a></li>
{% endfor %}
</ul>
{% endblock %}
Despite HTML being the format most often used, Jinja can be used with any
language, such as XML or TeX. Therefore it is important to *not* limit
jinja.vim to HTML only.
Components of jinja.vim
#######################
This is an overview of the problems jinja.vim solves and the files relevant to
the task.
Syntax highlighting
The code is entirely contained in `syntax/jinja.vim`, it's exactly what you
would expect.
File type detection
Detection of pure Jinja files is handled in `ftdetect/jinja.vim`. Detecting
the presence of Jinja code in a file from different file type (e.g. HTML) is
handled by `autoload/jinja.vim` and the function `jinja#DetectJinja`.
File type adjustment
The file type can be automatically adjusted by calling the function
`jinja#AdjustFiletype` from the file `autoload/jinja.vim`. It will check the
first few lines for the presence of Jinja and if necessary attach `.jinja`
to the file type.
We do not automatically adjust the file type. Instead the user should set up
the automatic calling of the function if they want to.
Testing
#######
The testing framework is vader.vim_; execute `:Vader test/*.vader` to run all
tests. These are are test suites:
ft-detection
Test for the correct detection of Jinja code and file type adjustment.
syntax
Test the syntax elements of a sample Jinja file.
.. _vader.vim: https://github.com/junegunn/vader.vim
The MIT License (MIT)
Copyright (c) 2016 Alejandro "HiPhish" Sanchez
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
===============================================================================
The above license applies to all parts of jinja.vim except for the following
files:
- 'syntax/jinja.vim': Syntax file from the Jinja project, 3-clause BSD
license, has been modified.
====[ License for 'syntax/jinja.vim' ]
Copyright (c) 2009 by the Jinja Team, see AUTHORS for more details.
Some rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials provided
with the distribution.
* The names of the contributors may not be used to endorse or
promote products derived from this software without specific
prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.. default-role:: code
Jinja syntax and file type detection for Vim
############################################
This plugin adds support for the Jinja_ template engine to Vim the Right Way™
by making use of Vim's dotted filetype syntax. This makes the plugin smaller
and simpler to maintain, while at the same time being more flexible by letting
Vim combine support for any host language (such as HTML) rather than pulling it
in through some hacky means.
There are a number of Jinja plugins out there, including an official one, but
they all force the file type to `jinja` and then pull in the HTML settings. By
making use of the dotted file type syntax we are not limited to HTML alone, we
can support any other host file type as well at no extra cost. To quote the
Jinja documentation:
A Jinja template is simply a text file. Jinja can generate any text-based
format (HTML, XML, CSV, LaTeX, etc.). A Jinja template doesn’t need to have
a specific extension: `.html`, `.xml`, or any other extension is just fine.
.. _Jinja: http://jinja.pocoo.org/
Installation
============
Use your preferred method of installing Vim plugins, manually or via package
manager. There is nothing out of the ordinary here.
Configuration
=============
Since this is just a syntax and filetype-detection plugin there is nothing to
configure, once a file has been identified as a Jinja file it will be
highlighted appropriately. Any file with the extension `.jinja` will be
recognised as a Jinja file.
On the other hand, if you want to use Jinja highlighting in other file types
like HTML you will have to set it up appropriately. For HTML support add the
following line to your `ftdetect/html.vim` file inside the `~/.vim/` (Vim) or
`$XDG_CONFIG_HOME/nvim/` (Neovim) directory:
.. code-block:: vim
autocmd! BufRead,BufNewFile *.html call jinja#AdjustFiletype()
The function `AdjustFiletype` is explained below.
The `AdjustFiletype` funtion
----------------------------
`AdjustFiletype` is a function provided by the plugin as a convenient way of
detecting the presence of Jinja code in a buffer and changing the file type if
necessary by appending `.jinja` to it.
Bugs and Caveats
================
Even though the dotted file type notation is the Right Way not all Vim plugins
are respecting it. If that is the case please bring the issue to the plugin
authors' attention; fixing the issue once in that plugin will forever benefit
everyone while applying a hack to my plugin is just shoving the problem under
the rug for the time being.
Another issue is detection of files with compound names, such as `.html.jina`;
I don't know how to handle them and the resulting file type will be just plain
`jinja`. Help would be greatly appreciated.
License
#######
Jinja.vim is licensed under the MIT license, except for files where otherwise
noted. The syntax file has been adapted from the official Jinja syntax file for
Vim, with all the superfluous content stripped away. The original was written
by Armin Ronacher.
https://github.com/pallets/jinja
The MIT License (MIT)
=====================
Copyright (c) 2016 Alejandro "HiPhish" Sanchez
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
" Author: Alejandro "HiPhish" Sanchez
" License: The MIT License {{{
" Copyright © 2016 Alejandro "HiPhish" Sanchez
"
" Permission is hereby granted, free of charge, to any person obtaining
" a copy of this software and associated documentation files (the "Software"),
" to deal in the Software without restriction, including without limitation
" the rights to use, copy, modify, merge, publish, distribute, sublicense,
" and/or sell copies of the Software, and to permit persons to whom the
" Software is furnished to do so, subject to the following conditions:
"
" The above copyright notice and this permission notice shall be included
" in all copies or substantial portions of the Software.
"
" THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
" EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
" OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
" IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
" DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
" TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
" OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
" }}}
" Try to detect Jinja code inside a buffer file, the function returns true if
" Jinja has been detected, false otherwise.
"
" parameter first: First line to check for the presence of Jija code.
" parameter last: Last line to check for the presence of Jija code.
"
" The parameters will get adjusted to account for files which are too small.
" This is because the function might get called by scripts that just assume a
" certain minimal length.
function! jinja#DetectJinja(first, last)
" How many lines to count, range takes precedence over default values
let l:first = min([a:first, line('$')])
let l:last = min([a:last, line('$')])
" The pattern of a Jinja instruction: either an expression {{...}}, a
" comment {#..#}, a statement {%...%}, or a line statement #..., or a line
" comment
let l:jinja_pattern = '\v\{\{.*\}\}|' .
\'\{\#.*\#\}|' .
\'\{\%\-?\s*(end.+|extends|block|macro|set|if|for|include|trans)>|' .
\'^\#\s*(extends|block|macro|set|if|for|include|trans)>|' .
\'^\#\#.+'
" Probe a number of lines for Jinja code, give up if none is found.
for l in range(l:first, l:last)
if getline(l) =~? l:jinja_pattern
return l
endif
endfor
endfun
" Appends '.jinja' to the 'filetype' option if Jinja code has been detected in
" the buffer.
function! jinja#AdjustFiletype()
if &filetype =~? 'jinja'
return
endif
" I picked the first five lines as an arbitrary count, we can increase the
" number if necessary.
if jinja#DetectJinja(1,5)
execute 'set filetype+=.jinja'
endif
endfun
*jinja.txt* filetype detection and syntax support
_ _ _ _ ~
(_|_)_ __ (_) __ ___ _(_)_ __ ___ ~
| | | '_ \ | |/ _` \ \ / / | '_ ` _ \ ~
| | | | | || | (_| |\ V /| | | | | | |~
_/ |_|_| |_|/ |\__,_(_)_/ |_|_| |_| |_|~
|__/ |__/ ~
Version: 1.0.0
Author: Alejandro "HiPhish" Sanchez
License: MIT License
==============================================================================
TABLE OF CONTENTS *jinja-contents*
1. Introduction .................................... |jinja-introduction|
2. Basic configuration ............................. |jinja-configuration|
3. Functions ....................................... |jinja-functions|
==============================================================================
INTRODUCTION *jinja-introduction*
*jinja.vim* provides support for Jinja 3 syntax highlighting and file type
detection in Vim using Vim's dotted filetype syntax. This allows you to use
Jinja with any other language you want, not just HTML alone.
File type detection will scan your file for lines resembling Jinja syntax and
can adjust the |'filetype'| option appropriately.
==============================================================================
CONFIGURATION *jinja-configuration*
Jinja.vim works out of the box, but if you want Vim to automatically detect
the presence of Jinja code in your files you will have to perform some basic
setup.
You can use the function |jinja#AdjustFiletype| to append 'jinja' to your
existing |'filetype'| option if Jinja code has been detected. A good way to
automate the process is to write to following line of code in the appropriate
file:
>
" For example ftdetect/html.vim
au! BufRead,BufNewFile *.html set ft=html | call jinja#AdjustFiletype()
<
==============================================================================
FUNCTIONS *jinja-functions*
jinja#AdjustFiletype() *jinja#AdjustFiletype*
Attempt detecting Jinja code in the current buffer, and if Jinja code was
detected the string '.jinja' will be appended to the |'filetype'| option
of the buffer.
This function is just a convenience wrapper for |jinja#DetectJinja| that
checks only the first five lines; use that function if you need more
control.
jinja#DetectJinja(first, last) *jinja#DetectJinja*
Detect Jinja code in the current buffer from 'first' to 'last' line. If
code was found the number of the first line containing that code will be
returned, otherwise 0 is returned.
This function might detect a false-positive if the buffer contains a line
that has Jinja code in it, but is not a Jinja file (e.g. a cheat sheet).
If that is a possibility you will have to use the returned line number to
do further filtering.
==============================================================================
vim:tw=78:ts=8:ft=help:norl:
" Author: Alejandro "HiPhish" Sanchez
" License: The MIT License {{{
" Copyright © 2016 Alejandro "HiPhish" Sanchez
"
" Permission is hereby granted, free of charge, to any person obtaining
" a copy of this software and associated documentation files (the "Software"),
" to deal in the Software without restriction, including without limitation
" the rights to use, copy, modify, merge, publish, distribute, sublicense,
" and/or sell copies of the Software, and to permit persons to whom the
" Software is furnished to do so, subject to the following conditions:
"
" The above copyright notice and this permission notice shall be included
" in all copies or substantial portions of the Software.
"
" THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
" EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
" OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
" IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
" DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
" TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
" OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
" }}}
" This is flawed: if the file name is 'foo.jinja' it will work fine, but if
" the file name is 'foo.html.jinja' we would want the file type to be
" 'html.jinja' instead of just 'jinja'. However, we cannot simply take
" everything after the first dot as the file type because something like
" `main.macros.html.jinja` would get the wrong file type as well.
autocmd! BufRead,BufNewFile *.jinja setfiletype jinja
" Oringinal author: Armin Ronacher <armin.ronacher@active-4.com>
" Modified by: Alejandro "HiPhish" Sanchez
" See the LICENSE file for copyright information
syntax case match
if exists("b:current_syntax") && b:current_syntax =~ 'jinja'
finish
endif
" Jinja template built-in tags and parameters (without filter, macro, is and raw, they
" have special threatment)
syn keyword jinjaStatement containedin=jinjaVarBlock,jinjaTagBlock,jinjaNested contained and if else in not or recursive as import
syn keyword jinjaStatement containedin=jinjaVarBlock,jinjaTagBlock,jinjaNested contained is filter skipwhite nextgroup=jinjaFilter
syn keyword jinjaStatement containedin=jinjaTagBlock contained macro skipwhite nextgroup=jinjaFunction
syn keyword jinjaStatement containedin=jinjaTagBlock contained block skipwhite nextgroup=jinjaBlockName
" Variable Names
syn match jinjaVariable containedin=jinjaVarBlock,jinjaTagBlock,jinjaNested contained /[a-zA-Z_][a-zA-Z0-9_]*/
syn keyword jinjaSpecial containedin=jinjaVarBlock,jinjaTagBlock,jinjaNested contained false true none False True None loop super caller varargs kwargs
" Filters
syn match jinjaOperator "|" containedin=jinjaVarBlock,jinjaTagBlock,jinjaNested contained skipwhite nextgroup=jinjaFilter
syn match jinjaFilter contained /[a-zA-Z_][a-zA-Z0-9_]*/
syn match jinjaFunction contained /[a-zA-Z_][a-zA-Z0-9_]*/
syn match jinjaBlockName contained /[a-zA-Z_][a-zA-Z0-9_]*/
" Jinja template constants
syn region jinjaString containedin=jinjaVarBlock,jinjaTagBlock,jinjaNested contained start=/"/ skip=/\(\\\)\@<!\(\(\\\\\)\@>\)*\\"/ end=/"/
syn region jinjaString containedin=jinjaVarBlock,jinjaTagBlock,jinjaNested contained start=/'/ skip=/\(\\\)\@<!\(\(\\\\\)\@>\)*\\'/ end=/'/
syn match jinjaNumber containedin=jinjaVarBlock,jinjaTagBlock,jinjaNested contained /[0-9]\+\(\.[0-9]\+\)\?/
" Operators
syn match jinjaOperator containedin=jinjaVarBlock,jinjaTagBlock,jinjaNested contained /[+\-*\/<>=!,:]/
syn match jinjaPunctuation containedin=jinjaVarBlock,jinjaTagBlock,jinjaNested contained /[()\[\]]/
syn match jinjaOperator containedin=jinjaVarBlock,jinjaTagBlock,jinjaNested contained /\./ nextgroup=jinjaAttribute
syn match jinjaAttribute contained /[a-zA-Z_][a-zA-Z0-9_]*/
" Jinja template tag and variable blocks
syn region jinjaNested matchgroup=jinjaOperator start="(" end=")" transparent display containedin=jinjaVarBlock,jinjaTagBlock,jinjaNested contained
syn region jinjaNested matchgroup=jinjaOperator start="\[" end="\]" transparent display containedin=jinjaVarBlock,jinjaTagBlock,jinjaNested contained
syn region jinjaNested matchgroup=jinjaOperator start="{" end="}" transparent display containedin=jinjaVarBlock,jinjaTagBlock,jinjaNested contained
syn region jinjaTagBlock matchgroup=jinjaTagDelim start=/{%-\?/ end=/-\?%}/ containedin=ALLBUT,jinjaTagBlock,jinjaVarBlock,jinjaRaw,jinjaString,jinjaNested,jinjaComment
syn region jinjaVarBlock matchgroup=jinjaVarDelim start=/{{-\?/ end=/-\?}}/ containedin=ALLBUT,jinjaTagBlock,jinjaVarBlock,jinjaRaw,jinjaString,jinjaNested,jinjaComment
" Jinja template 'raw' tag
syn region jinjaRaw matchgroup=jinjaRawDelim start="{%\s*raw\s*%}" end="{%\s*endraw\s*%}" containedin=ALLBUT,jinjaTagBlock,jinjaVarBlock,jinjaString,jinjaComment
" Jinja comments
syn region jinjaComment matchgroup=jinjaCommentDelim start="{#" end="#}" containedin=ALLBUT,jinjaTagBlock,jinjaVarBlock,jinjaString
" Block start keywords. A bit tricker. We only highlight at the start of a
" tag block and only if the name is not followed by a comma or equals sign
" which usually means that we have to deal with an assignment.
syn match jinjaStatement containedin=jinjaTagBlock contained /\({%-\?\s*\)\@<=\<[a-zA-Z_][a-zA-Z0-9_]*\>\(\s*[,=]\)\@!/
" and context modifiers
syn match jinjaStatement containedin=jinjaTagBlock contained /\<with\(out\)\?\s\+context\>/
command -nargs=+ HiLink hi def link <args>
HiLink jinjaPunctuation jinjaOperator
HiLink jinjaAttribute jinjaVariable
HiLink jinjaFunction jinjaFilter
HiLink jinjaTagDelim jinjaTagBlock
HiLink jinjaVarDelim jinjaVarBlock
HiLink jinjaCommentDelim jinjaComment
HiLink jinjaRawDelim jinja
HiLink jinjaSpecial Special
HiLink jinjaOperator Normal
HiLink jinjaRaw Normal
HiLink jinjaTagBlock PreProc
HiLink jinjaVarBlock PreProc
HiLink jinjaStatement Statement
HiLink jinjaFilter Function
HiLink jinjaBlockName Function
HiLink jinjaVariable Identifier
HiLink jinjaString Constant
HiLink jinjaNumber Constant
HiLink jinjaComment Comment
delcommand HiLink
let b:current_syntax = "jinja"
##############################################################
# Test detection of various Jinja elements in a non-jinja file
##############################################################
Given jinja (A comment):
{# A jinja comment #}
Execute:
Assert jinja#DetectJinja(1, 1)
Given jinja (A statement):
{% for item in items %}
Execute:
Assert jinja#DetectJinja(1, 1)
Given jinja (An expression):
{{ item }}
Execute:
Assert jinja#DetectJinja(1, 1)
Given jinja (A line-comment):
## A jinja comment
Execute:
Assert jinja#DetectJinja(1, 1)
Given jinja (A line statement):
# for item in items
Execute:
Assert jinja#DetectJinja(1, 1)
# We should test for more types of jinja elements
Given html (Try detecting auto-adjusting file type):
{# A jinja comment #}
<html>
<head>
<title>Sample HTML file</title>
</head>
<body>
<p>Hello world.</p>
</body>
</html>
Execute:
call jinja#AdjustFiletype()
Then:
AssertEqual 'html.jinja', &filetype
# ##########################################
# Syntax detection of various Jinja elements
# ##########################################
Given jinja (Sample of Jinja syntax):
{# This should be highlighted like a comment #}
{# Variables #}
{{ variable }}
{{ variable | with | filter }}
{{ filtering | with(arg, args) }}
{# Statements #}
{% jinja_statement %}
{% statement with arguments %}
{% function_call() %}
{# Control of command #}
{% if foo or bar %}
{% else if baz %}
{% endif %}
{% for foo in foos %}
{% endfor %}