Skip to content

Commit

Permalink
Add diff command
Browse files Browse the repository at this point in the history
  • Loading branch information
vinc committed Sep 15, 2024
1 parent 8421c49 commit 0f6546b
Show file tree
Hide file tree
Showing 3 changed files with 128 additions and 5 deletions.
121 changes: 121 additions & 0 deletions src/usr/diff.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
use crate::api::console::Style;
use crate::api::fs;
use crate::api::process::ExitCode;

use core::cmp;
use alloc::string::String;
use alloc::vec::Vec;
use alloc::vec;

#[derive(Debug, PartialEq)]
enum Diff {
Equal(String),
Insert(String),
Delete(String),
}

fn diff(old: &str, new: &str) -> Vec<Diff> {
let old: Vec<&str> = old.lines().collect();
let new: Vec<&str> = new.lines().collect();
backtrack(&old, &new, &lcs(&old, &new))
}

fn lcs(old: &[&str], new: &[&str]) -> Vec<Vec<usize>> {
let n = old.len();
let m = new.len();
let mut lcs = vec![vec![0; m + 1]; n + 1];

for i in 0..n {
for j in 0..m {
if old[i] == new[j] {
lcs[i + 1][j + 1] = lcs[i][j] + 1;
} else {
lcs[i + 1][j + 1] = cmp::max(lcs[i][j + 1], lcs[i + 1][j]);
}
}
}

lcs
}

fn backtrack(old: &[&str], new: &[&str], lcs: &[Vec<usize>]) -> Vec<Diff> {
let mut diff = Vec::new();
let mut i = old.len();
let mut j = new.len();

while i > 0 && j > 0 {
if old[i - 1] == new[j - 1] {
diff.push(Diff::Equal(old[i - 1].into()));
i -= 1;
j -= 1;
} else if lcs[i][j - 1] > lcs[i - 1][j] {
diff.push(Diff::Insert(new[j - 1].into()));
j -= 1;
} else {
diff.push(Diff::Delete(old[i - 1].into()));
i -= 1;
}
}

while i > 0 {
diff.push(Diff::Delete(old[i - 1].into()));
i -= 1;
}

while j > 0 {
diff.push(Diff::Insert(new[j - 1].into()));
j -= 1;
}

diff.reverse();
diff
}

pub fn main(args: &[&str]) -> Result<(), ExitCode> {
let csi_insert = Style::color("green");
let csi_delete = Style::color("red");
let csi_reset = Style::reset();
if let Ok(old) = fs::read_to_string(args[1]) {
if let Ok(new) = fs::read_to_string(args[2]) {
for op in diff(&old, &new) {
match op {
Diff::Equal(line) => {
println!(" {}", line);
}
Diff::Delete(line) => {
println!("{}-{}{}", csi_delete, line, csi_reset);
}
Diff::Insert(line) => {
println!("{}+{}{}", csi_insert, line, csi_reset);
}
}
}
}
}
Ok(())
}

#[test_case]
fn test_diff() {
assert_eq!(
diff("a", "a"),
vec![
Diff::Equal("a".into())
]
);
assert_eq!(
diff("a", "b"),
vec![
Diff::Insert("b".into()),
Diff::Delete("a".into())
]
);
assert_eq!(
diff("a\nb\nc\n", "a\nc\n"),
vec![
Diff::Equal("a".into()),
Diff::Delete("b".into()),
Diff::Equal("c".into())
]
);
}
1 change: 1 addition & 0 deletions src/usr/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ pub mod date;
pub mod decode;
pub mod delete;
pub mod dhcp;
pub mod diff;
pub mod disk;
pub mod edit;
pub mod elf;
Expand Down
11 changes: 6 additions & 5 deletions src/usr/shell.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,12 @@ use alloc::vec::Vec;
use core::sync::atomic::{fence, Ordering};

// TODO: Scan /bin
const AUTOCOMPLETE_COMMANDS: [&str; 39] = [
const AUTOCOMPLETE_COMMANDS: [&str; 40] = [
"2048", "calc", "chess", "copy", "date", "decode", "delete", "dhcp",
"disk", "edit", "elf", "encode", "env", "goto", "hash", "help", "hex",
"host", "http", "httpd", "install", "keyboard", "life", "lisp", "list",
"memory", "move", "net", "pci", "quit", "read", "shell", "socket", "tcp",
"time", "user", "vga", "view", "write",
"diff", "disk", "edit", "elf", "encode", "env", "goto", "hash", "help",
"hex", "host", "http", "httpd", "install", "keyboard", "life", "lisp",
"list", "memory", "move", "net", "pci", "quit", "read", "shell", "socket",
"tcp", "time", "user", "vga", "view", "write",
];

struct Config {
Expand Down Expand Up @@ -524,6 +524,7 @@ fn dispatch(args: &[&str], config: &mut Config) -> Result<(), ExitCode> {
"decode" => usr::decode::main(args),
"delete" => usr::delete::main(args),
"dhcp" => usr::dhcp::main(args),
"diff" => usr::diff::main(args),
"disk" => usr::disk::main(args),
"edit" => usr::edit::main(args),
"elf" => usr::elf::main(args),
Expand Down

0 comments on commit 0f6546b

Please sign in to comment.