Skip to content

Commit bfa250e

Browse files
committed
Merge branch 'r-0.0-1' into production
2 parents 6b7eed0 + a2677ca commit bfa250e

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

57 files changed

+3016
-0
lines changed

.Rbuildignore

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
^.*\.Rproj$
2+
^\.Rproj\.user$
3+
^API$
4+
^README\.Rmd$
5+
^README-.*\.png$
6+
^.travis.yml
7+
^appveyor\.yml$
8+
^tic\.R$

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
.Rproj.user
2+
.Rhistory
3+
.RData
4+
inst/doc

.travis.yml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
language: r
2+
cache: packages
3+
warnings_are_errors: false
4+
r_packages:
5+
- covr
6+
after_success:
7+
- Rscript -e 'library(covr); codecov()'

API

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# API for styler package
2+
3+
## Exported functions
4+
5+
get_transformers(strict = TRUE)
6+
style_pkg(pkg = ".", transformers = get_transformers())
7+
style_src(path = ".", transformers = get_transformers(), recursive = TRUE)
8+
style_text(text, transformers = get_transformers())

DESCRIPTION

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
Package: styler
2+
Title: Non-invasive Pretty Printing of R code
3+
Version: 0.0-1
4+
Authors@R: person("Kirill", "Müller", role = c("aut", "cre"), email = "[email protected]")
5+
Description:
6+
Pretty-prints R code without changing the user's formatting intent.
7+
Imports:
8+
rprojroot,
9+
utf8,
10+
withr,
11+
dplyr,
12+
tibble,
13+
tidyr,
14+
purrr,
15+
magrittr
16+
Suggests: testthat,
17+
knitr,
18+
rmarkdown,
19+
data.tree
20+
Remotes:
21+
krlmlr/utf8
22+
License: GPL-3
23+
Encoding: UTF-8
24+
LazyData: true
25+
Date: 2017-06-15
26+
BugReports: https://github.com/krlmlr/styler/issues
27+
URL: https://github.com/krlmlr/styler, http://krlmlr.github.io/styler
28+
Roxygen: list(markdown = TRUE, roclets = c("rd", "namespace", "pkgapi::api_roclet"))
29+
RoxygenNote: 6.0.1.9000
30+
VignetteBuilder: knitr

NAMESPACE

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# Generated by roxygen2: do not edit by hand
2+
3+
export(get_transformers)
4+
export(style_pkg)
5+
export(style_src)
6+
export(style_text)
7+
import(dplyr)
8+
import(tibble)
9+
import(tidyr)
10+
importFrom(purrr,map)
11+
importFrom(purrr,map2)
12+
importFrom(purrr,pmap)

NEWS.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
## styler 0.0-1 (2017-06-15)
2+
3+
Initial release, work in progress.
4+
5+
- Create and serialize nested parse data.
6+
- Internal support for indention of expressions with parentheses.
7+
- Adding and removing spaces around operators on flat parse data.

R/modify_pd.R

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
#' Update indention information of parse data
2+
#'
3+
#' @param pd A nested or flat parse table that is already enhanced with
4+
#' line break and space information via [create_filler()] or
5+
#' [create_filler_nested()].
6+
#' @param indent_by How many spaces should be added after the token of interest.
7+
#' @name update_indention
8+
NULL
9+
10+
#' @rdname update_indention
11+
indent_round <- function(pd, indent_by) {
12+
opening <- which(pd$token == "'('")
13+
if (length(opening) > 0) {
14+
start <- opening + 1
15+
stop <- nrow(pd) - 1
16+
} else {
17+
start <- stop <- 0
18+
}
19+
pd <- pd %>%
20+
mutate(indent = ifelse(seq_len(nrow(pd)) %in% start:stop, indent_by, 0)) %>%
21+
select_(~indent, ~newlines, ~everything())
22+
pd
23+
}
24+
25+
26+
27+
#' Update indention information of nested parse data
28+
#'
29+
#' These functions apply the update functions of the same name but without
30+
#' suffix nested to each level of nesting of the nested parse table.
31+
#' @param pd A nested parse table that is already enhanced with
32+
#' line break and space information via [create_filler_nested].
33+
#' @name update_indention_nested
34+
NULL
35+
36+
#' @rdname update_indention_nested
37+
indent_round_nested <- function(pd) {
38+
if (is.null(pd)) return(pd)
39+
pd <- pd %>%
40+
indent_round(indent_by = 2) %>%
41+
mutate(child = map(child, indent_round_nested))
42+
pd
43+
}
44+
45+
46+
#' Strip EOL spaces
47+
#'
48+
#' Remove end-of-line spaces.
49+
#' @param pd_nested A nested parse table.
50+
#' @return A nested parse table.
51+
strip_eol_spaces_nested <- function(pd_nested) {
52+
if (is.null(pd_nested)) return()
53+
pd_nested <- pd_nested %>%
54+
mutate(spaces = spaces * (newlines == 0),
55+
child = map(child, strip_eol_spaces_nested))
56+
pd_nested
57+
}

R/nested.R

Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
#' Obtain a nested parse table from a character vector
2+
#'
3+
#' [utils::getParseData()] is used to obtain a flat parse table from `text`.
4+
#' Subsequentially, it's representation is changed from a flat table into a
5+
#' nested parse table with [nest_parse_data()].
6+
#' @param text A character vector to parse.
7+
#' @return A nested parse table. Apart from the columns provided by
8+
#' `utils::getParseData()`, a column "short" with the first five characters of
9+
#' "text" is added, the nested subtibbles are in column "child".
10+
#' TODO:
11+
#' - Implement enhance_parse_data_nested()
12+
#' - Walk tree defined by `child`, compute whitespace information
13+
#' - Store indention depth in a separate column, unaffected by
14+
#' inter-token space
15+
#' - Implement compute_parse_data_nested_with_ws() as
16+
#' compute_parse_data_nested() + enhance_parse_data_nested()
17+
#' - Implement serialization of nested parse data
18+
#' - Use compute_parse_data_nested_with_ws() instead of
19+
#' compute_parse_data_flat_enhanced()
20+
#' - Perform all transformations on hierarchical structure
21+
#' - Compute text for a sub-element
22+
#' - Compute indentation
23+
#' - Braces
24+
#' - Function calls
25+
#' - Function definitions
26+
#' - Remove `includeText = TRUE`
27+
compute_parse_data_nested <- function(text) {
28+
parsed <- parse(text = text, keep.source = TRUE)
29+
parse_data <- tbl_df(utils::getParseData(parsed, includeText = TRUE))
30+
pd_nested <-
31+
parse_data %>%
32+
mutate_(child = ~rep(list(NULL), length(text))) %>%
33+
mutate_(short = ~substr(text, 1, 5)) %>%
34+
select_(~short, ~everything()) %>%
35+
nest_parse_data()
36+
37+
pd_nested
38+
}
39+
40+
#' Nest a flat parse table
41+
#'
42+
#' `nest_parse_data` groups `pd_flat` into a parse table with tokens that are
43+
#' a parent to other tokens (called internal) and such that are not (called
44+
#' child). Then, the token in child are joined to their parents in internal
45+
#' and all token information of the children is nested into a column "child".
46+
#' This is done recursively until we are only left with a nested tibble that
47+
#' contains one row: The nested parse table.
48+
#' @param pd_flat A flat parse table including both terminals and non-terminals.
49+
#' @seealso [compute_parse_data_nested()]
50+
#' @return A nested parse table.
51+
nest_parse_data <- function(pd_flat) {
52+
if (nrow(pd_flat) <= 1) return(pd_flat)
53+
split <-
54+
pd_flat %>%
55+
mutate_(internal = ~id %in% parent) %>%
56+
nest_("data", names(pd_flat))
57+
58+
child <- split$data[!split$internal][[1L]]
59+
internal <- split$data[split$internal][[1L]]
60+
61+
internal <- rename_(internal, internal_child = ~child)
62+
63+
nested <-
64+
child %>%
65+
mutate_(parent_ = ~parent) %>%
66+
nest_(., "child", setdiff(names(.), "parent_")) %>%
67+
left_join(internal, ., by = c("id" = "parent_")) %>%
68+
mutate_(child = ~Map(bind_rows, child, internal_child)) %>%
69+
mutate_(child = ~lapply(child, arrange_, ~line1, ~col1)) %>%
70+
select_(~-internal_child) %>%
71+
select_(~short, ~everything(), ~-text, ~text)
72+
73+
nest_parse_data(nested)
74+
}
75+
76+
#' Enrich nested parse table with space and linebreak information
77+
#'
78+
#' Uses [create_filler()] in a recursion add space and line break information
79+
#' separately on every level of nesting.
80+
#' @param pd_nested A nested parse table.
81+
#' @return A nested parse table with two new columns: newlines and spaces.
82+
#' @seealso [create_filler()]
83+
#' @importFrom purrr map
84+
create_filler_nested <- function(pd_nested) {
85+
if (is.null(pd_nested$child)) return()
86+
pd_nested <- pd_nested %>%
87+
create_filler() %>%
88+
mutate(child = map(child, create_filler_nested)) %>%
89+
select_(~spaces, ~newlines, ~lag_newlines, ~short, ~everything())
90+
}
91+
92+
#' Serialize a nested parse table
93+
#'
94+
#' Helper function that recursively extracts terminals from a nested tibble.
95+
#' @param pd_nested A nested parse table.
96+
#' @param pass_indent Level of indention of a token.
97+
#' @return A character vector with all terminal tokens in `pd_nested` plus
98+
#' the appropriate amount of white spaces and line breaks are inserted between
99+
#' them.
100+
#' @importFrom purrr pmap
101+
serialize_parse_data_nested_helper <- function(pd_nested, pass_indent) {
102+
out <- pmap(list(pd_nested$terminal, pd_nested$text, pd_nested$child,
103+
pd_nested$spaces, pd_nested$lag_newlines, pd_nested$indent),
104+
function(terminal, text, child, spaces, lag_newlines, indent) {
105+
total_indent <- pass_indent + indent
106+
preceding_linebreak <- if_else(lag_newlines > 0, 1, 0)
107+
if (terminal) {
108+
c(add_newlines(lag_newlines),
109+
add_spaces(total_indent * preceding_linebreak),
110+
text,
111+
add_spaces(spaces))
112+
} else {
113+
c(add_newlines(lag_newlines),
114+
add_spaces(total_indent * preceding_linebreak),
115+
serialize_parse_data_nested_helper(child, total_indent),
116+
add_spaces(spaces))
117+
}
118+
}
119+
)
120+
out
121+
}
122+
123+
#' Serialize a nested parse table
124+
#'
125+
#' Collapses a nested parse table into its character vector representation.
126+
#' @param pd_nested A nested parse table with line break, spaces and indention
127+
#' information.
128+
#' @return A character string.
129+
serialize_parse_data_nested <- function(pd_nested) {
130+
raw <- serialize_parse_data_nested_helper(pd_nested, pass_indent = 0) %>%
131+
unlist() %>%
132+
paste0(collapse = "") %>%
133+
strsplit("\n", fixed = TRUE) %>%
134+
.[[1L]]
135+
}

R/nested_to_tree.R

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
#' Convert a nested tibble into a node tree
2+
#'
3+
#' This function is convenient to display all nesting levels of a nested tibble
4+
#' at once.
5+
#' @param pd_nested A nested tibble.
6+
#' @return An object of class "Node" and "R6".
7+
#' @examples
8+
#' library("magrittr")
9+
#' code <- "a <- function(x) { if(x > 1) { 1+1 } else {x} }"
10+
#' l1 <- styler:::compute_parse_data_nested(code) %>%
11+
#' styler:::create_filler_nested() %>%
12+
#' styler:::create_node_from_nested_root()
13+
create_node_from_nested_root <- function(pd_nested) {
14+
n <- data.tree::Node$new("xxx")
15+
create_node_from_nested(pd_nested, n)
16+
n
17+
}
18+
19+
#' Create node from nested parse data
20+
#'
21+
#' @inheritParams create_node_from_nested_root
22+
#' @param parent The parent of the node to be created.
23+
#' @importFrom purrr map2
24+
create_node_from_nested <- function(pd_nested, parent) {
25+
if (is.null(pd_nested))
26+
return()
27+
28+
node_info <-
29+
pd_nested %>%
30+
transmute(formatted = paste0(token, ": ", short, " [", newlines, "/", spaces, "]")) %>%
31+
.[["formatted"]]
32+
33+
child_nodes <-
34+
node_info %>%
35+
map(parent$AddChild)
36+
37+
map2(pd_nested$child, child_nodes, create_node_from_nested)
38+
return()
39+
}

0 commit comments

Comments
 (0)