動作
こんな感じ。
tidy_source(text = "x") #> x tidy_source(text = "function(x){x+y}") #> function(x) { #> x + y #> }
途中にコメントが挟まるとエラーになる。
# これはOK tidy_source(text = c("iris %>%", " group_by(Species) # Comment Here")) #> iris %>% group_by(Species) # Comment Here # これはNG tidy_source(text = c("iris %>% # Comment Here", " group_by(Species)")) #> Error in base::parse(text = code, keep.source = FALSE) : #> <text>:1:10: unexpected SPECIAL #> 1: iris %>% %InLiNe_IdEnTiFiEr% #> ^
動作
仮にこういうやつを考える
txt <- "function(x) { print(x) x+1 #comment here }"
mask_comment()
7. How does tidy_source()
actually work?に書かれているように、deparse
はコメントを消してしまうので、まずはコメントを保護する。
txt <- formatR:::mask_comments(txt, 40L, TRUE) txt #> [1] "function ( x ) {" "print ( x )" #> [3] "x + 1 %InLiNe_IdEnTiFiEr% \"#comment here\"" "}" cat(txt, sep = "\n") #> function ( x ) { #> print ( x ) #> x + 1 %InLiNe_IdEnTiFiEr% "#comment here" #> }
tidy_block()
インデントを付けてひとつの文字列に結合する。この中でdeparse()
が使われるが、%inLiNe_IdEnTiFiEr%
があるのでコメントは消えない。
txt <- formatR:::tidy_block(txt, 40L, FALSE) txt #> [1] "function(x) {\n print(x)\n x + 1 %InLiNe_IdEnTiFiEr% \"#comment here\"\n}" cat(txt, sep = "\n") #> function(x) { #> print(x) #> x + 1 %InLiNe_IdEnTiFiEr% "#comment here" #> }
unmask_source()
マスクしていたコメントを文字列に戻す。
txt <- formatR:::unmask_source(txt) txt #> [1] "function(x) {\n print(x)\n x + 1 #comment here\n}" cat(txt, sep = "\n") #> function(x) { #> print(x) #> x + 1 #comment here #> }
reindent_lines()
デフォルトだとインデントは4つのスペースだが、違うインデントを用いる場合はgsub()
で置き換える。
感想
これが黒魔術か…という感じ。ASTで解釈しようとしてもコメントはそこに入ってこないので、まあこうするしかないといえばそうなような、別のやり方もあるような。ほかの言語だとどうやるんでしょう。