Skip to content

Commit

Permalink
shameful algebra on text blocks/text positions
Browse files Browse the repository at this point in the history
  • Loading branch information
nbacquey committed Nov 20, 2024
1 parent 23ef9f4 commit 74199c4
Showing 1 changed file with 65 additions and 2 deletions.
67 changes: 65 additions & 2 deletions topiary-core/src/tree_sitter.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use std::{collections::HashSet, fmt::Display};
use std::{cmp::{Ord, Ordering}, collections::HashSet, fmt::Display};

use serde::Serialize;
use topiary_tree_sitter_facade::{
Expand All @@ -22,7 +22,8 @@ pub enum Visualisation {
/// Refers to a position within the code. Used for error reporting, and for
/// comparing input with formatted output. The numbers are 1-based, because that
/// is how editors usually refer to a position. Derived from tree_sitter::Point.
#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize)]
/// Note that the order is the standard western reading order.
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Serialize)]
pub struct Position {
pub row: u32,
pub column: u32,
Expand Down Expand Up @@ -245,6 +246,68 @@ fn previous_non_comment<'tree>(node: Node<'tree>) -> Option<Node<'tree>> {
}
}

// Some section of contiguous characters in the input.
// It is assumed that `start <= end`, according to the order on `Position`.
#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
pub struct InputSection {
start: Position,
end: Position,
}

// This order only applies to disjoint sections, where it is the western reading order.
impl PartialOrd for InputSection {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
if self.end <= other.start {
Some(Ordering::Less)
} else if other.end <= self.start {
Some(Ordering::Greater)
} else if self == other {
Some(Ordering::Equal)
} else {
None
}
}
}

pub trait Diff<T,E> {
fn substract(self: &mut Self, other: &T) -> Result<(), E>;
}

impl Diff<InputSection, FormatterError> for Position {
fn substract(self: &mut Self, other: &InputSection) -> FormatterResult<()> {
if *self <= other.start {
// Nothing happens here
Ok(())
} else if other.end <= *self {
let mut row = self.row;
let mut column = self.column;
if row == other.end.row {
column = column + other.start.column - other.end.column
} else {
row = row + other.start.row - other.end.row
}
*self = Position{row, column};
Ok(())
} else {
Err(FormatterError::Internal("Tried to substract a section from a point it contains".into(), None))
}
}
}

impl Diff<InputSection, FormatterError> for InputSection {
fn substract(self: &mut Self, other: &Self) -> FormatterResult<()> {
if *self <= *other {
// Nothing happens here
Ok(())
} else if other <= self {
self.start.substract(other)?;
self.end.substract(other)
} else {
Err(FormatterError::Internal("Tried to diff input sections that weren't comparable".into(), None))
}
}
}

// Use the following heuristics to find a comment's anchor:
// If the comment is only prefixed by blank symbols on its line, then the anchor is the
// next non-comment sibling node.
Expand Down

0 comments on commit 74199c4

Please sign in to comment.