-
Notifications
You must be signed in to change notification settings - Fork 2.1k
Add copyToClipboard to bitcore-cli #4196
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
e7b8ccf
a612e6a
433e5db
61dfe7b
b00bed7
211ec9b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,3 +1,4 @@ | ||
| import { type StdioOptions, spawnSync } from 'child_process'; | ||
| import os from 'os'; | ||
| import path from 'path'; | ||
| import * as prompt from '@clack/prompts'; | ||
|
|
@@ -66,8 +67,12 @@ export class Utils { | |
| return Constants.COLOR[color.toLowerCase()].replace('%s', text); | ||
| } | ||
|
|
||
| static boldText(text: string) { | ||
| return '\x1b[1m' + text + '\x1b[22m'; | ||
| static boldText(text: string, isDim?: boolean) { | ||
| return '\x1b[1m' + text + '\x1b[22m' + (isDim ? '\x1b[2m' : ''); // 22 is the ANSI code to turn off bold AND dim. So, need to re-apply dim if applicable | ||
| } | ||
|
|
||
| static dimText(text: string, isBold?: boolean) { | ||
| return '\x1b[2m' + text + '\x1b[22m' + (isBold ? '\x1b[1m' : ''); // 22 is the ANSI code to turn off bold AND dim. So, need to re-apply bold if applicable | ||
| } | ||
|
|
||
| static italicText(text: string) { | ||
|
|
@@ -436,4 +441,69 @@ export class Utils { | |
| static colorizeChain(chain: string) { | ||
| return Utils.colorTextByChain(chain, chain); | ||
| } | ||
|
|
||
| static copyToClipboard(text: string): void { | ||
| const platform = os.platform(); | ||
| let attempts: Array<{ cmd: string; args: string[] }>; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Declaring as constant and pushing would mitigate potential downstream reassigns that you don't want.
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm fine leaving it as is. Pushing implies it's additive. I don't want to be adding. I want it to be defining based on the platform which is more intuitive when you see an assignment than a push. This function is not particularly complicated. I don't think it's a big risk that someone would overwrite it. |
||
|
|
||
| if (platform === 'darwin') { | ||
| attempts = [{ cmd: 'pbcopy', args: [] }]; | ||
| } else if (platform === 'linux') { | ||
| // Prefer wl-copy first (Wayland), then fall back to X11 tools. | ||
| attempts = [ | ||
| { cmd: 'wl-copy', args: [] }, | ||
| { cmd: 'xclip', args: ['-selection', 'clipboard'] }, | ||
| { cmd: 'xsel', args: ['--clipboard', '--input'] } | ||
| ]; | ||
| } else if (platform === 'win32') { | ||
| attempts = [{ cmd: 'clip', args: [] }]; | ||
| } else { | ||
| throw new Error(`Unsupported platform: ${platform}`); | ||
| } | ||
|
|
||
| const missing: string[] = []; | ||
| const failures: string[] = []; | ||
|
|
||
| for (const attempt of attempts) { | ||
| // wl-copy can fork and keep inherited pipes open; piping stderr/stdout can | ||
| // cause spawnSync to block even after successful copy. | ||
| const stdio: StdioOptions = attempt.cmd === 'wl-copy' | ||
| ? ['pipe', 'ignore', 'ignore'] | ||
| : ['pipe', 'ignore', 'pipe']; | ||
|
|
||
| const result = spawnSync(attempt.cmd, attempt.args, { | ||
| input: text, | ||
| encoding: 'utf8', | ||
| stdio | ||
| }); | ||
|
|
||
| if (result.error) { | ||
| const err = result.error as NodeJS.ErrnoException; | ||
| if (err.code === 'ENOENT') { | ||
| missing.push(attempt.cmd); | ||
| continue; | ||
| } | ||
| failures.push(`${attempt.cmd}: ${err.message}`); | ||
| continue; | ||
| } | ||
|
|
||
| if (result.status === 0) { | ||
| return; | ||
| } | ||
|
|
||
| const stderr = (result.stderr ?? '').trim(); | ||
| failures.push(`${attempt.cmd}: ${stderr || `exited with code ${result.status}`}`); | ||
| } | ||
|
|
||
| if (missing.length === attempts.length) { | ||
| throw new Error(`No clipboard utility found. Tried: ${attempts.map(a => a.cmd).join(', ')}`); | ||
| } | ||
|
|
||
| const detailParts = [ | ||
| failures.length ? `Failures: ${failures.join(' | ')}` : '', | ||
| missing.length ? `Not installed: ${missing.join(', ')}` : '' | ||
| ].filter(Boolean); | ||
|
|
||
| throw new Error(`Failed to copy to clipboard. ${detailParts.join(' ; ')}`); | ||
| } | ||
| }; | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it's worth cleaning up the TS errors for using pubKeyAction before it's defined. Give it an initial value and add it to the type declaration?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not seeing any such typescript errors. Maybe your editor's TS version is 6.x instead of the workspace's 5.x?