Ambushfall

Ambushfall

// Name: OCR
// Description: Capture a screenshot and recognize the text using tesseract.js
import "@johnlindquist/kit";
//both win and linux implementations were created by chatgpt (gpt4), without _any_ tests!! 😅
const captureScreenshot = async () => {
const tmpFile = kenvTmpPath(`screenshot-${Date.now()}.png`);
const scriptFile = kenvTmpPath('script.ps1');
if (isMac) {
await exec(`screencapture -i ${tmpFile}`);
} else if (isWin) {
const psScript = `Add-Type -AssemblyName System.Windows.Forms;
[System.Windows.Forms.SendKeys]::SendWait('%{PRTSC}');
Start-Sleep -m 500;
$clipboardData = Get-Clipboard -Format Image;
$clipboardData.Save('${tmpFile}', [System.Drawing.Imaging.ImageFormat]::Png);`;
// Save to file as powershell inline parsing is tricky, there are special rules to this and it's a pain.
// We already have write on disk, so there's really no point in encoding it as a string.
await writeFile(scriptFile, psScript.replace(/\n/g, ''))
// Execute saved file
await exec(`powershell -File "${scriptFile}"`);
} else if (isLinux) {
// Check if gnome-screenshot is available
try {
await exec('gnome-screenshot --version');
await exec(`gnome-screenshot -f ${tmpFile}`);
} catch (error) {
// If gnome-screenshot is not available, try using ImageMagick's 'import' command
await exec(`import ${tmpFile}`);
}
}
return tmpFile;
};
const recognizeText = async (filePath, language) => {
const { createWorker } = await npm("tesseract.js");
const worker = await createWorker();
await worker.loadLanguage(language);
await worker.initialize(language);
const { data } = await worker.recognize(filePath);
await worker.terminate();
return data.text;
};
const languages = [
{ name: "Spanish", value: "spa" },
{ name: "French", value: "fra" },
{ name: "Portuguese", value: "por" },
{ name: "English", value: "eng" },
];
//@todo train a model for typescript (https://github.com/tesseract-ocr/tesstrain)
// if ctrl is pressed, show a modal to select a language
const selectedLanguage = flag.ctrl
? await arg("Select a language:", languages)
: "eng";
// Hide the Kit modal before capturing the screenshot
await hide();
const filePath = await captureScreenshot();
if (!await pathExists(filePath)) exit()
const text = await recognizeText(filePath, selectedLanguage);
if (text) {
await clipboard.writeText(text.trim());
await notify("Text recognized and copied to clipboard");
} else {
await notify("No text found in the screenshot");
}
// Clean up temporary file
await remove(filePath);
// 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: () => 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
)
const shellScriptPath = kenvTmpPath(`${fileName}.${selectedLang.ext}`)
const editorConfig = {
hint: `Write code for ${selectedLang.ext} file.`,
description: 'Save to Run',
onInputSubmit: async (input: any) => {
selectedLang.ext == 'sh'
? await submit(`${input}
exit`)
: await 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: string) => {
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

// 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()
}
})