Skip to content

Commit

Permalink
Merge pull request #24 from keawade/tooling
Browse files Browse the repository at this point in the history
Tooling enforcement
  • Loading branch information
slinkardbrandon authored Oct 24, 2020
2 parents 79dbaa7 + 5df832e commit 48125a9
Show file tree
Hide file tree
Showing 7 changed files with 115 additions and 111 deletions.
10 changes: 8 additions & 2 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,11 @@ jobs:
- uses: actions-rs/toolchain@v1
with:
toolchain: stable
- run: cargo test
- run: cargo build --release --all-features
- name: Format
run: cargo fmt -- --check
- name: Lint
run: cargo clippy -- -D warnings
- name: Test
run: cargo test
- name: Build
run: cargo build --release --all-features
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
1 change: 1 addition & 0 deletions rustfmt.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
tab_spaces = 2
40 changes: 20 additions & 20 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,29 +6,29 @@ extern crate error_chain;
use clap::{App, Arg, ArgMatches};

pub mod errors {
error_chain! {}
error_chain! {}
}

pub mod load_toml;

pub fn read_args() -> ArgMatches<'static> {
App::new(crate_name!())
.version(crate_version!())
.author(crate_authors!())
.about(crate_description!())
.arg(
Arg::with_name("file")
.short("f")
.long("file")
.value_name("TOML_FILE")
.help("TOML file to ingest")
.takes_value(true),
)
.arg(
Arg::with_name("filter")
.help("Applies to the TOML input and produces filter results as TOML on standard output.")
.required(true)
.index(1),
)
.get_matches()
App::new(crate_name!())
.version(crate_version!())
.author(crate_authors!())
.about(crate_description!())
.arg(
Arg::with_name("file")
.short("f")
.long("file")
.value_name("TOML_FILE")
.help("TOML file to ingest")
.takes_value(true),
)
.arg(
Arg::with_name("filter")
.help("Applies to the TOML input and produces filter results as TOML on standard output.")
.required(true)
.index(1),
)
.get_matches()
}
17 changes: 8 additions & 9 deletions src/load_toml.rs
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");
}
154 changes: 76 additions & 78 deletions src/main.rs
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);
}

0 comments on commit 48125a9

Please sign in to comment.