✨ Add support for filters and license info
This commit is contained in:
parent
61e61a4e2c
commit
4542a9f6b2
5 changed files with 280 additions and 3 deletions
|
@ -8,4 +8,6 @@ Not everything is supported yet, but currently the following features are suppor
|
|||
- Definition support for the layer names
|
||||
- Definintion support for icons
|
||||
- Autocompletion for tagRenderings in questions.json
|
||||
- Definition support for tagRenderings in questions.json
|
||||
- Definition support for tagRenderings
|
||||
- Autocompletion for filter keys in questions.json
|
||||
- Definition support for filter keys
|
||||
|
|
|
@ -1,14 +1,28 @@
|
|||
import * as vscode from "vscode";
|
||||
import { layerCompletionProvider, layerDefinitionProvider } from "./theme";
|
||||
import { iconDefinitionProvider } from "./generic";
|
||||
import { tagRenderingCompletionProvider } from "./layers";
|
||||
import {
|
||||
filterCompletionProvider,
|
||||
filterDefinitionProvider,
|
||||
tagRenderingCompletionProvider,
|
||||
tagRenderingDefinitionProvider,
|
||||
} from "./layers";
|
||||
import { pathDefinitionProvider } from "./license_info";
|
||||
|
||||
export function activate(context: vscode.ExtensionContext) {
|
||||
// Activate all theme related features
|
||||
context.subscriptions.push(layerCompletionProvider, layerDefinitionProvider);
|
||||
|
||||
// Activate all layer related features
|
||||
context.subscriptions.push(tagRenderingCompletionProvider);
|
||||
context.subscriptions.push(
|
||||
tagRenderingCompletionProvider,
|
||||
tagRenderingDefinitionProvider,
|
||||
filterCompletionProvider,
|
||||
filterDefinitionProvider
|
||||
);
|
||||
|
||||
// Activate all license info related features
|
||||
context.subscriptions.push(pathDefinitionProvider);
|
||||
|
||||
// Activate all generic features
|
||||
context.subscriptions.push(iconDefinitionProvider);
|
||||
|
|
166
src/layers.ts
166
src/layers.ts
|
@ -11,6 +11,7 @@
|
|||
import * as vscode from "vscode";
|
||||
import {
|
||||
getCursorPath,
|
||||
getFilters,
|
||||
getRawCursorPath,
|
||||
getStartEnd,
|
||||
getTagRenderings,
|
||||
|
@ -18,6 +19,14 @@ import {
|
|||
} from "./utils";
|
||||
import { JSONPath } from "jsonc-parser";
|
||||
|
||||
/**
|
||||
* Tag rendering completion provider
|
||||
*
|
||||
* This provider will provide a list of existing tagRenderings for autocompletion
|
||||
*
|
||||
* JSON path:
|
||||
* - (layers.{index}.)tagRenderings.{index}(.builtin)
|
||||
*/
|
||||
export const tagRenderingCompletionProvider =
|
||||
vscode.languages.registerCompletionItemProvider(
|
||||
{
|
||||
|
@ -55,6 +64,11 @@ export const tagRenderingCompletionProvider =
|
|||
|
||||
/**
|
||||
* Tag rendering definition provider
|
||||
*
|
||||
* This provider will provide a definition for tagRenderings, allowing users to jump to the tagRendering definition
|
||||
*
|
||||
* JSON path:
|
||||
* - (layers.{index}.)tagRenderings.{index}(.builtin)
|
||||
*/
|
||||
export const tagRenderingDefinitionProvider =
|
||||
vscode.languages.registerDefinitionProvider(
|
||||
|
@ -154,3 +168,155 @@ export const tagRenderingDefinitionProvider =
|
|||
},
|
||||
}
|
||||
);
|
||||
|
||||
/**
|
||||
* Filter completion provider
|
||||
*
|
||||
* This provider will provide a list of existing filters for autocompletion
|
||||
*
|
||||
* JSON path:
|
||||
* - (layers.{index}.)filter.{index}
|
||||
*/
|
||||
export const filterCompletionProvider =
|
||||
vscode.languages.registerCompletionItemProvider(
|
||||
{
|
||||
language: "json",
|
||||
scheme: "file",
|
||||
pattern: "**/assets/layers/*/*.json",
|
||||
},
|
||||
{
|
||||
async provideCompletionItems(
|
||||
document: vscode.TextDocument,
|
||||
position: vscode.Position
|
||||
) {
|
||||
// Stop running if the file is called license_info.json
|
||||
if (document.fileName.includes("license_info")) {
|
||||
return [];
|
||||
}
|
||||
|
||||
console.log("filterCompletionProvider");
|
||||
const text = document.getText();
|
||||
const jsonPath = getCursorPath(text, position);
|
||||
|
||||
console.log(jsonPath);
|
||||
|
||||
const regex = /^(layers.\d+.)?filter\.\d+$/;
|
||||
if (regex.exec(jsonPath)) {
|
||||
const filters = await getFilters();
|
||||
console.log(`Got ${filters.length} filters`);
|
||||
|
||||
// Now we need to return the completion items
|
||||
return filters;
|
||||
}
|
||||
|
||||
return [];
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
/**
|
||||
* Filter definition provider
|
||||
*
|
||||
* This provider will provide a definition for filters, allowing users to jump to the filter definition
|
||||
*
|
||||
* JSON path:
|
||||
* - (layers.{index}.)filter.{index}
|
||||
*/
|
||||
export const filterDefinitionProvider =
|
||||
vscode.languages.registerDefinitionProvider(
|
||||
{
|
||||
language: "json",
|
||||
scheme: "file",
|
||||
pattern: "**/assets/layers/*/*.json",
|
||||
},
|
||||
{
|
||||
async provideDefinition(
|
||||
document: vscode.TextDocument,
|
||||
position: vscode.Position
|
||||
) {
|
||||
console.log("filterDefinitionProvider");
|
||||
const text = document.getText();
|
||||
const jsonPath = getCursorPath(text, position);
|
||||
const rawJsonPath = getRawCursorPath(text, position);
|
||||
|
||||
const regex = /^(layers.\d.)?filter.\d*$/;
|
||||
|
||||
if (regex.exec(jsonPath)) {
|
||||
const filter = getValueFromPath(text, rawJsonPath);
|
||||
|
||||
if (typeof filter === "string") {
|
||||
console.log("Found reference to filter", filter);
|
||||
if (filter.indexOf(".") === -1) {
|
||||
console.log("This is a built-in filter");
|
||||
// This is a built-in filter
|
||||
// Read the built-in filters file
|
||||
const layerFile = await vscode.workspace.findFiles(
|
||||
"assets/layers/filters/filters.json"
|
||||
);
|
||||
if (layerFile.length === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const layerText = await vscode.workspace.fs.readFile(
|
||||
layerFile[0]
|
||||
);
|
||||
const layerTextString = new TextDecoder().decode(layerText);
|
||||
const layer = JSON.parse(layerTextString);
|
||||
|
||||
const filterIndex = layer.filter.findIndex(
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
(f: any) => f.id === filter
|
||||
);
|
||||
|
||||
const path: JSONPath = ["filter", filterIndex];
|
||||
const startEnd = getStartEnd(layerTextString, path);
|
||||
|
||||
const link: vscode.DefinitionLink = {
|
||||
targetUri: layerFile[0],
|
||||
targetRange: startEnd,
|
||||
originSelectionRange: getStartEnd(text, rawJsonPath),
|
||||
};
|
||||
|
||||
return [link];
|
||||
} else {
|
||||
// This is a reference to a filter in another layer
|
||||
// We need to find the layer and the filter
|
||||
const layerName = filter.split(".")[0];
|
||||
const filterName = filter.split(".")[1];
|
||||
|
||||
const layerFile = await vscode.workspace.findFiles(
|
||||
`assets/layers/${layerName}/${layerName}.json`
|
||||
);
|
||||
if (layerFile.length === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const layerText = await vscode.workspace.fs.readFile(
|
||||
layerFile[0]
|
||||
);
|
||||
const layerTextString = new TextDecoder().decode(layerText);
|
||||
const layer = JSON.parse(layerTextString);
|
||||
|
||||
const filterIndex = layer.filter.findIndex(
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
(f: any) => f.id === filterName
|
||||
);
|
||||
|
||||
const path: JSONPath = ["filter", filterIndex];
|
||||
const startEnd = getStartEnd(layerTextString, path);
|
||||
|
||||
const link: vscode.DefinitionLink = {
|
||||
targetUri: layerFile[0],
|
||||
targetRange: startEnd,
|
||||
originSelectionRange: getStartEnd(text, rawJsonPath),
|
||||
};
|
||||
|
||||
return [link];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
},
|
||||
}
|
||||
);
|
||||
|
|
63
src/license_info.ts
Normal file
63
src/license_info.ts
Normal file
|
@ -0,0 +1,63 @@
|
|||
/**
|
||||
* This file contains all functions that should be used when editing license_info files
|
||||
* License info files are located in the /assets/{themes/layers}/{name}/license_info.json file
|
||||
*
|
||||
* This consists of the following functions:
|
||||
* - pathDefinitionProvider: Provides a definition for paths, allowing users to jump to the image file
|
||||
*/
|
||||
|
||||
import * as vscode from "vscode";
|
||||
import * as path from "path";
|
||||
import {
|
||||
getCursorPath,
|
||||
getRawCursorPath,
|
||||
getStartEnd,
|
||||
getValueFromPath,
|
||||
} from "./utils";
|
||||
|
||||
/**
|
||||
* Path definition provider
|
||||
*
|
||||
* This provider will provide a definition for paths, allowing users to jump to the image file
|
||||
*
|
||||
* JSON path:
|
||||
* - {index}.path
|
||||
*/
|
||||
export const pathDefinitionProvider =
|
||||
vscode.languages.registerDefinitionProvider(
|
||||
{
|
||||
language: "json",
|
||||
scheme: "file",
|
||||
pattern: "**/assets/*/*/license_info.json",
|
||||
},
|
||||
{
|
||||
provideDefinition(
|
||||
document: vscode.TextDocument,
|
||||
position: vscode.Position
|
||||
) {
|
||||
console.log("pathDefinitionProvider");
|
||||
const text = document.getText();
|
||||
const jsonPath = getCursorPath(text, position);
|
||||
const rawPath = getRawCursorPath(text, position);
|
||||
|
||||
const regex = /^\d+.path$/;
|
||||
if (regex.exec(jsonPath)) {
|
||||
const imageFile = getValueFromPath(text, rawPath);
|
||||
console.log("Found reference to filw", imageFile);
|
||||
|
||||
const imagePath = path.join(
|
||||
path.dirname(document.fileName),
|
||||
imageFile
|
||||
);
|
||||
|
||||
const link: vscode.LocationLink = {
|
||||
originSelectionRange: getStartEnd(text, rawPath),
|
||||
targetUri: vscode.Uri.file(imagePath),
|
||||
targetRange: new vscode.Range(0, 0, 0, 0),
|
||||
};
|
||||
|
||||
return [link];
|
||||
}
|
||||
},
|
||||
}
|
||||
);
|
32
src/utils.ts
32
src/utils.ts
|
@ -187,3 +187,35 @@ export async function getTagRenderings(): Promise<vscode.CompletionItem[]> {
|
|||
|
||||
return tagRenderings;
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility function to get the filters from the filters layer
|
||||
* //TODO: This should get ALL filters, not just from the filters layer
|
||||
*
|
||||
* @returns List of CompletionItems for tagRenderings
|
||||
*/
|
||||
export async function getFilters(): Promise<vscode.CompletionItem[]> {
|
||||
const filtersList: vscode.CompletionItem[] = [];
|
||||
|
||||
// Open the filters layer file
|
||||
const filtersFile = await vscode.workspace.findFiles(
|
||||
"assets/layers/filters/filters.json",
|
||||
"**/node_modules/**"
|
||||
);
|
||||
|
||||
if (filtersFile.length === 0) {
|
||||
console.error("filters.json not found");
|
||||
return [];
|
||||
}
|
||||
|
||||
const content = await vscode.workspace.fs.readFile(filtersFile[0]);
|
||||
const filters = JSON.parse(new TextDecoder().decode(content));
|
||||
|
||||
for (const filter of filters.filter) {
|
||||
filtersList.push(
|
||||
new vscode.CompletionItem(filter.id, vscode.CompletionItemKind.Value)
|
||||
);
|
||||
}
|
||||
|
||||
return filtersList;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue