Extendable skeletons for Vim using Python, Click and Jinja2

## Problem statement
As a member of the software team at *Datawise, Inc.*, I want my part of code to be identifiable. Not just due to vanity, but also
in order to be able to clearly identify the responsible when some part of our system fails.

For a long time, I believed that `git` is a perfect solution to this problem, as while being almost seemless, it allows one to track the authorship line-wise, which
is more than enough.

However, something happened recently, which made rethinking this belief. My coworker moved the folder containing my part of code during some routine refactoring.
As a result, git changed the authorship of every single line of my code, so my coworker became the "author".

I decided that while `git` is good most of the time, it would not be bad to supplement it with something simple and crude, so to distinguish my code more clearly and
robustly. Inspired by [vim-perl](https://github.com/vim-perl/vim-perl) plugin for Perl in Vim,
I decided that from now on, every single Python file I create, would start with the following header:

```
"""===============================================================================

        FILE: {filename}.py

       USAGE: ./{filename}.py

 DESCRIPTION: 

     OPTIONS: ---
REQUIREMENTS: ---
        BUGS: ---
       NOTES: ---
      AUTHOR: Alex Leontiev ({email})
ORGANIZATION: 
     VERSION: ---
     CREATED: 2020-11-13T15:54:47.995590
    REVISION: ---

==============================================================================="""
```

## Main work

### Part 1: Python Script

It was not very difficult. I put together the following simple script (you can find it at 
[https://github.com/nailbiter/for/blob/master/forpython/new_file.py](https://github.com/nailbiter/for/blob/master/forpython/new_file.py)):

```py
#!/usr/bin/env python3
from os.path import realpath, split, basename, join, splitext
import os.path
from os import access, X_OK, walk
from jinja2 import Template
import click
from datetime import datetime


def _get_template_dirname():
    dirname, _ = split(realpath(__file__))
    return join(dirname, "_new_file")


def _get_template_names():
    _, _, fns = next(walk(_get_template_dirname()))
    _TEMPLATE_EXT = ".jinja.py"
    return [fn[:-len(_TEMPLATE_EXT)] for fn in fns if fn.endswith(_TEMPLATE_EXT)]


def _render_template(fn, **kwargs):
    with open(join(_get_template_dirname(), fn)) as f:
        return Template(f.read()).render({
            **kwargs,
            "os": {"path": os.path},
            "converters": {
                "snake_to_camel": lambda s: "".join([s_.capitalize() for s_ in s.split("_")]),
            }})


@click.command()
@click.argument("fn", type=click.Path())
@click.option("-s", "--stdout", is_flag=True)
@click.option("-e", "--email", envvar="EMAIL", default="***@gmail.com")
@click.option("-o", "--organization", envvar="ORGANIZATION", default="")
@click.argument("archetype", type=click.Choice(_get_template_names()), default="default")
def new_file(fn, email, organization, archetype, stdout=False):
    s = _render_template(f"{archetype}.jinja.py",
                         filename=fn,
                         now=datetime.now(),
                         email=email,
                         is_executable=access(fn, X_OK),
                         organization=organization
                         )
    if stdout:
        print(s)
    else:
        with open(fn, "w") as f:
            f.write(s)


if __name__ == "__main__":
    new_file()
```

The script is basically used as

```
./new_file.py filename.py [archetype]
```

where optional `archetype` (hi, [maven](https://maven.apache.org/guides/introduction/introduction-to-archetypes.html)) 
is the name of any of the [predefined templates](https://github.com/nailbiter/for/tree/master/forpython/_new_file):

1. `default` (which is the default)
1. `click` (the template for a `click` script)
1. `class` (the template for a Python file containing a definition of a single class)
1. `test` (the template for [unittest](https://docs.python.org/ja/3/library/unittest.html))

When being called as above, the script takes the corresponding template, performs the necessary substititions, and writes it to `filename.py`. The additional flag `-s/--stdout` overwrites
this behaviour, instead writing the rendered template to `stdout`. Also, `-e` and `-o` flags and corresponding `EMAIL` and `ORGANIZATION` environment variables
are used to insert one's email and organization
to the header. Incidentally, I found that it is useful to use [direnv](https://github.com/direnv/direnv) to change these environment variables based on the directory where source
code is located, so to distinguish my own codes and the ones I do during my worktime. 


### Part 2: Hooking it into Vim
Finally, I need to somehow hook in into my Vim, so that ideally this script gets run every time I open the new file. Unfortunately, I did not find a way to do this prettily. Moreover,
now that script supports multiple archetypes, it is in principle impossible to decide which one to use at the time of file creation.

Therefore, I added the following to my [.vimrc](https://github.com/nailbiter/for/blob/master/.vimrc):

```
...
:au BufNewFile *.py 0r ~/.vim/skeletons/skeleton.py
...
```

where file [skeleton.py](https://github.com/nailbiter/for/blob/master/.vim/skeletons/skeleton.py) is defined as follows:

``` 
(maybe, set `chmod +x` and) run `Init`!
```

Now, every time I create the new `.py` file, it greets me with the message above, reminding me to run `Init <archetype>` Vim command, which is defined in my 
[python.vim](https://github.com/nailbiter/for/blob/master/.vim/ftplugin/python.vim) as
```
command! -nargs=? Init execute "!~/for/forpython/new_file.py % <args>"
```

so that it runs the script we made in Part 1.

## Future work

1. if anyone knows how to hook this or similar script into Emacs, I would be happy to hear
1. maybe, there is some way to hook the script into my Vim more seamlessly?