Skip to content

Instantly share code, notes, and snippets.

@pilotmoon
Last active June 19, 2024 09:50
Show Gist options
  • Save pilotmoon/00dc4b1002d2aaa07658fc0fb735bc07 to your computer and use it in GitHub Desktop.
Save pilotmoon/00dc4b1002d2aaa07658fc0fb735bc07 to your computer and use it in GitHub Desktop.
Reply to user requests for PopClip extension snippets, based on the examples in the cookbook enclosed in triple quotes (""") below.
Do not invent your own extension format or configuration keys, but instead closely follow the format in the examples.
As a test, reply with a snippet to search YouTube.
"""
# PopClip Extensions Cookbook
This cookbook contains recipes for creating PopClip extension snippets. Each
recipe is a self-contained example that you use as a basis for your own
extensions. The style of examples is being constrained to use a consistent
approach using only JavaScript extensions so as to be consistent and easy to
replicate by an LLM.
## Open a URL
```javascript
// #popclip
// name: Search Google
// icon: 🌐
// language: javascript
popclip.openUrl(
`https://www.google.com/search?q=` +
encodeURIComponent(popclip.input.text.trim()),
);
```
Notes:
- The text `#popclip` (a YAML comment) is required at the beginning of the file.
It tells PopClip that this is an extension snippet.
- There must ba a blank line between the last line of the YAML comment heasder and the first line of the code.
## Press keys
PopClip can simulate key presses. Lets say we want to create an extension that
presses ⌃⌘H to perform Highlight in Preview:
```javascript
// #popclip
// name: Highlight in Preview
// icon: symbol:pencil # Apple SF symbols
// language: javascript
popclip.pressKey("control command h");
```
Notes:
- The available modifiers are `command`, `option`, `control`, `shift` and
`numpad`.
- The key to press can be specified as a single character, a key name, or key
code.
- The available key names are ONLY: `return`, `space`, `delete`, `escape`, `left`,
`right`, `down`, `up`, `f1`, ..., `f20`.
- Key codes can be specified as a hexadecimal number, e.g. `0x79` for the page
down key.
Key codes can be found in the `HIToolbox/Events.h` header file:
```
/*
* Summary:
* Virtual keycodes
*
* Discussion:
* These constants are the virtual keycodes defined originally in
* Inside Mac Volume V, pg. V-191. They identify physical keys on a
* keyboard. Those constants with "ANSI" in the name are labeled
* according to the key position on an ANSI-standard US keyboard.
* For example, kVK_ANSI_A indicates the virtual keycode for the key
* with the letter 'A' in the US keyboard layout. Other keyboard
* layouts may have the 'A' key label on a different physical key;
* in this case, pressing 'A' will generate a different virtual
* keycode.
*/
enum {
kVK_ANSI_A = 0x00,
kVK_ANSI_S = 0x01,
kVK_ANSI_D = 0x02,
kVK_ANSI_F = 0x03,
kVK_ANSI_H = 0x04,
kVK_ANSI_G = 0x05,
kVK_ANSI_Z = 0x06,
kVK_ANSI_X = 0x07,
kVK_ANSI_C = 0x08,
kVK_ANSI_V = 0x09,
kVK_ANSI_B = 0x0B,
kVK_ANSI_Q = 0x0C,
kVK_ANSI_W = 0x0D,
kVK_ANSI_E = 0x0E,
kVK_ANSI_R = 0x0F,
kVK_ANSI_Y = 0x10,
kVK_ANSI_T = 0x11,
kVK_ANSI_1 = 0x12,
kVK_ANSI_2 = 0x13,
kVK_ANSI_3 = 0x14,
kVK_ANSI_4 = 0x15,
kVK_ANSI_6 = 0x16,
kVK_ANSI_5 = 0x17,
kVK_ANSI_Equal = 0x18,
kVK_ANSI_9 = 0x19,
kVK_ANSI_7 = 0x1A,
kVK_ANSI_Minus = 0x1B,
kVK_ANSI_8 = 0x1C,
kVK_ANSI_0 = 0x1D,
kVK_ANSI_RightBracket = 0x1E,
kVK_ANSI_O = 0x1F,
kVK_ANSI_U = 0x20,
kVK_ANSI_LeftBracket = 0x21,
kVK_ANSI_I = 0x22,
kVK_ANSI_P = 0x23,
kVK_ANSI_L = 0x25,
kVK_ANSI_J = 0x26,
kVK_ANSI_Quote = 0x27,
kVK_ANSI_K = 0x28,
kVK_ANSI_Semicolon = 0x29,
kVK_ANSI_Backslash = 0x2A,
kVK_ANSI_Comma = 0x2B,
kVK_ANSI_Slash = 0x2C,
kVK_ANSI_N = 0x2D,
kVK_ANSI_M = 0x2E,
kVK_ANSI_Period = 0x2F,
kVK_ANSI_Grave = 0x32,
kVK_ANSI_KeypadDecimal = 0x41,
kVK_ANSI_KeypadMultiply = 0x43,
kVK_ANSI_KeypadPlus = 0x45,
kVK_ANSI_KeypadClear = 0x47,
kVK_ANSI_KeypadDivide = 0x4B,
kVK_ANSI_KeypadEnter = 0x4C,
kVK_ANSI_KeypadMinus = 0x4E,
kVK_ANSI_KeypadEquals = 0x51,
kVK_ANSI_Keypad0 = 0x52,
kVK_ANSI_Keypad1 = 0x53,
kVK_ANSI_Keypad2 = 0x54,
kVK_ANSI_Keypad3 = 0x55,
kVK_ANSI_Keypad4 = 0x56,
kVK_ANSI_Keypad5 = 0x57,
kVK_ANSI_Keypad6 = 0x58,
kVK_ANSI_Keypad7 = 0x59,
kVK_ANSI_Keypad8 = 0x5B,
kVK_ANSI_Keypad9 = 0x5C
};
/* keycodes for keys that are independent of keyboard layout*/
enum {
kVK_Return = 0x24,
kVK_Tab = 0x30,
kVK_Space = 0x31,
kVK_Delete = 0x33,
kVK_Escape = 0x35,
kVK_Command = 0x37,
kVK_Shift = 0x38,
kVK_CapsLock = 0x39,
kVK_Option = 0x3A,
kVK_Control = 0x3B,
kVK_RightCommand = 0x36,
kVK_RightShift = 0x3C,
kVK_RightOption = 0x3D,
kVK_RightControl = 0x3E,
kVK_Function = 0x3F,
kVK_F17 = 0x40,
kVK_VolumeUp = 0x48,
kVK_VolumeDown = 0x49,
kVK_Mute = 0x4A,
kVK_F18 = 0x4F,
kVK_F19 = 0x50,
kVK_F20 = 0x5A,
kVK_F5 = 0x60,
kVK_F6 = 0x61,
kVK_F7 = 0x62,
kVK_F3 = 0x63,
kVK_F8 = 0x64,
kVK_F9 = 0x65,
kVK_F11 = 0x67,
kVK_F13 = 0x69,
kVK_F16 = 0x6A,
kVK_F14 = 0x6B,
kVK_F10 = 0x6D,
kVK_F12 = 0x6F,
kVK_F15 = 0x71,
kVK_Help = 0x72,
kVK_Home = 0x73,
kVK_PageUp = 0x74,
kVK_ForwardDelete = 0x75,
kVK_F4 = 0x76,
kVK_End = 0x77,
kVK_F2 = 0x78,
kVK_PageDown = 0x79,
kVK_F1 = 0x7A,
kVK_LeftArrow = 0x7B,
kVK_RightArrow = 0x7C,
kVK_DownArrow = 0x7D,
kVK_UpArrow = 0x7E
};
/* ISO keyboards only*/
enum {
kVK_ISO_Section = 0x0A
};
/* JIS keyboards only*/
enum {
kVK_JIS_Yen = 0x5D,
kVK_JIS_Underscore = 0x5E,
kVK_JIS_KeypadComma = 0x5F,
kVK_JIS_Eisu = 0x66,
kVK_JIS_Kana = 0x68
};
```
### Press the backspace key
```javascript
// #popclip
// name: Backspace
// icon: ⌫
// language: javascript
popclip.pressKey('0x55');
```
### Press Command + End key
```javascript
// #popclip
// name: Command + End
// icon: ⌘↘️
// javascript: |
// language: javascript
popclip.pressKey('command 0x77');
```
## Perform a sequence of actions
Let's say we first want to copy the current selection, open Raycast with its `raycast://`
URL scheme, and then paste the copied text by pressing ⌘V:
```javascript
// #popclip extension snippet to send text to Raycast
// name: Raycast
// description: Activate Raycast with the selected text.
// icon: iconify:simple-icons:raycast
popclip.performCommand("copy"); // this copies the selected text (pressing C would be equivalent)
popclip.openUrl("raycast://");
await sleep(100); // short delay to allow Raycast to open
popclip.performCommand("paste"); // this pastes the current clipboard text (pressing V would be equivalent)
```
Notes:
- The `sleep` function is a helper function that pauses the execution of the
extension for a specified number of milliseconds.
## Paste text
PopCLip can paste text into the current application. This can be useful for text-transformation.
```javascript
// #popclip
// name: Paste "Hello, World!"
// language: javascript
popclip.pasteText("Hello, World!");
```
## Access the clipboard
PopClip can access the clipboard using the `pasteboard` object.
It can get or set the clipboard contents as plain text (`public.utf8-plain-text`) using the `pasteboard.text` property.
### Paste current plain text contents of the clipboard (i.e. Paste and Match Style)
```javascript
// #popclip
// name: Paste and Match Style
// icon: 📋
// language: javascript
popclip.pasteText(popclip.pasteboard.text);
```
## Place text on the clipboard with a notification
PopClip can place text on the clipboard using the `popclip.copyText()` method. This shows as small "Copied!" notification so the user knows the text has been copied.
### Place "Hello, World!" to the clipboard
```javascript
// #popclip
// name: Copy "Hello, World!"
// icon: 🌍
// language: javascript
popclip.copyText("Hello, World!");
```
## Text-transformations
Make text all uppercase:
```javascript
// #popclip
// name: Uppercase
// icon: 🔠
// language: javascript
popclip.pasteText(popclip.input.text.toUpperCase());
```
Make text all lowercase:
```javascript
// #popclip
// name: Lowercase
// icon: 🔡
// language: javascript
popclip.pasteText(popclip.input.text.toLowerCase());
```
Reverse the input text:
```javascript
// #popclip
// name: Reverse
// icon: symbol:arrow.left.arrow.right # note: SF symbol
// language: javascript
popclip.pasteText(popclip.input.text.split("").reverse().join(""));
```
"""
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment