Skip to content

Commit

Permalink
feat: add output format option
Browse files Browse the repository at this point in the history
  • Loading branch information
azat-io committed Oct 31, 2024
1 parent 32d877a commit a7e9baa
Show file tree
Hide file tree
Showing 2 changed files with 74 additions and 33 deletions.
12 changes: 11 additions & 1 deletion readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ The list includes the comment text, the file path, and additional metadata, such

Todoctor supports the following command-line options:

### --month \<N>
### --month

Specifies the number of months to include when tracking TODOs in the repository. If not provided, defaults to 3 months.

Expand Down Expand Up @@ -191,6 +191,16 @@ Example:
todoctor --exclude-keywords WARNING --exclude-keywords DEPRECATED
```

### --output-format

You can specify the format of the report. Possible options are `html` and `json`. The default value is `html`.

Example:

```sh
todoctor --output-format json
```

### --output

You can define the folder where the report file will be saved. By default it is `todoctor` folder in the project root.
Expand Down
95 changes: 63 additions & 32 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
use clap::{ArgAction, CommandFactory, Parser};
use clap::{ArgAction, CommandFactory, Parser, ValueEnum};
use futures::future::join_all;
use indicatif::{ProgressBar, ProgressStyle};
use open;
use serde_json::json;
use serde_json::{json, Value};
use std::fs::File;
use std::io::{self, BufRead, BufReader, BufWriter, Write};
use std::path::{Path, PathBuf};
Expand Down Expand Up @@ -33,6 +33,12 @@ use tokio::sync::Semaphore;

const HISTORY_TEMP_FILE: &str = "todo_history_temp.json";

#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, ValueEnum, Debug)]
enum OutputFormat {
Html,
Json,
}

#[derive(Parser, Debug)]
#[command(
name = "todoctor",
Expand All @@ -58,6 +64,10 @@ struct Cli {
#[arg(short = 'E', long, action = ArgAction::Append)]
exclude_keywords: Vec<String>,

/// Output format
#[arg(short, long, default_value = "html")]
output_format: OutputFormat,

/// Output directory
#[arg(short, long, default_value = "todoctor")]
output: String,
Expand Down Expand Up @@ -91,6 +101,8 @@ async fn main() {
.map(|values| values.map(String::from).collect())
.unwrap_or_else(Vec::new);

let output_format = args.get_one::<OutputFormat>("output_format").unwrap();

let output_directory = args.get_one::<String>("output").unwrap();

if !check_git_repository(".").await {
Expand Down Expand Up @@ -358,41 +370,60 @@ async fn main() {
"version": version,
});

let mut escaped_json_data = json_data.clone();
escape_json_values(&mut escaped_json_data);

let escaped_json_string = serde_json::to_string(&escaped_json_data)
.expect("Error: Could not serializing JSON");
generate_output(*output_format, output_directory, json_data).await;
}

let dist_path: PathBuf =
get_dist_path().expect("Error: Could not get current dist path.");
async fn generate_output(
output_format: OutputFormat,
output_directory: &str,
json_data: Value,
) {
match output_format {
OutputFormat::Html => {
let dist_path: PathBuf = get_dist_path()
.expect("Error: Could not get current dist path.");

copy_dir_recursive(&dist_path, Path::new(output_directory))
.await
.expect("Error copying directory");

copy_dir_recursive(&dist_path, Path::new(output_directory))
.await
.expect("Error copying directory");
let mut escaped_json_data = json_data.clone();
escape_json_values(&mut escaped_json_data);

let index_path = Path::new(output_directory).join("index.html");
if fs::metadata(&index_path).await.is_ok() {
let mut index_content = fs::read_to_string(&index_path)
.await
.expect("Error reading index.html");
let escaped_json_string = serde_json::to_string(&escaped_json_data)
.expect("Error: Could not serializing JSON");

if let Some(pos) = index_content.find("</head>") {
let script_tag: String = format!(
"<script>window.data = {};</script>",
escaped_json_string
);
index_content.insert_str(pos, &script_tag);
let index_path = Path::new(output_directory).join("index.html");
if fs::metadata(&index_path).await.is_ok() {
let mut index_content = fs::read_to_string(&index_path)
.await
.expect("Error reading index.html");

if let Some(pos) = index_content.find("</head>") {
let script_tag = format!(
"<script>window.data = {};</script>",
escaped_json_string
);
index_content.insert_str(pos, &script_tag);

fs::write(&index_path, index_content)
.await
.expect("Error writing modified index.html");
} else {
eprintln!("Error: No </head> tag found in index.html");
}

fs::write(&index_path, index_content)
.await
.expect("Error writing modified index.html");
} else {
eprintln!("Error: No </head> tag found in index.html");
if let Err(e) = open::that(&index_path) {
eprintln!("Error: Cannot open index.html: {:?}", e);
}
}
}
OutputFormat::Json => {
let json_path = Path::new(output_directory).join("report.json");
let mut file = File::create(&json_path)
.expect("Failed to create JSON report file");
file.write_all(json_data.to_string().as_bytes())
.expect("Failed to write JSON data");
}
}

if let Err(e) = open::that(&index_path) {
eprintln!("Error: Cannot open index.html: {:?}", e);
}
}

0 comments on commit a7e9baa

Please sign in to comment.