Skip to content

Commit

Permalink
add list option
Browse files Browse the repository at this point in the history
  • Loading branch information
piyoppi committed Nov 10, 2024
1 parent ecf7983 commit c260066
Show file tree
Hide file tree
Showing 5 changed files with 182 additions and 36 deletions.
80 changes: 52 additions & 28 deletions src/chiritori.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use crate::{
code::{
formatter::{self, BlockFormatter, Formatter},
list::build_list,
remover::{
self,
marker::{
Expand All @@ -26,8 +27,6 @@ use std::{
};

pub struct ChiritoriConfiguration {
pub delimiter_start: String,
pub delimiter_end: String,
pub time_limited_configuration: TimeLimitedConfiguration,
pub marker_tag_configuration: MarkerTagConfiguration,
}
Expand All @@ -43,12 +42,44 @@ pub struct MarkerTagConfiguration {
pub marker_removal_tags: HashSet<String>,
}

pub fn clean(content: Rc<String>, config: ChiritoriConfiguration) -> String {
let tokens = tokenizer::tokenize(&content, &config.delimiter_start, &config.delimiter_end);
pub fn clean(
content: Rc<String>,
delimiters: (String, String),
config: ChiritoriConfiguration,
) -> String {
let (delimiter_start, delimiter_end) = delimiters;
let tokens = tokenizer::tokenize(&content, &delimiter_start, &delimiter_end);

let parsed = parser::parse(&tokens);
let mut builder_map: HashMap<String, Box<dyn RemovalEvaluator>> = HashMap::new();
let remover = build_remover(config, content.clone());
let (removed, markers) = remover.remove(parsed, &content);

let removed_pos = remover::get_removed_pos(&markers);
let formatter = build_formatters();
let structure_formatters: Vec<Box<dyn BlockFormatter>> = vec![Box::new(
formatter::block_indent_remover::BlockIndentRemover {},
)];

formatter::format(&removed, &removed_pos, &formatter, &structure_formatters)
}

pub fn list(
content: Rc<String>,
delimiters: (String, String),
config: ChiritoriConfiguration,
) -> String {
let (delimiter_start, delimiter_end) = delimiters;
let tokens = tokenizer::tokenize(&content, &delimiter_start, &delimiter_end);

let parsed = parser::parse(&tokens);
let remover = build_remover(config, content.clone());
let (_, markers) = remover.remove(parsed, &content);

build_list(&content, &markers)
}

fn build_remover(config: ChiritoriConfiguration, content: Rc<String>) -> Remover {
let mut builder_map: HashMap<String, Box<dyn RemovalEvaluator>> = HashMap::new();
builder_map.insert(
config.time_limited_configuration.tag_name,
Box::new(
Expand All @@ -71,31 +102,24 @@ pub fn clean(content: Rc<String>, config: ChiritoriConfiguration) -> String {
let remove_strategy_map: RemoveStrategies = vec![
(
Box::new(UnwrapBlockMarkerAvailability::new("unwrap-block")),
Box::new(UnwrapBlockMarkerBuilder {
content: Rc::clone(&content),
}),
Box::new(UnwrapBlockMarkerBuilder { content }),
),
(
Box::new(RangeMarkerAvailability::default()),
Box::new(RangeMarkerBuilder::default()),
),
];

let remover = Remover::new(builder_map, remove_strategy_map);
let (removed, markers) = remover.remove(parsed, &content);
Remover::new(builder_map, remove_strategy_map)
}

let removed_pos = remover::get_removed_pos(&markers);
let formatter: Vec<Box<dyn Formatter>> = vec![
fn build_formatters() -> Vec<Box<dyn Formatter>> {
vec![
Box::new(formatter::indent_remover::IndentRemover {}),
Box::new(formatter::empty_line_remover::EmptyLineRemover {}),
Box::new(formatter::prev_line_break_remover::PrevLineBreakRemover {}),
Box::new(formatter::next_line_break_remover::NextLineBreakRemover {}),
];
let structure_formatters: Vec<Box<dyn BlockFormatter>> = vec![Box::new(
formatter::block_indent_remover::BlockIndentRemover {},
)];

formatter::format(&removed, &removed_pos, &formatter, &structure_formatters)
]
}

#[cfg(test)]
Expand All @@ -107,10 +131,8 @@ mod tests {
use std::io::prelude::*;
use std::{fs::File, path::PathBuf};

fn create_test_config(delimiter_start: &str, delimiter_end: &str) -> ChiritoriConfiguration {
fn create_test_config() -> ChiritoriConfiguration {
ChiritoriConfiguration {
delimiter_start: String::from(delimiter_start),
delimiter_end: String::from(delimiter_end),
time_limited_configuration: TimeLimitedConfiguration {
tag_name: String::from("time-limited"),
current: Local::now(),
Expand Down Expand Up @@ -165,9 +187,9 @@ mod tests {
</body>
</html>"#,
);

let config = create_test_config("<!--", "-->");
let result = clean(content.into(), config);
let config = create_test_config();
let delimiters = (String::from("<!--"), String::from("-->"));
let result = clean(content.into(), delimiters, config);

assert_eq!(result, expected);
}
Expand Down Expand Up @@ -217,8 +239,9 @@ console.log("Temporary code while feature2 is not released")
"#,
);

let config = create_test_config("/* <", "> */");
let result = clean(content.into(), config);
let config = create_test_config();
let delimiters = (String::from("/* <"), String::from("> */"));
let result = clean(content.into(), delimiters, config);

assert_eq!(result, expected);
}
Expand All @@ -244,8 +267,9 @@ console.log("Temporary code while feature2 is not released")
.read_to_string(&mut expected_content)
.expect("Failed to load an expected content file");

let config = create_test_config("/* <", "> */");
let result = clean(input_content.into(), config);
let config = create_test_config();
let delimiters = (String::from("/* <"), String::from("> */"));
let result = clean(input_content.into(), delimiters, config);

assert_eq!(result, expected_content);
}
Expand Down
1 change: 1 addition & 0 deletions src/code.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
pub mod formatter;
pub mod list;
pub mod remover;
pub mod utils;
115 changes: 115 additions & 0 deletions src/code/list.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
use super::{
remover::RemoveMarker,
utils::line_break_pos_finder::{find_next_line_break_pos, find_prev_line_break_pos},
};

const MARKER_START: &str = "\x1b[32m_start\x1b[31m";
const MARKER_END: &str = "\x1b[32m‾end\x1b[0m";
const MARKER_START_LEN: usize = MARKER_START.len();
const MARKER_END_LEN: usize = MARKER_END.len();

const HEAD_START: &str = "\n--------[ ";
const HEAD_END: &str = " ]--------\n";

pub fn build_item(content: &str, start: usize, end: usize) -> String {
if end - start == 0 || content.is_empty() {
return String::new();
}

let bytes = content.as_bytes();
let line_start = find_prev_line_break_pos(content, bytes, start, false)
.map(|v| v + 1)
.unwrap_or(0);
let line_end_start_pos = find_prev_line_break_pos(content, bytes, end - 1, false)
.map(|v| v + 1)
.unwrap_or(0);
let line_end =
find_next_line_break_pos(content, bytes, end - 1, false).unwrap_or(content.len());

let marker_start_ofs_len = start - line_start;
let marker_end_ofs_len = end - line_end_start_pos - 1;
let mut result = String::with_capacity(
marker_start_ofs_len
+ MARKER_START_LEN
+ 1
+ (end - start)
+ 1
+ marker_end_ofs_len
+ MARKER_END_LEN,
);

result.push_str(&" ".repeat(marker_start_ofs_len));
result.push_str(MARKER_START);
result.push('\n');
result.push_str(&content[line_start..line_end]);
result.push('\n');
result.push_str(&" ".repeat(marker_end_ofs_len));
result.push_str(MARKER_END);

result
}

pub fn build_list(content: &str, markers: &[RemoveMarker]) -> String {
markers
.iter()
.zip(1..=markers.len())
.map(|((range, _), idx)| {
let mut res = String::from(HEAD_START);
res.push_str(&idx.to_string());
res.push_str(HEAD_END);
res.push_str(&build_item(content, range.start, range.end));

res
})
.collect()
}

#[cfg(test)]
mod tests {
use super::*;
use rstest::rstest;
use std::ops::Range;

#[rstest]
// 0 10
// 012345678901234567
#[case("aaa+bbbb+ccc+dddd", 4..11, format!("{}{}+{}+{}{}", "", MARKER_START, "bbbb+ccc", " ", MARKER_END))]
#[case("aaa+bbbb+ccc+dddd", 3..11, format!("{}{}+{}+{}{}", " ", MARKER_START, "aaa+bbbb+ccc", " ", MARKER_END))]
#[case("aaa+bbbb+ccc+dddd", 2..11, format!("{}{}+{}+{}{}", " ", MARKER_START, "aaa+bbbb+ccc", " ", MARKER_END))]
#[case("aaa+bbbb+ccc+dddd", 4..12, format!("{}{}+{}+{}{}", "", MARKER_START, "bbbb+ccc", " ", MARKER_END))]
#[case("aaa+bbbb+ccc+dddd", 4..13, format!("{}{}+{}+{}{}", "", MARKER_START, "bbbb+ccc", " ", MARKER_END))]
#[case("aaa+bbbb+ccc+dddd", 4..16, format!("{}{}+{}+{}{}", "", MARKER_START, "bbbb+ccc+dddd", " ", MARKER_END))]
#[case("abcd", 1..2, format!("{}{}+{}+{}{}", " ", MARKER_START, "abcd", " ", MARKER_END))]
#[case("", 0..0, "")]
fn test_build_item(
#[case] content: &str,
#[case] range: Range<usize>,
#[case] expected: String,
) {
let content = content.replace('+', "\n");

assert_eq!(
build_item(&content, range.start, range.end),
expected.replace('+', "\n")
);
}

#[test]
fn test_build_list() {
// 0123456789012345678
let content = "aaaa+bbbb+cccc+dddd".replace('+', "\n");
let markers = [(1..2, None), (7..12, None)];

let expected_item1 = build_item(&content, 1, 2);
let expected_item2 = build_item(&content, 7, 12);

assert_eq!(
build_list(&content, &markers),
format!(
"{}1{}{}{}2{}{}",
HEAD_START, HEAD_END, expected_item1, HEAD_START, HEAD_END, expected_item2
)
.replace('+', "\n")
)
}
}
2 changes: 1 addition & 1 deletion src/code/remover.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use removal_evaluator::RemovalEvaluator;
use std::collections::HashMap;
use std::ops::Range;

type RemoveMarker = (Range<usize>, Option<usize>);
pub type RemoveMarker = (Range<usize>, Option<usize>);
pub type RemovedMarker = (usize, Option<usize>);

type RemovalEvaluators = HashMap<String, Box<dyn RemovalEvaluator>>;
Expand Down
20 changes: 13 additions & 7 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,10 @@ struct Args {
/// Name of removal-marker to be removed
#[arg(long, default_value = "vec![]")]
removal_marker_target_name: Vec<String>,

/// List source code to be removed
#[arg(short, long)]
list: bool,
}

fn main() {
Expand All @@ -73,8 +77,6 @@ fn main() {
let marker_removal_tags = HashSet::from_iter(args.removal_marker_target_name);

let config = ChiritoriConfiguration {
delimiter_start: args.delimiter_start,
delimiter_end: args.delimiter_end,
time_limited_configuration: TimeLimitedConfiguration {
tag_name: args.time_limited_tag_name,
time_offset: args.time_limited_time_offset,
Expand All @@ -89,13 +91,17 @@ fn main() {
},
};

let cleaned = chiritori::clean(content, config);
let output = if args.list {
chiritori::list(content, (args.delimiter_start, args.delimiter_end), config)
} else {
chiritori::clean(content, (args.delimiter_start, args.delimiter_end), config)
};

if let Some(output) = args.output {
let mut f = File::create(output).expect("file not found");
f.write_all(cleaned.as_bytes())
if let Some(filename) = args.output {
let mut f = File::create(filename).expect("file not found");
f.write_all(output.as_bytes())
.expect("something went wrong writing the file");
} else {
print!("{}", cleaned);
print!("{}", output);
}
}

0 comments on commit c260066

Please sign in to comment.