前置き
RStudioはキーボードショートカットのカスタマイズができる。
だが、好きなキーボードショートカットを追加しようとするとRStudioの設定だけでは完結しない。具体的にはアドインを作る必要がある。アドインにはショートカットが設定できるので、目的の動きをするアドインを作ってキーボードショートカットを割り当てれば良い。
しかしアドインを作るのはそこそこ面倒だ。そこで今回紹介するshrtcts
パッケージだ。このパッケージを使えばアドインを自作することなく*1、ショートカットを追加できる。
インストール
CRANにはないので、remotes
パッケージを使うなどしてgithubからインストールする。
# install.packages("remotes") remotes::install_github("gadenbuie/shrtcts")
初期設定
ショートカットの登録はshrtcts::add_rstudio_shortcuts()
関数により行う。この関数を後述する設定ファイルの記述後に実行するか、R起動時に自動的に実行されるように.Rprofile
に次の記述を追加しておく。
if (interactive() && requireNamespace("shrtcts", quietly = TRUE)) { shrtcts::add_rstudio_shortcuts() }
後述するが、ショートカットはまずアドインとして登録され、それに対するキーボードショートカットは設定から編集するという手順をとる。そうではなく、設定時にキーボードショートカットを記述しておき、それに基づいてキーボードショートカットの登録までやってしまうということもできる。その場合は次のようにset_keyboard_shortcuts = TRUE
を指定しておく。
if (interactive() && requireNamespace("shrtcts", quietly = TRUE)) { shrtcts::add_rstudio_shortcuts(set_keyboard_shortcuts = TRUE) }
ショートカットの設定
ショートカットの定義は設定ファイルに記述する。設定ファイルはホームディレクトリ~/
または~/.config/
以下に.shrcts.R
または.shrtcts.yaml
を作成し、そこに記述する。拡張子から分かるように前者はR、後者はYAMLで記述する。Rだと微妙にハマった*2ので、以下ではYAMLでの説明をする。
なお、設定ファイルはshrtcts::edit_shortcuts()
関数を実行することでも開ける*3。
設定ファイルには最低限Name
とBinding
の2つが必要となる。
- Name: test Binding: praise::praise
Name
にはショートカットの名前を記述する。アドインのリストや、キーボードショートカットの設定画面で使われるので分かりやすく書いておく。Binding
には実行するRの関数か、Rのコードを書いておく。- ちなみに
praise::praise()
は実行すると励ましの言葉が出力される便利な関数だ。 - アドインの設定ファイル(
addins.dcf
)だと関数名を書いておく必要がある箇所だが、.shrtcts.yaml
では任意のRコードを記述できる。shrtcts
が記述に基づいて関数を定義してくれるためだ。 - 複数行に渡るような複雑な例は後ほど示す。
- ちなみに
設定を記述して保存したら、ショートカットをアドインとして登録するためにRStudioを再起動する(もし.Rprofile
を編集していないのであればshrtcts::add_rstudio_shortcuts()
を実行してから再起動する)。
これにより、アドインとしてショートカットが実行可能になる。あとはTools > Modify Keyboard Shortcuts...
から作成したショートカットにキーを割り当てれば良い。
なお、前述のようにキーボードショートカットの割当てまでやってしまいたかったら、次のようにShortcut
へショートカットの内容を記述しておく。
- Name: test Binding: praise::praise Shortcut: Ctrl+Alt+P
あとはshrtcts::add_rstudio_shortcuts(set_keyboard_shortcuts = TRUE)
を実行して再起動すれば良い(または.Rprofile
に記述しておく)。ただこれはキーボードショートカットの設定のJSONが標準的ではない方法で編集されるということなので、その点は留意しておく。
なお、ショートカットは最大100件まで登録できるらしい。
オプション
上述のName
, Binding
, Shortcut
以外にも指定できるものがあり、ドキュメントに解説がある(ドキュメントにあるように、R形式の設定ファイルの場合はroxygen2
のタグとして記述する)。
これらのうち、Interactive
は挙動に影響するので理解しておく必要がある。
true
(既定値)の場合、関数がインタラクティブに実行される。つまりコンソールで実行され、コンソールに結果が返る。false
の場合、関数はバックグラウンドで実行され、コンソールには出力されない。次に例を示すが、この指定はエディタ中で文字列を編集するような場合に役立つ。
ショートカットの例
単にインタラクティブに関数を実行するだけならあまり迷うことはないが、編集中のファイルに文字列を挿入したり削除したりしようとすると少々複雑になる。
具体的にはrstudioapi
パッケージの力を借りる必要がある。
例を2つあげる。
1. Pythonのコードチャンクを挿入する
RStudioには、R Markdown編集中にCtrl+Alt+IでRのコードチャンクを挿入するという便利なショートカットがある。R MarkdownはPythonを書くのにも便利なので、Pythonのコードチャンクが欲しいという場合があるだろう。次のようなショートカットを書けばPythonのコードチャンクを挿入できる。
- Name: Insert Python code chunk Binding: | context <- rstudioapi::getActiveDocumentContext() id <- context$id location <- c(context$selection[[1]]$range$start) text <- "```{python}\n\n```" rstudioapi::insertText(location, text, id) rstudioapi::setCursorPosition(location + c(1, 0)) Interactive: false
rstudioapi::getActiveDocumentContext()
は編集中のドキュメントや、カーソル位置に関する情報を取得する。rstudioapi::insertText(location, text, id)
はid
で指定したドキュメントのlocation
の位置にtext
を挿入する。rstudioapi::setCursorPosition(location)
はlocation
の位置にカーソルを移動する。上記コード中で+ c(1, 0)
としているのは、コードチャンクの中にカーソルを移動させるため。
ちなみに実際のCtrl+Alt+I
は割と高機能で、コードチャンク中で実行するとチャンクオプションを引き継いだままコードチャンクの分割ができたりする。したがって上記は簡易版である。
2. バックスペース
私はCtrl+H
にバックスペースが割り当てられていないと辛いタイプの人間なのだが、標準ではバックスペースにキーボードショートカットが割り当てられていないので、特にWindows上のRStudioでこれを実現しようとすると結構面倒くさい。多分(アドインを使わない限りは)RStudioだけだと完結しない。ではrstudioapi
を使えば簡単にできるかというと、キー入力を送信するような関数はなさそうで、これも難しそうだった。
rstudioapi
のドキュメントを見ると、文字を消す例ではmodifyRange()
が使用されていた。
最終的に次のようにした。バックスペースの挙動は意外と複雑という気付きがあった。
- Name: Backspace Binding: | context <- rstudioapi::getActiveDocumentContext() id <- context$id location_start <- c(context$selection[[1]]$range$start) location_end <- c(context$selection[[1]]$range$end) ## スタート位置の調整 if (!all(location_start == location_end)) { # pass (選択が範囲の場合、範囲内のみを消す) } else if (location_start[2] == 1) { # 行頭である if (location_start[1] > 1) { # 先頭行ではない # 前の行の末尾が開始点(前の行末の改行を消す) location_start = c(location_start[1] - 1, Inf) } } else { # 行の途中であり、範囲選択でなければカーソルの前の1文字を消す location_start = location_start - c(0, 1) } rstudioapi::modifyRange(rstudioapi::document_range(location_start, location_end), "", id) Interactive: false
shrtcts
パッケージを使ったショートカットの登録は多少は準備は要るものの、アドインを自作して登録するよりずっと簡単で、設定の共有もしやすい。上記例はgistに公開しておいた。
*1:中身を軽く見てみたところ、設定ファイルに基づいて関数を定義し、その関数をshrtctsパッケージのアドインとして登録することで目的を達成しているようだ。賢い。
*2:(私が書き方を間違えているだけかもしれないが)Rで記述する場合はfunction() {}で囲って関数にしておかないとrstudioapiを利用した関数を記述した場合にRStudio not runningの注意が表示されるようだった。
*3:このときファイルが無ければ.shrtcts.Rを作成できるが、手元(macOS)で試したところロケーションは/Library/Application Support/shrtcts/.shrtcts.Rだった。ドキュメントの記載と場所が違うが、一応これでも動くらしい。