Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
piyoppi committed Dec 16, 2024
1 parent 217a0dd commit 4c09103
Show file tree
Hide file tree
Showing 4 changed files with 128 additions and 39 deletions.
8 changes: 5 additions & 3 deletions chiritori/src/chiritori.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ use crate::{
},
removal_evaluator::RemovalEvaluator,
Remover,
},
}, utils::line_map::build_line_map,
},
parser, tokenizer,
};
Expand Down Expand Up @@ -79,7 +79,8 @@ pub fn list(
.map(|v| (v, true))
.collect();

build_list(&content, &markers)
let line_map = build_line_map(&content);
build_list(&content, &markers, Some(&line_map))
}

pub fn list_all(
Expand All @@ -94,7 +95,8 @@ pub fn list_all(
let remover = build_remover(config, content.clone());
let markers = remover.build_remove_marker_all(&parsed);

build_list(&content, &markers)
let line_map = build_line_map(&content);
build_list(&content, &markers, Some(&line_map))
}

fn build_remover(config: ChiritoriConfiguration, content: Rc<String>) -> Remover {
Expand Down
121 changes: 85 additions & 36 deletions chiritori/src/code/list.rs
Original file line number Diff line number Diff line change
@@ -1,25 +1,27 @@

use super::{
remover::RemoveMarker,
utils::line_break_pos_finder::{find_next_line_break_pos, find_prev_line_break_pos},
utils::{line_break_pos_finder::{find_next_line_break_pos, find_prev_line_break_pos}, line_map::find_line},
};

const MARKER_START: &str = "\x1b[32m_start\x1b[0m";
const MARKER_END: &str = "\x1b[32m‾end\x1b[0m";
const START_COLOR: &str = "\x1b[31m";
const START_COLOR_YELLOW: &str = "\x1b[33m";
const END_COLOR: &str = "\x1b[0m";
const RESET_COLOR: &str = "\x1b[0m";
const MARKER_START_LEN: usize = MARKER_START.len();
const MARKER_END_LEN: usize = MARKER_END.len();
const START_COLOR_LEN: usize = START_COLOR.len();
const START_COLOR_YELLOW_LEN: usize = START_COLOR_YELLOW.len();
const END_COLOR_LEN: usize = END_COLOR.len();
const RESET_COLOR_LEN: usize = RESET_COLOR.len();

const HEAD_START: &str = "-------- [ ";
const HEAD_END: &str = "--------";
const REMOVAL_HEAD: &str = " ] Ready ";
const PENDING_REMOVAL_HEAD: &str = " ] Pending ";
const LINE_COLUMN_WIDTH: usize = 9;

pub fn build_item(content: &str, start: usize, end: usize, is_removal: &bool) -> String {
pub fn build_item(content: &str, start: usize, end: usize, is_removal: &bool, line_map: Option<&Vec<usize>>) -> String {
if end - start == 0 || content.is_empty() {
return String::new();
}
Expand All @@ -44,36 +46,62 @@ pub fn build_item(content: &str, start: usize, end: usize, is_removal: &bool) ->
(START_COLOR_YELLOW, START_COLOR_YELLOW_LEN)
};

let mut removed = String::with_capacity(
(line_end - line_start)
+ (content[color_start..color_end].lines().count() * (start_color_len + RESET_COLOR_LEN))
);
removed.push_str(&content[line_start..color_start]);
removed.push_str(&content[color_start..color_end].lines().map(|l| {
let mut str = String::with_capacity(start_color_len + l.len() + RESET_COLOR_LEN);
str.push_str(start_color);
str.push_str(l);
str.push_str(RESET_COLOR);
str
}).collect::<Vec<_>>().join("\n"));
removed.push_str(&content[color_end..line_end]);
removed.push('\n');

let (code_block, column_ofs) = if let Some(line_map) = line_map {
let line_start_pos = find_line(line_map, line_start);
let line_end_pos = find_line(line_map, line_end);
let mut line_iter = removed.lines();
(
&(line_start_pos..=line_end_pos).map(|i| {
let line_column = format!("{:width$} {}", i, "|", width = LINE_COLUMN_WIDTH - 2);
line_iter.next().map(|l| format!("{line_column}{l}\n")).unwrap_or("".to_string())
}).collect(),
LINE_COLUMN_WIDTH
)
} else {
(&removed, 0)
};

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
+ start_color_len
+ (line_end - line_start)
+ END_COLOR_LEN
+ 1
+ marker_end_ofs_len
+ MARKER_END_LEN,
(marker_start_ofs_len + column_ofs + MARKER_START_LEN) // start marker
+ 1 // \n
+ removed.len() // code block
+ 1 // \n
+ (marker_end_ofs_len + column_ofs + MARKER_END_LEN) // end marker
);

result.push_str(&" ".repeat(marker_start_ofs_len));
// Print a start marker
result.push_str(&" ".repeat(marker_start_ofs_len + column_ofs));
result.push_str(MARKER_START);
result.push('\n');
result.push_str(&content[line_start..color_start]);
result.push_str(start_color);
result.push_str(&content[color_start..color_end]);
result.push_str(END_COLOR);
result.push_str(&content[color_end..line_end]);
result.push('\n');
result.push_str(&" ".repeat(marker_end_ofs_len));

// Print a code block
result.push_str(code_block);

// Print an end marker
result.push_str(&" ".repeat(marker_end_ofs_len + column_ofs));
result.push_str(MARKER_END);

result
}

pub fn build_list(content: &str, markers: &[(RemoveMarker, bool)]) -> String {
pub fn build_list(content: &str, markers: &[(RemoveMarker, bool)], line_map: Option<&Vec<usize>>) -> String {
let mut output: String = markers
.iter()
.zip(1..=markers.len())
Expand All @@ -88,7 +116,7 @@ pub fn build_list(content: &str, markers: &[(RemoveMarker, bool)]) -> String {
});
res.push_str(HEAD_END);
res.push('\n');
res.push_str(&build_item(content, range.start, range.end, is_removal));
res.push_str(&build_item(content, range.start, range.end, is_removal, line_map));

res
})
Expand All @@ -101,20 +129,22 @@ pub fn build_list(content: &str, markers: &[(RemoveMarker, bool)]) -> String {

#[cfg(test)]
mod tests {
use crate::code::utils::line_map::build_line_map;

use super::*;
use rstest::rstest;
use std::ops::Range;

#[rstest]
// 0 10
// 012345678901234567
#[case("aaa+bbbb+ccc+dddd", 4..11, format!("{}{}+{}{}{}{}{}+{}{}", "", MARKER_START, "", START_COLOR, "bbbb+cc", END_COLOR, "c", " ", MARKER_END))]
#[case("aaa+bbbb+ccc+dddd", 3..11, format!("{}{}+{}{}{}{}{}+{}{}", " ", MARKER_START, "aaa", START_COLOR, "+bbbb+cc", END_COLOR, "c", " ", MARKER_END))]
#[case("aaa+bbbb+ccc+dddd", 2..11, format!("{}{}+{}{}{}{}{}+{}{}", " ", MARKER_START, "aa", START_COLOR, "a+bbbb+cc", END_COLOR, "c", " ", MARKER_END))]
#[case("aaa+bbbb+ccc+dddd", 4..12, format!("{}{}+{}{}{}{}{}+{}{}", "", MARKER_START, "", START_COLOR, "bbbb+ccc", END_COLOR, "", " ", MARKER_END))]
#[case("aaa+bbbb+ccc+dddd", 4..13, format!("{}{}+{}{}{}{}{}+{}{}", "", MARKER_START, "", START_COLOR, "bbbb+ccc", END_COLOR, "", " ", MARKER_END))]
#[case("aaa+bbbb+ccc+dddd", 4..16, format!("{}{}+{}{}{}{}{}+{}{}", "", MARKER_START, "", START_COLOR, "bbbb+ccc+ddd", END_COLOR, "d", " ", MARKER_END))]
#[case("abcd", 1..2, format!("{}{}+{}{}{}{}{}+{}{}", " ", MARKER_START, "a", START_COLOR, "b", END_COLOR, "cd", " ", MARKER_END))]
#[case("aaa+bbbb+ccc+dddd", 4..11, format!("{}{}{}{}{}{}{}{}{}{}{}{}{}", MARKER_START, "+", START_COLOR, "bbbb", RESET_COLOR, "+", START_COLOR, "cc", RESET_COLOR, "c", "+", " ", MARKER_END))]
#[case("aaa+bbbb+ccc+dddd", 3..11, format!("{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", " ", MARKER_START, "+", "aaa", START_COLOR, "", RESET_COLOR, "+", START_COLOR, "bbbb", RESET_COLOR, "+", START_COLOR, "cc", RESET_COLOR, "c", "+", " ", MARKER_END))]
#[case("aaa+bbbb+ccc+dddd", 2..11, format!("{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", " ", MARKER_START, "+", "aa", START_COLOR, "a", RESET_COLOR, "+", START_COLOR, "bbbb", RESET_COLOR, "+", START_COLOR, "cc", RESET_COLOR, "c", "+", " ", MARKER_END))]
#[case("aaa+bbbb+ccc+dddd", 4..12, format!("{}{}{}{}{}{}{}{}{}{}{}{}", MARKER_START, "+", START_COLOR, "bbbb", RESET_COLOR, "+", START_COLOR, "ccc", RESET_COLOR, "+", " ", MARKER_END))]
#[case("aaa+bbbb+ccc+dddd", 4..13, format!("{}{}{}{}{}{}{}{}{}{}{}{}", MARKER_START, "+", START_COLOR, "bbbb", RESET_COLOR, "+", START_COLOR, "ccc", RESET_COLOR, "+", " ", MARKER_END))]
#[case("aaa+bbbb+ccc+dddd", 4..16, format!("{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", MARKER_START, "+", START_COLOR, "bbbb", RESET_COLOR, "+", START_COLOR, "ccc", RESET_COLOR, "+", START_COLOR, "ddd", RESET_COLOR, "d", "+", " ", MARKER_END))]
#[case("abcd", 1..2, format!("{}{}{}{}{}{}{}{}{}{}{}", " ", MARKER_START, "+", "a", START_COLOR, "b", RESET_COLOR, "cd", "+", " ", MARKER_END))]
#[case("", 0..0, "")]
fn test_build_item(
#[case] content: &str,
Expand All @@ -124,13 +154,32 @@ mod tests {
let content = content.replace('+', "\n");

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

#[test]
fn test_build_item_with_line_number() {
let content = "aaaaaaa
bbbbbbb
ccccccc
ddddddd
eeeeeee";
assert_eq!(
build_item(content, 19, 30, &true, Some(&build_line_map(content))),
format!(
"{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}",
" ", MARKER_START, "+",
" 3 |", "ccc", START_COLOR, "cccc", RESET_COLOR, "+",
" 4 |", START_COLOR, "dddddd", RESET_COLOR, "d", "+",
" ", MARKER_END
).replace('+', "\n")
);
}

#[rstest]
#[case("aaa+bbbb+ccc+dddd", 4..11, format!("{}{}+{}{}{}{}{}+{}{}", "", MARKER_START, "", START_COLOR_YELLOW, "bbbb+cc", END_COLOR, "c", " ", MARKER_END))]
#[case("aaa+bbbb+ccc+dddd", 4..11, format!("{}{}{}{}{}{}{}{}{}{}{}{}{}", MARKER_START, "+", START_COLOR_YELLOW, "bbbb", RESET_COLOR, "+", START_COLOR_YELLOW, "cc", RESET_COLOR, "c", "+", " ", MARKER_END))]
fn test_build_item_pending_removal_range(
#[case] content: &str,
#[case] range: Range<usize>,
Expand All @@ -139,7 +188,7 @@ mod tests {
let content = content.replace('+', "\n");

assert_eq!(
build_item(&content, range.start, range.end, &false),
build_item(&content, range.start, range.end, &false, None),
expected.replace('+', "\n")
);
}
Expand All @@ -150,11 +199,11 @@ mod tests {
let content = "aaaa+bbbb+cccc+dddd".replace('+', "\n");
let markers = [((1..2, None), true), ((7..12, None), false)];

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

assert_eq!(
build_list(&content, &markers),
build_list(&content, &markers, None),
format!(
"\n{}1{}{}\n{}\n{}2{}{}\n{}\n",
HEAD_START,
Expand Down
1 change: 1 addition & 0 deletions chiritori/src/code/utils.rs
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
pub mod char_pos_finder;
pub mod line_break_pos_finder;
pub mod line_map;
37 changes: 37 additions & 0 deletions chiritori/src/code/utils/line_map.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
pub fn build_line_map(content: &str) -> Vec<usize> {
content.char_indices().fold(vec![], |mut acc, (byte_pos, c)| {
if c == '\n' {
acc.push(byte_pos)
}

acc
})
}

pub fn find_line(line_map: &[usize], needle: usize) -> usize {
let found = line_map.iter().position(|v| *v > needle);

if let Some(found) = found {
found + 1
} else {
line_map.len() + 1
}
}

#[cfg(test)]
mod tests {
use super::*;

const CONTENT: &str = "abc+def+efg+hijkl+mnopq";

#[test]
fn test_build_line_map() {
assert_eq!(build_line_map(&CONTENT.replace('+', "\n")), vec![3, 7, 11, 17]);
}

#[test]
fn test_find_line() {
let mapped = build_line_map(&CONTENT.replace('+', "\n"));
assert_eq!(find_line(&mapped, 9), 3);
}
}

0 comments on commit 4c09103

Please sign in to comment.