a whole ENTIRE THING
This commit is contained in:
1 parent
f87b3e7fe2
commit
985970453c
8 files changed
+299
-3
No files matched your search
Generated
+8
@@ -6,6 +6,14 @@ version = 4
|
|||||||
name = "lda_ansi"
|
name = "lda_ansi"
|
||||||
version = "0.0.1"
|
version = "0.0.1"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "lda_sd_visualizer"
|
||||||
|
version = "0.0.1"
|
||||||
|
dependencies = [
|
||||||
|
"lda_ansi",
|
||||||
|
"lda_strdist",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "lda_strdist"
|
name = "lda_strdist"
|
||||||
version = "0.0.1"
|
version = "0.0.1"
|
||||||
+1
-1
@@ -1,3 +1,3 @@
|
|||||||
[workspace]
|
[workspace]
|
||||||
members = ["lda_ansi","lda_strdist"]
|
members = ["lda_ansi", "lda_sd_visualizer","lda_strdist"]
|
||||||
resolver = "2"
|
resolver = "2"
|
||||||
+1
-1
Submodule lda_ansi updated: 03e55e7ae7...de4c23020d.
@@ -0,0 +1,8 @@
|
|||||||
|
[package]
|
||||||
|
name = "lda_sd_visualizer"
|
||||||
|
version = "0.0.1"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
lda_ansi = { version = "0.0.1", path = "../lda_ansi" }
|
||||||
|
lda_strdist = { version = "0.0.1", path = "../lda_strdist" }
|
||||||
@@ -0,0 +1,253 @@
|
|||||||
|
#![allow(unused_variables)]
|
||||||
|
|
||||||
|
mod test;
|
||||||
|
use lda_strdist::{levenstein_distance, EditCost, EditOperation};
|
||||||
|
|
||||||
|
use lda_ansi::{
|
||||||
|
ansi_backbone::Style as StyleConstruct,
|
||||||
|
ansi_colors_2::{ansi_color_interface::ColorContext, Color},
|
||||||
|
ansi_styles::Style,
|
||||||
|
AnsiStyles,
|
||||||
|
};
|
||||||
|
|
||||||
|
/// produce new thing with lint, inefficient, ass
|
||||||
|
///
|
||||||
|
/// not by chatgpt
|
||||||
|
pub fn compare_format(str1: &str, str2: &str) -> (String, String) {
|
||||||
|
let (_, ops) = levenstein_distance(str1, str2, &EditCost::default());
|
||||||
|
let mut ops = ops.into_iter();
|
||||||
|
let deleted_style = StyleConstruct::new().color(Color::Red.fg()).to_owned();
|
||||||
|
let added_style = StyleConstruct::new().color(Color::Green.fg()).to_owned();
|
||||||
|
|
||||||
|
let mut first_vec: Vec<AnsiStyles> = Vec::new();
|
||||||
|
let mut second_vec: Vec<AnsiStyles> = Vec::new();
|
||||||
|
|
||||||
|
let Some(mut recentest_edit) = ops.next() else {
|
||||||
|
return ("".into(), "".into());
|
||||||
|
};
|
||||||
|
|
||||||
|
let different = |edit: &EditOperation, fv: &mut Vec<AnsiStyles>, sv: &mut Vec<AnsiStyles>| {
|
||||||
|
use EditOperation::*;
|
||||||
|
match *edit {
|
||||||
|
Delete { char } => {
|
||||||
|
let mut f = AnsiStyles::init(&char.to_string());
|
||||||
|
f.add_style(&deleted_style);
|
||||||
|
fv.push(f);
|
||||||
|
}
|
||||||
|
Insert { char } => {
|
||||||
|
let mut f = AnsiStyles::init(&char.to_string());
|
||||||
|
f.add_style(&added_style);
|
||||||
|
sv.push(f);
|
||||||
|
}
|
||||||
|
Match { char } => {
|
||||||
|
let f = AnsiStyles::init(&char.to_string())
|
||||||
|
.style(StyleConstruct::new().style(Style::Reset).to_owned());
|
||||||
|
sv.push(f.clone());
|
||||||
|
fv.push(f);
|
||||||
|
}
|
||||||
|
Substitute { from, to } => {
|
||||||
|
let tos = AnsiStyles::init(&to.to_string()).style(added_style.clone());
|
||||||
|
sv.push(tos);
|
||||||
|
let froms = AnsiStyles::init(&from.to_string()).style(deleted_style.clone());
|
||||||
|
fv.push(froms);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
different(&recentest_edit, &mut first_vec, &mut second_vec);
|
||||||
|
// for first thing
|
||||||
|
|
||||||
|
for i in ops {
|
||||||
|
if std::mem::discriminant(&i) == std::mem::discriminant(&recentest_edit) {
|
||||||
|
use EditOperation::*;
|
||||||
|
match i {
|
||||||
|
Delete { char } => {
|
||||||
|
if let Some(f) = first_vec.last_mut() {
|
||||||
|
f.text.push(char)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Insert { char } => {
|
||||||
|
if let Some(s) = second_vec.last_mut() {
|
||||||
|
s.text.push(char)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Match { char } => {
|
||||||
|
if let Some(f) = first_vec.last_mut() {
|
||||||
|
f.text.push(char)
|
||||||
|
};
|
||||||
|
if let Some(s) = second_vec.last_mut() {
|
||||||
|
s.text.push(char)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
Substitute { from, to } => {
|
||||||
|
if let Some(f) = first_vec.last_mut() {
|
||||||
|
f.text.push(from)
|
||||||
|
};
|
||||||
|
if let Some(s) = second_vec.last_mut() {
|
||||||
|
s.text.push(to)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
different(&i, &mut first_vec, &mut second_vec);
|
||||||
|
};
|
||||||
|
|
||||||
|
recentest_edit = i;
|
||||||
|
}
|
||||||
|
let first_str: String = first_vec.into_iter().map(String::from).collect();
|
||||||
|
let second_str: String = second_vec.into_iter().map(String::from).collect();
|
||||||
|
(first_str, second_str)
|
||||||
|
}
|
||||||
|
|
||||||
|
// you can tell right away what code this is
|
||||||
|
struct FilterConfig<F, G>
|
||||||
|
where
|
||||||
|
F: Fn(&EditOperation) -> bool,
|
||||||
|
G: Fn(&EditOperation) -> Option<char>,
|
||||||
|
{
|
||||||
|
should_be_colored: F,
|
||||||
|
extract_char: G,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<F, G> FilterConfig<F, G>
|
||||||
|
where
|
||||||
|
F: Fn(&EditOperation) -> bool,
|
||||||
|
G: Fn(&EditOperation) -> Option<char>,
|
||||||
|
{
|
||||||
|
fn new(should_be_colored: F, extract_char: G) -> Self {
|
||||||
|
Self {
|
||||||
|
should_be_colored,
|
||||||
|
extract_char,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn split_operations<F, G>(
|
||||||
|
f_ops: &Vec<EditOperation>,
|
||||||
|
config: &FilterConfig<F, G>,
|
||||||
|
color: StyleConstruct,
|
||||||
|
reset: StyleConstruct,
|
||||||
|
) -> String
|
||||||
|
where
|
||||||
|
F: Fn(&EditOperation) -> bool,
|
||||||
|
G: Fn(&EditOperation) -> Option<char>,
|
||||||
|
{
|
||||||
|
let mut result = Vec::new();
|
||||||
|
let mut current_group = AnsiStyles::new();
|
||||||
|
let mut last_group_was_colored: bool;
|
||||||
|
if let Some(first_op) = f_ops.first() {
|
||||||
|
last_group_was_colored = (config.should_be_colored)(first_op);
|
||||||
|
if last_group_was_colored {
|
||||||
|
current_group.add_style(&color);
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
return String::new();
|
||||||
|
}
|
||||||
|
for op in f_ops {
|
||||||
|
let this_should_be_colored = (config.should_be_colored)(op);
|
||||||
|
if this_should_be_colored {
|
||||||
|
if !current_group.text.is_empty() && !last_group_was_colored {
|
||||||
|
result.push(current_group);
|
||||||
|
current_group = AnsiStyles::new();
|
||||||
|
current_group.add_style(&color);
|
||||||
|
}
|
||||||
|
if let Some(c) = (config.extract_char)(op) {
|
||||||
|
current_group.text.push(c);
|
||||||
|
}
|
||||||
|
last_group_was_colored = this_should_be_colored;
|
||||||
|
} else {
|
||||||
|
if last_group_was_colored {
|
||||||
|
result.push(current_group);
|
||||||
|
current_group = AnsiStyles::new();
|
||||||
|
current_group.add_style(&reset);
|
||||||
|
}
|
||||||
|
if let EditOperation::Match { char: c } = op {
|
||||||
|
current_group.text.push(*c);
|
||||||
|
}
|
||||||
|
last_group_was_colored = this_should_be_colored;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !current_group.text.is_empty() {
|
||||||
|
result.push(current_group);
|
||||||
|
}
|
||||||
|
|
||||||
|
result.into_iter().map(String::from).collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn filter_from(f_ops: &Vec<EditOperation>) -> String {
|
||||||
|
let red = StyleConstruct::new().color(Color::Red.fg()).to_owned();
|
||||||
|
let reset = StyleConstruct::new().style(Style::Reset).to_owned();
|
||||||
|
|
||||||
|
let config = FilterConfig::new(
|
||||||
|
|op| {
|
||||||
|
matches!(
|
||||||
|
op,
|
||||||
|
EditOperation::Delete { .. } | EditOperation::Substitute { .. }
|
||||||
|
)
|
||||||
|
},
|
||||||
|
|op| match op {
|
||||||
|
EditOperation::Delete { char } => Some(*char),
|
||||||
|
EditOperation::Substitute { from, .. } => Some(*from),
|
||||||
|
_ => None,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
split_operations(f_ops, &config, red, reset)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn filter_to(f_ops: &Vec<EditOperation>) -> String {
|
||||||
|
let blue = StyleConstruct::new().color(Color::Blue.fg()).to_owned();
|
||||||
|
let reset = StyleConstruct::new().style(Style::Reset).to_owned();
|
||||||
|
|
||||||
|
let config = FilterConfig::new(
|
||||||
|
|op| {
|
||||||
|
matches!(
|
||||||
|
op,
|
||||||
|
EditOperation::Insert { .. } | EditOperation::Substitute { .. }
|
||||||
|
)
|
||||||
|
},
|
||||||
|
|op| match op {
|
||||||
|
EditOperation::Insert { char } => Some(*char),
|
||||||
|
EditOperation::Substitute { to, .. } => Some(*to),
|
||||||
|
_ => None,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
split_operations(f_ops, &config, blue, reset)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// another way you do it, with chatgpt.
|
||||||
|
pub fn compare2_format(str1: &str, str2: &str) -> (String, String) {
|
||||||
|
let (_, ops) = levenstein_distance(str1, str2, &EditCost::default());
|
||||||
|
let to = filter_to(&ops);
|
||||||
|
let from = filter_from(&ops);
|
||||||
|
(from, to)
|
||||||
|
}
|
||||||
|
|
||||||
|
// struct FilterConfig {
|
||||||
|
// should_be_colored: Box<dyn Fn(&EditOperation) -> bool>,
|
||||||
|
// extract_char: Box<dyn Fn(&EditOperation) -> Option<char>>,
|
||||||
|
// }
|
||||||
|
|
||||||
|
// impl FilterConfig {
|
||||||
|
// fn new<F, G>(should_be_colored: F, extract_char: G) -> Self
|
||||||
|
// where
|
||||||
|
// F: 'static + Fn(&EditOperation) -> bool,
|
||||||
|
// G: 'static + Fn(&EditOperation) -> Option<char>,
|
||||||
|
// {
|
||||||
|
// Self {
|
||||||
|
// should_be_colored: Box::new(should_be_colored),
|
||||||
|
// extract_char: Box::new(extract_char),
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// fn split_operations(
|
||||||
|
// f_ops: &Vec<EditOperation>,
|
||||||
|
// config: &FilterConfig,
|
||||||
|
// color: StyleConstruct,
|
||||||
|
// reset: StyleConstruct,
|
||||||
|
// ) -> String {
|
||||||
|
// ...
|
||||||
|
// }
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
#![allow(unused)] // SHUT UP
|
||||||
|
|
||||||
|
use lda_ansi::{ansi_backbone::Style as StyleConstruct, ansi_styles::Style};
|
||||||
|
use lda_sd_visualizer::{compare2_format, compare_format};
|
||||||
|
use lda_strdist::{levenstein_distance, wrapper_::EditOperationVec, EditCost};
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let str1 = "this is similar";
|
||||||
|
let str2 = "is this important";
|
||||||
|
let (_, uuh) = levenstein_distance(str1, str2, &EditCost::default());
|
||||||
|
println!("{}", EditOperationVec(&uuh));
|
||||||
|
let (str1, str2) = compare2_format(str1, str2 );
|
||||||
|
println!("{str1} {0}changed to {str2}{0}", StyleConstruct::new().style(Style::Reset));
|
||||||
|
println!("{str1:#?} and {str2:#?}");
|
||||||
|
// holy shit it works
|
||||||
|
|
||||||
|
// NO IT DOESNT
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
#![cfg(test)]
|
||||||
|
|
||||||
|
// use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn it_works() {
|
||||||
|
let result = 2 + 2;
|
||||||
|
assert_eq!(result, 4);
|
||||||
|
}
|
||||||
+1
-1
Submodule lda_strdist updated: 6b24262927...34bd99d3b4.
Reference in new issue
Block a user