• 作成:

Surfingkeysを用いて、ChatGPTのWebプロンプトでEnterを押した時に改行する設定を行いました

ChatGPT Plus契約しました

QoL上げるのも大事かなと思ってChatGPT Plusを契約しました。

DeepLの変わりに出来る拡張機能はまだ開発できてませんし、 ChatGPT APIと別枠だからAPIを利用するならPlus料金は無駄になるのではとか、 Copilot XとEmacs連携させて使うならChatGPT Plusは余分じゃないかとか、色々懸念点はありますが。

しかし一ヶ月間の契約期間を通じて、GPT-4のパフォーマンスを確認する価値はあると考えています。

改行設定が難しい

ChatGPTのプロンプトではShift+Enterで改行をするのですが、私は他のチャットアプリ(Slack, Discordなど)と統一してC-mで改行してEnterで投稿するようにしたいです。切り分けは難しい…

しかしそれはどうも難しいことがChatGPTと壁打ちすると分かってきました。

私の環境ではxkeysnailKeyhacと言ったOSレベルのアプリケーションで、 C-mEnterを同一にするように設定していて、その設定を変えるのは他の操作への影響を考えると難しいです。

仕方がないので妥協して、 C-mでもEnterでも改行するようにして、 C-Enterで投稿するようにします。

Surfingkeysの設定でどうにかなるはず

多分それはSurfingkeysimapの設定でどうにかなると思ったのですが、 ChatGPTの画面でだけ行う方法がよく分かりませんでした。

最悪ページのURLを生で取れるからそれで分岐できるとは思うのですが、あんまり行儀の良い方法だとは思えないのですよね。

README.mdを全部読んだけど無いか仕方ないと思って分岐しようと思ったのですが、念の為ソースコード検索したら普通にドメイン指定できることが分かりました。

function imap(new_keystroke, old_keystroke, domain, new_annotation)

https://github.com/brookhong/Surfingkeys/blob/08369cdfa082cd3a07553049d96d0bad621563b6/src/content_scripts/common/api.js#L221

ではとりあえずこの設定で良いのではないでしょうか。

imap("<Enter>", "<Shift+Enter>", /chat\.openai\.com/);
imap("<Ctrl+Enter>", "<Enter>", /chat\.openai\.com/);

これで一回改行に成功してOKだと思ったのですが、 2回Enterを押すと送信に変わってしまいますね… 順序の違いで上書きが起きている?

imap("<Ctrl+Enter>", "<Enter>", /chat\.openai\.com/);
imap("<Enter>", "<Shift+Enter>", /chat\.openai\.com/);

に順番を変えてみましたが変化なし。どうやら順番は関係ないようです。

元々空行2回は許可しないのかなあと思ったのですが、 Shift+Enterを直接何度も打ってもちゃんと改行されるんですよね。

インジェクションでどうにかしました

なりふりかまっていられないので、コンテンツスクリプトを直接実行することにしました。

// 特定のアプリケーションで、Enterを改行に留めます。
// 本当はC-mで改行でEnterで送信したいのですが、
// OSレベルのアプリケーションでC-mとEnterを同一にしていると難しいです。
// かなり強引な方法をとっていることは分かっているので、
// 穏当な方法に修正したいです。

/**
 * Enterが押された場合のイベント実行を停止します。
 * Ctrl+Enterの場合は停止しません。
 * 単純にimapで移し替えを行うことは出来なかったので強引な手法を使っています。
 */
function disableSubmitWhereTextareaWhenEnter(event) {
  if (
    event instanceof KeyboardEvent &&
    event.target.tagName === "TEXTAREA" &&
    event.code === "Enter" &&
    !event.ctrlKey
  ) {
    event.stopPropagation();
  }
}

// コンテンツスクリプトを自由に実行する必要があるため、
// imapのドメイン指定などでは表現しきれません。
if (window.location.hostname === "chat.openai.com") {
  // textareaをquerySelectorAllする方法は読み込みタイミングの問題か使えませんでした。
  document.addEventListener("keydown", disableSubmitWhereTextareaWhenEnter, { capture: true });
}

これでとりあえず解決しました。というかログとかを読んだ感じだと、一回目空行を入力した時に空行になるのはChatGPTの元からの仕様みたいですね。

もしかしたらimapを使った普通の方法でもうまくいくのかもしれません。強引な手法で解決できてしまったのでデバッグしつつ頑張る気力はもうありませんが。