Tips
Tips are a collection of answers to user questions in GitHub Discussions and our Discord organized by topic.
Audio
Cancel Audio with Keyboard Shortcut
// Name: Cancel Audio with Keyboard Shortcut
// Group: Audio
import "@johnlindquist/kit"
// Start saying long thing
say(`I have so much to say I'm just going to keep talking until someone shuts me up`)
registerShortcut("opt x", () => {
say("") //will cancel
process.exit() // you need to exit or else the shortcuts will keep the script active
})
registerShortcut("opt y", () => {
say("You're done", {
name: "Alice",
rate: 0.5,
pitch: 2,
})
process.exit()
})
Clipboard
Format Latest Clipboard Item
// Name: Format Latest Clipboard Item
// Group: Clipboard
import "@johnlindquist/kit"
let text = await paste()
let newText = text.replace("a", "b")
await setSelectedText(newText)
Data
Database Read/Write Example
// Name: Database Read/Write Example
// Description: Add/remove items from a list of fruit
// Group: Data
import "@johnlindquist/kit"
let fruitDb = await db(["apple", "banana", "orange"])
while (true) {
let fruitToAdd = await arg("Add a fruit", md(fruitDb.items.map(fruit => `* ${fruit}`).join("\n")))
fruitDb.items.push(fruitToAdd)
await fruitDb.write()
let fruitToDelete = await arg("Delete a fruit", fruitDb.items)
fruitDb.items = fruitDb.items.filter(fruit => fruit !== fruitToDelete)
await fruitDb.write()
}
Edit the Keys and Values of an Object
// Name: Edit the Keys and Values of an Object
// Group: Data
import "@johnlindquist/kit"
let data = {
name: "John",
age: 42,
location: "USA",
}
let result = await fields(
Object.entries(data).map(([key, value]) => ({
name: key,
label: key,
value: String(value),
}))
)
let newData = Object.entries(data).map(([key], i) => ({
[key]: result[i],
}))
inspect(newData)
Populate db example
// Name: Populate db example
// Description: Shows how to pre-populate database
// Group: Data
// Pass in a function to generate data for the db
// Because this script is named "db-basic.js"
// The database is found at "~/.kenv/db/_db-basic.json"
let reposDb = await db(async () => {
let response = await get("https://api.github.com/users/johnlindquist/repos")
return response.data.map(({ name, description, html_url }) => {
return {
name,
description,
value: html_url,
}
})
})
let repoUrl = await arg("Select repo to open:", reposDb.items)
exec(`open "${repoUrl}"`)
Desktop
Get Active App on Mac
// Name: Get Active App on Mac
// Group: Desktop
// MAC ONLY!
import "@johnlindquist/kit"
// Always hide immmediately if you're not going to show a prompt
await hide()
// Note: This uses "https://www.npmjs.com/package/@johnlindquist/mac-frontmost" inside Kit.app,
// but you can import that package directly (or another similar package) if you prefer
let info = await getActiveAppInfo()
if (info.bundleIdentifier === "com.google.Chrome") {
await keyboard.pressKey(Key.LeftSuper, Key.T)
await keyboard.releaseKey(Key.LeftSuper, Key.T)
}
Editor
Append Text to Editor
// Name: Append Text to Editor
// Group: Editor
import "@johnlindquist/kit"
let sentence = `This is a sentence that will be appended to the editor.`
let words = sentence.split(" ")
setInterval(() => {
let word = words.shift()
if (word) {
editor.append(word + " ")
}
}, 100)
await editor({
lineNumbers: "on",
fontFamily: "Menlo",
})
Preview Markdown
// Name: Preview Markdown
// Group: Editor
import "@johnlindquist/kit"
let value = `
# Hello World
## Markdown Features
Here are some examples of markdown features:
- **Bold Text**
- *Italic Text*
- \`Inline Code\`
1. First item in a numbered list
2. Second item in a numbered list
> Blockquote
![Image Alt Text](https://example.com/image.jpg "Image Title")
~~~javascript
console.log("Code block with syntax highlighting");
~~~
Here is a table:
| Header 1 | Header 2 |
| -------- | -------- |
| Row 1 Col 1 | Row 1 Col 2 |
| Row 2 Col 1 | Row 2 Col 2 |
`.trim()
await editor({
value,
onInput: async input => {
setPreview(md(input))
},
})
Markdown
Generate Tips.md from Scripts
// Name: Generate Tips.md from Scripts
// Group: Markdown
import { Script } from "@johnlindquist/kit"
let scripts = await getScripts()
// Check if kit-docs is a kenv
let kenv = path.basename(projectPath())
let isKitDocsInAKenv = kenv !== ".kenv"
let outFilePath = projectPath("TIPS.md")
if (isKitDocsInAKenv) {
scripts = scripts.filter(script => script.kenv === kenv)
}
scripts.sort((a, b) => a.group.localeCompare(b.group))
// Group by group
let groups: {
[key: string]: Script[]
} = {}
for (let script of scripts) {
if (!groups[script.group]) groups[script.group] = []
groups[script.group].push(script)
}
// Convert Groups into Markdown h2's with the Content Below
let markdownBody = ``
for (let [group, scripts] of Object.entries(groups)) {
markdownBody += `## ${group}\n\n`
for (let script of scripts.sort((a, b) => a.name.localeCompare(b.name))) {
let content = await readFile(script.filePath, "utf8")
markdownBody += `### ${script.name}\n\n`
markdownBody += "```ts\n"
markdownBody += content
markdownBody += "\n```\n\n"
}
}
let markdown = `# Tips
Tips are a collection of answers to user questions in GitHub Discussions and our Discord organized by topic.
${markdownBody}
`.trim()
await writeFile(outFilePath, markdown)
Prompt
Force a User to Pick an Option
// Name: Force a User to Pick an Option
// Group: Prompt
import "@johnlindquist/kit"
let animals = ["dog", "cat", "rabbit", "horse", "elephant"]
let secondsRemaining = 3
let getHint = secondsRemaining => `Hurry! You only have ${secondsRemaining} seconds to choose an animal...`
let animal = ""
animal = await arg(
{
hint: getHint(secondsRemaining),
onInit: async () => {
while (secondsRemaining > 0 && !animal) {
setHint(getHint(secondsRemaining))
await wait(1000)
secondsRemaining--
}
if (!animal) exit()
},
},
animals
)
await div(md(`# Phew! You made it! You chose ${animal}`))
Progress Panel
// Name: Progress Panel
// Group: Prompt
import "@johnlindquist/kit"
let first = ""
let second = ""
let third = ""
let progressPanel = () =>
md(`# Progress:
- ${first || "Waiting first value"}
- ${second || "Waiting second value"}
- ${third || "Waiting third value"}
`)
first = await arg("Enter the first value", progressPanel)
second = await arg("Enter the second value", progressPanel)
third = await arg("Enter the third value", progressPanel)
await div(
md(`# You entered:
- ${first}
- ${second}
- ${third}
`)
)
Provide Contextual Search Information
// Name: Provide Contextual Search Information
// Group: Prompt
import "@johnlindquist/kit"
let choices = [
{
// Always show
name: "Please contact support if you don't see your fruit",
info: true,
},
{
// Only show when there are no results
name: "No fruits match your search",
miss: true,
},
"apple",
"banana",
"orange",
]
await arg(
{
placeholder: "Select a fruit for your basket",
enter: "Checkout",
},
choices
)
Return to the Main Script on Escape
// Name: Return to the Main Script on Escape
// Group: Prompt
import "@johnlindquist/kit"
await div({
html: md(`# Hello`),
shortcuts: [
{
key: "escape",
onPress: async () => {
await mainScript()
},
},
],
})
Rewind Prompts
// Name: Rewind Prompts
// Group: Prompt
import { Shortcut } from "@johnlindquist/kit"
let currentStep = 0
let direction = 1
let shortcuts: Shortcut[] = [
{
key: "escape",
onPress: async () => {
submit("")
},
},
]
let step1 = async () =>
await arg({
placeholder: "one",
shortcuts,
})
let step2 = async () =>
await arg({
placeholder: "two",
shortcuts,
})
let step3 = async () =>
await arg({
placeholder: "three",
shortcuts,
})
let steps = [
{ prompt: step1, value: "" },
{ prompt: step2, value: "" },
{ prompt: step3, value: "" },
]
while (currentStep < steps.length) {
let step = steps[currentStep]
step.value = await step.prompt()
direction = step.value ? 1 : -1
currentStep += direction
if (currentStep < 0) {
exit() // Pressing escape on the first prompt will exit the script
}
}
inspect(steps)
Single Keystroke Demo
// Name: Single Keystroke Demo
// Group: Prompt
import "@johnlindquist/kit"
let choice = await arg({
placeholder: "Choose a color",
choices: [
{ name: "[R]ed", value: "red" },
{ name: "[G]reen", value: "green" },
{ name: "[B]lue", value: "blue" },
],
})
await div(md(`You chose ${choice}`))
Strict Mode
// Name: Strict Mode
// Group: Prompt
import "@johnlindquist/kit"
let fruit = await arg(
{
placeholder: "Select a fruit",
hint: "Type 'Grape' and hit enter",
strict: false,
},
["Apple", "Banana", "Cherry"]
)
await div(md(fruit))
Styles
Adjust the CSS of Choices
// Name: Adjust the CSS of Choices
// Group: Styles
import "@johnlindquist/kit"
let choice = await arg({
css: `
.light-purple {
background-color: #c8a2c8;
}
.medium-purple {
background-color: #967bb6;
}
.dark-purple {
background-color: #5d4777;
}
.focused {
box-shadow: inset .5rem 0 0 0 #ffffffee;
}
`,
placeholder: "Choose a shade of purple",
choices: [
{ name: "[L]ight Purple", value: "light-purple", className: "light-purple", focusedClassName: "focused" },
{ name: "[M]edium Purple", value: "medium-purple", className: "medium-purple", focusedClassName: "focused" },
{ name: "[D]ark Purple", value: "dark-purple", className: "dark-purple", focusedClassName: "focused" },
],
})
await div(md(`You chose ${choice}`))