feat: fix outline

This commit is contained in:
Andrew Bastin
2021-09-14 21:30:58 +05:30
parent a07cc7e560
commit 1dee098ca2
6 changed files with 344 additions and 33 deletions

View File

@@ -61,10 +61,11 @@ export function useCodemirror(
el: Ref<any | null>,
value: Ref<string>,
options: CodeMirrorOptions
) {
): { cm: Ref<CodeMirror.Position | null>; cursor: Ref<CodeMirror.Position> } {
const { $colorMode } = useContext() as any
const cm = ref<CodeMirror.Editor | null>(null)
const cursor = ref<CodeMirror.Position>({ line: 0, ch: 0 })
const updateEditorConfig = () => {
Object.keys(options.extendedEditorConfig).forEach((key) => {
@@ -135,6 +136,10 @@ export function useCodemirror(
value.value = instance.getValue()
}
})
cm.value.on("cursorActivity", (instance) => {
cursor.value = instance.getCursor()
})
}
// Boot-up CodeMirror, set the value and listeners
@@ -192,10 +197,20 @@ export function useCodemirror(
}
})
// Push cursor updates
watch(cursor, (value) => {
if (value !== cm.value?.getCursor()) {
cm.value?.focus()
console.log(value)
cm.value?.setCursor(value)
}
})
// Watch color mode updates and update theme
watch(() => $colorMode.value, setTheme)
return {
cm,
cursor,
}
}

View File

@@ -2,7 +2,7 @@ export function convertIndexToLineCh(
text: string,
i: number
): { line: number; ch: number } {
const lines = text.split("/n")
const lines = text.split("\n")
let line = 0
let counter = 0
@@ -21,3 +21,18 @@ export function convertIndexToLineCh(
throw new Error("Invalid input")
}
export function convertLineChToIndex(
text: string,
lineCh: { line: number; ch: number }
): number {
const textSplit = text.split("\n")
if (textSplit.length < lineCh.line) throw new Error("Invalid position")
const tillLineIndex = textSplit
.slice(0, lineCh.line)
.reduce((acc, line) => acc + line.length + 1, 0)
return tillLineIndex + lineCh.ch
}

View File

@@ -19,7 +19,75 @@
* - end: int - the end exclusive offset of the syntax error
*
*/
export default function jsonParse(str) {
type JSONEOFValue = {
kind: "EOF"
start: number
end: number
}
type JSONNullValue = {
kind: "Null"
start: number
end: number
}
type JSONNumberValue = {
kind: "Number"
start: number
end: number
value: number
}
type JSONStringValue = {
kind: "String"
start: number
end: number
value: string
}
type JSONBooleanValue = {
kind: "Boolean"
start: number
end: number
value: boolean
}
type JSONPrimitiveValue =
| JSONNullValue
| JSONEOFValue
| JSONStringValue
| JSONNumberValue
| JSONBooleanValue
export type JSONObjectValue = {
kind: "Object"
start: number
end: number
// eslint-disable-next-line no-use-before-define
members: JSONObjectMember[]
}
export type JSONArrayValue = {
kind: "Array"
start: number
end: number
// eslint-disable-next-line no-use-before-define
values: JSONValue[]
}
export type JSONValue = JSONObjectValue | JSONArrayValue | JSONPrimitiveValue
export type JSONObjectMember = {
kind: "Member"
start: number
end: number
key: JSONStringValue
value: JSONValue
}
export default function jsonParse(
str: string
): JSONObjectValue | JSONArrayValue {
string = str
strLen = str.length
start = end = lastEnd = -1
@@ -37,15 +105,15 @@ export default function jsonParse(str) {
}
}
let string
let strLen
let start
let end
let lastEnd
let code
let kind
let string: string
let strLen: number
let start: number
let end: number
let lastEnd: number
let code: number
let kind: string
function parseObj() {
function parseObj(): JSONObjectValue {
const nodeStart = start
const members = []
expect("{")
@@ -63,9 +131,9 @@ function parseObj() {
}
}
function parseMember() {
function parseMember(): JSONObjectMember {
const nodeStart = start
const key = kind === "String" ? curToken() : null
const key = kind === "String" ? (curToken() as JSONStringValue) : null
expect("String")
expect(":")
const value = parseVal()
@@ -73,14 +141,14 @@ function parseMember() {
kind: "Member",
start: nodeStart,
end: lastEnd,
key,
key: key!,
value,
}
}
function parseArr() {
function parseArr(): JSONArrayValue {
const nodeStart = start
const values = []
const values: JSONValue[] = []
expect("[")
if (!skip("]")) {
do {
@@ -96,7 +164,7 @@ function parseArr() {
}
}
function parseVal() {
function parseVal(): JSONValue {
switch (kind) {
case "[":
return parseArr()
@@ -111,14 +179,19 @@ function parseVal() {
lex()
return token
}
return expect("Value")
return expect("Value") as never
}
function curToken() {
return { kind, start, end, value: JSON.parse(string.slice(start, end)) }
function curToken(): JSONPrimitiveValue {
return {
kind: kind as any,
start,
end,
value: JSON.parse(string.slice(start, end)),
}
}
function expect(str) {
function expect(str: string) {
if (kind === str) {
lex()
return
@@ -137,11 +210,17 @@ function expect(str) {
throw syntaxError(`Expected ${str} but found ${found}.`)
}
function syntaxError(message) {
type SyntaxError = {
message: string
start: number
end: number
}
function syntaxError(message: string): SyntaxError {
return { message, start, end }
}
function skip(k) {
function skip(k: string) {
if (kind === k) {
lex()
return true
@@ -227,7 +306,7 @@ function lex() {
function readString() {
ch()
while (code !== 34 && code > 31) {
if (code === 92) {
if (code === (92 as any)) {
// \
ch()
switch (code) {
@@ -299,7 +378,7 @@ function readNumber() {
if (code === 69 || code === 101) {
// E e
ch()
if (code === 43 || code === 45) {
if (code === (43 as any) || code === (45 as any)) {
// + -
ch()
}

100
helpers/newOutline.ts Normal file
View File

@@ -0,0 +1,100 @@
import {
JSONArrayValue,
JSONObjectMember,
JSONObjectValue,
JSONValue,
} from "./jsonParse"
type RootEntry =
| {
kind: "RootObject"
astValue: JSONObjectValue
}
| {
kind: "RootArray"
astValue: JSONArrayValue
}
type ObjectMemberEntry = {
kind: "ObjectMember"
name: string
astValue: JSONObjectMember
astParent: JSONObjectValue
}
type ArrayMemberEntry = {
kind: "ArrayMember"
index: number
astValue: JSONValue
astParent: JSONArrayValue
}
type PathEntry = RootEntry | ObjectMemberEntry | ArrayMemberEntry
export function getJSONOutlineAtPos(
jsonRootAst: JSONObjectValue | JSONArrayValue,
posIndex: number
): PathEntry[] | null {
try {
const rootObj = jsonRootAst
if (posIndex > rootObj.end || posIndex < rootObj.start)
throw new Error("Invalid position")
let current: JSONValue = rootObj
const path: PathEntry[] = []
if (rootObj.kind === "Object") {
path.push({
kind: "RootObject",
astValue: rootObj,
})
} else {
path.push({
kind: "RootArray",
astValue: rootObj,
})
}
while (current.kind === "Object" || current.kind === "Array") {
if (current.kind === "Object") {
const next: JSONObjectMember | undefined = current.members.find(
(member) => member.start <= posIndex && member.end >= posIndex
)
if (!next) throw new Error("Couldn't find child")
path.push({
kind: "ObjectMember",
name: next.key.value,
astValue: next,
astParent: current,
})
current = next.value
} else {
const nextIndex = current.values.findIndex(
(value) => value.start <= posIndex && value.end >= posIndex
)
if (nextIndex < 0) throw new Error("Couldn't find child")
const next: JSONValue = current.values[nextIndex]
path.push({
kind: "ArrayMember",
index: nextIndex,
astValue: next,
astParent: current,
})
current = next
}
}
return path
} catch (e: any) {
return null
}
}