fix undo I think
This commit is contained in:
parent
8c750ac2dc
commit
a7ed7b87f2
408
codetab.ts
408
codetab.ts
@ -12,6 +12,152 @@ const historyDebounceFrames = 20;
|
|||||||
|
|
||||||
const fontHeight = font.height;
|
const fontHeight = font.height;
|
||||||
|
|
||||||
|
|
||||||
|
const keywords = [
|
||||||
|
"break",
|
||||||
|
"case",
|
||||||
|
"catch",
|
||||||
|
"class",
|
||||||
|
"const",
|
||||||
|
"continue",
|
||||||
|
"debugger",
|
||||||
|
"default",
|
||||||
|
"delete",
|
||||||
|
"do",
|
||||||
|
"else",
|
||||||
|
"export",
|
||||||
|
"extends",
|
||||||
|
"finally",
|
||||||
|
"for",
|
||||||
|
"function",
|
||||||
|
"if",
|
||||||
|
"import",
|
||||||
|
"in",
|
||||||
|
"instanceof",
|
||||||
|
"new",
|
||||||
|
"return",
|
||||||
|
"super",
|
||||||
|
"switch",
|
||||||
|
"this",
|
||||||
|
"throw",
|
||||||
|
"try",
|
||||||
|
"typeof",
|
||||||
|
"var",
|
||||||
|
"void",
|
||||||
|
"while",
|
||||||
|
"with",
|
||||||
|
"let",
|
||||||
|
"static",
|
||||||
|
"yield",
|
||||||
|
"await",
|
||||||
|
"enum",
|
||||||
|
"implements",
|
||||||
|
"interface",
|
||||||
|
"package",
|
||||||
|
"private",
|
||||||
|
"protected",
|
||||||
|
"public",
|
||||||
|
"=>",
|
||||||
|
];
|
||||||
|
const values = [
|
||||||
|
"false",
|
||||||
|
"null",
|
||||||
|
"true",
|
||||||
|
"undefined",
|
||||||
|
];
|
||||||
|
const operator = [
|
||||||
|
"&&",
|
||||||
|
"||",
|
||||||
|
"??",
|
||||||
|
"--",
|
||||||
|
"++",
|
||||||
|
".",
|
||||||
|
"?.",
|
||||||
|
"<",
|
||||||
|
"<=",
|
||||||
|
">",
|
||||||
|
">=",
|
||||||
|
"!=",
|
||||||
|
"!==",
|
||||||
|
"==",
|
||||||
|
"===",
|
||||||
|
"+",
|
||||||
|
"-",
|
||||||
|
"%",
|
||||||
|
"&",
|
||||||
|
"|",
|
||||||
|
"^",
|
||||||
|
"/",
|
||||||
|
"*",
|
||||||
|
"**",
|
||||||
|
"<<",
|
||||||
|
">>",
|
||||||
|
">>>",
|
||||||
|
"=",
|
||||||
|
"+=",
|
||||||
|
"-=",
|
||||||
|
"%=",
|
||||||
|
"&=",
|
||||||
|
"|=",
|
||||||
|
"^=",
|
||||||
|
"/=",
|
||||||
|
"*=",
|
||||||
|
"**=",
|
||||||
|
"<<=",
|
||||||
|
">>=",
|
||||||
|
">>>=",
|
||||||
|
"!",
|
||||||
|
"?",
|
||||||
|
"~",
|
||||||
|
"...",
|
||||||
|
];
|
||||||
|
const punctuation = [
|
||||||
|
"(",
|
||||||
|
")",
|
||||||
|
"[",
|
||||||
|
"]",
|
||||||
|
"{",
|
||||||
|
"}",
|
||||||
|
".",
|
||||||
|
":",
|
||||||
|
";",
|
||||||
|
",",
|
||||||
|
];
|
||||||
|
|
||||||
|
const builtinColor = COLOR.BLUE;
|
||||||
|
const keywordColor = COLOR.PURPLE;
|
||||||
|
const operatorColor = COLOR.CYAN;
|
||||||
|
const valueColor = COLOR.ORANGE;
|
||||||
|
const stringColor = COLOR.GREEN;
|
||||||
|
const regexColor = COLOR.PINK;
|
||||||
|
const punctuationColor = COLOR.LIGHTGRAY;
|
||||||
|
const commentColor = COLOR.DARKGREEN;
|
||||||
|
const identifierColor = COLOR.YELLOW;
|
||||||
|
const invalidColor = COLOR.RED;
|
||||||
|
|
||||||
|
const caretColor = COLOR.WHITE;
|
||||||
|
const selectionColor = COLOR.DARKBLUE;
|
||||||
|
|
||||||
|
const backgroundColor = COLOR.DARKERBLUE;
|
||||||
|
|
||||||
|
const tokenColors = {
|
||||||
|
"StringLiteral": stringColor,
|
||||||
|
"NoSubstitutionTemplate": stringColor,
|
||||||
|
"TemplateHead": stringColor,
|
||||||
|
"TemplateMiddle": stringColor,
|
||||||
|
"TemplateTail": stringColor,
|
||||||
|
"RegularExpressionLiteral": regexColor,
|
||||||
|
"MultiLineComment": commentColor,
|
||||||
|
"SingleLineComment": commentColor,
|
||||||
|
"IdentifierName": identifierColor,
|
||||||
|
"PrivateIdentifier": identifierColor,
|
||||||
|
"NumericLiteral": valueColor,
|
||||||
|
"Punctuator": punctuationColor,
|
||||||
|
"WhiteSpace": punctuationColor,
|
||||||
|
"LineTerminatorSequence": punctuationColor,
|
||||||
|
"Invalid": invalidColor,
|
||||||
|
}
|
||||||
|
|
||||||
const transformForCopy = (text: string) => {
|
const transformForCopy = (text: string) => {
|
||||||
text = text.replaceAll("➡", "➡️");
|
text = text.replaceAll("➡", "➡️");
|
||||||
text = text.replaceAll("⬅", "⬅️");
|
text = text.replaceAll("⬅", "⬅️");
|
||||||
@ -31,7 +177,7 @@ const transformForPaste = (text: string) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const state = {
|
const state = {
|
||||||
history: [{code: getCodeSheet(page.activeSheet), anchor: 0, focus: 0}],
|
history: [] as Array<{code: string, anchor: number, focus: number}>,
|
||||||
historyDebounce: 0,
|
historyDebounce: 0,
|
||||||
historyIndex: 0,
|
historyIndex: 0,
|
||||||
undo() {
|
undo() {
|
||||||
@ -68,7 +214,9 @@ const state = {
|
|||||||
},
|
},
|
||||||
startSnapping() {
|
startSnapping() {
|
||||||
console.log('start snapping', this.historyIndex);
|
console.log('start snapping', this.historyIndex);
|
||||||
|
if (this.historyDebounce <= 0) {
|
||||||
this.historyIndex += 1;
|
this.historyIndex += 1;
|
||||||
|
}
|
||||||
if (this.history.length > this.historyIndex) {
|
if (this.history.length > this.historyIndex) {
|
||||||
this.history.length = this.historyIndex;
|
this.history.length = this.historyIndex;
|
||||||
}
|
}
|
||||||
@ -291,204 +439,11 @@ const pixelToIndex = (str: string, x: number, y: number) => {
|
|||||||
return prefix + j;
|
return prefix + j;
|
||||||
}
|
}
|
||||||
|
|
||||||
const keywords = [
|
|
||||||
"break",
|
|
||||||
"case",
|
|
||||||
"catch",
|
|
||||||
"class",
|
|
||||||
"const",
|
|
||||||
"continue",
|
|
||||||
"debugger",
|
|
||||||
"default",
|
|
||||||
"delete",
|
|
||||||
"do",
|
|
||||||
"else",
|
|
||||||
"export",
|
|
||||||
"extends",
|
|
||||||
"finally",
|
|
||||||
"for",
|
|
||||||
"function",
|
|
||||||
"if",
|
|
||||||
"import",
|
|
||||||
"in",
|
|
||||||
"instanceof",
|
|
||||||
"new",
|
|
||||||
"return",
|
|
||||||
"super",
|
|
||||||
"switch",
|
|
||||||
"this",
|
|
||||||
"throw",
|
|
||||||
"try",
|
|
||||||
"typeof",
|
|
||||||
"var",
|
|
||||||
"void",
|
|
||||||
"while",
|
|
||||||
"with",
|
|
||||||
"let",
|
|
||||||
"static",
|
|
||||||
"yield",
|
|
||||||
"await",
|
|
||||||
"enum",
|
|
||||||
"implements",
|
|
||||||
"interface",
|
|
||||||
"package",
|
|
||||||
"private",
|
|
||||||
"protected",
|
|
||||||
"public",
|
|
||||||
"=>",
|
|
||||||
];
|
|
||||||
const values = [
|
|
||||||
"false",
|
|
||||||
"null",
|
|
||||||
"true",
|
|
||||||
"undefined",
|
|
||||||
];
|
|
||||||
const operator = [
|
|
||||||
"&&",
|
|
||||||
"||",
|
|
||||||
"??",
|
|
||||||
"--",
|
|
||||||
"++",
|
|
||||||
".",
|
|
||||||
"?.",
|
|
||||||
"<",
|
|
||||||
"<=",
|
|
||||||
">",
|
|
||||||
">=",
|
|
||||||
"!=",
|
|
||||||
"!==",
|
|
||||||
"==",
|
|
||||||
"===",
|
|
||||||
"+",
|
|
||||||
"-",
|
|
||||||
"%",
|
|
||||||
"&",
|
|
||||||
"|",
|
|
||||||
"^",
|
|
||||||
"/",
|
|
||||||
"*",
|
|
||||||
"**",
|
|
||||||
"<<",
|
|
||||||
">>",
|
|
||||||
">>>",
|
|
||||||
"=",
|
|
||||||
"+=",
|
|
||||||
"-=",
|
|
||||||
"%=",
|
|
||||||
"&=",
|
|
||||||
"|=",
|
|
||||||
"^=",
|
|
||||||
"/=",
|
|
||||||
"*=",
|
|
||||||
"**=",
|
|
||||||
"<<=",
|
|
||||||
">>=",
|
|
||||||
">>>=",
|
|
||||||
"!",
|
|
||||||
"?",
|
|
||||||
"~",
|
|
||||||
"...",
|
|
||||||
];
|
|
||||||
const punctuation = [
|
|
||||||
"(",
|
|
||||||
")",
|
|
||||||
"[",
|
|
||||||
"]",
|
|
||||||
"{",
|
|
||||||
"}",
|
|
||||||
".",
|
|
||||||
":",
|
|
||||||
";",
|
|
||||||
",",
|
|
||||||
];
|
|
||||||
|
|
||||||
const builtinColor = COLOR.BLUE;
|
|
||||||
const keywordColor = COLOR.PURPLE;
|
|
||||||
const operatorColor = COLOR.CYAN;
|
|
||||||
const valueColor = COLOR.ORANGE;
|
|
||||||
const stringColor = COLOR.GREEN;
|
|
||||||
const regexColor = stringColor;
|
|
||||||
const punctuationColor = COLOR.LIGHTGRAY;
|
|
||||||
const commentColor = COLOR.DARKGREEN;
|
|
||||||
const identifierColor = COLOR.RED;
|
|
||||||
const invalidColor = COLOR.DARKRED;
|
|
||||||
|
|
||||||
const tokenColors = {
|
|
||||||
"StringLiteral": stringColor,
|
|
||||||
"NoSubstitutionTemplate": stringColor,
|
|
||||||
"TemplateHead": stringColor,
|
|
||||||
"TemplateMiddle": stringColor,
|
|
||||||
"TemplateTail": stringColor,
|
|
||||||
"RegularExpressionLiteral": regexColor,
|
|
||||||
"MultiLineComment": commentColor,
|
|
||||||
"SingleLineComment": commentColor,
|
|
||||||
"IdentifierName": identifierColor,
|
|
||||||
"PrivateIdentifier": identifierColor,
|
|
||||||
"NumericLiteral": valueColor,
|
|
||||||
"Punctuator": punctuationColor,
|
|
||||||
"WhiteSpace": punctuationColor,
|
|
||||||
"LineTerminatorSequence": punctuationColor,
|
|
||||||
"Invalid": invalidColor,
|
|
||||||
}
|
|
||||||
|
|
||||||
const drawCodeField = (code: string, x: number, y: number, w: number, h: number) => {
|
|
||||||
const {
|
|
||||||
scrollX,
|
|
||||||
scrollY,
|
|
||||||
anchor,
|
|
||||||
focus,
|
|
||||||
} = state;
|
|
||||||
fillRect(x, y, w, h, COLOR.DARKERBLUE);
|
|
||||||
if (anchor !== focus) {
|
|
||||||
for (let i = Math.min(anchor, focus); i < Math.max(anchor, focus); i++) {
|
|
||||||
const sel = indexToRect(code, i);
|
|
||||||
fillRect(x+sel.x-scrollX, y+sel.y-scrollY, sel.w+2, sel.h, COLOR.WHITE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const rect = indexToRect(code, focus);
|
|
||||||
fillRect(x+rect.x-scrollX, y+rect.y-scrollY, 1, rect.h, COLOR.YELLOW);
|
|
||||||
|
|
||||||
const builtins = Object.keys(getBuiltins());
|
|
||||||
const tokens = [...tokenize(code)];
|
|
||||||
let cx = 0;
|
|
||||||
let cy = 0;
|
|
||||||
tokens.forEach((token) => {
|
|
||||||
if (token.type === "LineTerminatorSequence") {
|
|
||||||
cx=0;
|
|
||||||
cy+=fontHeight+1;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const lines = token.value.split("\n");
|
|
||||||
lines.forEach((line, i) => {
|
|
||||||
let color = tokenColors[token.type];
|
|
||||||
if (keywords.includes(token.value)) {
|
|
||||||
color = keywordColor;
|
|
||||||
}
|
|
||||||
if (values.includes(token.value)) {
|
|
||||||
color = valueColor;
|
|
||||||
}
|
|
||||||
if (operator.includes(token.value)) {
|
|
||||||
color = operatorColor;
|
|
||||||
}
|
|
||||||
if (punctuation.includes(token.value)) {
|
|
||||||
color = punctuationColor;
|
|
||||||
}
|
|
||||||
if (builtins.includes(token.value)) {
|
|
||||||
color = builtinColor;
|
|
||||||
}
|
|
||||||
drawText(1+x+cx-scrollX, 1+y+cy-scrollY, line, color);
|
|
||||||
if (i === lines.length-1) {
|
|
||||||
cx += measureText(line)+1;
|
|
||||||
} else {
|
|
||||||
cx=0;
|
|
||||||
cy+=fontHeight+1;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const update = async () => {
|
const update = async () => {
|
||||||
const { focus } = state;
|
const { focus } = state;
|
||||||
|
if (state.history.length === 0) {
|
||||||
|
state.snapshot();
|
||||||
|
}
|
||||||
if (state.historyDebounce > 0) {
|
if (state.historyDebounce > 0) {
|
||||||
state.historyDebounce -= 1;
|
state.historyDebounce -= 1;
|
||||||
if (state.historyDebounce <= 0) {
|
if (state.historyDebounce <= 0) {
|
||||||
@ -591,7 +546,64 @@ const update = async () => {
|
|||||||
|
|
||||||
const draw = () => {
|
const draw = () => {
|
||||||
clearScreen();
|
clearScreen();
|
||||||
drawCodeField(state.code, 0, 8, 128, 112);
|
const {
|
||||||
|
scrollX,
|
||||||
|
scrollY,
|
||||||
|
anchor,
|
||||||
|
focus,
|
||||||
|
code,
|
||||||
|
} = state;
|
||||||
|
const x = 0;
|
||||||
|
const y = 8;
|
||||||
|
const w = 128;
|
||||||
|
const h = 112;
|
||||||
|
fillRect(x, y, w, h, backgroundColor);
|
||||||
|
if (anchor !== focus) {
|
||||||
|
for (let i = Math.min(anchor, focus); i < Math.max(anchor, focus); i++) {
|
||||||
|
const sel = indexToRect(code, i);
|
||||||
|
fillRect(x+sel.x-scrollX, y+sel.y-scrollY, sel.w+2, sel.h, selectionColor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const rect = indexToRect(code, focus);
|
||||||
|
fillRect(x+rect.x-scrollX, y+rect.y-scrollY, 1, rect.h, caretColor);
|
||||||
|
|
||||||
|
const builtins = Object.keys(getBuiltins());
|
||||||
|
const tokens = [...tokenize(code)];
|
||||||
|
let cx = 0;
|
||||||
|
let cy = 0;
|
||||||
|
tokens.forEach((token) => {
|
||||||
|
if (token.type === "LineTerminatorSequence") {
|
||||||
|
cx=0;
|
||||||
|
cy+=fontHeight+1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const lines = token.value.split("\n");
|
||||||
|
lines.forEach((line, i) => {
|
||||||
|
let color = tokenColors[token.type];
|
||||||
|
if (keywords.includes(token.value)) {
|
||||||
|
color = keywordColor;
|
||||||
|
}
|
||||||
|
if (values.includes(token.value)) {
|
||||||
|
color = valueColor;
|
||||||
|
}
|
||||||
|
if (operator.includes(token.value)) {
|
||||||
|
color = operatorColor;
|
||||||
|
}
|
||||||
|
if (punctuation.includes(token.value)) {
|
||||||
|
color = punctuationColor;
|
||||||
|
}
|
||||||
|
if (builtins.includes(token.value)) {
|
||||||
|
color = builtinColor;
|
||||||
|
}
|
||||||
|
drawText(1+x+cx-scrollX, 1+y+cy-scrollY, line, color);
|
||||||
|
if (i === lines.length-1) {
|
||||||
|
cx += measureText(line)+1;
|
||||||
|
} else {
|
||||||
|
cx=0;
|
||||||
|
cy+=fontHeight+1;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
export const codetab = {
|
export const codetab = {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user