Ambushfall

Ambushfall

// Preview: docs
// Menu: Open Project
// Description: Opens a project in vscode
// Shortcut: cmd shift .
import "@johnlindquist/kit";
const envPath = await env('PROJECT_DIR');
const projectDir = home(envPath);
const projectList = await readdir(projectDir);
let { projects, write } = await db("projects", {
projects: projectList,
})
projectList.forEach(async value => {
if (!projects.includes(value)) {
projects.push(value);
await write()
}
})
onTab("Open", async () => {
let project = await arg("Open project:", projects.map(project => project.split('\\').pop()))
edit('', path.resolve(projectDir, project))
})
onTab("Add Path", async () => {
while (true) {
let project = await arg(
"Add path to project:",
md(projects.map(project => `* ${project.split('\\').pop()}`).join("\n"))
)
projects.push(project)
await write()
}
})
onTab("Remove", async () => {
while (true) {
let project = await arg("Open project:", projects.map(project => project.split('\\').pop()))
project.split(':').length > 1 ? await rm(path.resolve(project)) : await rm(path.resolve(projectDir, project))
let indexOfProject = projects.indexOf(project)
projects.splice(indexOfProject, 1)
await write()
}
})
onTab("New Project", async () => {
while (true) {
let project = await arg(
{
placeholder: "Create new project:", debounceInput: 400,
enter: "Create", validate: async (input) => {
let exists = await isDir(path.resolve(projectDir, input));
if (exists) {
return `${input} already exists`;
}
return true;
}
},
)
projects.push(project)
mkdir(path.resolve(projectDir, project))
await write()
}
})

import "@johnlindquist/kit"
// Menu: Search Anime
// Description: Use the jikan.moe API to search anime
// Author: John Lindquist, Updated by Ambushfall
let anime = await arg("Anime:")
let response = await get(
`https://api.jikan.moe/v4/anime?q=${anime}`
)
let { images, title } = response.data.data[0]
let { jpg } = images
let { image_url, small_image_url, large_image_url } = jpg
const html = `<a :href="url">
<img :src="url" />
<div class="card__name">
<span>${title}</span>
</div>
</a>`;
let wg = await widget(html, {
state: {
url: large_image_url
}
})
wg.onResized(async () => {
wg.fit()
})
// win32 on-click not working so this does nothing really.
// TODO: When on click starts working change state to the next result
// wg.onClick((event) => event.targetId === "x" ? wg.close() : inspect(event.targetId));

// Menu: Clipboard History
// Description: Copy something from the clipboard history
// Shortcut: command shift v
import "@johnlindquist/kit"
let { history } = await db("clipboard-history")
let { value, type } = await arg("What to paste?", () => {
return history.map(({ value, type, timestamp, secret }) => {
return {
type,
name: secret ? value.slice(0, 4).padEnd(10, "*") : value,
value: {
value,
type,
},
description: timestamp,
preview:
type === "image"
? md(`![timestamp](${value})`)
: value.includes("\n")
? `<div class="font-mono text-xs">${value
.split("\n")
.map((line) => `<p>${line}</p>`)
.join("")}<div>`
: null,
}
})
})
if (type === "image") {
await copyPathAsImage(value)
await keystroke("command v")
}
if (type === "text") {
await setSelectedText(value)
}

// Menu: Copy to Clipboard
// Description: Save to Clipboard history
// Shortcut: command shift c
import "@johnlindquist/kit"
let { write, history } = await db("clipboard-history", { history: [{ value: "", type: "", timestamp: "", secret: "" }] })
const clipboardVal = await clipboard.readText();
const newValue = {
value: clipboardVal,
timestamp: new Date(Date.now()).toLocaleString('en-GB', { timeZone: 'UTC' }),
secret: clipboardVal.includes('secret'),
type: /(http)?s?:?(\/\/[^"']*\.(?:png|jpg|jpeg|gif|png|svg))/i.test(clipboardVal) ? "image" : "text"
}
history.push(newValue)
await write()

// Name: Theme Maker
// Description: Test Themes
import "@johnlindquist/kit"
const themePath = kenvPath('theme.json');
if (!(await isFile(themePath))) {
let defaultTheme = `{
"foreground": "#ffffff",
"accent": "#fbbf24",
"ui": "#343434",
"background": "#000000",
"opacity": "0.85"
}`.trim()
await writeFile(themePath, defaultTheme)
}
const theme = await readJson(themePath)
const { foreground, accent, ui, background, opacity } = theme
const list = ["foreground", "accent", "ui", "background"]
const valueList = [foreground, accent, ui, background, opacity]
const arrayList = list.map((value, index) => {
return { type: "color", label: value, value: valueList[index] }
})
arrayList.push({ type: "range", label: "Opacity", value: opacity })
await fields({
onChange: (input, { value }) => {
const [foreground, accent, ui, background, opacity] = value
theme.foreground = foreground
theme.accent = accent
theme.ui = ui
theme.background = background
theme.opacity = opacity
setTheme(theme);
writeJson(themePath, theme)
},
fields: arrayList,
})
let result = await div(md(`# Success!`))

import "@johnlindquist/kit"
// Name: Widget Theme Picker
// Description: Color Picker HTML
let themePath = kenvPath("theme.json")
if (!(await isFile(themePath))) {
let defaultTheme = `{
"foreground": "#ffffff",
"accent": "#fbbf24",
"ui": "#343434",
"background": "#000000",
"opacity": "0.85"
}`.trim()
await writeFile(themePath, defaultTheme)
}
const theme = await readJson(themePath)
const { foreground, accent, ui, background, opacity } = theme
let w = await widget(
`
<div class="flex flex-col w-full h-full p-8">
foreground:
<input type="color" label="foreground" data-label="foreground" value="${foreground}" />
background:
<input type="color" label="background" data-label="background" value="${background}" />
accent:
<input type="color" label="accent" data-label="accent" value="${accent}"/>
ui:
<input type="color" label="ui" data-label="ui" value="${ui}"/>
opacity:
<input type="range" min="0" max="1" step="0.01" label="opacity" data-label="opacity" value="${opacity}"/>
</div>`,
{
width: 300,
height: 300,
draggable: false,
}
)
w.onInput(event => {
setTheme({
[event.dataset.label]: event.value,
})
theme[event.dataset.label] = event.value
writeJson(themePath, theme)
})
setIgnoreBlur(true)
await mainScript()

// Name: Theme Maker
// Description: Test Themes
import "@johnlindquist/kit"
const setArgOptions = (key, val) => {
return {
name: key, type: "color", input: val, onInput: async input => {
const scriptObj = {}
scriptObj[key] = input
setScriptTheme(scriptObj)
}
}
}
let foreground = setArgOptions("foreground", "#ffffff")
let accent = await arg(setArgOptions("accent", "#fbbf24"))
let ui = await arg(setArgOptions("ui", "#343434"))
let background = await arg(setArgOptions("background", "#000000"));
let opacity = await arg({
type: "range",
name: "opacity",
input: "85",
onInput: async input => setScriptTheme({opacity:`0.${input}`})
})
let result = await div(md(`# Success!`))
// Name: Run .bat/.ps1/.sh
// Description: Process Output to Kit via stream
import "@johnlindquist/kit"
// @ts-expect-error
import { backToMainShortcut, highlightJavaScript } from "@johnlindquist/kit"
// --- Create a shell script to run -----------------
// `tmpPath` will store the file here:
// ~/.kenv/tmp/process-shell-script-output/example.*
// Note: linux shell will only work with WSL or you can provide the Args for ps1 using the .sh extension if you have gitbash
const fileName = "example"
const selectedLang = {
name: '',
args: '',
ext: '',
echo: '',
set setVal(keyValueList: string[]) {
this[keyValueList[0]] = keyValueList[1];
}
};
const objGen = (_lang: string, _ext: string, _args?: string) => {
_args = _args ? _args : ""
return {
name: _lang,
description: `Run Script using ${_lang}`,
value: _lang,
id: _ext,
arguments: _args,
preview: async () => highlightJavaScript(tmpPath(`${fileName}.${_ext}`))
}
}
const LangOptions = [
objGen("PowerShell",
"ps1",
"powershell -NoProfile -NonInteractive –ExecutionPolicy Bypass -File "
), objGen("Batch", "bat"),
objGen("Bash", "sh"
)]
const promptEditor = ["yes", "no"]
const selectedValue = await arg("Use editor?", promptEditor
)
const useEditor = selectedValue === "yes" ? true : false
// define select options
await arg({
placeholder: "Select Scripting Language...",
enter: "Select",
shortcuts: [backToMainShortcut],
onChoiceFocus: async (input, { focused }) => {
selectedLang.setVal = ["args", focused["arguments"]]
selectedLang.setVal = ["ext", focused.id]
selectedLang.setVal = ["name", focused.name]
selectedLang.setVal = ["echo", selectedLang.ext == "bat" ? "@echo off" : ""]
}
}, LangOptions)
let shellScriptPath = tmpPath(`${fileName}.${selectedLang.ext}`)
const editorConfig = {
hint: `Write code for ${selectedLang.ext} file.`,
description: 'Save to Run',
onInputSubmit: async (input: any) => {
selectedLang.ext == "sh" ? submit(`${input}
exit`) : submit(input)
}
}
// Using ping to simulate waiting for a long process and because it's natively supported across PS and Bat files
// Note: If you use a code that would natively not run in bat like "ls" it will
let scriptContents = useEditor ? await editor(editorConfig) : `${selectedLang.echo}
echo "hello"
echo "Done"
${selectedLang.ext == "sh" ? "exit" : ""}
`
await writeFile(shellScriptPath, scriptContents);
// Just a wrapper to highlight with code in PS style
const codeWrapper = (string: string, extension: any) => `
\`\`\`${extension}
${string}
\`\`\`
`
let output = ``
// This is used to avoid kit window closing on process exit
let divPromise = div()
const outHandler = async (out: any) => {
output += `${out}\n`;
setDiv(
await highlight(`${codeWrapper(output, selectedLang.ext)}`)
)
};
// Note: We have to use this janky way of executing PS as it would launch in Notepad or fail entirely.
const execArgs = selectedLang.ext == "sh" ? `cd ${tmpPath()} && bash ${fileName}.sh` : `${selectedLang.args}${shellScriptPath}`
// inspect(execArgs)
let { stdout } = execLog(execArgs, outHandler)
setAlwaysOnTop(true);
setIgnoreBlur(true);
await divPromise
// Name: JSON to TS-Interfaces
// Description: Quickly get an Interface from JSON
// Author: Ambushfall
// Snippet: json..ts
// Inspired by: Marin Muštra's JSON to TypeScript
import '@johnlindquist/kit';
import { EditorConfig } from '@johnlindquist/kit/types/kitapp';
const JsonToTS = await npm('json-to-ts');
const TSWrapper = (string: string) => `
\`\`\`ts
${string}
\`\`\`
`
const JSONWrapper = (string: string) => `
\`\`\`json
${string}
\`\`\`
`
const editorConfig:EditorConfig = {
hint: "Write then submit to obtain results",
description: 'JSON Values to Interface',
onInputSubmit: async (input: string) => submit(input)
}
// Initialize editor and Parse JSON
const json = await editor(editorConfig)
const obj = JSON.parse(json);
const types = `${JsonToTS(obj).join('\n\n')}\n`;
// Place text into ClipBoard and show results
setSelectedText(types)
await div(await highlight(`# Success! Result Copied to Clipboard!
## Input:${JSONWrapper(json)}
## Output:${TSWrapper(types)}`));