Introduction

THIS WIKI IS A WORK IN PROGRESS

Profile

Profiles can be either a json or yaml file.

Paths

All paths that are given via the profile can have system/environment variables embedded. They start with a $ and then the name (e.g. $HOME). Optionally they can also be enclosed with braces (e.g. ${HOME}). This syntax is both valid/used for unix and windows systems (instead of windows %...% syntax).

Additionally, paths can start with a ~ which corresponds to the user home directory:

  • Unix: /home/test ($HOME)
  • Windows: C:\Users\test

Layout

Yaml

# Optional: Other profiles which will be used as base for this one. The order in which they are specified matters, the higher up the higher the priority for overwrites of values.
# Default: None
extends:
  - base_profile_name

# Optional: Variables for all `dotfiles`
# Default: None
# DON'T add '-' infront of the variable names (e.g. - OS: "linux")
variables:
  RUSTC_PATH: "/usr/bin/rustc"
  OS: "linux"


# Optional: Content transformer. These will take the content of a dotfile, process it and return a new version of it.
transformers:
  - LineTerminator: CRLF

# Optional: Target path of config dir; used when no specific deploy_location was given
# Default: `$PUNKTF_TARGET`
target: "/home/demo/.config"

# Optional: Hooks which are executed once before the deployment.
# Default: None
pre_hooks:
  - echo "Foo"

# Optional: Hooks which are executed once after the deployment.
# Default: None
post_hooks:
  - echo "Bar"

# `dotfiles` to be deployed
dotfiles:
    # Relative path in `dotfiles/`
  - path: init.vim.win

	# Optional: Alternative name for the dotfile. This name will be used instead of [`Dotfile::path`] when
	# deploying. If this is set and the dotfile is a folder, it will be deployed under the given
	# name and not in the root source directory.
	# Default: None
	rename: init.vim

	# Optional: Alternative deploy target path. This will be used instead of [`Profile::target`] when
	# deploying.
	# Default: None
	overwrite_target: "/home/demo/.config/nvim"

	# Optional: Custom variables for the specific file (same as above)
	# Default: None
	variables: []

	# Optional: Content transformer. These will take the content of a dotfile, process it and return a new version of it.
	transformers:
	- LineTerminator: CRLF

	# Optional: Merge operation/kind (like: Ask, Keep, Overwrite)
	# Default: Overwrite
	merge: Overwrite

	# Optional: Whether this file is a template or not (skips template actions (replace, ..) if not)
	# Default: true
	template: false

	# Optional: Higher priority `dotfile` is allowed to overwrite lower priority one
	# Default: None
	priority: 2

# Symlinks to be created
links:
	# Absolute path to target of the link
  - source_path: "$HOME/configurations"
	# Absolute path to the source of the link
	target_path: "~/.config"
	# Optional: Will replace existing symlink at target (overwrite). But only if the file at the target is a symlink.
	# Default: true
	replace: false

Json

{
	"extends": [
        "base_profile_name"
    ],
	"variables": {
		"RUSTC_PATH": "/usr/bin/rustc",
		"OS": "linux",
		//, ...
	},
    "transformers": [
        { "LineTerminator": "CRLF" }
    ],
	"target": "/home/demo/.config",
	"pre_hooks": ["echo \"Foo\""],
	"post_hooks": ["echo \"Bar\""],
	"dotfiles": [
		{
			"path": "init.vim.linux",
			"rename": "init.vim",
			"overwrite_target": "/home/demo/.config/nvim"
			"variables": {
				//...
			},
            "transformers": [
                 { "LineTerminator": "CRLF" }
            ],
			"merge": "Overwrite",
			"template": false,
			"priority": 2,
		}
		//, ...
	]
}

Dotfile

A dotfile, in the sense punktf uses it, can be of two different kinds:

  • A normal file
  • A directory containing files

The options for both are the same (look at [[Profiles|Profiles]] for more details), but they differ in some ways:

  1. If a directory get's deployed all files contained within it will also get deployed.

  2. The contents of a directory are put in the root of the deployment target directory

    For example:

    • profile.target: /home/demo
    • dotfile.path: config_linux (is directory)

    Then all children of config_linux will be deployed under /home/demo e.g. /home/demo/.bashrc

    This behaviour can be influenced in two different ways:

    1. Set dotfile.overwrite_target: This will used instead of profile.target. All files will still land in the root.

    2. Set dotfile.rename: With this option a name for the directory can be set

      For example:

      • profile.target: /home/demo
      • dotfile.path: config_linux (is directory)
      • dotfile.rename: .config

      Then all children of config_linux will be deployed under /home/demo/.config e.g. /home/demo/.config/.bashrc

Template

Default system environment variables

punktf injects some default system environment variables if they are not present. These variable are set during compilation of punktf so you get the values of the compiling system. In most cases the values should be the same when running a compiled executable on another system.

The following are implemented (can be overwritten by defining a environment variable with the same name):

  • PUNKTF_TARGET_ARCH: Architecture of the system which compiled punktf
  • PUNKTF_TARGET_OS: Operating system of the system which compiled punktf
  • PUNKTF_TARGET_FAMILY: Family of the operating system which compiled punktf

The following variables are accessible for templates and hooks (can not be overwritten by defining a environment variable with the same name):

  • PUNKTF_CURRENT_SOURCE: punktf source directory used for the current operation
  • PUNKTF_CURRENT_TARGET: punktf target directory used for the current operation
  • PUNKTF_CURRENT_PROFILE: punktf profile used for the current operation

The values for these variables are available at https://doc.rust-lang.org/reference/conditional-compilation.html.

Syntax

The syntax is heavily inspired by https://handlebarsjs.com/.

Comment blocks

Document template blocks. Will not be copied over to final output.

Syntax

{{!-- This is a comment --}}

Escape blocks

Everything inside will be copied over as is. It can be used to copied over {{ or }} without it being interpreted as a template block.

Syntax

{{{ This will be copied over {{ as is }} even with the "{{" inside }}}

Variable blocks

Define a variable which will be inserted instead of the block. The value of the variable can be gotten from three different environments which can be defined by specifying a prefix:

  1. $: System environment
  2. #: Profile-variables defined in the profile
  3. &: Dotfile-variables defined in the dotfile section of a profile

To search in more than one environment, these prefixes can be combined. The order they appear in is important, as they will be searched in order of appearance. If one environment does not have a value set for the variable, the next one is searched.

If no prefixes are defined, it will default to &#.

Valid symbols/characters for a variable name are: (a..z|A..Z|0-9|_)

Syntax

{{$&#OS}}

Print blocks will simply print everything contained within the block to the command line. The content of the print block won't be resolved, meaning it will be printed 1 to 1 (e.g. no variables are resolved).

Syntax

{{@print Hello World}}

If blocks

Supported are if, elif, else and fi. Each if block must have a fi block as a final closing block. In between the if and fi block can be zero or multiple elif blocks with a final optional else block. Each if related block must be prefixed with {{@ and end with }}.

Currently the only supported if syntax is:

  • Check if the value of a variable is (not) equal to the literal given: {{VAR}} (==|!=) "LITERAL"
  • Check if a value for a variable (not) exists: (!){{VAR}}

Other blocks can be nested inside the if, elif and else bodies.

Syntax

{{@if {{OS}}}}
        {{@if {{&OS}} != "windows"}}
	        print("OS is not windows")
        {{@elif {{OS}} == "windows"}}
	        {{{!-- This is a nested comment. Below it is a nested variable block. --}}}
	        print("OS is {{OS}}")
        {{@else}}
	        {{{!-- This is a nested comment. --}}}
	        print("Can never get here. {{{ {{OS}} is neither `windows` nor not `windows`. }}}")
        {{@fi}}
{{@else}}
	print("No value for variable `OS` set")
{{@fi}}

{{@if !{{OS}}}}
    {{!-- Run when variable `OS` does not exist/is not set --}}
{{@fi}}

Content Transformer

Transforms run once for each defined dotfile during the deploy process.

They can either be specified for a whole profile, in which case each dotfile is transformed by them or they can be attached to a specific dotfile.

A transform takes the contents of a dotfile, processes it and returns a new version of the content.

The contents are either a resolved template or a non-template dotfile.

Order of execution

  1. Content transformers specified in the profile
  2. Content transformers specified in the specific dotfile

Available Transformers

LineTerminator

The LineTerminator transformer replaces all occurrences of one kind of line terminator with a other one.

Options

  • LF will replace all \r\n with a single \n (windows style -> unix style)
  • CRLF will replace all \n with a \r\n (unix style -> windows style)

Usage

Define the following in either the root of the profile or a specific dotfile:

transformers:
  - LineTerminator: CRLF

Contributors

Many thanks to all the people who helped make punktf an awesome dotfile manager.

If you feel you're missing from this list, feel free to add yourself in a PR.