mirror of
https://github.com/wavetermdev/inshellisense.git
synced 2026-08-05 13:43:30 -07:00
feat: handle additional struct components & enable full pass on almost all completion specs
Signed-off-by: cpendery <cpendery@vt.edu>
This commit is contained in:
@@ -13,17 +13,31 @@ type Suggestion struct {
|
||||
}
|
||||
|
||||
var (
|
||||
cmdDelimiter = regexp.MustCompile(`(\|\|)|(&&)|(;)`)
|
||||
cmdDelimiter = regexp.MustCompile(`(\|\|)|(&&)|(;)`)
|
||||
lastSuggestionCmd = ""
|
||||
lastSuggestion = []Suggestion{}
|
||||
)
|
||||
|
||||
func LoadSuggestions(cmd string) []Suggestion {
|
||||
func loadSuggestions(cmd string) (suggestions []Suggestion) {
|
||||
activeCmd := ParseCommand(cmd)
|
||||
if len(activeCmd) <= 0 {
|
||||
return []Suggestion{}
|
||||
return
|
||||
}
|
||||
log.Println(activeCmd, activeCmd[0].token)
|
||||
if spec, ok := specs.Specs[activeCmd[0].token]; ok {
|
||||
rootToken := activeCmd[0]
|
||||
if !rootToken.complete {
|
||||
return
|
||||
}
|
||||
if spec, ok := specs.Specs[rootToken.token]; ok {
|
||||
log.Println(spec.Description)
|
||||
}
|
||||
return []Suggestion{}
|
||||
return
|
||||
}
|
||||
|
||||
func LoadSuggestions(cmd string) []Suggestion {
|
||||
if cmd == lastSuggestionCmd {
|
||||
return lastSuggestion
|
||||
}
|
||||
suggestions := loadSuggestions(cmd)
|
||||
lastSuggestionCmd, lastSuggestion = cmd, suggestions
|
||||
return suggestions
|
||||
}
|
||||
|
||||
+142
-49
@@ -3,6 +3,20 @@ import * as fs from "fs";
|
||||
import * as path from "path";
|
||||
import * as process from "process";
|
||||
import * as child_process from "child_process";
|
||||
import ProgressBar = require("progress");
|
||||
|
||||
const exclusions = new Set(["deno.ts", "rush.ts"]);
|
||||
|
||||
const clearAllNewlines = (input: string): string => {
|
||||
return input.replaceAll(/[\r\n]+/g, "");
|
||||
};
|
||||
|
||||
function chunk<T>(arr: T[], chuckSize: number): T[][] {
|
||||
const arrays: T[][] = [];
|
||||
for (let i = 0; i < arr.length; i += chuckSize)
|
||||
arrays.push(arr.slice(i, i + chuckSize));
|
||||
return arrays;
|
||||
}
|
||||
|
||||
const main = async () => {
|
||||
const basePath = path.join(process.cwd(), ".fig");
|
||||
@@ -15,70 +29,149 @@ const main = async () => {
|
||||
const directoryItems = await fsAsync.readdir(basePath, {
|
||||
withFileTypes: true,
|
||||
});
|
||||
await Promise.all(
|
||||
[directoryItems[10]].map(async (directoryItem) => {
|
||||
if (!directoryItem.isFile()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const spec: Fig.Spec = (
|
||||
await import(path.join(basePath, directoryItem.name))
|
||||
).default;
|
||||
|
||||
if (typeof spec === "function") {
|
||||
return;
|
||||
}
|
||||
|
||||
const filenameWithoutExtension = path.parse(directoryItem.name).name;
|
||||
const subcommand = spec as unknown as Fig.Subcommand;
|
||||
const generatedCode = generateGolang(
|
||||
subcommand,
|
||||
filenameWithoutExtension
|
||||
);
|
||||
await fsAsync.writeFile(
|
||||
path.join(
|
||||
process.cwd(),
|
||||
"..",
|
||||
"specs",
|
||||
`${filenameWithoutExtension}.go`
|
||||
),
|
||||
generatedCode
|
||||
);
|
||||
})
|
||||
const progressBar = new ProgressBar(
|
||||
"extracting [:bar] :percent (:current/:total)",
|
||||
{
|
||||
total: directoryItems.length,
|
||||
complete: "=",
|
||||
incomplete: " ",
|
||||
width: 20,
|
||||
}
|
||||
);
|
||||
|
||||
const dirItemChunks = chunk(directoryItems, 10);
|
||||
for (const dirChunk of dirItemChunks) {
|
||||
await Promise.all(
|
||||
dirChunk.map(async (directoryItem) => {
|
||||
if (!directoryItem.isFile()) {
|
||||
progressBar.tick();
|
||||
return;
|
||||
}
|
||||
if (exclusions.has(directoryItem.name)) {
|
||||
progressBar.tick();
|
||||
return;
|
||||
}
|
||||
|
||||
const spec: Fig.Spec = (
|
||||
await import(path.join(basePath, directoryItem.name))
|
||||
).default;
|
||||
|
||||
if (typeof spec === "function") {
|
||||
progressBar.tick();
|
||||
return;
|
||||
}
|
||||
|
||||
const filenameWithoutExtension = path.parse(directoryItem.name).name;
|
||||
const subcommand = spec as unknown as Fig.Subcommand;
|
||||
const generatedCode = generateGolang(
|
||||
subcommand,
|
||||
filenameWithoutExtension
|
||||
);
|
||||
await fsAsync.writeFile(
|
||||
path.join(
|
||||
process.cwd(),
|
||||
"..",
|
||||
"specs",
|
||||
`${filenameWithoutExtension}.go`
|
||||
),
|
||||
generatedCode
|
||||
);
|
||||
progressBar.tick();
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
const generatedFilesPath = path.join(process.cwd(), "..", "specs");
|
||||
child_process.exec(`gofmt -w ${generatedFilesPath}`);
|
||||
};
|
||||
|
||||
const generateTemplate = (template: Fig.Template): string => {
|
||||
switch (template) {
|
||||
case "filepaths":
|
||||
return "model.TemplateFilepaths";
|
||||
case "folders":
|
||||
return "model.TemplateFolders";
|
||||
case "history":
|
||||
return "model.TemplateHistory";
|
||||
case "help":
|
||||
return "model.TemplateHelp";
|
||||
}
|
||||
throw Error("unknown template value");
|
||||
};
|
||||
|
||||
const genName = (name: Fig.SingleOrArray<string> | undefined): string => {
|
||||
if (name == null) return "";
|
||||
return Array.isArray(name)
|
||||
? `Name: []string{${name.map((n) => `"${n}"`).join(",")}},`
|
||||
: `Name: "${name}",`;
|
||||
};
|
||||
|
||||
const genDescription = (description: string | undefined): string => {
|
||||
return description != null
|
||||
? `Description: "${clearAllNewlines(description)}",`
|
||||
: "";
|
||||
};
|
||||
|
||||
const genTemplates = (
|
||||
template: Fig.SingleOrArray<Fig.Template> | undefined
|
||||
): string => {
|
||||
if (template == null) return "";
|
||||
const templates = Array.isArray(template) ? template : [template];
|
||||
return `Templates: []model.Template{${templates
|
||||
.map((t) => generateTemplate(t))
|
||||
.join(",")}},`;
|
||||
};
|
||||
|
||||
const genOptions = (options: Fig.Option[] | undefined): string => {
|
||||
return options != null ? generateOptions(options) : "";
|
||||
};
|
||||
|
||||
const genArgs = (args: Fig.SingleOrArray<Fig.Arg> | undefined): string => {
|
||||
return args != null ? generateArgs(args) : "";
|
||||
};
|
||||
|
||||
const genSubcommands = (
|
||||
subcommand: Fig.SingleOrArray<Fig.Subcommand> | undefined
|
||||
): string => {
|
||||
if (subcommand == null) return "";
|
||||
const subcommands = Array.isArray(subcommand) ? subcommand : [subcommand];
|
||||
return `Subcommands: []model.Subcommand{${subcommands
|
||||
.map((s) => generateSubcommand(s))
|
||||
.join(",")}},`;
|
||||
};
|
||||
|
||||
const generateArgs = (args: Fig.SingleOrArray<Fig.Arg>): string => {
|
||||
return "";
|
||||
const argList = Array.isArray(args) ? args : [args];
|
||||
const generatedArgs = argList.map((arg) => {
|
||||
return `{
|
||||
${genTemplates(arg.template)}
|
||||
${genName(arg.name)}
|
||||
${genDescription(arg.description)}
|
||||
},`;
|
||||
});
|
||||
return `Args: []model.Arg{${generatedArgs}},`;
|
||||
};
|
||||
|
||||
const generateOptions = (options: Fig.Option[]): string => {
|
||||
return "";
|
||||
const generatedOptions = options.map((option) => {
|
||||
return `{
|
||||
${genName(option.name)}
|
||||
${genDescription(option.description)}
|
||||
${genArgs(option.args)}
|
||||
}`;
|
||||
});
|
||||
return `Options: []model.Option{${generatedOptions}},`;
|
||||
};
|
||||
|
||||
const generateSubcommand = (subcommand: Fig.Subcommand): string => {
|
||||
const name = Array.isArray(subcommand.name)
|
||||
? `Name: []string{${subcommand.name.map((n) => `"${n}"`).join(",")}},`
|
||||
: `Name: "${subcommand.name}",`;
|
||||
|
||||
const description =
|
||||
subcommand.description != null
|
||||
? `Description: "${subcommand.description}",`
|
||||
: "";
|
||||
|
||||
const args = subcommand.args != null ? generateArgs(subcommand.args) : "";
|
||||
const options =
|
||||
subcommand.options != null ? generateOptions(subcommand.options) : "";
|
||||
|
||||
return `model.Subcommand{
|
||||
${name}
|
||||
${description}
|
||||
${args}
|
||||
${options}
|
||||
}`.replaceAll(/\s/g, "");
|
||||
${genName(subcommand.name)}
|
||||
${genDescription(subcommand.description)}
|
||||
${genArgs(subcommand.args)}
|
||||
${genOptions(subcommand.options)}
|
||||
${genSubcommands(subcommand.subcommands)}
|
||||
}`;
|
||||
};
|
||||
|
||||
const generateGolang = (
|
||||
|
||||
Generated
+441
-4
File diff suppressed because it is too large
Load Diff
@@ -4,8 +4,19 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^20.6.0",
|
||||
"@types/progress": "^2.0.5",
|
||||
"@withfig/autocomplete-types": "^1.28.0",
|
||||
"ts-node": "^10.9.1",
|
||||
"typescript": "^5.2.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"@fig/autocomplete-generators": "^2.2.5",
|
||||
"@fig/autocomplete-helpers": "^1.0.7",
|
||||
"@fig/autocomplete-hooks": "^1.0.2",
|
||||
"@withfig/api-bindings": "^0.30.3",
|
||||
"progress": "^2.0.3",
|
||||
"semver": "^7.5.4",
|
||||
"strip-json-comments": "^5.0.1",
|
||||
"yaml": "^2.3.2"
|
||||
}
|
||||
}
|
||||
@@ -1,12 +1,24 @@
|
||||
{
|
||||
"ts-node": {
|
||||
"transpileOnly": true,
|
||||
"files": true,
|
||||
"compilerOptions": {
|
||||
"module": "commonjs"
|
||||
}
|
||||
},
|
||||
"compilerOptions": {
|
||||
"target": "esnext",
|
||||
"module": "commonjs",
|
||||
"moduleResolution": "node",
|
||||
"declaration": true,
|
||||
"outDir": "./build",
|
||||
"strict": true,
|
||||
"esModuleInterop": true,
|
||||
"types": ["@withfig/autocomplete-types", "node"]
|
||||
"types": ["@withfig/autocomplete-types", "node"],
|
||||
// rule changes
|
||||
"noImplicitAny": false,
|
||||
"strictNullChecks": false,
|
||||
"allowSyntheticDefaultImports": true
|
||||
},
|
||||
"exclude": ["node_modules/", "fig/", "build/"]
|
||||
}
|
||||
|
||||
@@ -3,8 +3,9 @@ package model
|
||||
type Subcommand struct {
|
||||
Name interface{} //single or array string, required
|
||||
Description string
|
||||
Args interface{} //single or array Arg, optional
|
||||
Args []Arg
|
||||
Options []Option
|
||||
Subcommands []Subcommand
|
||||
}
|
||||
|
||||
type Option struct {
|
||||
@@ -14,9 +15,9 @@ type Option struct {
|
||||
}
|
||||
|
||||
type Arg struct {
|
||||
Name string //single, optional
|
||||
Description string //single, optional
|
||||
Template Template //single, optional
|
||||
Name string //single, optional
|
||||
Description string //single, optional
|
||||
Templates []Template
|
||||
}
|
||||
|
||||
type Template string
|
||||
@@ -25,6 +26,7 @@ const (
|
||||
TemplateFilepaths Template = "filepaths"
|
||||
TemplateFolders Template = "folders"
|
||||
TemplateHistory Template = "history"
|
||||
TemplateHelp Template = "help"
|
||||
)
|
||||
|
||||
var (
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
// Code generated by autocomplete/extract/extract.ts. DO NOT EDIT.
|
||||
|
||||
package specs
|
||||
|
||||
import (
|
||||
"github.com/cpendery/clac/autocomplete/model"
|
||||
)
|
||||
|
||||
func init() {
|
||||
Specs["afplay"] = model.Subcommand{Name: "afplay", Description: "AudioFilePlay"}
|
||||
}
|
||||
Reference in New Issue
Block a user