[CLI] Improve REPL experience - fix prompt editing and multi-line paste

Resolved 💬 3 comments Opened Oct 4, 2025 by JFK Closed Oct 7, 2025

問題

現在のkagura replには以下の問題があります:

1. プロンプト(>>>)が編集可能

>>> print("hello")  # ← ここでBackspaceを押すと
>> print("hello")   # プロンプトが消えてしまう

問題点:

  • プロンプトが消えると改行が崩れる
  • 誤操作でREPLが壊れやすい

2. 複数行コードのペーストが失敗

# 以下をコピペしようとすると失敗
@agent
async def test():
    """test"""
    pass

問題点:

  • 複数行のコード定義がペーストできない
  • インデントが崩れる
  • エージェント定義が面倒

3. 編集体験が悪い

問題点:

  • ヒストリー検索がない(上矢印で前のコマンド)
  • 補完がない
  • シンタックスハイライトがない

提案する解決策

prompt_toolkit を使用

IPython/ptpythonのような高機能REPLを実装:

from prompt_toolkit import PromptSession
from prompt_toolkit.lexers import PygmentsLexer
from prompt_toolkit.styles import style_from_pygments_cls
from pygments.lexers.python import PythonLexer
from pygments.styles import get_style_by_name

session = PromptSession(
    lexer=PygmentsLexer(PythonLexer),
    style=style_from_pygments_cls(get_style_by_name('monokai')),
)

while True:
    text = session.prompt('>>> ', multiline=False)

機能

  1. プロンプト保護
  • >>> は編集不可
  • Backspaceで削除されない
  1. 複数行サポート
  • Meta+Enter(Alt+Enter)で複数行モード
  • 自動インデント検出
  • ペースト時の自動処理
  1. 編集機能
  • Ctrl+R でヒストリー検索
  • 上下矢印でヒストリー移動
  • Tab補完(将来的に)
  • シンタックスハイライト
  1. Vi/Emacsキーバインディング

実装例

# src/kagura/cli/repl.py
from prompt_toolkit import PromptSession
from prompt_toolkit.history import FileHistory
from prompt_toolkit.auto_suggest import AutoSuggestFromHistory
from prompt_toolkit.lexers import PygmentsLexer
from pygments.lexers.python import PythonLexer
import asyncio

class KaguraREPL:
    """Improved REPL with prompt_toolkit"""

    def __init__(self):
        self.session = PromptSession(
            history=FileHistory('~/.kagura/repl_history'),
            auto_suggest=AutoSuggestFromHistory(),
            lexer=PygmentsLexer(PythonLexer),
            multiline=False,
            prompt_continuation='... ',
        )

    async def run(self):
        """Run REPL loop"""
        print("Kagura REPL - Type /help for commands")

        while True:
            try:
                text = await self.session.prompt_async('>>> ')

                # 複数行チェック
                if self.needs_more_lines(text):
                    lines = [text]
                    while True:
                        continuation = await self.session.prompt_async('... ')
                        if not continuation.strip():
                            break
                        lines.append(continuation)
                    text = '\n'.join(lines)

                # 実行
                if text.startswith('/'):
                    await self.handle_command(text)
                else:
                    await self.execute_code(text)

            except KeyboardInterrupt:
                continue
            except EOFError:
                break

期待される改善

Before (現在)

>>> @agent  ← Backspaceで削除可能
>> async def test():  ← インデント崩れる
SyntaxError  ← ペースト失敗

After (改善後)

>>> @agent  ← Backspaceで削除不可
... async def test():  ← 自動継続
...     """test"""  ← インデント保持
...     pass
... 
<Agent 'test'>  ← 正常動作

タスク

  • [ ] prompt_toolkit を依存関係に追加
  • [ ] KaguraREPLクラスを実装
  • [ ] プロンプト保護機能
  • [ ] 複数行入力サポート
  • [ ] ヒストリー機能(~/.kagura/repl_history)
  • [ ] シンタックスハイライト
  • [ ] キーバインディング
  • [ ] テスト追加

優先度

High - REPLは開発体験の中核機能

関連

  • RFC-006: Live Coding (Chat Modeでも同じ問題)

参考

View original on GitHub ↗

This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗