-
Notifications
You must be signed in to change notification settings - Fork 1.5k
fix(windows): address clipboard copy failure in TUI #8997
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: main
Are you sure you want to change the base?
Changes from all commits
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 |
|---|---|---|
|
|
@@ -1130,9 +1130,14 @@ export function useTerminalPaneLifecycle({ | |
| if (!selection) { | ||
| return | ||
| } | ||
| void window.api.ui.writeClipboardText(selection).catch(() => { | ||
| /* ignore clipboard write failures */ | ||
| }) | ||
| void window.api.ui | ||
| .writeClipboardText(selection) | ||
| .then(() => { | ||
| // TODO(orca): Show a "Copied" toast notification | ||
| }) | ||
| .catch(() => { | ||
| // TODO(orca): Show a "Copy failed" toast notification | ||
| }) | ||
|
Comment on lines
+1133
to
+1140
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. 🩺 Stability & Availability | 🔴 Critical | 🏗️ Heavy lift Debounce the clipboard write to prevent a Because This will cause severe CPU spikes, UI freezing, and clipboard write failures on Windows when "copy on select" ( Move this call inside the existing |
||
| }) | ||
| selectionDisposablesRef.current.set(pane.id, selectionDisposable) | ||
| // Hide mouse cursor while typing — classic terminal UX, scoped to the | ||
|
|
||
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.
🔒 Security & Privacy | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
Repository: stablyai/orca
Length of output: 151
🏁 Script executed:
Repository: stablyai/orca
Length of output: 50369
🏁 Script executed:
Repository: stablyai/orca
Length of output: 7438
🌐 Web query:
PowerShell $input stdin Set-Clipboard -Value $input encoding newline handling powershell.exe documentation💡 Result:
In PowerShell, the $input variable is an automatic, enumerator-based variable that captures all data passed to a script, function, or script block via the pipeline [1][2]. When you pipe data to Set-Clipboard, the cmdlet does not directly read from a standard input stream (stdin) in the traditional shell sense; rather, it receives objects directly from the PowerShell pipeline [3]. Regarding the behavior of Set-Clipboard: 1. Newline Handling: By design, Set-Clipboard, when receiving multiple objects or string input through the pipeline, may append newlines between items depending on how the input is passed and formatted [4][5]. It is known to perform a ToString conversion on objects by default, which can lead to unexpected formatting if not explicitly controlled (e.g., using Out-String -Stream before piping to Set-Clipboard) [6]. 2. Encoding: Set-Clipboard is a high-level PowerShell cmdlet designed to abstract clipboard access across platforms (PowerShell 7.x+) or leverage Windows APIs [3][7]. It generally manages text encoding automatically to ensure compatibility with the clipboard's requirements, avoiding the manual character encoding complexities associated with legacy external utilities like clip.exe [8][9]. 3. Stdin vs. Pipeline: It is important to distinguish that $input is for handling pipeline-bound data within PowerShell code, not for reading stdin from external processes or redirection in the way that native Linux or Windows CMD shells operate [10]. If you need to relay pipeline data to an external application that expects actual stdin, you must explicitly pipe $input to that application [10][11]. 4. Documentation: Official documentation for Set-Clipboard is available via the Microsoft Learn platform [4]. For specific nuances regarding $input, refer to the about_Automatic_Variables help topic in PowerShell [1]. Because Set-Clipboard is an internal cmdlet, it does not share the same stdin encoding limitations that external binaries (like clip.exe) often encounter when they interpret input based on the active console's code page [12][9].
Citations:
🏁 Script executed:
Repository: stablyai/orca
Length of output: 6363
🌐 Web query:
PowerShell $input Set-Clipboard stdin UTF-8 InputEncoding multiline string behavior official documentation💡 Result:
When piping multiline string input to the Set-Clipboard cmdlet in PowerShell, the encoding and handling of that input depend on how it is read into the system. Official documentation states that Set-Clipboard accepts string values [1][2], and when you pipe data to it, PowerShell processes that input as strings [2]. However, direct piping (e.g., echo "multiline" | Set-Clipboard) does not always implicitly read the entire stdin buffer using UTF-8; instead, it relies on the host's current input encoding settings [3][4]. On Windows, the primary issue is that [Console]::InputEncoding frequently defaults to the system's legacy OEM/ANSI code page (e.g., CP1252) rather than UTF-8 [5]. Consequently, if your input contains non-ASCII characters, reading that input via [Console]::In.ReadToEnd or similar methods may result in character corruption (mojibake) because the bytes are decoded using the legacy code page [5]. To ensure correct UTF-8 handling for multiline input when using Set-Clipboard, you must explicitly set the input encoding before reading the stream [5]. The recommended approach is to include the following configuration in your script [5]: [Console]::InputEncoding = [System.Text.Encoding]::UTF8 $input | Set-Clipboard Alternatively, to avoid encoding issues entirely, you can encode your input as Base64 before passing it to PowerShell, then decode it within the session [5]: $bytes = [Convert]::FromBase64String([Console]::In.ReadToEnd) [System.Text.Encoding]::UTF8.GetString($bytes) | Set-Clipboard Regarding multiline string behavior, Set-Clipboard preserves line breaks correctly as part of the string object [1][2]. Unlike the legacy clip.exe utility, which often appends a trailing newline to the clipboard contents [6][7], Set-Clipboard handles the piped string content as provided [7]. If you encounter unexpected trailing newlines or empty lines, ensure your input generation command does not add them (e.g., use Out-String -NoNewLine) [7].
Citations:
🏁 Script executed:
Repository: stablyai/orca
Length of output: 3856
🌐 Web query:
site:learn.microsoft.com PowerShell about_Automatic_Variables input stdin pipeline $input💡 Result:
The $input automatic variable in PowerShell is an enumerator that provides access to input objects passed to a function, scriptblock, or script file via the pipeline [1][2][3]. It is only available within these specific contexts [1][2]. Key characteristics and behaviors of $input include: Availability and Scope: $input is available in functions, scriptblocks (including unnamed ones), and script files [1][2]. It is also available to commands executed via the -Command parameter of the pwsh executable [1][2]. Enumeration: Because $input is an enumerator, it can be used to iterate over the collection of all input objects [1][2]. Once you access its properties, the enumerator may be consumed; to reuse the data, you should store the contents of $input in another variable [1][2]. Behavior in Function Blocks: - Without begin, process, or end blocks: $input enumerates all input passed to the function [1][2]. - In a process block: $input contains the current object in the pipeline [1][2]. Note that the process block automatically advances the enumerator [1][2]. - In an end block: $input enumerates all input passed to the function [1][2]. - You cannot use $input in both the process block and the end block within the same function or scriptblock [1][2]. Important Note on Pipelines: While $input relates to PowerShell pipeline objects, it is distinct from the stdin stream used in other shells [4]. PowerShell does not connect native stdin directly to the PowerShell pipeline [4]. For standard advanced functions, it is generally recommended to use defined parameters with ValueFromPipeline support instead of relying on $input [5]. The automatic variables $_ or $PSItem are typically used to access the current pipeline object within a process block, rather than $input [5].
Citations:
🌐 Web query:
Microsoft Learn PowerShell Console InputEncoding native stdin about_Character_Encoding $input automatic variable💡 Result:
In PowerShell, character encoding for stdin and interaction with native programs is managed through specific configuration variables and.NET properties. Character Encoding and Stdin PowerShell handles character encoding for stdin and native program communication via the automatic variable $OutputEncoding and the.NET property [Console]::InputEncoding [1][2]. 1. $OutputEncoding: This automatic variable determines the encoding PowerShell uses when piping data to external (native) programs via stdin [1][3]. It does not affect redirection operators (>, >>) or cmdlet file output, which are controlled by other mechanisms like $PSDefaultParameterValues [1]. 2. [Console]::InputEncoding: This.NET property controls the encoding the console uses to read input [4][5]. It maps to the Windows SetConsoleCP function [2]. For consistent behavior with native applications, it is widely recommended to keep $OutputEncoding and [Console]::InputEncoding synchronized [2]. Mismatches between these settings often lead to character corruption when passing non-ASCII data to native commands [2][6]. The common practice to ensure alignment is: [Console]::InputEncoding = [Console]::OutputEncoding = [System.Text.Encoding]::UTF8 $input Automatic Variable The $input automatic variable is used to access input passed to a function, scriptblock, or script file [7][8]. - Nature of $input: It is an enumerator, not a standard collection [8][9]. Because it is an enumerator, it can only be consumed once [9]. Accessing it—or using methods like MoveNext—advances the enumerator, and once the data has been read or the enumerator is fully consumed, it will appear empty [8][9]. - Scope and Behavior: - In a function without a process block, $input enumerates all pipeline input provided to that function [8]. - In a process block, $input typically enumerates the single object currently in the pipeline (though developers generally prefer using $_ or $PSItem in this context to avoid consuming the enumerator) [8][10]. - Once accessed, the data is removed from the enumerator [8][9]. If you need to reuse the input, you should store the contents of $input in another variable (e.g., $data = $input) before accessing it [8]. References: [11] about_Character_Encoding - PowerShell | Microsoft Learn [1] about_Automatic_Variables - PowerShell | Microsoft Learn [4] Console.InputEncoding Property (System) - Microsoft Learn [5] Details about console encoding in PowerShell (GitHub Gist) [2] PowerShell/PowerShell Issue
#8584(GitHub)Citations:
morePowerShell/PowerShell#25698Set the Windows PowerShell fallback to UTF-8
powershell.execan decode stdin with the legacy console code page here, so non-ASCII or multiline clipboard text can be mangled, and$inputis an enumerator rather than a raw stdin string. Set[Console]::InputEncodingto UTF-8 and pipe the text intoSet-Clipboardexplicitly.