diff --git a/ui-tui/src/app.tsx b/ui-tui/src/app.tsx index b6ecf42e71..6cd3775d39 100644 --- a/ui-tui/src/app.tsx +++ b/ui-tui/src/app.tsx @@ -14,6 +14,7 @@ import { Thinking } from './components/thinking.js' import { COMMANDS, HOTKEYS, INTERPOLATION_RE, MAX_CTX, PLACEHOLDERS, TOOL_VERBS, ZERO } from './constants.js' import { type GatewayClient, type GatewayEvent } from './gatewayClient.js' import * as inputHistory from './lib/history.js' +import { writeOsc52Clipboard } from './lib/osc52.js' import { upsert } from './lib/messages.js' import { estimateRows, flat, fmtK, hasInterpolation, pick, userDisplay } from './lib/text.js' import { DEFAULT_THEME, fromSkin, type Theme } from './theme.js' @@ -661,7 +662,7 @@ export function App({ gw }: { gw: GatewayClient }) { return true } - process.stdout.write(`\x1b]52;c;${Buffer.from(target.text).toString('base64')}\x07`) + writeOsc52Clipboard(target.text) sys('copied to clipboard') return true diff --git a/ui-tui/src/components/markdown.tsx b/ui-tui/src/components/markdown.tsx index 99f24a59b1..adee83ad28 100644 --- a/ui-tui/src/components/markdown.tsx +++ b/ui-tui/src/components/markdown.tsx @@ -8,50 +8,51 @@ function MdInline({ t, text }: { t: Theme; text: string }) { const re = /(\[(.+?)\]\((https?:\/\/[^\s)]+)\)|\*\*(.+?)\*\*|`([^`]+)`|\*(.+?)\*|(https?:\/\/[^\s]+))/g let last = 0 - let match: RegExpExecArray | null - while ((match = re.exec(text)) !== null) { - if (match.index > last) { + for (const m of text.matchAll(re)) { + const i = m.index ?? 0 + + if (i > last) { parts.push( - {text.slice(last, match.index)} + {text.slice(last, i)} ) } - if (match[2] && match[3]) { + if (m[2] && m[3]) { parts.push( - {match[2]} + {m[2]} ) - } else if (match[4]) { + } else if (m[4]) { parts.push( - {match[4]} + {m[4]} ) - } else if (match[5]) { + } else if (m[5]) { parts.push( - {match[5]} + {m[5]} ) - } else if (match[6]) { + } else if (m[6]) { parts.push( - {match[6]} + {m[6]} ) - } else if (match[7]) { + } else if (m[7]) { parts.push( - {match[7]} + {m[7]} ) } - last = match.index + match[0].length + last = i + m[0].length } if (last < text.length) { diff --git a/ui-tui/src/lib/osc52.ts b/ui-tui/src/lib/osc52.ts new file mode 100644 index 0000000000..01688aca6a --- /dev/null +++ b/ui-tui/src/lib/osc52.ts @@ -0,0 +1,3 @@ +export function writeOsc52Clipboard(s: string): void { + process.stdout.write('\x1b]52;c;' + Buffer.from(s, 'utf8').toString('base64') + '\x07') +}