Skip to content

Commit

Permalink
feat: quick fix for lang files
Browse files Browse the repository at this point in the history
  • Loading branch information
Joelant05 committed Aug 23, 2022
1 parent f7f618c commit c9dbe1a
Show file tree
Hide file tree
Showing 2 changed files with 70 additions and 32 deletions.
73 changes: 41 additions & 32 deletions src/components/Languages/Lang.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import type { languages, editor } from 'monaco-editor'
import type { languages, editor, Range } from 'monaco-editor'
import { BedrockProject } from '/@/components/Projects/Project/BedrockProject'
import { colorCodes } from './Common/ColorCodes'
import { Language } from './Language'
import { App } from '/@/App'
import { useMonaco } from '/@/utils/libs/useMonaco'
import { guessValue } from './Lang/guessValue'

export const config: languages.LanguageConfiguration = {
comments: {
Expand Down Expand Up @@ -77,7 +78,6 @@ const completionItemProvider: languages.CompletionItemProvider = {
)
} else {
// Generate a value based on the key
// 1. Check whether the cursor is after a key and equals sign, but no value yet (e.g. "tile.minecraft:dirt.name=")
const line = model
.getValueInRange(
new Range(
Expand All @@ -88,37 +88,10 @@ const completionItemProvider: languages.CompletionItemProvider = {
)
)
.toLowerCase()
if (line[line.length - 1] === '=') {
// 2. Find the part of the key that isn't a common key prefix/suffix (e.g. the identifier)
const commonParts = ['name', 'tile', 'item', 'entity', 'action']
const key = line.substring(0, line.length - 1)
let uniqueParts = key
.split('.')
.filter((part) => !commonParts.includes(part))

// 3. If there are 2 parts and one is spawn_egg, then state that "Spawn " should be added to the front of the value
const spawnEggIndex = uniqueParts.indexOf('spawn_egg')
const isSpawnEgg =
uniqueParts.length === 2 && spawnEggIndex >= 0
if (isSpawnEgg)
uniqueParts.slice(spawnEggIndex, spawnEggIndex + 1)

// 4. If there is still multiple parts left, search for the part with a namespaced identifier, as that is commonly the bit being translated (e.g. "minecraft:pig" -> "Pig")
if (uniqueParts.length > 1) {
const id = uniqueParts.find((part) => part.includes(':'))
if (id) uniqueParts = [id]
}

// 5. Hopefully there is only one part left now, if there isn't, the first value will be used. If the value is a namespace (contains a colon), remove the namespace, then capitalise and propose
if (uniqueParts[0].includes(':'))
uniqueParts[0] = uniqueParts[0].split(':').pop() ?? ''
const translation = `${
isSpawnEgg ? 'Spawn ' : ''
}${uniqueParts[0]
.split('_')
.map((val) => `${val[0].toUpperCase()}${val.slice(1)}`)
.join(' ')}`

// Check whether the cursor is after a key and equals sign, but no value yet (e.g. "tile.minecraft:dirt.name=")
if (line[line.length - 1] === '=') {
const translation = (await guessValue(line)) ?? ''
suggestions.push({
label: translation,
insertText: translation,
Expand All @@ -138,6 +111,41 @@ const completionItemProvider: languages.CompletionItemProvider = {
}
},
}
const codeActionProvider: languages.CodeActionProvider = {
provideCodeActions: async (
model: editor.ITextModel,
range: Range,
context: languages.CodeActionContext
) => {
const actions: languages.CodeAction[] = []
for (const marker of context.markers) {
const line = model.getLineContent(marker.startLineNumber)
const val = await guessValue(line)

actions.push({
title: 'Add value to key',
diagnostics: [marker],
kind: 'quickfix',
edit: {
edits: [
{
resource: model.uri,
edit: {
range,
text: `${line}=${val}`,
},
},
],
},
isPreferred: true,
})
}
return {
actions: actions,
dispose: () => {},
}
},
}

export class LangLanguage extends Language {
constructor() {
Expand All @@ -147,6 +155,7 @@ export class LangLanguage extends Language {
config,
tokenProvider,
completionItemProvider,
codeActionProvider,
})

// Highlight namespaces
Expand Down
29 changes: 29 additions & 0 deletions src/components/Languages/Lang/guessValue.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
export async function guessValue(line: string) {
// 1. Find the part of the key that isn't a common key prefix/suffix (e.g. the identifier)
const commonParts = ['name', 'tile', 'item', 'entity', 'action']
const key = line.substring(0, line.length - 1)
let uniqueParts = key
.split('.')
.filter((part) => !commonParts.includes(part))

// 2. If there are 2 parts and one is spawn_egg, then state that "Spawn " should be added to the front of the value
const spawnEggIndex = uniqueParts.indexOf('spawn_egg')
const isSpawnEgg = uniqueParts.length === 2 && spawnEggIndex >= 0
if (isSpawnEgg) uniqueParts.slice(spawnEggIndex, spawnEggIndex + 1)

// 3. If there is still multiple parts left, search for the part with a namespaced identifier, as that is commonly the bit being translated (e.g. "minecraft:pig" -> "Pig")
if (uniqueParts.length > 1) {
const id = uniqueParts.find((part) => part.includes(':'))
if (id) uniqueParts = [id]
}

// 4. Hopefully there is only one part left now, if there isn't, the first value will be used. If the value is a namespace (contains a colon), remove the namespace, then capitalise and propose
if (uniqueParts[0].includes(':'))
uniqueParts[0] = uniqueParts[0].split(':').pop() ?? ''
const translation = `${isSpawnEgg ? 'Spawn ' : ''}${uniqueParts[0]
.split('_')
.map((val) => `${val[0].toUpperCase()}${val.slice(1)}`)
.join(' ')}`

return translation
}

0 comments on commit c9dbe1a

Please sign in to comment.