Skip to content

Commit

Permalink
cli: use new diff technology too
Browse files Browse the repository at this point in the history
  • Loading branch information
Nadrieril committed Jan 2, 2025
1 parent 176a32f commit 2cd19c9
Show file tree
Hide file tree
Showing 5 changed files with 71 additions and 37 deletions.
18 changes: 10 additions & 8 deletions src/analyses/compute_rules.rs
Original file line number Diff line number Diff line change
Expand Up @@ -337,7 +337,7 @@ impl RenderablePredicate<'_> {
}

/// Intermediate representation used in the display process.
pub(crate) struct RenderableTypingRule<'a> {
struct RenderableTypingRule<'a> {
name: Rule,
preconditions: Vec<RenderablePredicate<'a>>,
postconditions: Vec<RenderablePredicate<'a>>,
Expand All @@ -353,7 +353,7 @@ impl<'a> TypingRule<'a> {
cstrs
}

pub(crate) fn make_renderable(
fn make_renderable(
&'a self,
_a: &'a Arenas<'a>,
style: PredicateStyle,
Expand Down Expand Up @@ -444,19 +444,21 @@ impl<'a> TypingRule<'a> {
options: self.options,
})
}
pub fn display_to_tree<'d>(
&self,
a: &'d Arenas<'d>,
style: PredicateStyle,
) -> Result<DisplayTree<'d>, IncompatibleStyle> {
Ok(self.make_renderable(a, style)?.display_to_tree(a, style))
}

pub fn display(&self, style: PredicateStyle) -> Result<String, IncompatibleStyle> {
let a = &Arenas::default();
Ok(self.make_renderable(a, style)?.display(style))
Ok(self.display_to_tree(a, style)?.to_string())
}
}

impl<'a> RenderableTypingRule<'a> {
pub fn display(&self, style: PredicateStyle) -> String {
let a = &Arenas::default();
self.display_to_tree(a, style).to_string()
}

pub fn display_to_tree<'d>(&self, a: &'d Arenas<'d>, style: PredicateStyle) -> DisplayTree<'d> {
let preconditions = DisplayTree::sep_by(
a,
Expand Down
40 changes: 27 additions & 13 deletions src/ast/printer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,68 +6,82 @@ use crate::*;
pub mod display_tree;
pub use display_tree::*;

pub trait Style {
pub trait Style: Display + AsRef<str> {
fn green(&self) -> String;
fn red(&self) -> String;
fn comment(&self) -> String;
fn dimmed(&self) -> String;
fn tooltip(&self, text: &str) -> String;
fn inherited_ref(&self) -> String;
fn code(&self) -> String;

fn wrap_in_tag(&self, tag_name: &str, tag_args: Option<(&str, &str)>) -> String {
let tag_args = tag_args
.map(|(k, v)| format!("{k}=\"{v}\""))
.unwrap_or_default();
format!("<{tag_name} {tag_args}>{self}</{tag_name}>")
}
fn span_style(&self, style: &str) -> String {
self.wrap_in_tag("span", Some(("style", style)))
}
fn apply_colorize<'a>(&'a self, f: impl Fn(&'a str) -> colored::ColoredString) -> String {
// Apply line-by-line so that we can split by line later without messing up escape codes.
self.as_ref().lines().map(|line| f(line)).join("\n")
}
}

impl<T: Display + AsRef<str>> Style for T {
fn green(&self) -> String {
if cfg!(target_arch = "wasm32") {
format!("<span style=\"color: green\">{self}</span>")
self.span_style("color: green")
} else {
use colored::Colorize;
<_ as Colorize>::green(self.as_ref()).to_string()
self.apply_colorize(<_ as Colorize>::green)
}
}
fn red(&self) -> String {
if cfg!(target_arch = "wasm32") {
format!("<span style=\"color: red\">{self}</span>")
self.span_style("color: red")
} else {
use colored::Colorize;
<_ as Colorize>::red(self.as_ref()).to_string()
self.apply_colorize(<_ as Colorize>::red)
}
}
fn dimmed(&self) -> String {
if cfg!(target_arch = "wasm32") {
format!("<span style=\"opacity: 0.5\">{self}</span>")
self.span_style("opacity: 0.5")
} else {
use colored::Colorize;
<_ as Colorize>::dimmed(self.as_ref()).to_string()
self.apply_colorize(<_ as Colorize>::dimmed)
}
}
fn comment(&self) -> String {
if cfg!(target_arch = "wasm32") {
format!("<span style=\"color: dimgray\">{self}</span>")
self.span_style("color: dimgray")
} else {
use colored::Colorize;
<_ as Colorize>::dimmed(self.as_ref()).to_string()
self.apply_colorize(<_ as Colorize>::dimmed)
}
}
fn tooltip(&self, text: &str) -> String {
if cfg!(target_arch = "wasm32") {
format!("<span title=\"{text}\">{self}</span>")
self.wrap_in_tag("span", Some(("title", text)))
} else {
self.to_string()
}
}
fn inherited_ref(&self) -> String {
if cfg!(target_arch = "wasm32") {
format!("<span class=\"inherited-ref\">{self}</span>")
self.wrap_in_tag("span", Some(("class", "inherited-ref")))
} else {
use colored::Colorize;
<_ as Colorize>::dimmed(self.as_ref()).to_string()
self.apply_colorize(<_ as Colorize>::dimmed)
}
.tooltip("inherited reference")
}
fn code(&self) -> String {
if cfg!(target_arch = "wasm32") {
format!("<code>{self}</code>")
self.wrap_in_tag("code", None)
} else {
format!("`{self}`")
}
Expand Down
2 changes: 1 addition & 1 deletion src/ast/printer/display_tree.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ pub struct DisplayTree<'a> {

/// Compute the length of this string as displayed on the screen (i.e. ignoring html tags or ansi
/// escapes, depending on context).
fn len_ignoring_markup(s: &str) -> usize {
pub(crate) fn len_ignoring_markup(s: &str) -> usize {
if cfg!(target_arch = "wasm32") {
// Compute string length skipping html tags.
let mut in_tag = false;
Expand Down
42 changes: 31 additions & 11 deletions src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -106,23 +106,26 @@ impl CliState {
right: RuleOptions,
) -> Result<String, IncompatibleStyle> {
let style = self.predicate_style;
let arenas = &Arenas::default();
let a = &Arenas::default();
let type_of_interest = style.type_of_interest();
let joint_rules = compute_joint_rules(arenas, type_of_interest, left, right);
let joint_rules = compute_joint_rules(a, type_of_interest, left, right);

let mut out = String::new();
for joint_rule in joint_rules {
let (left, right) = joint_rule.left_and_right();
let (left, right) = joint_rule.as_ref().left_and_right();
let left = left
.map(|r| r.display(style))
.transpose()?
.map(|r| r.display_to_tree(a, style).unwrap())
.unwrap_or_default();
let right = right
.map(|r| r.display(style))
.transpose()?
.map(|r| r.display_to_tree(a, style).unwrap())
.unwrap_or_default();
out += &DiffState::side_by_side(&left, &right);
let _ = writeln!(&mut out);
let (mut left, mut right, has_diff) = left.diff_display_has_diff(&right);
if !has_diff {
left = left.dimmed();
right = right.dimmed();
}
out += &side_by_side(&left, &right);
out += "\n";
}
Ok(out)
}
Expand Down Expand Up @@ -413,6 +416,19 @@ pub fn display_rules(
Ok(out)
}

fn side_by_side(left: &str, right: &str) -> String {
let mut out = String::new();
for x in left.lines().zip_longest(right.lines()) {
let (l, r) = x.or("", "");
let pad = 80usize
.checked_sub(len_ignoring_markup(l))
.unwrap_or_default();
let pad = " ".repeat(pad);
let _ = writeln!(&mut out, " {l}{pad} | {r}");
}
out
}

#[derive(Clone, Copy, PartialEq, Eq)]
enum DiffState {
Both,
Expand All @@ -439,13 +455,17 @@ impl DiffState {
use DiffState::*;
let mut out = String::new();
for x in left.lines().zip_longest(right.lines()) {
let (l, r) = x.or(" ", " ");
let (l, r) = x.or("", "");
let pad = 80usize
.checked_sub(len_ignoring_markup(l))
.unwrap_or_default();
let pad = " ".repeat(pad);
let same = l == r;
let l_state = if same { Both } else { Old };
let r_state = if same { Both } else { New };
let l = l_state.color_line(l);
let r = r_state.color_line(r);
let _ = writeln!(&mut out, " {l:80} | {r}");
let _ = writeln!(&mut out, " {l}{pad} | {r}");
}
out
}
Expand Down
6 changes: 2 additions & 4 deletions src/wasm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -278,12 +278,10 @@ pub fn display_joint_rules_js(
.map(|joint_rule| {
let (left, right) = joint_rule.as_ref().left_and_right();
let left = left
.map(|r| r.make_renderable(a, style).unwrap())
.map(|r| r.display_to_tree(a, style))
.map(|r| r.display_to_tree(a, style).unwrap())
.unwrap_or_default();
let right = right
.map(|r| r.make_renderable(a, style).unwrap())
.map(|r| r.display_to_tree(a, style))
.map(|r| r.display_to_tree(a, style).unwrap())
.unwrap_or_default();
let (mut left, mut right, has_diff) = left.diff_display_has_diff(&right);
if !has_diff {
Expand Down

0 comments on commit 2cd19c9

Please sign in to comment.