-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #24 from keawade/tooling
Tooling enforcement
- Loading branch information
Showing
7 changed files
with
115 additions
and
111 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,7 +2,7 @@ | |
authors = ["Brandon Slinkard <[email protected]>"] | ||
edition = "2018" | ||
name = "tq" | ||
version = "0.1.3" | ||
version = "0.1.4" | ||
|
||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
tab_spaces = 2 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,25 +1,24 @@ | ||
use std::fs::File; | ||
use std::io::{self, Read}; | ||
use toml; | ||
|
||
use crate::errors::*; | ||
|
||
pub fn load_toml_from_file(name: &str) -> Result<toml::Value> { | ||
let mut file = File::open(name).chain_err(|| format!("Failed to open file: {:?}", &name))?; | ||
let mut contents = String::new(); | ||
let _ = file.read_to_string(&mut contents); | ||
let mut file = File::open(name).chain_err(|| format!("Failed to open file: {:?}", &name))?; | ||
let mut contents = String::new(); | ||
let _ = file.read_to_string(&mut contents); | ||
|
||
toml::from_str(&contents).chain_err(|| "File is not valid TOML.") | ||
toml::from_str(&contents).chain_err(|| "File is not valid TOML.") | ||
} | ||
|
||
pub fn load_toml_from_stdin() -> Result<toml::Value> { | ||
let mut content = String::new(); | ||
let _ = io::stdin().lock().read_to_string(&mut content); | ||
let mut content = String::new(); | ||
let _ = io::stdin().lock().read_to_string(&mut content); | ||
|
||
toml::from_str(&content).chain_err(|| "File is not valid TOML.") | ||
toml::from_str(&content).chain_err(|| "File is not valid TOML.") | ||
} | ||
|
||
#[test] | ||
fn load_toml_from_file_without_crash() { | ||
let _foo = load_toml_from_file("../tests/fixtures/test_01.toml"); | ||
let _foo = load_toml_from_file("../tests/fixtures/test_01.toml"); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,90 +1,88 @@ | ||
use toml; | ||
|
||
fn main() { | ||
let matches = tq::read_args(); | ||
|
||
let toml_file: toml::Value = match matches.value_of("file") { | ||
Some(file) => tq::load_toml::load_toml_from_file(file).unwrap(), | ||
None => tq::load_toml::load_toml_from_stdin().unwrap(), | ||
}; | ||
let matches = tq::read_args(); | ||
|
||
/*** | ||
* One of the first things we'll want to do is deal with filters | ||
* and how to pipe results from one filter to another. From the JQ manual: | ||
* "Generally, things that would be done with loops and iteration in other languages are just done by gluing filters together in jq." | ||
* The same can be said for tq. | ||
* | ||
* It's important to remember that every filter has an input and an output. | ||
* Even literals like "hello" or 42 are filters - they take an input but | ||
* always produce the same literal as output. Operations that combine two | ||
* filters, like addition, generally feed the same input to both and combine | ||
* the results. So, you can implement an averaging filter as add / length - | ||
* feeding the input array both to the add filter and the length filter | ||
* and then performing the division. | ||
*/ | ||
let toml_file: toml::Value = match matches.value_of("file") { | ||
Some(file) => tq::load_toml::load_toml_from_file(file).unwrap(), | ||
None => tq::load_toml::load_toml_from_stdin().unwrap(), | ||
}; | ||
|
||
/*** | ||
* Basic filters: | ||
* | ||
* Identity: . | ||
* - The absolute simplest filter is: . | ||
* This is a filter that takes its input and produces it unchanged as output. That is, this is the identity operator. | ||
* | ||
* Object Identifier-Index: .foo, .foo.bar | ||
* - The simplest useful filter is: .foo | ||
* When given TOML as an input, it gets the value in the table row "foo" | ||
* | ||
* Optional Object Identifier Index: .foo? | ||
* - Just like .foo, but does not output even an error when . is not an array or an object. | ||
* | ||
* Generic Object Index: .[<string>] | ||
* - You can also look up fields of an object using syntax like .["foo"] | ||
* (.foo above is a shorthand version of this, but only for identifier-like strings). | ||
* | ||
* Array Index: .[2] | ||
* When the index value is an integer, .[<value>] can index arrays. Arrays are zero-based, so .[2] returns the third element. | ||
* | ||
* Pipe: | | ||
* Combines two filters by feeding the output(s) of the one on the left into | ||
* the input of the one on the right. It's pretty much the same as the Unix shell's | ||
* pipe, if you're used to that. If the one on the left produces multiple results, | ||
* the one on the right will be run for each of those results. So, the expression | ||
* .[] | .foo retrieves the "foo" field of each element of the input array. Note | ||
* that .a.b.c is the same as .a | .b | .c. Note too that . is the input value at | ||
* the particular stage in a "pipeline", specifically: where the . expression | ||
* appears. Thus .a | . | .b is the same as .a.b, as the . in the middle refers | ||
* to whatever value .a produced. | ||
*/ | ||
/*** | ||
* One of the first things we'll want to do is deal with filters | ||
* and how to pipe results from one filter to another. From the JQ manual: | ||
* "Generally, things that would be done with loops and iteration in other languages are just done by gluing filters together in jq." | ||
* The same can be said for tq. | ||
* | ||
* It's important to remember that every filter has an input and an output. | ||
* Even literals like "hello" or 42 are filters - they take an input but | ||
* always produce the same literal as output. Operations that combine two | ||
* filters, like addition, generally feed the same input to both and combine | ||
* the results. So, you can implement an averaging filter as add / length - | ||
* feeding the input array both to the add filter and the length filter | ||
* and then performing the division. | ||
*/ | ||
|
||
// Step 1, read the input string, determine execution order | ||
// Step 2: access the toml_file to get strings, tables, etc | ||
// Step 3: handle various piping scenarios | ||
// Step 4: output | ||
let full_filter_string = matches.value_of("filter").unwrap(); | ||
let filter_pass = full_filter_string.split("|"); | ||
/*** | ||
* Basic filters: | ||
* | ||
* Identity: . | ||
* - The absolute simplest filter is: . | ||
* This is a filter that takes its input and produces it unchanged as output. That is, this is the identity operator. | ||
* | ||
* Object Identifier-Index: .foo, .foo.bar | ||
* - The simplest useful filter is: .foo | ||
* When given TOML as an input, it gets the value in the table row "foo" | ||
* | ||
* Optional Object Identifier Index: .foo? | ||
* - Just like .foo, but does not output even an error when . is not an array or an object. | ||
* | ||
* Generic Object Index: .[<string>] | ||
* - You can also look up fields of an object using syntax like .["foo"] | ||
* (.foo above is a shorthand version of this, but only for identifier-like strings). | ||
* | ||
* Array Index: .[2] | ||
* When the index value is an integer, .[<value>] can index arrays. Arrays are zero-based, so .[2] returns the third element. | ||
* | ||
* Pipe: | | ||
* Combines two filters by feeding the output(s) of the one on the left into | ||
* the input of the one on the right. It's pretty much the same as the Unix shell's | ||
* pipe, if you're used to that. If the one on the left produces multiple results, | ||
* the one on the right will be run for each of those results. So, the expression | ||
* .[] | .foo retrieves the "foo" field of each element of the input array. Note | ||
* that .a.b.c is the same as .a | .b | .c. Note too that . is the input value at | ||
* the particular stage in a "pipeline", specifically: where the . expression | ||
* appears. Thus .a | . | .b is the same as .a.b, as the . in the middle refers | ||
* to whatever value .a produced. | ||
*/ | ||
|
||
let mut value: toml::Value = toml_file.clone(); | ||
for filter_str in filter_pass { | ||
if filter_str.trim() == "." { | ||
continue; | ||
} | ||
// Step 1, read the input string, determine execution order | ||
// Step 2: access the toml_file to get strings, tables, etc | ||
// Step 3: handle various piping scenarios | ||
// Step 4: output | ||
let full_filter_string = matches.value_of("filter").unwrap(); | ||
let filter_pass = full_filter_string.split('|'); | ||
|
||
let keys = filter_str.split("."); | ||
let _count = filter_str.split(".").count(); | ||
let mut value: toml::Value = toml_file; | ||
for filter_str in filter_pass { | ||
if filter_str.trim() == "." { | ||
continue; | ||
} | ||
|
||
let mut val: toml::Value = value; | ||
for key in keys { | ||
let trimmed_key = key.trim(); | ||
if trimmed_key == "" { | ||
continue; | ||
} | ||
let keys = filter_str.split('.'); | ||
let _count = filter_str.split('.').count(); | ||
|
||
val = val.get(trimmed_key).unwrap().clone(); | ||
} | ||
let mut val: toml::Value = value; | ||
for key in keys { | ||
let trimmed_key = key.trim(); | ||
if trimmed_key == "" { | ||
continue; | ||
} | ||
|
||
value = val; | ||
val = val.get(trimmed_key).unwrap().clone(); | ||
} | ||
|
||
println!("{}", &value); | ||
std::process::exit(0); | ||
value = val; | ||
} | ||
|
||
println!("{}", &value); | ||
std::process::exit(0); | ||
} |