Чото поменял
This commit is contained in:
52
src/App.tsx
52
src/App.tsx
@@ -1,49 +1,16 @@
|
|||||||
import { defaultKeymap, historyKeymap, history } from '@codemirror/commands'
|
import { noop } from 'lodash'
|
||||||
import { EditorView, drawSelection, dropCursor, keymap } from '@codemirror/view'
|
import { Editor } from './Editor'
|
||||||
import { defaultHighlightStyle, indentOnInput, syntaxHighlighting } from '@codemirror/language'
|
|
||||||
import { Extension } from '@codemirror/state'
|
|
||||||
import { closeBrackets, closeBracketsKeymap } from '@codemirror/autocomplete'
|
|
||||||
import { searchKeymap } from '@codemirror/search'
|
|
||||||
import { useEffect, useRef, useState } from 'react'
|
|
||||||
import { getTextPlugin } from './getTextPlugin'
|
|
||||||
import { mathPlugin } from './mathPlugin'
|
|
||||||
|
|
||||||
const basicSetup: Extension = [
|
|
||||||
history(),
|
|
||||||
drawSelection(),
|
|
||||||
dropCursor(),
|
|
||||||
indentOnInput(),
|
|
||||||
syntaxHighlighting(defaultHighlightStyle, { fallback: true }),
|
|
||||||
closeBrackets(),
|
|
||||||
keymap.of([...closeBracketsKeymap, ...defaultKeymap, ...searchKeymap, ...historyKeymap]),
|
|
||||||
mathPlugin(),
|
|
||||||
]
|
|
||||||
|
|
||||||
export const App = () => {
|
export const App = () => {
|
||||||
const ref = useRef<HTMLDivElement>(null)
|
return <Editor text={testText} onChange={noop} />
|
||||||
const view = useRef<EditorView>()
|
|
||||||
const [text, setText] = useState(testText)
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
view.current = new EditorView({
|
|
||||||
doc: text,
|
|
||||||
extensions: [basicSetup, getTextPlugin(setText)],
|
|
||||||
parent: ref.current!,
|
|
||||||
})
|
|
||||||
|
|
||||||
return () => view.current?.destroy()
|
|
||||||
}, [])
|
|
||||||
|
|
||||||
return <div className="cm-editor-mount" ref={ref}></div>
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default App
|
|
||||||
|
|
||||||
const testText = `
|
const testText = `
|
||||||
2 + 2 * 2
|
2 + 2 * 2
|
||||||
sqrt(3^2 + 4^2)
|
sqrt(3^2 + 4^2)
|
||||||
2 inch to cm
|
5cm + 0.2 m in inch
|
||||||
cos(45 deg)
|
cos(45 deg)
|
||||||
|
0.1 + 0.2
|
||||||
|
|
||||||
a = 25
|
a = 25
|
||||||
b = a * 2
|
b = a * 2
|
||||||
@@ -53,4 +20,13 @@ pow2(6)
|
|||||||
|
|
||||||
2 * 2
|
2 * 2
|
||||||
last + 1
|
last + 1
|
||||||
|
|
||||||
|
f(x) = (sin(x) + cos(x/2)) * 5
|
||||||
|
|
||||||
|
a = [1, 2, 3; 2+2, 5, 6]
|
||||||
|
a[2, 3]
|
||||||
|
a[1:2, 2]
|
||||||
|
b = [1, 2; 3, 4]
|
||||||
|
b * a
|
||||||
|
a[3, 1:3] = [7, 8, 9]
|
||||||
`
|
`
|
||||||
|
|||||||
42
src/Editor.tsx
Normal file
42
src/Editor.tsx
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
import { defaultKeymap, historyKeymap, history } from '@codemirror/commands'
|
||||||
|
import { EditorView, drawSelection, dropCursor, keymap } from '@codemirror/view'
|
||||||
|
import { defaultHighlightStyle, indentOnInput, syntaxHighlighting } from '@codemirror/language'
|
||||||
|
import { Extension } from '@codemirror/state'
|
||||||
|
import { closeBrackets, closeBracketsKeymap } from '@codemirror/autocomplete'
|
||||||
|
import { searchKeymap } from '@codemirror/search'
|
||||||
|
import { useEffect, useRef } from 'react'
|
||||||
|
import { textObserverPlugin } from './textObserverPlugin'
|
||||||
|
import { mathPlugin } from './mathPlugin'
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
text: string
|
||||||
|
onChange: (text: string) => void
|
||||||
|
}
|
||||||
|
|
||||||
|
export const Editor = ({ text, onChange }: Props) => {
|
||||||
|
const ref = useRef<HTMLDivElement>(null)
|
||||||
|
const view = useRef<EditorView>()
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
view.current = new EditorView({
|
||||||
|
doc: text,
|
||||||
|
extensions: [basicSetup, textObserverPlugin(onChange)],
|
||||||
|
parent: ref.current!,
|
||||||
|
})
|
||||||
|
|
||||||
|
return () => view.current?.destroy()
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
return <div className="cm-editor-mount" ref={ref}></div>
|
||||||
|
}
|
||||||
|
|
||||||
|
const basicSetup: Extension = [
|
||||||
|
history(),
|
||||||
|
drawSelection(),
|
||||||
|
dropCursor(),
|
||||||
|
indentOnInput(),
|
||||||
|
syntaxHighlighting(defaultHighlightStyle, { fallback: true }),
|
||||||
|
closeBrackets(),
|
||||||
|
keymap.of([...closeBracketsKeymap, ...defaultKeymap, ...searchKeymap, ...historyKeymap]),
|
||||||
|
mathPlugin(),
|
||||||
|
]
|
||||||
@@ -17,6 +17,32 @@ body {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.math-result {
|
.math-result {
|
||||||
color: grey;
|
color: rgb(80, 80, 80);
|
||||||
margin-left: 8px;
|
margin-left: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.matrix-wrapper {
|
||||||
|
display: flex;
|
||||||
|
margin-left: 8px;
|
||||||
|
margin-top: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.matrix-result {
|
||||||
|
color: rgb(80, 80, 80);
|
||||||
|
}
|
||||||
|
|
||||||
|
.matrix-wrapper::before {
|
||||||
|
min-width: 4px;
|
||||||
|
content: ' ';
|
||||||
|
border: 1px solid rgb(140, 140, 140);
|
||||||
|
border-right: 0;
|
||||||
|
margin-right: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.matrix-wrapper::after {
|
||||||
|
min-width: 4px;
|
||||||
|
content: ' ';
|
||||||
|
border: 1px solid rgb(140, 140, 140);
|
||||||
|
border-left: 0;
|
||||||
|
margin-left: 6px;
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
import ReactDOM from 'react-dom/client'
|
import ReactDOM from 'react-dom/client'
|
||||||
import App from './App.tsx'
|
import { App } from './App.tsx'
|
||||||
import './index.css'
|
import './index.css'
|
||||||
|
|
||||||
const root = document.getElementById('root')
|
const root = document.getElementById('root')
|
||||||
|
|||||||
3
src/math.ts
Normal file
3
src/math.ts
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
import { create, all } from 'mathjs'
|
||||||
|
|
||||||
|
export const math = create(all, { number: 'BigNumber', precision: 16 })
|
||||||
@@ -1,7 +1,5 @@
|
|||||||
import { Decoration, DecorationSet, EditorView, ViewPlugin, ViewUpdate, WidgetType } from '@codemirror/view'
|
import { Decoration, DecorationSet, EditorView, ViewPlugin, ViewUpdate, WidgetType } from '@codemirror/view'
|
||||||
import { create, all } from 'mathjs'
|
import { math } from './math'
|
||||||
|
|
||||||
export const math = create(all, { number: 'BigNumber' })
|
|
||||||
|
|
||||||
export const mathPlugin = () =>
|
export const mathPlugin = () =>
|
||||||
ViewPlugin.fromClass(
|
ViewPlugin.fromClass(
|
||||||
@@ -30,21 +28,53 @@ const createDecorations = (view: EditorView) => {
|
|||||||
|
|
||||||
for (let i = 1; i <= view.state.doc.lines; i++) {
|
for (let i = 1; i <= view.state.doc.lines; i++) {
|
||||||
const { text, to } = view.state.doc.line(i)
|
const { text, to } = view.state.doc.line(i)
|
||||||
|
let decoration: Decoration | null = null
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const result = parser.evaluate(text)
|
const result = parser.evaluate(text)
|
||||||
|
|
||||||
if (result?.isBigNumber) {
|
if (result?.isBigNumber || result?.type === 'Unit') {
|
||||||
parser.set('last', result)
|
parser.set('last', result)
|
||||||
|
|
||||||
const decoration = Decoration.widget({
|
decoration = Decoration.widget({
|
||||||
widget: new MathResult(result.toPrecision()),
|
widget: new MathResult(result.toString()),
|
||||||
side: 1,
|
side: 1,
|
||||||
})
|
})
|
||||||
|
}
|
||||||
|
|
||||||
widgets.push(decoration.range(to))
|
if (result?.type === 'DenseMatrix') {
|
||||||
|
parser.set('last', result)
|
||||||
|
|
||||||
|
const size = result.size()
|
||||||
|
|
||||||
|
switch (size.length) {
|
||||||
|
case 1:
|
||||||
|
decoration = Decoration.widget({
|
||||||
|
widget: new MathResult(result.toString()),
|
||||||
|
side: 1,
|
||||||
|
})
|
||||||
|
break
|
||||||
|
|
||||||
|
case 2:
|
||||||
|
decoration = Decoration.widget({
|
||||||
|
widget: new Matrix(result),
|
||||||
|
side: 1,
|
||||||
|
})
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof result === 'function') {
|
||||||
|
decoration = Decoration.widget({
|
||||||
|
widget: new MathResult(result.syntax),
|
||||||
|
side: 1,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
} catch (e) {}
|
} catch (e) {}
|
||||||
|
|
||||||
|
if (decoration) {
|
||||||
|
widgets.push(decoration.range(to))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return Decoration.set(widgets)
|
return Decoration.set(widgets)
|
||||||
@@ -72,6 +102,47 @@ class MathResult extends WidgetType {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class Matrix extends WidgetType {
|
||||||
|
constructor(readonly result: any) {
|
||||||
|
super()
|
||||||
|
}
|
||||||
|
|
||||||
|
eq(other: MathResult) {
|
||||||
|
return other.result == this.result
|
||||||
|
}
|
||||||
|
|
||||||
|
toDOM() {
|
||||||
|
const wrapper = document.createElement('div')
|
||||||
|
wrapper.className = 'matrix-wrapper'
|
||||||
|
|
||||||
|
const table = document.createElement('table')
|
||||||
|
table.className = 'matrix-result'
|
||||||
|
wrapper.appendChild(table)
|
||||||
|
|
||||||
|
const array = this.result.toArray()
|
||||||
|
for (const row of array) {
|
||||||
|
const tr = document.createElement('tr')
|
||||||
|
tr.className = 'matrix-row'
|
||||||
|
|
||||||
|
for (const col of row) {
|
||||||
|
const td = document.createElement('td')
|
||||||
|
td.className = 'matrix-col'
|
||||||
|
td.innerText = col.toString()
|
||||||
|
|
||||||
|
tr.appendChild(td)
|
||||||
|
}
|
||||||
|
|
||||||
|
table.appendChild(tr)
|
||||||
|
}
|
||||||
|
|
||||||
|
return wrapper
|
||||||
|
}
|
||||||
|
|
||||||
|
ignoreEvent() {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
type Range<T> = {
|
type Range<T> = {
|
||||||
readonly from: number
|
readonly from: number
|
||||||
readonly to: number
|
readonly to: number
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { ViewPlugin, ViewUpdate } from '@codemirror/view'
|
import { ViewPlugin, ViewUpdate } from '@codemirror/view'
|
||||||
|
|
||||||
export const getTextPlugin = (callback: (text: string) => void) =>
|
export const textObserverPlugin = (callback: (text: string) => void) =>
|
||||||
ViewPlugin.define(() => ({
|
ViewPlugin.define(() => ({
|
||||||
update(update: ViewUpdate) {
|
update(update: ViewUpdate) {
|
||||||
if (update.docChanged) {
|
if (update.docChanged) {
|
||||||
Reference in New Issue
Block a user