// 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 Ambushfalllet 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 } = imageslet { image_url, small_image_url, large_image_url } = jpgconst 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 vimport "@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 cimport "@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 Themesimport "@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 } = themeconst 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] = valuetheme.foreground = foregroundtheme.accent = accenttheme.ui = uitheme.background = backgroundtheme.opacity = opacitysetTheme(theme);writeJson(themePath, theme)},fields: arrayList,})let result = await div(md(`# Success!`))
import "@johnlindquist/kit"// Name: Widget Theme Picker// Description: Color Picker HTMLlet 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 } = themelet 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.valuewriteJson(themePath, theme)})setIgnoreBlur(true)await mainScript()
// Name: Theme Maker// Description: Test Themesimport "@johnlindquist/kit"const setArgOptions = (key, val) => {return {name: key, type: "color", input: val, onInput: async input => {const scriptObj = {}scriptObj[key] = inputsetScriptTheme(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 streamimport "@johnlindquist/kit"// @ts-expect-errorimport { 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 gitbashconst 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 optionsawait 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 willlet 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 styleconst codeWrapper = (string: string, extension: any) => `\`\`\`${extension}${string}\`\`\``let output = ``// This is used to avoid kit window closing on process exitlet 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 TypeScriptimport '@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 JSONconst json = await editor(editorConfig)const obj = JSON.parse(json);const types = `${JsonToTS(obj).join('\n\n')}\n`;// Place text into ClipBoard and show resultssetSelectedText(types)await div(await highlight(`# Success! Result Copied to Clipboard!## Input:${JSONWrapper(json)}## Output:${TSWrapper(types)}`));