Skip to content

Commit

Permalink
Fix nested feature flags (#8)
Browse files Browse the repository at this point in the history
Closes #8
  • Loading branch information
jonvmey authored Jun 16, 2020
1 parent b05b81f commit 069a7e1
Show file tree
Hide file tree
Showing 5 changed files with 29 additions and 21 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ 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.
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. Features can be nested.
```
FEATURE1
```
Expand Down
36 changes: 16 additions & 20 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,23 +83,21 @@ impl Config {
fn template_file(&self, source: &Path, dest: &Path) -> Result<(), Box<dyn Error>> {
let source = BufReader::new(File::open(source)?);
let mut dest = File::create(dest)?;
let mut in_disabled_feature = false;
let mut feature_stack = Vec::new();

for line in source.lines() {
let line = line?;
let feature = self.is_feature_enable_or_disable(&line);

match feature {
Some(enabled) => {
if in_disabled_feature {
in_disabled_feature = false;
} else if !enabled {
in_disabled_feature = true;
let mut line = line?;
match Config::get_feature(&line) {
Some(feature) => match feature_stack.last() {
Some((last, _)) if *last == feature => {
feature_stack.pop();
},
_ => {
feature_stack.push((feature.to_owned(), self.is_enabled(&feature)));
}
}
None => {
if !in_disabled_feature {
let mut line = line;
if feature_stack.iter().all(|(_, enabled)| *enabled) {
for (key, value) in &self.substitutions {
line = line.replace(key, value);
}
Expand All @@ -113,21 +111,19 @@ impl Config {
Ok(())
}

fn is_feature_enable_or_disable(&self, line: &str) -> Option<bool> {
fn get_feature(line: &str) -> Option<&str> {
let re = Regex::new("^\\s*### .*$").unwrap();
if re.is_match(line) {
let found_feature = &line.trim()[3..].trim();
for feature in &self.features {
if found_feature == feature {
return Some(true);
}
}
Some(false)
Some(line.trim()[3..].trim())
} else {
None
}
}

fn is_enabled(&self, feature: &str) -> bool {
self.features.iter().any(|f| f == feature)
}

pub fn template(&self, source_dir: &str, dest_dir: &str) -> Result<(), Box<dyn Error>> {
for entry in WalkDir::new(source_dir) {
let source_file = entry?;
Expand Down
10 changes: 10 additions & 0 deletions test/dotfiles/template
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,13 @@ this should *NOT* appear
### OTHER FEATURE
this should *NOT* appear (test indentation)
### OTHER FEATURE
### FEATURE1
### FEATURE2
this should appear (test nested features)
### FEATURE2
### FEATURE1
### OTHER FEATURE
### FEATURE2
this should *NOT* appear (test nested features)
### FEATURE2
### OTHER FEATURE
1 change: 1 addition & 0 deletions test/expected/template
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,4 @@ Test a shell command: 1234

this should appear
this should appear (test indentation)
this should appear (test nested features)
1 change: 1 addition & 0 deletions test/rules
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ VAR WITH SPACES=variable
EMPTY VARIABLE=

FEATURE1
FEATURE2
# More comments...

SHELL_COMMAND=SHELL echo 1234

0 comments on commit 069a7e1

Please sign in to comment.