Skip to content

feat: チャットのどの部分でも空白なしでコピーできる #1875

Description

@chikara813

起きていること

ターミナルセルの Claude の返信をマウスで選択し、右クリック > コピーすると、返信の
テキストではなく「描画された画面」がクリップボードに入ります。貼り付けた結果には
描画に由来するノイズがそのまま残るので、手作業での修正が必要になります。

  • 継続行すべての先頭に付く 2 個の空白(Claude Code は返信本文をインデントして
    描画し、1 行目の 1 桁目に マーカーを置くため)
  • 文の切れ目ではなく セルの桁幅で入る強制改行
  • 各行をセル幅まで埋める 行末の空白

実際に貼り付けた例(原文ママ):

  The request: investigate why copying a chat result out of MulmoTerminal leaves a space
  at the start of each line.

  What I achieved: ruled out configuration and the app's copy path by reading the 4.10.1
  bundle and your config, confirmed no matching existing issue, verified                 
  /api/transcript/last-turn returns the reply with no leading spaces.

実害のあるケース: 2 行にまたがる URL

普通の文章であればインデントは見た目の問題ですが、長い URL では値そのものが壊れます。

Claude Code はターミナルのソフトラップに任せず、自分でハードラップして継続行を
インデントし直します。そのため後半は xterm が wrap と印を付けない、独立したバッファ行
になります。cols=100、156 文字の URL で実測した結果:

[19] isWrapped=false lead=0  "● https://dev.azure.com/…/_workitems/edit/27377/?viewSourceW"
[20] isWrapped=false lead=2  "  orkItemId=99999&tab=history&referrer=copy-paste-repro-case"

20 行目が isWrapped = false であるため、getSelection() は論理行として繋ぎ直さず、
改行で連結します。クリップボードに入るのは次のものです。

https://dev.azure.com/…/_workitems/edit/27377/?viewSourceW
  orkItemId=99999&tab=history&referrer=copy-paste-repro-case

URL がトークンの途中で分断され、その中に \n と空白 2 個が混入します。手で直さない限り
どこにも貼り付けられません。ソフトラップされていれば xterm が論理行として繋ぎ直すので、
URL はそのままコピーできたはずです。

コピーではなくクリックしても回避できません。WebLinksAddon 3.7.8 は読み込まれていますが、
繋ぎ直すのは xterm が wrap と印を付けた行だけで、この継続行には印が付いていません。
そのため検出されるリンクは折り返し位置で終わり、クリックすると本来の URL ではなく
切り詰められた前半が開きます。

期待する挙動

会話のどの部分でも、ターミナルのインデント・折り返し位置・パディングが付かない、
書かれたとおりのテキストが得られること。最新のターンに限らず、上にさかのぼった過去の
やり取りも同じであること。

コピー処理のバグではない理由

不具合報告ではなく機能要望として出すため、事前に次を確認しました。

  • copyOnSelect: false の場合、右クリックのコピーは xterm 自身の経路を通ります。
    contextmenu で xterm が selectionText を helper textarea に書き込んで選択状態に
    するため、クリップボードには terminal.getSelection() がそのまま入ります。
  • MulmoTerminal 側の選択フックは、空の選択と重複した選択を捨てるだけで、テキストには
    手を加えていません。クライアントにもサーバにも空白を前置する処理はありません。
  • MulmoTerminal を一切介さずに再現しました。node-pty 経由で claude を起動し、
    cols=100 のヘッドレス xterm バッファに流し込んで、トリムを無効にして行を読み戻し
    たものです。返信の行は の行がインデント 0、継続行はすべてインデント 2 でした。

つまり空白は描画された画面そのものに含まれています。選択によるコピーでは、本アプリに
限らずどのターミナルでもこれ以上のことはできません。

要望

エージェント自身の transcript から選択可能なテキストとして描画される、セッションの
会話ビューをデスクトップで使いたい。
そうすれば、どのターンのどの部分でも選択してきれいにコピー
でき、画面の選択が唯一の出口である状態も終わります。「最後の返信をコピー」ボタンでは
不十分です。1 ターンだけが直り、それより上のすべてには問題が残ります。

#1755 はこの種のビューを、ペインではなく claude 自身の transcript を読む形でスマホ向けに計画
したもので、#1822 ではその範囲をまだ検討中かと思います。
デスクトップには対応するものがありません。

再現手順

  1. Claude のセルを動かし、複数行の文章の返信を出させる。
  2. 返信本文をマウスでドラッグ選択する。
  3. 右クリック > コピー。
  4. 任意のプレーンテキストエディタに貼り付ける。
  5. 2 行目以降のすべての行に空白 2 個が付き、セル幅で改行され、行末が空白で埋められて
    いる。

実害のあるケースの手順

  1. セル幅より長い URL を Claude に出力させる。
  2. ドラッグ選択して右クリック > コピー。
  3. 貼り付ける。URL がトークンの途中で分断され、折り返し位置に改行と空白 2 個が入る。

環境

  • mulmoterminal 4.10.1(npm install)
  • Node v24.18.0
  • Windows 11 Pro, 10.0.26200.8973
  • Claude Code 2.1.231
  • gh 2.97.0
  • tmux: このホストには未インストール
  • codex: 未インストール
  • ブラウザ: Google Chrome 151.0.7922.174(64-bit, Windows)
  • 関係する設定: copyOnSelect: false, terminalSubmit: "cr"

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions