I’m working on different Open Source projects and most of them have different coding style guidelines. Mostly spaces or tabs or different tabwidth. The easiest thing would be to store these information in the git config of the project. So here is a easy and secure way to have modelines in the git config.

So first I set the modelines (here for the Samba project):
git config --add vim.modeline "tabstop=8 shiftwidth=8 noexpandtab cindent"

or for a specific language:
git config --add vim.modeline-python "tabstop=4 shiftwidth=4 expandtab"

Then copy this plugin into ~/.vim/plugin folder.

The modeline you defined in your git config will be appended to the :setlocal command of vim. It only allows a limited set of setlocal commands to be used. It will not execute any arbitrary code and you probably are the only person modifying the git config. You can change the allowed commands by adding the following to your ~/.vimrc file

    let g:git_modelines_allowed_items = [
                \ "textwidth",   "tw",
                \ "softtabstop", "sts",
                \ "tabstop",     "ts",
                \ "shiftwidth",  "sw",
                \ "expandtab",   "et",   "noexpandtab", "noet",
                \ "filetype",    "ft",
                \ "foldmethod",  "fdm",
                \ "readonly",    "ro",   "noreadonly", "noro",
                \ "rightleft",   "rl",   "norightleft", "norl",
                \ "cindent",     "cin",  "nocindent", "nocin",
                \ "smartindent", "si",   "nosmartindent", "nosi",
                \ "autoindent",  "ai",   "noautoindent", "noai",
                \ "spell",
                \ "spelllang"
                \ ]

* New script which only allows a specified list
* Use sandbox command for set
* Added git repository
* Set only locally when reading the buffer

10 thoughts on “vim modelines in git config

  1. @Leif Looks like you introduce a security hole into your system. Someone could trick you to checkout a git repository which already has a .vimrc file in it. If you then open a file in that git project you would execute whatever arbitrary code the .vimrc file includes.

    My approach is more secure here, cause a) you’re the only one who controls the git config file and b) it is limited to the :set command of vim ๐Ÿ™‚

  2. Very dangeruous! You should at least consider using exe “:sandbox set “…

    Attack: I will just put .git in a subdirectory of a project and your extension will execute anything on yourt machine with modeline like ‘ ts=4 | !ls -l ~/.ssh/id_rsa’

    — Martian

  3. Looks better! ๐Ÿ™‚

    2 more things you might consider and get lot of fame on github ๐Ÿ˜‰

    It may be better to hook it as autocommand when file is loaded. You should use :setlocal instead of :set in such case. The plugin work only when opening vim inside git tree and for example I am sometimes wandering in single session among two-three related projects.
    Also if you have any plugin setting options on a per filetype basis, it will override those set in vim.modeline.

    It would be nice to define modeline on per filetype basis: many projects are a mix of different languages and e.g. python “standard” (PEP8) says 4 spaces (sw=4 et) while some other files use different settings (for example Makefile: sw=8 noet)

    Getting complicated…

  4. Thanks, this is what I was looking for, and in my opinion the best way to set code style settings per project. I did make the following change:

    let git_path = shellescape(expand("%:p:h"))
    let git_config_modeline = system("cd " . git_path . "&& git config --get vim.modeline." . &ft)
    let git_config_modeline = system("cd " . git_path . "&& git config --get vim.modeline")

    This executes git in the path of the buffer instead of the current directory of vim, which can be useful when having files from multiple projects open in one vim session.

Leave a Reply

Your email address will not be published. Required fields are marked *