shithub: purgatorio

ref: 76f5318cbd58fbe2bfc8cb51856bfa217c673bb7
dir: /appl/wm/vixen/vixen/change.b/

View raw version
Mod: adt {
	o: int;
	p: Pos;
	s: string;
	pick {
	Ins or
	Del =>
		# o & p are for start of change
	}

	invert:	fn(m: self ref Mod): ref Mod;
	text:	fn(m: self ref Mod): string;
};

Change: adt {
	inverted:	int;  # whether this is inverted.  significant for cursor position after applying
	l:	list of ref Mod;  # hd of list is last modification (also at later positions in file)
	ogen, ngen:	big;  # gen before and after this change

	beginpos:	fn(c: self ref Change): Pos;
	invert:		fn(c: self ref Change): ref Change;
	text:		fn(c: self ref Change): string;
};


Mod.invert(mm: self ref Mod): ref Mod
{
	pick m := mm {
	Ins =>	return ref Mod.Del (m.o, m.p, m.s);
	Del =>	return ref Mod.Ins (m.o, m.p, m.s);
	}
}

modtags := array[] of {"Ins", "Del"};
Mod.text(mm: self ref Mod): string
{
	s := sprint("Mod.%s(", modtags[tagof mm]);
	pick m := mm {
	Ins =>	s += sprint("o=%d, p=%s, s=%q", m.o, m.p.text(), m.s);
	Del =>	s += sprint("o=%d, p=%s, s=%q", m.o, m.p.text(), m.s);
	}
	s += ")";
	return s;
}

Change.beginpos(c: self ref Change): Pos
{
	if(c.inverted)
		m := hd c.l;
	else
		m = hd rev(c.l);
	return m.p;
}

Change.invert(cc: self ref Change): ref Change
{
	c := ref Change (!cc.inverted, nil, cc.ngen, cc.ogen);
	for(l := rev(cc.l); l != nil; l = tl l)
		c.l = (hd l).invert()::c.l;
	return c;
}

Change.text(c: self ref Change): string
{
	s := sprint("Change(inverted=%d, ogen=%bd, ngen=%bd\n", c.inverted, c.ogen, c.ngen);
	for(l := c.l; l != nil; l = tl l)
		s += "\t"+(hd l).text()+"\n";
	s += ")";
	return s;
}