dotbot
dotbot copied to clipboard
Templating support?
I don't know how hard it would be, but would it be possible to allow for templating support in the case of files with only minute differences? That would be really useful for me.
It's a neat idea!
The approach I currently use is that I have my common config in a dotfiles repo, and I have per-machine configs in branches in a dotfiles-local repo. And then I use include
s to include the machine-specific config. At least for the software I use, most of them do support some kind of include
mechanism, so this works out fine for me. And for software that does work like this, I think this is a cleaner solution.
But for software that doesn't support any kind of include
mechanism, I can see that it could be frustrating. I wonder if it's possible to do templating in a simple and clean way... thoughts?
Also, this is another example of an idea that could be initially developed as a plugin and then could potentially be merged in as a first-party plugin.
I've implemented a hosts
option (dictionary) for the link
plugin in my fork project. It allows to define the names of hosts this configuration should be applied on.
The difference between dotbot is that I'm using multiple configuration files as described in the Design Concept, but maybe this can be ported for dotbot too.
Snowsaw looks neat!
Hmm, so between (1) includes, (2) templating, and (3) host-based per-machine configs, which one is the cleanest solution?
Dotbot already supports (1) in a natural way. At least for the programs I use, that has been sufficient, but I recognize that it doesn't work for everything.
Dotbot doesn't implement (2). Dotbot can do (3), but it's kinda clunky (with a bash script).
Kinda related issues: #96, #81, #44
Thanks, but it would not exist in this form without your awesome project it is based on 😉
I would vote for (1) which opens up a way to do some kind of dependencies and would like to suggest my host
option as a single feature since it can not be directly be seen as a kind of template.
[...] with only minute differences.
@ashkitten Can you please explain this a bit more detailed?
not @ashkitten but maybe having the same issue: I use dotbot on my macbook and on some cloud machine. Some ssh
config options apply only for macbook, others for cloud. Ideally, I'd use the Include
command in my .ssh/config
. Unfortunately, this is only available since version 7.3 but an older version is installed in the cloud machine.
If dotbot knew templates I would transform the main config into a template and source the environment-depending parts from my dotfiles-local
repository.
In summary, I like the dotfiles-local
approach but see templates as a good solution for software that does not include Include
.
I had a similar issue, with .ssh/config
, and here's how I did it with my dotfiles-local
repository. The main config is in the master branch, and the macOS specific config is in the mac branch (see the added lines 1-4), where master is periodically merged into mac. Seems to work all right for me.
Templating support is something I'm open to considering, if we can come up with a nice design for it.
What I don't like about templating is having to introduce additional syntax, not being able to parse/syntax highlight config files properly anymore (e.g. a templated .ssh/config
is no longer a valid sshconfig), and having to escape actual config file contents if they conflict with the templating.
While this is pretty old, i thought i might add my opinion on this.
Note that these are most definitely not the cleanest solutions but they do not modify the actual file so the original .ssh/config
is still useable as is
- Add per platform and/or hostname files like
.ssh/config_win32
,.ssh/config_darwin
- Add additional templating file like
.ssh/config.template
and this could work with platform and/or hostname specific files and you can just put.ssh/config_common
and then in the template specify what kind of combination of prefixing, suffixing, etc, you want
I use a custom plugin to template files using jinja2.
It creates a separate directive to template a source file using given parameters. You can see it in action here. It can also do some basic (and clunky) platform detection.
Heres the code (Maybe it will be useful to someone):
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import os
import platform
import dotbot
from jinja2 import Environment, FileSystemLoader
class Template(dotbot.Plugin):
_directive = 'template'
def can_handle(self, directive):
return directive == self._directive
def handle(self, directive, data):
if directive == self._directive:
for temp in data:
target, opts = list(temp.items())[0]
self._log.info("Rendering template %s" % target)
try:
target = os.path.expanduser(target)
params = self._parse_params(opts['params'])
self._render_template(opts['source_file'], params, target)
except:
self._log.error("Could not render %s" % target)
return False
return True
else:
raise ValueError('Cannot handle this directive %s' % directive)
def _parse_params(self, params):
params = self._add_homedir(params)
params = self._parse_platform_specific(params)
return params
def _add_homedir(self, params):
params['HOME_DIR'] = os.environ['HOME']
return params
def _parse_platform_specific(self, params):
if '__UNAME__' in params:
uname = platform.system()
for k in params['__UNAME__'].keys():
params[k] = params['__UNAME__'][k][uname]
del params['__UNAME__']
return params
def _render_template(self, template_file, params, target):
cwd = self._context.base_directory()
template_dir = os.path.dirname(
os.path.abspath(cwd + '/' + template_file))
jinja_env = Environment(loader=FileSystemLoader(template_dir))
template = jinja_env.get_template(os.path.basename(template_file))
with open(target, 'w') as target_file:
target_file.write(template.render(params))
@ssbanerje if you're interested, you could separate that plugin into a separate repo, and we could add it to the list of plugins.
Sure. I have added it to the wiki under template
. Here is a link to the repo for folks who see this issue.
Thank you!