Skip to content

Commit 002fa4b

Browse files
committed
new editor things
1 parent fabdc4c commit 002fa4b

25 files changed

Lines changed: 2133 additions & 3 deletions

File tree

dist/demo/2025_2/polycope/main.js

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -449,6 +449,21 @@ export const createEditorEnv = () => {
449449
let postfix = balance > 0 ? "<)".repeat(balance) : "";
450450
return prefix + inner + postfix;
451451
}
452+
function dog(selected) {
453+
let balance = 0;
454+
const inner = selected.map((v) => {
455+
const s = getCaretopeSinkFromAdrId(v);
456+
if (s.isFirst())
457+
if (s.isAfterEditorSink) {
458+
balance--;
459+
return "<)";
460+
}
461+
return s.isFirst() ? "(>" : "" + s.charEl.innerText;
462+
});
463+
let prefix = balance < 0 ? "(>".repeat(Math.abs(balance)) : "";
464+
let postfix = balance > 0 ? "<)".repeat(balance) : "";
465+
return prefix + inner + postfix;
466+
}
452467
e1.addEventListener("scroll", () => {
453468
renderCaret();
454469
});
@@ -507,6 +522,7 @@ export const createEditorEnv = () => {
507522
for (const cursor of cursors) {
508523
if (cursor.getAdr().id !== cursors[0].getAdr().id) removeCursor(cursor);
509524
}
525+
clearStyleSelectionSinks();
510526
for (const { setAdr, getAdr } of cursors) {
511527
setAdr({ ...getAdr(), selected: calcSelection(getAdr()) });
512528
}
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
class Node {
2+
constructor({ list, prev, next, data, id }) {
3+
this.id = id;
4+
this.pointers = new Set();
5+
6+
this.list = list;
7+
this.prev = prev;
8+
this.next = next;
9+
this.data = data;
10+
11+
list.nodeFromId.set(this.id, this);
12+
}
13+
}
14+
15+
export class DLinkedList {
16+
listeners = [];
17+
onChange(f) {
18+
this.listeners.push(f);
19+
}
20+
pointer(node) {
21+
let _node = node;
22+
const p = {
23+
get node() {
24+
return _node;
25+
},
26+
set node(newNode) {
27+
_node.pointers.delete(p);
28+
newNode.pointers.add(p);
29+
_node = newNode;
30+
},
31+
};
32+
node.pointers.add(p);
33+
return p;
34+
}
35+
36+
nodeFromId = new Map();
37+
38+
start = new Node({ list: this });
39+
end = this.start;
40+
41+
addAfter(prev, data, dontPropagate, id) {
42+
if (prev === undefined) throw new Error("trying to addAfter undefined");
43+
const newNode = new Node({
44+
id,
45+
list: this,
46+
pointers: new Set(),
47+
prev,
48+
next: prev.next,
49+
data,
50+
});
51+
data.node = newNode;
52+
if (newNode.next) newNode.next.prev = newNode;
53+
prev.next = newNode;
54+
55+
if (prev === this.end) this.end = newNode;
56+
57+
this.listeners.forEach((f) =>
58+
f({
59+
method: "addAfter",
60+
args: arguments,
61+
returns: newNode,
62+
})
63+
);
64+
65+
return newNode;
66+
}
67+
68+
remove(node) {
69+
if (!node) throw new Error("passed a non-node to remove!");
70+
if (node === this.start) throw new Error("cannot remove start node");
71+
node.removed = true;
72+
73+
node.prev.next = node.next;
74+
if (node.next !== undefined) node.next.prev = node.prev;
75+
76+
// move pointers to previous node
77+
for (const pointer of node.pointers) pointer.node = node.prev;
78+
79+
if (node === this.end) this.end = node.prev;
80+
81+
this.listeners.forEach((f) =>
82+
f({
83+
method: "remove",
84+
args: arguments,
85+
returns: node.prev,
86+
})
87+
);
88+
89+
return node.prev;
90+
}
91+
92+
*[Symbol.iterator]() {
93+
let cur = this.start.next;
94+
while (cur !== undefined) {
95+
yield cur;
96+
cur = cur.next;
97+
}
98+
}
99+
*traverseWithStart() {
100+
let cur = this.start;
101+
while (cur !== undefined) {
102+
yield cur;
103+
cur = cur.next;
104+
}
105+
}
106+
*traverseForward(node) {
107+
let cur = node.next;
108+
while (cur !== undefined) {
109+
yield cur;
110+
cur = cur.next;
111+
}
112+
}
113+
}
Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
import { MapWithInverse } from "../../../lib/structure/data.js";
2+
3+
import { DLinkedList } from "./DLinkedList.js";
4+
5+
export function createSyncedListAndListOfLists() {
6+
// string of character objects
7+
const l = new DLinkedList();
8+
9+
// now I want a list of lists that I can add and remove from
10+
// that is synced with the `ll`
11+
12+
// list of lines of character objects
13+
const lol = new DLinkedList();
14+
const line0Node = lol.addAfter(lol.start, createLine());
15+
16+
// let's sync em up
17+
18+
const lolFroml = new MapWithInverse();
19+
const lFromlol = lolFroml.inverse;
20+
lolFroml.set(l.start, line0Node.data.start);
21+
22+
l.onChange(({ method, args, returns }) => {
23+
if (method === "addAfter") {
24+
const [prev, newData, dontPropagate] = args;
25+
const newNode = returns;
26+
27+
if (dontPropagate) return;
28+
29+
// find the node corresponding to `prev` in `lol`
30+
const lolPrev = lolFroml.get(prev);
31+
// then
32+
// if node is a newline, create new line
33+
if (newNode.data.char === "\n") {
34+
const newLine = createLine();
35+
const newLineNode = lol.addAfter(lolPrev.list.node, newLine, true);
36+
37+
lolFroml.set(newNode, newLine.start);
38+
39+
// and move over everything in the line!
40+
// get everything in lolPrev.list after lolPrev and move it over!
41+
for (const node of lolPrev.list.traverseForward(lolPrev)) {
42+
lolPrev.list.remove(node, true);
43+
// move correspondence to new node
44+
lolFroml.set(
45+
lFromlol.get(node),
46+
newLine.addAfter(newLine.end, node.data, true)
47+
);
48+
}
49+
}
50+
// else addAfter corresponding node
51+
else {
52+
const lolNewNode = lolPrev.list.addAfter(lolPrev, newNode.data, true);
53+
lolFroml.set(newNode, lolNewNode);
54+
}
55+
}
56+
if (method === "remove") {
57+
const [node, dontPropagate] = args;
58+
const prev = returns;
59+
60+
if (dontPropagate) return;
61+
62+
// find the node corresponding to `node` in `lol`
63+
const lolRemove = lolFroml.get(node);
64+
// then
65+
const line = lolRemove.list;
66+
// if node is a newline, remove line and join two lines
67+
if (node.data.char === "\n") {
68+
lol.remove(line.node, true);
69+
70+
const lineBefore = line.node.prev.data;
71+
for (const node of line) {
72+
const newNode = lineBefore.addAfter(lineBefore.end, node.data, true);
73+
lFromlol.set(newNode, lFromlol.get(node));
74+
}
75+
}
76+
// else remove the node
77+
else {
78+
lolRemove.list.remove(lolRemove, true);
79+
}
80+
}
81+
});
82+
83+
// Now for the backwards direction!
84+
85+
lol.onChange(({ method, args, returns }) => {
86+
if (method === "addAfter") {
87+
const [prev, newData, dontPropagate] = args;
88+
const newNode = returns;
89+
90+
if (dontPropagate) return;
91+
92+
// new line, so add \n
93+
const lPrev = lFromlol.get(prev.data.end);
94+
const newlNewlineNode = l.addAfter(lPrev, { char: "\n" }, true);
95+
lFromlol.set(newNode.data.start, newlNewlineNode);
96+
}
97+
if (method === "remove") {
98+
const [node, dontPropagate] = args;
99+
const prev = returns;
100+
101+
if (dontPropagate) return;
102+
103+
const lNode = lFromlol.get(node.data.start);
104+
105+
if (lNode === l.start) {
106+
if (node.next === undefined) throw `can't remove the only line!`;
107+
const firstNewLineNode = node.next.data.start;
108+
109+
l.remove(lFromlol.get(firstNewLineNode), true);
110+
lFromlol.set(firstNewLineNode, l.start);
111+
} else {
112+
l.remove(lNode, true);
113+
}
114+
for (const n of node.data) l.remove(lFromlol.get(n));
115+
}
116+
});
117+
118+
//... We'll have to set up listeners whenever new lines are created
119+
120+
function createLine() {
121+
const line = new DLinkedList();
122+
line.onChange(({ method, args, returns }) => {
123+
if (method === "addAfter") {
124+
const [prev, newData, dontPropagate] = args;
125+
const newNode = returns;
126+
127+
if (dontPropagate) return;
128+
129+
// simply add character
130+
const newLineNode = l.addAfter(lFromlol.get(prev), newData, true);
131+
lFromlol.set(newLineNode, newNode);
132+
}
133+
if (method === "remove") {
134+
const [node, dontPropagate] = args;
135+
const prev = returns;
136+
137+
if (dontPropagate) return;
138+
139+
// simply remove character
140+
l.remove(lFromlol.get(node), true);
141+
}
142+
});
143+
return line;
144+
}
145+
146+
return { l, lol, lolFroml, lFromlol };
147+
}

0 commit comments

Comments
 (0)