diff options
author | Guillaume Pasquet <dev@etenil.net> | 2022-02-24 23:19:51 +0000 |
---|---|---|
committer | Guillaume Pasquet <dev@etenil.net> | 2022-02-24 23:19:51 +0000 |
commit | 30dd79ca9480ddb9db19030113d14ede49272411 (patch) | |
tree | 821fa5904e992e2086642a2a33dba16d8c49df66 | |
parent | 79a577031c062a4e3f79f39c8d18ea7edb8a425e (diff) |
Fix #4: Color output
-rw-r--r-- | .gitlab-ci.yml | 3 | ||||
-rw-r--r-- | Cargo.lock | 12 | ||||
-rw-r--r-- | Cargo.toml | 1 | ||||
-rw-r--r-- | src/executor.rs | 31 | ||||
-rw-r--r-- | src/main.rs | 68 | ||||
-rw-r--r-- | src/output.rs | 104 | ||||
-rw-r--r-- | test_api/test_api_get.barb | 1 |
7 files changed, 157 insertions, 63 deletions
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index f406606..de5d876 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -9,7 +9,8 @@ variables: test: stage: test script: - - cargo test --all --verbose + - apt install libjq1 libjq-dev libonig-dev libonig5 + - JQ_LIB_DIR=/usr/lib/x86_64-linux-gnu cargo test --all --verbose # pretty: # stage: test @@ -39,6 +39,7 @@ name = "barb" version = "0.1.5" dependencies = [ "clap 3.0.14", + "colored", "jq-rs", "jsonformat", "serde", @@ -128,6 +129,17 @@ dependencies = [ ] [[package]] +name = "colored" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3616f750b84d8f0de8a58bda93e08e2a81ad3f523089b05f1dffecab48c6cbd" +dependencies = [ + "atty", + "lazy_static", + "winapi", +] + +[[package]] name = "crc32fast" version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -18,3 +18,4 @@ serde = "1.0.130" serde_json = "1.0.70" jsonformat = "1.2.0" jq-rs = "0.4.1" +colored = "2.0.0" diff --git a/src/executor.rs b/src/executor.rs index bd948b5..40a2857 100644 --- a/src/executor.rs +++ b/src/executor.rs @@ -1,9 +1,11 @@ use crate::barbfile::BarbFile; +use crate::output::BarbOutput; use std::collections::HashMap; use ureq; use ureq::Error as UreqError; + pub struct Context { vars: HashMap<String, String>, } @@ -57,32 +59,24 @@ impl Executor { Executor { context } } - fn make_req(&self, bfile: &BarbFile, print_req: bool, print_headers: bool) -> ureq::Request { - if print_req { - println!( - "{} {}", - bfile.method_as_string().as_str(), - self.context.substitute(&bfile.url()).as_str() - ); - } + fn make_req(&self, bfile: &BarbFile, output: &BarbOutput) -> ureq::Request { + output.req(bfile.method_as_string(), self.context.substitute(&bfile.url())); let mut req = ureq::request( bfile.method_as_string().as_str(), self.context.substitute(&bfile.url()).as_str(), ); for header in bfile.headers() { + let hdr_val = self.context.substitute(header.value()); req = req.set( header.name(), - self.context.substitute(header.value()).as_str(), + hdr_val.as_str(), ); - if print_headers { - println!( - "{} {}", - header.name(), - self.context.substitute(header.value()) - ); - } + output.req_hdr(header.name().to_string(), hdr_val); } + + output.end_req(); + req } @@ -105,10 +99,9 @@ impl Executor { pub fn execute( &mut self, bfile: &BarbFile, - print_req: bool, - print_headers: bool, + output: &BarbOutput, ) -> Result<ureq::Response, String> { - self.run(bfile, self.make_req(&bfile, print_req, print_headers)) + self.run(bfile, self.make_req(&bfile, output)) } } diff --git a/src/main.rs b/src/main.rs index 6099020..a02938a 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,12 +1,13 @@ mod barbfile; mod executor; +mod output; use jq_rs; -use jsonformat::{format_json, Indentation}; use std::slice::Iter; use barbfile::BarbFile; use executor::{Context, Executor}; +use output::BarbOutput; use clap::Parser; @@ -27,30 +28,14 @@ struct Args { raw: bool, #[clap(short, long)] filter: Option<String>, + #[clap(short, long)] + path: Option<String>, + #[clap(short, long)] + no_color: bool, files: Vec<String>, } impl Args { - pub fn print_req(&self) -> bool { - return !self.body - } - - pub fn print_headers(&self) -> bool { - self.headers || self.all_headers || !self.body - } - - pub fn print_body(&self) -> bool { - !self.headers || self.body - } - - pub fn raw_body(&self) -> bool { - self.raw - } - - pub fn req_headers(&self) -> bool { - self.all_headers - } - pub fn files_iter(&self) -> Iter<String> { self.files.iter() } @@ -58,6 +43,17 @@ impl Args { pub fn jq_filter(&self) -> &Option<String> { &self.filter } + + pub fn output(&self) -> BarbOutput { + BarbOutput::new( + !self.body, + self.all_headers, + self.headers || self.all_headers || !self.body, + !self.headers || self.body, + self.raw, + !self.no_color, + ) + } } fn apply_filters(args: &Args, bfile: &BarbFile, body: String) -> Result<String, String> { @@ -76,30 +72,16 @@ fn run_file(args: &Args, executor: &mut Executor, file_name: &String) -> Result< .as_str(), ) .map_err(|_| format!("Failed to parse file '{}'", file_name))?; - let response = executor.execute(&bfile, args.print_req(), args.req_headers())?; - - if args.print_headers() { - println!("{} {}", response.status(), response.status_text()); - for header_name in response.headers_names() { - println!( - "{}: {}", - header_name, - // Header is guaranteed to exist - response.header(header_name.as_str()).unwrap() - ); - } - } + let output = args.output(); + let response = executor.execute(&bfile, &output)?; - if args.print_body() { - let body = apply_filters(args, &bfile, response.into_string().unwrap())?; - println!( - "{}", - match args.raw_body() { - true => body, - false => format_json(body.as_str(), Indentation::Default), - } - ); + output.status(response.status(), response.status_text()); + for header_name in response.headers_names() { + output.resp_hdr(header_name.to_string(), response.header(header_name.as_str()).unwrap()); } + output.end_resp_hdr(); + + output.body(apply_filters(args, &bfile, response.into_string().unwrap())?); Ok(()) } diff --git a/src/output.rs b/src/output.rs new file mode 100644 index 0000000..d181d0f --- /dev/null +++ b/src/output.rs @@ -0,0 +1,104 @@ +use colored::*; +use jsonformat::{format_json, Indentation}; +use std::fmt::Display; + +pub struct BarbOutput { + request: bool, + req_headers: bool, + headers: bool, + body: bool, + raw_body: bool, + color: bool, +} + +impl BarbOutput { + fn _print_header<T, I>(&self, name: T, value: I) + where T: Display, I: Display{ + println!("{}: {}", name, value); + } + + pub fn new(request: bool, req_headers: bool, headers: bool, body: bool, raw_body: bool, color: bool) -> BarbOutput { + BarbOutput { + request, + req_headers, + headers, + body, + raw_body, + color, + } + } + + pub fn req(&self, method: String, url: String) { + if !self.request { + return; + } + if self.color { + println!("{} {}", method.purple(), url.purple()); + } else { + println!("{} {}", method, url); + } + } + + pub fn req_hdr(&self, name: String, value: String) { + if !self.req_headers { + return; + } + if self.color { + self._print_header(name.yellow(), value); + } else { + self._print_header(name, value); + } + } + + pub fn end_req(&self) { + if self.req_headers || self.request { + println!(""); + } + } + + pub fn resp_hdr(&self, name: String, value: &str) { + if !self.headers { + return; + } + if self.color { + self._print_header(name.blue(), value); + } else { + self._print_header(name, value); + } + } + + pub fn end_resp_hdr(&self) { + if self.headers { + println!(""); + } + } + + pub fn status(&self, code: u16, text: &str) { + if !self.headers { + return; + } + if self.color { + if code >= 400 { + println!("{} {}", code.to_string().red(), text.red()); + } else { + println!("{} {}", code.to_string().green(), text); + } + } else { + println!("{} {}", code, text); + } + } + + pub fn body(&self, body: String) { + if !self.body { + return; + } + + println!( + "{}", + match self.raw_body { + true => body, + false => format_json(body.as_str(), Indentation::Default), + } + ); + } +} diff --git a/test_api/test_api_get.barb b/test_api/test_api_get.barb index 6bdf592..9746f24 100644 --- a/test_api/test_api_get.barb +++ b/test_api/test_api_get.barb @@ -1 +1,2 @@ #GET^http://localhost:8080/ +#Foo: Bar |