From d3a8d88906ea602f24bb2a7cd9147d28e6ed3d48 Mon Sep 17 00:00:00 2001 From: kesslern Date: Sat, 15 Feb 2020 10:48:29 -0500 Subject: [PATCH] Add arbitrary shell commands --- README.md | 7 +++++++ src/lib.rs | 44 ++++++++++++++++++++++++++++++++---------- test/dotfiles/template | 2 ++ test/expected/template | 2 ++ test/rules | 2 ++ 5 files changed, 47 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index fcaaacf..b4bf8d5 100644 --- a/README.md +++ b/README.md @@ -6,6 +6,7 @@ Storing dotfiles in git repositories allows them to be shared across multiple co ## Features * Make string substitutions in files according to configured key/value pairs. +* Use output from arbitrary shell commands in templated dotfiles (e.g. for passwords with GNU Pass). * Toggle chunks of files per feature flags. * Binary files are copied without templating. * File permissions are preserved. @@ -39,6 +40,12 @@ asdf=aoeu ``` will replace all occurances of `{SUBSTITION ONE}` with `123`, `[font size]` with `19`, and `asdf` with `aoeu`. +#### Arbitrary Shell Commands +If the `=` separating key/value pairs is immediately proceeded by `SHELL `, dot-templater will run the provided command and use the stdout when templating dotfiles. Providing following line in a config file will substitute any occurrance of `SHELL_COMMAND` with `1234`. +``` +SHELL_COMMAND=SHELL echo 1234 +``` + #### Feature Flags Any line in the rules configuration file that does not include a `=` character and is not a comment will enable the feature name that matches the line. Dotfiles can designate togglable features with three octothorpes followed by the feature name. ``` diff --git a/src/lib.rs b/src/lib.rs index c25b59b..3124601 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -13,6 +13,7 @@ use std::io::Lines; use std::io::Read; use std::io::Write; use std::path::Path; +use std::process::Command; use walkdir::WalkDir; pub struct Config { @@ -30,7 +31,7 @@ impl Config { for line in lines { let line = line?; - match Config::parse_line(line) { + match Config::parse_line(line)? { Some(value) => match value { ConfigValue::Feature(it) => { config.features.push(it); @@ -46,28 +47,51 @@ impl Config { Ok(config) } - fn parse_line(line: String) -> Option { + fn run_command(command: String) -> Result> { + let stdout = Command::new("sh") + .arg("-c") + .arg(&command) + .output()? + .stdout; + + return Ok(String::from_utf8(stdout)?.trim().to_owned()); + } + + + fn parse_line(line: String) -> Result, Box> { let mut line = line.trim().to_string(); if line.is_empty() || line.starts_with("#") { - return None; + return Ok(None); } match line.chars().position(|c| c == '=') { Some(idx) => { - let mut var = line.split_off(idx); - var.remove(0); - return Some(ConfigValue::Substitution { - key: line, - value: var, - }); + let mut value = line.split_off(idx); + value.remove(0); + + if value.starts_with("SHELL ") { + let command = value.split_off(6); + let result = &Config::run_command(command)?; + + return Ok(Some(ConfigValue::Substitution { + key: line, + value: result.to_owned(), + })); + } else { + return Ok(Some(ConfigValue::Substitution { + key: line, + value: value, + })); + } } None => { - return Some(ConfigValue::Feature(line)); + return Ok(Some(ConfigValue::Feature(line))); } } } + fn template_file(&self, source: &Path, dest: &Path) -> Result<(), Box> { let source = BufReader::new(File::open(source)?); let mut dest = File::create(dest)?; diff --git a/test/dotfiles/template b/test/dotfiles/template index 98b2531..1312c0d 100644 --- a/test/dotfiles/template +++ b/test/dotfiles/template @@ -4,6 +4,8 @@ Are BASICs really better than dogs? Weird equals stuff can happen: 4 EQUALS +Test a shell command: SHELL_COMMAND + ### FEATURE1 this should appear ### FEATURE1 diff --git a/test/expected/template b/test/expected/template index b559523..f2bdc05 100644 --- a/test/expected/template +++ b/test/expected/template @@ -4,5 +4,7 @@ Are cats really better than dogs? Weird equals stuff can happen: ==== +Test a shell command: 1234 + this should appear this should appear (test indentation) diff --git a/test/rules b/test/rules index 1eb9202..f87949d 100644 --- a/test/rules +++ b/test/rules @@ -11,3 +11,5 @@ EMPTY VARIABLE= FEATURE1 # More comments... + +SHELL_COMMAND=SHELL echo 1234