mirror of
https://github.com/IRBorisov/ConceptPortal.git
synced 2025-06-26 04:50:36 +03:00
Add syntax highlighting
This commit is contained in:
parent
67d60ade1c
commit
616ceebcb3
|
@ -4,7 +4,7 @@
|
|||
"version": "1.0.0",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"prepare": "lezer-generator src/components/RSInput/rslang.grammar -o src/components/RSInput/rslangparser.ts",
|
||||
"prepare": "lezer-generator src/components/RSInput/rslang/rslang.grammar -o src/components/RSInput/rslang/parser.ts",
|
||||
"test": "jest",
|
||||
"dev": "vite",
|
||||
"build": "tsc && vite build",
|
||||
|
|
|
@ -1,7 +0,0 @@
|
|||
import {styleTags, tags} from '@lezer/highlight';
|
||||
|
||||
export const highlighting = styleTags({
|
||||
Identifier: tags.name,
|
||||
Number: tags.number,
|
||||
String: tags.string
|
||||
});
|
|
@ -1,11 +1,13 @@
|
|||
import { bracketMatching } from '@codemirror/language';
|
||||
import { Extension } from '@codemirror/state';
|
||||
import { tags as t } from '@lezer/highlight';
|
||||
import { createTheme } from '@uiw/codemirror-themes';
|
||||
import CodeMirror, { BasicSetupOptions, ReactCodeMirrorProps, ReactCodeMirrorRef } from '@uiw/react-codemirror';
|
||||
import { EditorView } from 'codemirror';
|
||||
import { Ref, useMemo } from 'react';
|
||||
|
||||
import { useConceptTheme } from '../../context/ThemeContext';
|
||||
import { RSLanguage } from './rslang';
|
||||
|
||||
const editorSetup: BasicSetupOptions = {
|
||||
highlightSpecialChars: true,
|
||||
|
@ -37,6 +39,7 @@ const editorSetup: BasicSetupOptions = {
|
|||
|
||||
const editorExtensions = [
|
||||
EditorView.lineWrapping,
|
||||
RSLanguage,
|
||||
bracketMatching()
|
||||
];
|
||||
|
||||
|
@ -62,15 +65,16 @@ function RSInput({
|
|||
fontFamily: 'inherit',
|
||||
background: editable ? '#ffffff' : '#f0f2f7',
|
||||
foreground: '#000000',
|
||||
selection: '#036dd626',
|
||||
selectionMatch: '#036dd626',
|
||||
selection: '#aacef2',
|
||||
caret: '#5d00ff',
|
||||
},
|
||||
styles: [
|
||||
// { tag: t.comment, color: '#787b8099' },
|
||||
// { tag: t.variableName, color: '#0080ff' },
|
||||
// { tag: [t.string, t.special(t.brace)], color: '#5c6166' },
|
||||
// { tag: t.definition(t.typeName), color: '#5c6166' },
|
||||
{ tag: t.name, class: 'text-[#b266ff]' }, // GlobalID
|
||||
{ tag: t.variableName, class: 'text-[#24821a]' }, // LocalID
|
||||
{ tag: t.propertyName, class: '' }, // Radical
|
||||
{ tag: t.keyword, class: 'text-[#001aff]' }, // keywords
|
||||
{ tag: t.controlKeyword, class: 'font-semibold'}, // R | I | D
|
||||
{ tag: t.unit, class: 'text-[0.75rem]' }, // indicies
|
||||
]
|
||||
}), [editable]);
|
||||
|
||||
|
@ -81,20 +85,21 @@ function RSInput({
|
|||
fontFamily: 'inherit',
|
||||
background: editable ? '#070b12' : '#374151',
|
||||
foreground: '#e4e4e7',
|
||||
selection: '#ffae00b0',
|
||||
selectionMatch: '#ffae00b0',
|
||||
selection: '#8c6000',
|
||||
caret: '#ffaa00'
|
||||
},
|
||||
styles: [
|
||||
// { tag: t.comment, color: '#787b8099' },
|
||||
// { tag: t.variableName, color: '#0080ff' },
|
||||
// { tag: [t.string, t.special(t.brace)], color: '#5c6166' },
|
||||
// { tag: t.definition(t.typeName), color: '#5c6166' },
|
||||
{ tag: t.name, class: 'text-[#dfbfff]' }, // GlobalID
|
||||
{ tag: t.variableName, class: 'text-[#69bf60]' }, // LocalID
|
||||
{ tag: t.propertyName, class: '' }, // Radical
|
||||
{ tag: t.keyword, class: 'text-[#808dff]' }, // keywords
|
||||
{ tag: t.controlKeyword, class: 'font-semibold'}, // R | I | D
|
||||
{ tag: t.unit, class: 'text-[0.75rem]' }, // indicies
|
||||
]
|
||||
}), [editable]);
|
||||
|
||||
return (
|
||||
<div className={`w-full h-[${height}] ${cursor}`}>
|
||||
<div className={`w-full h-[${height}] ${cursor} text-lg`}>
|
||||
<CodeMirror
|
||||
ref={innerref}
|
||||
basicSetup={editorSetup}
|
|
@ -1,20 +0,0 @@
|
|||
@top Program { expression* }
|
||||
|
||||
@skip { space }
|
||||
|
||||
expression {
|
||||
Identifier |
|
||||
String |
|
||||
Application { "(" expression* ")" }
|
||||
}
|
||||
|
||||
@tokens {
|
||||
space { @whitespace+ }
|
||||
Identifier { $[a-zA-Z_\-0-9]+ }
|
||||
String { '"' (!["\\] | "\\" _)* '"' }
|
||||
"(" ")"
|
||||
}
|
||||
|
||||
@detectDelim
|
||||
|
||||
@external propSource highlighting from "./highlight.ts"
|
|
@ -0,0 +1,14 @@
|
|||
import {styleTags, tags} from '@lezer/highlight';
|
||||
|
||||
export const highlighting = styleTags({
|
||||
Index: tags.unit,
|
||||
ComplexIndex: tags.unit,
|
||||
Integer: tags.literal,
|
||||
|
||||
Radical: tags.propertyName,
|
||||
Global: tags.name,
|
||||
Local: tags.variableName,
|
||||
|
||||
TextFunction: tags.keyword,
|
||||
ConstructPrefix: tags.controlKeyword
|
||||
});
|
|
@ -0,0 +1,8 @@
|
|||
import {LRLanguage} from "@codemirror/language"
|
||||
|
||||
import { parser } from './parser';
|
||||
|
||||
export const RSLanguage = LRLanguage.define({
|
||||
parser: parser,
|
||||
languageData: {}
|
||||
});
|
|
@ -0,0 +1,11 @@
|
|||
// This file was generated by lezer-generator. You probably shouldn't edit it.
|
||||
export const
|
||||
Expression = 1,
|
||||
TextFunction = 2,
|
||||
ComplexIndex = 3,
|
||||
ConstructPrefix = 4,
|
||||
Integer = 5,
|
||||
Global = 6,
|
||||
Radical = 7,
|
||||
Local = 8,
|
||||
Index = 9
|
18
rsconcept/frontend/src/components/RSInput/rslang/parser.ts
Normal file
18
rsconcept/frontend/src/components/RSInput/rslang/parser.ts
Normal file
|
@ -0,0 +1,18 @@
|
|||
// This file was generated by lezer-generator. You probably shouldn't edit it.
|
||||
import {LRParser} from "@lezer/lr"
|
||||
import {highlighting} from "./highlight.ts"
|
||||
export const parser = LRParser.deserialize({
|
||||
version: 14,
|
||||
states: "!^QVQPOOO}QPO'#C^OOQO'#C^'#C^O!SQQO'#CdOOQO'#Cj'#CjOOQO'#Cf'#CfQVQPOOOOQO,58x,58xOOQO,59O,59OOOQO-E6d-E6d",
|
||||
stateData: "#a~O]OS~OSSOTSOUSOVSO_PO`POaPObQOcQOdQOeQOfRO~ORVO~OXWOSWXTWXUWXVWXZWX_WX`WXaWXbWXcWXdWXeWXfWX~Oa_T]UVSbcde`bf~",
|
||||
goto: "n_PP`PPPPP`PdPPPjTSOUQUORXUTTOU",
|
||||
nodeNames: "⚠ Expression TextFunction ComplexIndex ConstructPrefix Integer Global Radical Local Index",
|
||||
maxTerm: 22,
|
||||
propSources: [highlighting],
|
||||
skippedNodes: [0],
|
||||
repeatNodeCount: 1,
|
||||
tokenData: ".p~RqX^#Ypq#Y!Q!R%m!R![%u!c!d&b!e!f&b!f!g&p!h!i&x!k!l'W!r!s']!t!u'k!u!v&b!v!w&b!z!{&b#R#S'{#T#U'{#U#V(W#V#W)j#W#X*y#X#d'{#d#e-P#e#f'{#f#g-o#g#o'{#y#z#Y$f$g#Y5i6S'{#BY#BZ#Y$IS$I_#Y$I|$JO#Y$JT$JU#Y$KV$KW#Y&FU&FV#Y~#_Z]~X^#Ypq#Y!Q![$Q#y#z#Y$f$g#Y#BY#BZ#Y$IS$I_#Y$I|$JO#Y$JT$JU#Y$KV$KW#Y&FU&FV#Y~$VZT~X^$xpq$x!Q![$Q#y#z$x$f$g$x#BY#BZ$x$IS$I_$x$I|$JO$x$JT$JU$x$KV$KW$x&FU&FV$x~$}YT~X^$xpq$x#y#z$x$f$g$x#BY#BZ$x$IS$I_$x$I|$JO$x$JT$JU$x$KV$KW$x&FU&FV$xQ%rPXQ!Q![%mR%|QRPXQ|}&S!Q![%mP&VP!R![&YP&_PRP|}&S~&eP!Q![&h~&mPU~!Q![&h~&uPS~!Q![&h~&{Q!Q![&h#]#^'R~'WOa~~']OS~~'`Q!Q![&h#f#g'f~'kO_~~'pPS~!Q!['s~'xPV~!Q!['s~(QQf~#T#o'{5i6S'{~(]Sf~#T#c'{#c#d(i#d#o'{5i6S'{~(nSf~#T#c'{#c#d(z#d#o'{5i6S'{~)PSf~#T#`'{#`#a)]#a#o'{5i6S'{~)dQc~f~#T#o'{5i6S'{~)oRf~#T#U)x#U#o'{5i6S'{~)}Sf~#T#f'{#f#g*Z#g#o'{5i6S'{~*`Sf~#T#W'{#W#X*l#X#o'{5i6S'{~*sQb~f~#T#o'{5i6S'{~+OSf~#T#X'{#X#Y+[#Y#o'{5i6S'{~+aSf~#T#U'{#U#V+m#V#o'{5i6S'{~+rSf~#T#c'{#c#d,O#d#o'{5i6S'{~,TSf~#T#c'{#c#d,a#d#o'{5i6S'{~,fSf~#T#`'{#`#a,r#a#o'{5i6S'{~,yQd~f~#T#o'{5i6S'{~-USf~#T#f'{#f#g-b#g#o'{5i6S'{~-iQ`~f~#T#o'{5i6S'{~-tSf~#T#X'{#X#Y.Q#Y#o'{5i6S'{~.VSf~#T#W'{#W#X.c#X#o'{5i6S'{~.jQe~f~#T#o'{5i6S'{",
|
||||
tokenizers: [0, 1],
|
||||
topRules: {"Expression":[0,1]},
|
||||
tokenPrec: 94
|
||||
})
|
|
@ -0,0 +1,61 @@
|
|||
@top Expression { token* }
|
||||
|
||||
@skip { space }
|
||||
|
||||
@tokens {
|
||||
space { @whitespace+ }
|
||||
Index { $[0-9]+ }
|
||||
ComplexIndex { $[1-9](","$[1-9])* }
|
||||
Integer { space$[0-9]+space? }
|
||||
|
||||
bigPr { "Pr" }
|
||||
smallPr { "pr" }
|
||||
filter { "Fi" }
|
||||
card { "card" }
|
||||
bool { "bool" }
|
||||
debool { "debool" }
|
||||
red { "red" }
|
||||
|
||||
ConstructPrefix { "D" | "R" | "I" }
|
||||
|
||||
Global { $[XCSDAPTF]$[0-9]+ }
|
||||
Radical { "R"$[0-9]+ }
|
||||
local { $[_a-zα-ω]$[a-zα-ω]* }
|
||||
|
||||
"(" ")"
|
||||
"[" "]"
|
||||
"{" "}"
|
||||
|
||||
@precedence { filter bigPr Global Radical ConstructPrefix }
|
||||
@precedence { card bool debool red smallPr local }
|
||||
@precedence { Integer space }
|
||||
}
|
||||
|
||||
TextFunction {
|
||||
bigPr ComplexIndex |
|
||||
smallPr ComplexIndex |
|
||||
filter ComplexIndex |
|
||||
card | bool | debool | red
|
||||
}
|
||||
|
||||
Local { local Index? }
|
||||
|
||||
token {
|
||||
TextFunction |
|
||||
ConstructPrefix |
|
||||
Integer |
|
||||
Global |
|
||||
Radical |
|
||||
Local
|
||||
}
|
||||
|
||||
@detectDelim
|
||||
|
||||
@external propSource highlighting from "./highlight.ts"
|
||||
|
||||
//@asciiLetter matches $[a-zA-Z]
|
||||
//@asciiLowercase matches $[a-z]
|
||||
//@asciiUppercase is equivalent to $[A-Z]
|
||||
//@digit matches $[0-9]
|
||||
//@whitespace matches any character the Unicode standard defines as whitespace.
|
||||
//@eof matches the end of the input
|
|
@ -1,5 +0,0 @@
|
|||
// This file was generated by lezer-generator. You probably shouldn't edit it.
|
||||
export const
|
||||
Program = 1,
|
||||
Identifier = 2,
|
||||
String = 3
|
|
@ -1,22 +0,0 @@
|
|||
// This file was generated by lezer-generator. You probably shouldn't edit it.
|
||||
import {LRParser} from "@lezer/lr"
|
||||
import {highlighting} from "./highlight.ts"
|
||||
export const parser = LRParser.deserialize({
|
||||
version: 14,
|
||||
states: "!WQVQPOOObQPO'#CbOOQO'#Cg'#CgOOQO'#Cc'#CcQVQPOOOOQO,58|,58|OpQPO,58|OOQO-E6a-E6aOOQO1G.h1G.h",
|
||||
stateData: "!O~OYOS~OQQORQOTPO~OQQORQOSTOTPO~OQQORQOSWOTPO~O",
|
||||
goto: "s[PPPPPP]cPPPmXQOPSUQSOQUPTVSUXROPSU",
|
||||
nodeNames: "⚠ Program Identifier String ) ( Application",
|
||||
maxTerm: 11,
|
||||
nodeProps: [
|
||||
["openedBy", 4,"("],
|
||||
["closedBy", 5,")"]
|
||||
],
|
||||
propSources: [highlighting],
|
||||
skippedNodes: [0],
|
||||
repeatNodeCount: 1,
|
||||
tokenData: "%[~RbX^!Zpq!Zrs#Oxy$lyz$q}!O$v!Q![$v!c!}$v#R#S$v#T#o$v#y#z!Z$f$g!Z#BY#BZ!Z$IS$I_!Z$I|$JO!Z$JT$JU!Z$KV$KW!Z&FU&FV!Z~!`YY~X^!Zpq!Z#y#z!Z$f$g!Z#BY#BZ!Z$IS$I_!Z$I|$JO!Z$JT$JU!Z$KV$KW!Z&FU&FV!Z~#RVOr#Ors#hs#O#O#O#P#m#P;'S#O;'S;=`$f<%lO#O~#mOR~~#pRO;'S#O;'S;=`#y;=`O#O~#|WOr#Ors#hs#O#O#O#P#m#P;'S#O;'S;=`$f;=`<%l#O<%lO#O~$iP;=`<%l#O~$qOT~~$vOS~~${TQ~}!O$v!Q![$v!c!}$v#R#S$v#T#o$v",
|
||||
tokenizers: [0],
|
||||
topRules: {"Program":[0,1]},
|
||||
tokenPrec: 0
|
||||
})
|
|
@ -19,11 +19,17 @@
|
|||
}
|
||||
|
||||
.cm-editor {
|
||||
@apply border shadow rounded clr-border px-2
|
||||
@apply border shadow rounded clr-border px-1
|
||||
}
|
||||
.cm-editor.cm-focused {
|
||||
@apply border shadow rounded outline-2 outline
|
||||
}
|
||||
.cm-matchingBracket {
|
||||
@apply font-semibold
|
||||
}
|
||||
.cm-nonmatchingBracket {
|
||||
@apply font-bold text-red-500
|
||||
}
|
||||
|
||||
@layer components {
|
||||
h1 {
|
||||
|
|
|
@ -4,7 +4,7 @@ import { useCallback, useLayoutEffect, useMemo, useRef, useState } from 'react';
|
|||
import Button from '../../components/Common/Button';
|
||||
import Label from '../../components/Common/Label';
|
||||
import { Loader } from '../../components/Common/Loader';
|
||||
import RSInput from '../../components/RSInput/RSInput';
|
||||
import RSInput from '../../components/RSInput';
|
||||
import { getSymbolSubstitute, TextWrapper } from '../../components/RSInput/textEditing';
|
||||
import { useRSForm } from '../../context/RSFormContext';
|
||||
import useCheckExpression from '../../hooks/useCheckExpression';
|
||||
|
|
Loading…
Reference in New Issue
Block a user