ラクにしたいでR:【RStudio】R Markdownで前のチャンクをコピーする

R Markdownで前のチャンクをコピーする

RStudioでR Markdown編集時に直前のチャンクをコピーして楽したい話。

tidyverseに出会ってRにはまっている。
Rでコードを書いて実行し、結果を残すのにR Markdownはとても便利だ。
試行錯誤しつつ進める際、実行したあとにコードを編集して再度実行することもできるが、
その場合は途中経過の出力が消えてしまう。

そこで前のチャンク内容をコピーして、新たなチャンクとして編集、実行することが非常に多い。
範囲選択してコピーペーストを繰り返していたが、きっとラクな機能が準備されているに違いない。
RStudioでは多くのショートカットキーが用意されている。
メニューの[Tools]-[Keyboard Shortcuts Help]
(Alt+Shift+K)で主要なキーショートカットが確認できる。
また、メニューの[Tools]-[Modify Keyboard
Shortcuts…]を見ると色々なショートカットが用意されていることがわかる。
しかしチャンクに関するものはほとんどなく、お目当てのものは無かった。

主要なエディタならマクロ機能があるのではと考えたが、それも見つからなかった。

そこで目をつけたのがコードスニペット機能だ。
特定の文字列をタイプするとあらかじめ登録しておいたものに置換してくれる。
調べるとRのコードを埋め込んで実行結果を使えるようだ。

試行錯誤の上、カーソル位置の直前のチャンク内容を出力するコードスニペットを作成することができた。

スニペット

カーソル位置の直前のチャンク内容を出力するコードスニペットは以下の通り。

snippet cc
  `r
  cc_bq3 <- paste(rep(intToUtf8(96), 3), collapse = "")
  cc_all <- rstudioapi::getSourceEditorContext()
  cc_src <- cc_all$contents
  cc_cpos <- cc_all$selection
  cc_pos <- cc_cpos[[1]]$range$start
  cc_srcs <- cc_src[1:cc_pos[["row"]]]
  cc_exp1 <- paste(c("^", cc_bq3, "\\{.*\\}$"), collapse = "")
  cc_spos <- tail(grep(cc_exp1, cc_srcs), n = 1)
  cc_exp2 <- paste(c("^", cc_bq3, "$"), collapse = "")
  cc_epos <- tail(grep(cc_exp2 , cc_srcs), n = 1) 
  paste(cc_srcs[cc_spos:cc_epos], collapse = "\n")  
  `

使い方

  1. コードスニペットをRStudioに登録する
    メニューの[Tools]-[Edit Code Snippets…]から左のペインでMarkdownを選択し、
    右のペインで上のコードをコピペする。
    最後の一行 ` までが必要なので忘れないように。
    ちなみにこの記号`はback quoteとかbacktickと呼ぶらしい。
    シングルクォーテーションと違うので注意。
  2. スニペットを使う
    R Markdownファイルの編集画面でccとタイプした後、
    Shiftを押しながらTABキーでスニペットが展開される。
    前にチャンクがなければ何も入力されない(ccが消える)

コードの説明

back quote(`)を直接使わず、intToUtf8(96)を使って”`“を使っている。
スニペットで実行するRのコード内で`を見つけるとそこで実行が止まってしまうため。
バックスラッシュなどでエスケープできないか試したが解決できなかった。
intToUtf8(96)を使うことで回避ができたので、これでヨシとする。

cc_all <- rstudioapi::getSourceEditorContext()

現在のソースエディタの内容を取得する。

cc_src <- cc_all$contents

ソースエディタのソース全体を取得する。

cc_cpos <- cc_all$selection
cc_pos <- cc_cpos[[1]]$range$start

選択範囲が取得できるらしいが、現在のカーソル位置が返ってくるのでそれを使っている。

cc_srcs <- cc_src[1:cc_pos[["row"]]]

現在のカーソルの行数までのソースを別変数cc_srcsに格納。

cc_exp1 <- paste(c("^", cc_bq3, "\\{.*\\}$"), collapse = "") 
cc_spos <- tail(grep(cc_exp1, cc_srcs), n = 1)

““`{” ではじまり、“}”で終わる行数を探し、一番最後のものだけ取り出す。(直前のチャンクの開始行数)

cc_exp2 <- paste(c("^", cc_bq3, "$"), collapse = "") cc_epos <- tail(grep(cc_exp2 , cc_srcs), n = 1) 

““`”である行数を探し、一番最後のものだけ取り出す。(直前のチャンクの終了行数)

paste(cc_srcs[cc_spos:cc_epos], collapse = "\n")

直前のチャンクの内容を出力

動作確認環境

  • OS: Ubuntu 22.04.5 LTS
  • RStudio: RStudio 2024.04.2+764

コメント

タイトルとURLをコピーしました