ラクにしたいでR:【RStudio】R Markdownで前のチャンクをコピーする
R Markdownで前のチャンクをコピーする (12/29更新:バックスラッシュを含むチャンクだとうまくコピーできないことがわかり修正) RStudioでR Markdown編集時に直前のチャンクをコピーして楽したい話。 (Quartoドキュメントでも使えた) tidyverseに出会ってRにはまっている。 Rでコードを書いて実行し、結果を残すのにR Markdownはとても便利だ。 試行錯誤しつつ進める際、実行したあとにコードを編集して再度実行することもできるが、 その場合は途中経過の出力が消えてしまう。 そこで前のチャンク内容をコピーして、新たなチャンクとして編集、実行することが非常に多い。 範囲選択してコピーペーストを繰り返していたが、きっとラクな機能が準備されているに違いない。 RStudioでは多くのショートカットキーが用意されている。 メニューの[Tools]-[Keyboard Shortcuts Help] (Alt+Shift+K)で主要なキーショートカットが確認できる。 また、メニューの[Tools]-[Modify Keyboard Shortcuts…]を見ると色々なショートカットが用意されていることがわかる。 しかしチャンクに関するものはほとんどなく、お目当てのものは無かった。 主要なエディタならマクロ機能があるのではと考えたが、それも見つからなかった。 そこで目をつけたのがコードスニペット機能だ。 特定の文字列をタイプするとあらかじめ登録しておいたものに置換してくれる。 調べるとRのコードを埋め込んで実行結果を使えるようだ。 試行錯誤の上、カーソル位置の直前のチャンク内容を出力するコードスニペットを作成することができた。 スニペット <p> カーソル位置の直前のチャンク内容を出力するコードスニペットは以下の通り。 </p> <pre><code>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) cc_txt <- gsub('\\\\' , '\\\\\\\\', cc_srcs[cc_spos:cc_epos]) paste(cc_txt , collapse = "\n") ` 使い方 コードスニペットをRStudioに登録する メニューの[Tools]-[Edit Code Snippets…]から左のペインでMarkdownを選択し、 右のペインで上のコードをコピペする。 最後の一行 ` までが必要なので忘れないように。 ちなみにこの記号`はback quoteとかbacktickと呼ぶらしい。 シングルクォーテーションと違うので注意。 スニペットを使う R Markdownファイルの編集画面でccとタイプした後、 Shiftを押しながらTABキーでスニペットが展開される。 前にチャンクがなければ何も入力されない(ccが消える) <p id="caption-attachment-3261" class="wp-caption-text"> スニペット編集画面 </p> コードの説明 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 ...