Skip to content

Commit

Permalink
Issue #44: Implement exporting table in csv format
Browse files Browse the repository at this point in the history
  • Loading branch information
AmrDeveloper committed Jan 19, 2024
1 parent ae43b2d commit 05acf42
Show file tree
Hide file tree
Showing 5 changed files with 118 additions and 6 deletions.
28 changes: 28 additions & 0 deletions Cargo.lock

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

1 change: 1 addition & 0 deletions crates/gitql-ast/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,4 @@ license = "MIT"
[dependencies]
lazy_static = "1.4.0"
chrono = "0.4.31"
csv = "1.3.0"
21 changes: 21 additions & 0 deletions crates/gitql-ast/src/object.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
use std::error::Error;

use csv::Writer;

use crate::value::Value;

/// In memory representation of the list of [`Value`] in one Row
Expand Down Expand Up @@ -52,4 +56,21 @@ impl GitQLObject {
pub fn len(&self) -> usize {
self.groups.len()
}

/// Export the GitQLObject as CSV String
pub fn as_csv(&self) -> Result<String, Box<dyn Error>> {
let mut writer = Writer::from_writer(vec![]);
writer.write_record(self.titles.clone())?;
let row_len = self.titles.len();
if let Some(group) = self.groups.get(0) {
for row in &group.rows {
let mut values_row: Vec<String> = Vec::with_capacity(row_len);
for value in &row.values {
values_row.push(value.to_string());
}
writer.write_record(values_row)?;
}
}
Ok(String::from_utf8(writer.into_inner()?)?)
}
}
52 changes: 52 additions & 0 deletions crates/gitql-cli/src/arguments.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,20 @@
#[derive(Debug, PartialEq)]
/// Represent the different type of available formats
pub enum OutputFormat {
/// Render the output as table
Render,
/// Print the output in csv format
CSV,
}

/// Arguments for GitQL
#[derive(Debug, PartialEq)]
pub struct Arguments {
pub repos: Vec<String>,
pub analysis: bool,
pub pagination: bool,
pub page_size: usize,
pub output_format: OutputFormat,
}

/// Create a new instance of Arguments with the default settings
Expand All @@ -15,6 +25,7 @@ impl Arguments {
analysis: false,
pagination: false,
page_size: 10,
output_format: OutputFormat::Render,
}
}
}
Expand Down Expand Up @@ -111,6 +122,24 @@ pub fn parse_arguments(args: &Vec<String>) -> Command {
arguments.page_size = page_size;
arg_index += 1;
}
"--output" | "-o" => {
arg_index += 1;
if arg_index >= args_len {
let message = format!("Argument {} must be followed by output format", arg);
return Command::Error(message);
}

let output_type = &args[arg_index].to_lowercase();
if output_type == "csv" {
arguments.output_format = OutputFormat::CSV;
} else if output_type == "render" {
arguments.output_format = OutputFormat::Render;
} else {
return Command::Error("Invalid output format".to_string());
}

arg_index += 1;
}
_ => return Command::Error(format!("Unknown command {}", arg)),
}
}
Expand Down Expand Up @@ -150,6 +179,7 @@ pub fn print_help_list() {
println!("-q, --query <GQL Query> GitQL query to run on selected repositories");
println!("-p, --pagination Enable print result with pagination");
println!("-ps, --pagesize Set pagination page size [default: 10]");
println!("-o, --output Set output format [render, csv]");
println!("-a, --analysis Print Query analysis");
println!("-h, --help Print GitQL help");
println!("-v, --version Print GitQL Current Version");
Expand Down Expand Up @@ -227,4 +257,26 @@ mod tests {
let command = parse_arguments(&arguments);
assert!(matches!(command, Command::Error { .. }));
}

#[test]
fn test_arguments_with_valid_output_format() {
let arguments = vec![
"gitql".to_string(),
"--output".to_string(),
"csv".to_string(),
];
let command = parse_arguments(&arguments);
assert!(!matches!(command, Command::Error { .. }));
}

#[test]
fn test_arguments_with_invalid_output_format() {
let arguments = vec![
"gitql".to_string(),
"--output".to_string(),
"text".to_string(),
];
let command = parse_arguments(&arguments);
assert!(matches!(command, Command::Error { .. }));
}
}
22 changes: 16 additions & 6 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use gitql_ast::environment::Environment;
use gitql_cli::arguments;
use gitql_cli::arguments::Arguments;
use gitql_cli::arguments::Command;
use gitql_cli::arguments::OutputFormat;
use gitql_cli::diagnostic_reporter;
use gitql_cli::diagnostic_reporter::DiagnosticReporter;
use gitql_cli::render;
Expand Down Expand Up @@ -150,12 +151,21 @@ fn execute_gitql_query(
// Render the result only if they are selected groups not any other statement
let engine_result = evaluation_result.ok().unwrap();
if let SelectedGroups(mut groups, hidden_selection) = engine_result {
render::render_objects(
&mut groups,
&hidden_selection,
arguments.pagination,
arguments.page_size,
);
match arguments.output_format {
OutputFormat::Render => {
render::render_objects(
&mut groups,
&hidden_selection,
arguments.pagination,
arguments.page_size,
);
}
OutputFormat::CSV => {
if let Ok(csv) = groups.as_csv() {
println!("{}", csv);
}
}
}
}

let engine_duration = engine_start.elapsed();
Expand Down

0 comments on commit 05acf42

Please sign in to comment.