improve intellisense

This commit is contained in:
Asaki Yuki 2026-01-18 03:24:03 +07:00
parent ac412b798c
commit 6a5addb383
15 changed files with 39393 additions and 483 deletions

View file

@ -20,14 +20,14 @@
"main": "dist/index.js", "main": "dist/index.js",
"types": "dist/index.d.ts", "types": "dist/index.d.ts",
"scripts": { "scripts": {
"build": "npx tsc", "build": "tsc",
"dev": "npx tsc --watch", "dev": "tsc --watch",
"test": "bun test/app.ts", "test": "bun test/app.ts",
"test:watch": "bun --watch test/app.ts", "test:watch": "bun --watch test/app.ts",
"prefetch": "bun scripts/prefetch", "prefetch": "bun scripts/prefetch",
"gen:enums": "bun scripts/write/enum", "gen:enums": "bun scripts/write/enum",
"vanilla:defs": "bun scripts/vanilladefs", "vanilla:defs": "bun scripts/vanilladefs",
"vanilla:autocomplete": "bun scripts/autocomplete-build" "gen:autocomplete": "bun scripts/autocomplete-build"
}, },
"devDependencies": { "devDependencies": {
"@types/node": "^25.0.3", "@types/node": "^25.0.3",

View file

@ -6,32 +6,47 @@ function toCamelCase(str: string) {
return str.replace(/[-_]\w/g, m => m[1].toUpperCase()) return str.replace(/[-_]\w/g, m => m[1].toUpperCase())
} }
const type: string[] = [] const intelliSense: string[] = [
const $$namespace: string[] = [] 'import { Type as T } from "../enums/Type.js"\n',
"export type Namespace = keyof IntelliSense;",
"export type Element<T extends Namespace> = IntelliSense[T]",
"export type VanillaType<T extends Namespace, K extends Element<T>> = IntelliSense[T][K]\n",
"export type IntelliSense = {",
]
const intelliSense: string[] = ['import * as mc from "./elements.js"\n', "export type IntelliSense = {"] const intelliSenseTypeEachNamespace: string[] = []
const paths: string[] = ["export const paths = {"]
for (const [namespace, element] of Object.entries(data)) { for (const [namespace, element] of Object.entries(data)) {
if (namespace === "undefined") continue if (namespace === "undefined") continue
$$namespace.push(`"${namespace}"`)
const $namespace = toCamelCase("_" + namespace) const $namespace = toCamelCase("_" + namespace)
const eType: string[] = [] const eType: string[] = [],
eType3: string[] = [`export type ${$namespace}Type = {`],
ePaths: string[] = [` "${namespace}": {`]
for (const [ePath, info] of Object.entries(<any>element)) { for (const [ePath, info] of Object.entries(<any>element)) {
const { file, type, extend } = <any>info const { file, type, extend } = <any>info
eType.push(`"${ePath}"`) eType.push(`"${ePath}"`)
eType3.push(` "${ePath}": T.${type.toUpperCase()},`)
ePaths.push(` "${ePath}": "${file}",`)
} }
intelliSense.push(` "${namespace}": mc.${$namespace},`) eType3.push("}\n")
ePaths.push(" },")
type.push(`export type ${$namespace} = ${eType.join(" | ")};`) paths.push(ePaths.join("\n"))
intelliSense.push(` "${namespace}": ${$namespace}Type,`)
intelliSenseTypeEachNamespace.push(eType3.join("\n"))
} }
intelliSense.push("}") intelliSense.push("}")
fs.writeFileSync( paths.push("}")
"src/types/vanilla/elements.ts",
`export type Namespace = ${$$namespace.join(" | ")}\n\n` + type.join("\n"),
)
fs.writeFileSync("src/types/vanilla/intellisense.ts", intelliSense.join("\n")) fs.writeFileSync(
"src/types/vanilla/intellisense.ts",
intelliSense.join("\n") + "\n\n" + intelliSenseTypeEachNamespace.join("\n"),
)
fs.writeFileSync("src/types/vanilla/paths.ts", paths.join("\n"))

View file

@ -1,4 +1,4 @@
export {} // 👈 BẮT BUỘC export {}
declare global { declare global {
interface String { interface String {

View file

@ -35,6 +35,10 @@ for (const key in schema) {
} }
} }
if (enumName === "Type") {
fileData.push(` UNKNOWN = "unknown",`)
}
fileData.push("}") fileData.push("}")
fs.writeFile(`${enumPath}${enumName}.ts`, fileData.join("\n")) fs.writeFile(`${enumPath}${enumName}.ts`, fileData.join("\n"))

View file

@ -1,5 +1,8 @@
import { Namespace } from "../types/vanilla/elements.js" import { IntelliSense, Namespace, Element, VanillaType } from "../types/vanilla/intellisense.js"
import { IntelliSense } from "../types/vanilla/intellisense.js" import { paths } from "../types/vanilla/paths.js"
import { UI } from "./UI.js" import { UI } from "./UI.js"
export function Modify<T extends Namespace>(namespace: T, name: IntelliSense[T]) {} export function Modify<T extends Namespace, K extends Element<T>>(namespace: T, name: K) {
// @ts-ignore -- TS cannot prove this, but runtime guarantees it
return new UI<VanillaType<T, K>>(undefined, name, namespace, paths[namespace][name])
}

View file

@ -3,22 +3,30 @@ import { Memory } from "../compilers/Memory.js"
import { Renderer } from "../types/enums/Renderer.js" import { Renderer } from "../types/enums/Renderer.js"
import { Type } from "../types/enums/Type.js" import { Type } from "../types/enums/Type.js"
import { Properties } from "../types/properties/components.js" import { Properties } from "../types/properties/components.js"
import { Namespace, VanillaType } from "../types/vanilla/intellisense.js"
import { Class } from "./Class.js" import { Class } from "./Class.js"
import { RandomString } from "./Utils.js" import { RandomString } from "./Utils.js"
import util from "node:util" import util from "node:util"
export class UI<T extends Type, K extends Renderer | null = null> extends Class { export class UI<T extends Type, K extends Renderer | null = null> extends Class {
private path: string path: string
name: string name: string
namespace: string namespace: string
extend?: UI<Type, Renderer | null> extend?: UI<Type, Renderer | null>
canExtend: boolean
controls = new Map<string, [UI<Type, Renderer | null>, Properties<Type, Renderer | null>]>() controls = new Map<string, [UI<Type, Renderer | null>, Properties<Type, Renderer | null>]>()
properties: Properties<T, K> = <any>{} properties: Properties<T, K> = <any>{}
constructor(public type?: T, name?: string, namespace?: string, path?: string) { constructor(
public type?: T,
name?: string,
namespace?: string,
path?: string,
) {
super() super()
if (name === "namespace") { if (name === "namespace") {
@ -26,12 +34,14 @@ export class UI<T extends Type, K extends Renderer | null = null> extends Class
process.exit(1) process.exit(1)
} }
this.name = name?.match(/^\w+/)?.[0] || RandomString(16) this.name = name?.match(/^(\w|\/)+/)?.[0] || RandomString(16)
this.namespace = namespace || RandomString(16) this.namespace = namespace || RandomString(16)
if (!path) this.path = `@/${this.namespace}` if (!path) this.path = `@/${this.namespace}`
else this.path = path else this.path = path
this.canExtend = this.name.search("/") === -1
Memory.register_ui(this.path, this) Memory.register_ui(this.path, this)
} }
@ -79,7 +89,7 @@ export class UI<T extends Type, K extends Renderer | null = null> extends Class
} }
return `\x1b[33mUI\x1b[0m<\x1b[92m${ return `\x1b[33mUI\x1b[0m<\x1b[92m${
this.type || `${this.extend}` this.type || this.extend ? `${this.extend}` : "ANY"
}\x1b[0m> \x1b[92m"${this}\x1b[92m"\x1b[0m ${util.inspect(obj, opts)}\n` }\x1b[0m> \x1b[92m"${this}\x1b[92m"\x1b[0m ${util.inspect(obj, opts)}\n`
} }
} }

View file

@ -116,7 +116,7 @@ export function Custom<R extends Renderer>(
renderer: R, renderer: R,
properties?: Properties<Type.CUSTOM, R>, properties?: Properties<Type.CUSTOM, R>,
name?: string, name?: string,
namespace?: string namespace?: string,
) { ) {
const custom = new UI<Type.CUSTOM, R>(Type.CUSTOM, name, namespace) const custom = new UI<Type.CUSTOM, R>(Type.CUSTOM, name, namespace)
if (properties) custom.setProperties({ renderer, ...properties }) if (properties) custom.setProperties({ renderer, ...properties })
@ -171,8 +171,11 @@ export function Extends<T extends Type, K extends Renderer | null>(
element: UI<T, K>, element: UI<T, K>,
properties?: Properties<T, K>, properties?: Properties<T, K>,
name?: string, name?: string,
namespace?: string namespace?: string,
) { ) {
if (!element.canExtend) {
throw new Error("Cannot extend a UI that cannot be extended")
}
const ui = new UI<T, K>(undefined, name, namespace) const ui = new UI<T, K>(undefined, name, namespace)
if (properties) ui.setProperties(properties) if (properties) ui.setProperties(properties)
ui.extend = element ui.extend = element

View file

@ -1,35 +1,36 @@
export enum Type { export enum Type {
SELECTION_WHEEL = "selection_wheel", SELECTION_WHEEL = "selection_wheel",
PANEL = "panel", PANEL = "panel",
SCREEN = "screen", SCREEN = "screen",
STACK_PANEL = "stack_panel", STACK_PANEL = "stack_panel",
LABEL = "label", LABEL = "label",
IMAGE = "image", IMAGE = "image",
INPUT_PANEL = "input_panel", INPUT_PANEL = "input_panel",
CUSTOM = "custom", CUSTOM = "custom",
GRID = "grid", GRID = "grid",
FACTORY = "factory", FACTORY = "factory",
BUTTON = "button", BUTTON = "button",
TOGGLE = "toggle", TOGGLE = "toggle",
SLIDER = "slider", SLIDER = "slider",
EDIT_BOX = "edit_box", EDIT_BOX = "edit_box",
DROPDOWN = "dropdown", DROPDOWN = "dropdown",
SCROLL_VIEW = "scroll_view", SCROLL_VIEW = "scroll_view",
SLIDER_BOX = "slider_box", SLIDER_BOX = "slider_box",
SCROLLBAR_BOX = "scrollbar_box", SCROLLBAR_BOX = "scrollbar_box",
SCROLL_TRACK = "scroll_track", SCROLL_TRACK = "scroll_track",
GRID_PAGE_INDICATOR = "grid_page_indicator", GRID_PAGE_INDICATOR = "grid_page_indicator",
IMAGE_CYCLER = "image_cycler", IMAGE_CYCLER = "image_cycler",
LABEL_CYCLER = "label_cycler", LABEL_CYCLER = "label_cycler",
COLLECTION_PANEL = "collection_panel", COLLECTION_PANEL = "collection_panel",
TOOLTIP_TRIGGER = "tooltip_trigger", TOOLTIP_TRIGGER = "tooltip_trigger",
TAB = "tab", TAB = "tab",
CAROUSEL_LABEL = "carousel_label", CAROUSEL_LABEL = "carousel_label",
COMBOX = "combox", COMBOX = "combox",
LAYOUT = "layout", LAYOUT = "layout",
STACK_GRID = "stack_grid", STACK_GRID = "stack_grid",
JOYSTICK = "joystick", JOYSTICK = "joystick",
RICH_TEXT = "rich_text", RICH_TEXT = "rich_text",
SIXTEEN_NINE_LAYOUT = "sixteen_nine_layout", SIXTEEN_NINE_LAYOUT = "sixteen_nine_layout",
MUL_LINES = "mul_lines", MUL_LINES = "mul_lines",
UNKNOWN = "unknown",
} }

View file

@ -2,6 +2,7 @@ import { AnimValue, Array2, Binding, PropertyBags, Value, Variable } from "../va
export interface Control { export interface Control {
visible?: Value<boolean> visible?: Value<boolean>
ignored?: Value<boolean>
enabled?: Value<boolean> enabled?: Value<boolean>
layer?: Value<number> layer?: Value<number>
z_order?: Value<number> z_order?: Value<number>

File diff suppressed because one or more lines are too long

View file

@ -1,2 +1 @@
export * from "./elements.js"
export * from "./intellisense.js" export * from "./intellisense.js"

File diff suppressed because it is too large Load diff

19435
src/types/vanilla/paths.ts Normal file

File diff suppressed because it is too large Load diff

View file

@ -1 +1,7 @@
import { Modify } from ".." import { Extends, GlobalVariables, Modify } from ".."
const vanilla = Modify("anvil_pocket", "slots_panel").setProperties({
ignored: true,
})
console.log(vanilla.path)

View file

@ -3,10 +3,8 @@
"target": "esnext", "target": "esnext",
"module": "nodenext", "module": "nodenext",
"moduleResolution": "nodenext", "moduleResolution": "nodenext",
"outDir": "dist", "outDir": "dist",
"declaration": true, "declaration": true,
"sourceMap": false, "sourceMap": false,
"strict": true, "strict": true,
"esModuleInterop": true, "esModuleInterop": true,
@ -14,5 +12,5 @@
"tsBuildInfoFile": ".tsbuildinfo" "tsBuildInfoFile": ".tsbuildinfo"
}, },
"include": ["src/**/*"], "include": ["src/**/*"],
"exclude": ["node_modules", "dist"] "exclude": ["node_modules"]
} }