Skip to content

Commit f852dc1

Browse files
committed
feat(text): adding getSelectedTextEx
1 parent 5cbc936 commit f852dc1

File tree

2 files changed

+70
-14
lines changed

2 files changed

+70
-14
lines changed

src/lib/text.ts

Lines changed: 52 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,56 @@ import { Channel } from "../core/enum.js"
22

33
global.getSelectedText = async () => {
44
await global.hide()
5+
await sendWait(Channel.KEYBOARD_COPY)
6+
const result = await global.paste()
7+
if (result?.replace(/[\r\n]/g, "") === "") return ""
8+
return result
9+
}
10+
11+
/**
12+
* Robust selected text retrieval with polling and optional clipboard restore.
13+
* Returns a structured result without changing existing getSelectedText.
14+
*/
15+
global.getSelectedTextEx = async (
16+
options?: {
17+
restoreClipboard?: boolean
18+
timeoutMs?: number
19+
pollMs?: number
20+
}
21+
) => {
22+
const restore = options?.restoreClipboard !== false
23+
const timeoutMs = Number.isFinite(options?.timeoutMs) ? (options?.timeoutMs as number) : 1000
24+
const pollMs = Number.isFinite(options?.pollMs) ? (options?.pollMs as number) : 75
525

26+
const prev = await global.paste()
27+
await global.hide()
628
await sendWait(Channel.KEYBOARD_COPY)
729

8-
const result = await global.paste()
30+
const start = Date.now()
31+
let current = ""
32+
while (Date.now() - start < timeoutMs) {
33+
current = await global.paste()
34+
if (current && current !== prev) break
35+
await new Promise((r) => setTimeout(r, pollMs))
36+
}
937

10-
if (result?.replace(/[\r\n]/g, "") === "") {
11-
return ""
38+
// Classify
39+
const value = current || ""
40+
const ok = Boolean(value)
41+
const reason = ok ? undefined : (prev ? "unchanged" : "no-selection")
42+
43+
if (restore) {
44+
try {
45+
// Only restore if we actually changed the clipboard and we still hold that value
46+
if (ok && (await global.paste()) === value) {
47+
await global.copy(prev)
48+
}
49+
} catch {
50+
// ignore restore errors
51+
}
1252
}
1353

14-
return result
54+
return { ok, value, reason }
1555
}
1656

1757
/**
@@ -22,13 +62,15 @@ await setSelectedText(`Script Kit is awesome!`)
2262
```
2363
*/
2464

25-
global.setSelectedText = async (text = "", hide = true) => {
65+
global.setSelectedText = async (
66+
text: string = "",
67+
options?: boolean | { hide?: boolean; method?: "typing" | "clipboard" | "auto" }
68+
) => {
69+
// Back-compat: second param as boolean means hide
70+
const hide = typeof options === "boolean" ? options : options?.hide !== false
71+
const method = typeof options === "object" ? options?.method : undefined
2672
if (hide) await global.hide()
27-
28-
return await sendWait(Channel.SET_SELECTED_TEXT, {
29-
text,
30-
hide,
31-
})
73+
return await sendWait(Channel.SET_SELECTED_TEXT, { text, hide, method })
3274
}
3375

3476
global.cutText = () => sendWait(Channel.CUT_TEXT)

src/types/platform.d.ts

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -316,7 +316,16 @@ type Say = (text: string, options?: any) => Promise<string>
316316

317317
type Beep = () => Promise<void>
318318

319-
type SetSelectedText = (text: string, hide?: boolean) => Promise<void>
319+
type SetSelectedText = (
320+
text: string,
321+
hideOrOptions?: boolean | { hide?: boolean; method?: 'typing' | 'clipboard' | 'auto' }
322+
) => Promise<void>
323+
324+
type GetSelectedTextEx = (options?: {
325+
restoreClipboard?: boolean
326+
timeoutMs?: number
327+
pollMs?: number
328+
}) => Promise<{ ok: boolean; value: string; reason?: 'unchanged' | 'no-selection' }>
320329

321330
type KeyStroke = (keyString: string) => Promise<string>
322331

@@ -646,10 +655,15 @@ declare global {
646655
* ```ts
647656
* await setSelectedText("Hello from Script Kit!");
648657
* ```
649-
* Grab text from the focused app. Literally triggers a "cmd?ctrl+c", so expect a similar behavior.
650-
* [Examples](https://scriptkit.com?query=setSelectedText) | [Docs](https://johnlindquist.github.io/kit-docs/#setSelectedText) | [Discussions](https://github.com/johnlindquist/kit/discussions?discussions_q=setSelectedText)
651-
*/
658+
* Grab text from the focused app. Literally triggers a "cmd?ctrl+c", so expect a similar behavior.
659+
* [Examples](https://scriptkit.com?query=setSelectedText) | [Docs](https://johnlindquist.github.io/kit-docs/#setSelectedText) | [Discussions](https://github.com/johnlindquist/kit/discussions?discussions_q=setSelectedText)
660+
*/
652661
var setSelectedText: SetSelectedText
662+
/**
663+
* Robust selected text retrieval that optionally restores the previous clipboard
664+
* and provides structured results for downstream logic.
665+
*/
666+
var getSelectedTextEx: GetSelectedTextEx
653667
var setSelectedFile: SetSelectedFile
654668
var setWindowBoundsByIndex: SetWindowBoundsByIndex
655669
/**

0 commit comments

Comments
 (0)