9
9
10
10
# ' @describeIn update_indention Inserts indetion based on round brackets.
11
11
indent_round <- function (pd , indent_by ) {
12
- indention_needed <- needs_indention(pd , token = " '('" )
13
- if (indention_needed ) {
14
- opening <- which(pd $ token == " '('" )
15
- start <- opening + 1
16
- stop <- nrow(pd ) - 1
17
- if (start > stop ) return (pd )
18
-
19
- pd <- pd %> %
20
- mutate(indent = indent + ifelse(seq_len(nrow(pd )) %in% start : stop ,
21
- indent_by , 0 ))
22
- }
23
-
24
- pd %> %
25
- set_unindention_child(token = " ')'" , unindent_by = indent_by )
12
+ indent_indices <- compute_indent_indices(pd , token = " '('" )
13
+ pd $ indent [indent_indices ] <- pd $ indent [indent_indices ] + indent_by
14
+ set_unindention_child(pd , token = " ')'" , unindent_by = indent_by )
26
15
}
16
+
27
17
# ' @rdname update_indention
28
18
indent_curly <- function (pd , indent_by ) {
29
- indention_needed <- needs_indention(pd , token = " '{'" )
30
- if (indention_needed ) {
31
- opening <- which(pd $ token == " '{'" )
32
- start <- opening + 1
33
- stop <- nrow(pd ) - 1
34
- if (start > stop ) return (pd )
35
-
36
- pd <- pd %> %
37
- mutate(indent = indent + ifelse(seq_len(nrow(pd )) %in% start : stop ,
38
- indent_by , 0 ))
39
- }
40
- pd %> %
41
- set_unindention_child(token = " '}'" , unindent_by = indent_by )
42
- }
43
-
44
- # ' Check whether indention is needed
45
- # '
46
- # ' @param pd A parse table.
47
- # ' @param token Which token the check should be based on.
48
- # ' @return returns `TRUE` if indention is needed, `FALSE` otherwise. Indention
49
- # ' is needed:
50
- # ' * if `token` occurs in `pd`.
51
- # ' * if there is no child that starts on the same line as `token` and
52
- # ' "opens" indention without closing it on this line.
53
- # ' @return `TRUE` if indention is needed, `FALSE` otherwise.
54
- needs_indention <- function (pd , token = " '('" ) {
55
- opening <- which(pd $ token %in% token )[1 ]
56
- if (is.na(opening )) return (FALSE )
57
- before_first_break <- which(pd $ lag_newlines > 0 )[1 ] - 1
58
- if (is.na(before_first_break )) return (FALSE )
59
- ! any(pd $ multi_line [opening : before_first_break ])
19
+ indent_indices <- compute_indent_indices(pd , token = " '{'" )
20
+ pd $ indent [indent_indices ] <- pd $ indent [indent_indices ] + indent_by
21
+ set_unindention_child(pd , token = " '}'" , unindent_by = indent_by )
60
22
}
61
23
62
24
# ' @rdname update_indention
63
25
indent_op <- function (pd , indent_by , token = c(math_token ,
64
26
" SPECIAL-PIPE" )) {
65
- if (needs_indention(pd , token )) {
66
- opening <- which(pd $ token %in% token )
67
- start <- opening [1 ] + 1
68
- stop <- nrow(pd )
69
- pd <- pd %> %
70
- mutate(indent = indent + ifelse(seq_len(nrow(pd )) %in% start : stop ,
71
- indent_by , 0 ))
72
- }
27
+ indent_indices <- compute_indent_indices(pd , token , indent_last = TRUE )
28
+ pd $ indent [indent_indices ] <- pd $ indent [indent_indices ] + indent_by
73
29
pd
74
30
}
75
31
76
32
# ' @describeIn update_indention Same as indent_op, but only indents one token
77
33
# ' after `token`, not all remaining.
78
34
indent_assign <- function (pd , indent_by , token = c(" LEFT_ASSIGN" , "
79
35
EQ_ASSIGN" )) {
80
- if (needs_indention(pd , token )) {
81
- opening <- which(pd $ token %in% token )
82
- start <- opening + 1
83
- stop <- start + 1
84
- pd <- pd %> %
85
- mutate(indent = indent + ifelse(seq_len(nrow(pd )) %in% start : stop ,
86
- indent_by , 0 ))
87
- }
36
+ indent_indices <- compute_indent_indices(pd , token , indent_last = TRUE )
37
+ pd $ indent [indent_indices ] <- pd $ indent [indent_indices ] + indent_by
88
38
pd
89
39
}
90
40
@@ -98,15 +48,56 @@ indent_without_paren <- function(pd, indent_by = 2) {
98
48
pd
99
49
}
100
50
51
+ # ' Compute the indices that need indention
52
+ # '
53
+ # ' Based on `token`, find the rows in `pd` that need to be indented.
54
+ # ' @param pd A parse table.
55
+ # ' @param token A character vector with tokens.
56
+ # ' @param indent_last Flag to indicate whether the last token in `pd` should
57
+ # ' be indented or not. See 'Details'.
58
+ # ' @details
59
+ # ' For example when `token` is a parenthesis, the closing parenthesis does not
60
+ # ' need indention, but if token is something else, for example a plus (+), the
61
+ # ' last token in `pd` needs indention.
62
+ compute_indent_indices <- function (pd , token = " '('" , indent_last = FALSE ) {
63
+ npd <- nrow(pd )
64
+ opening <- which(pd $ token %in% token )[1 ]
65
+ if (! needs_indention(pd , opening )) return (numeric (0 ))
66
+ start <- opening + 1
67
+ stop <- npd - ifelse(indent_last , 0 , 1 )
68
+ which(between(seq_len(npd ), start , stop ))
69
+ }
70
+
71
+
72
+ # ' Check whether indention is needed
73
+ # '
74
+ # ' @param pd A parse table.
75
+ # ' @param opening the index of the opening parse table. Since always computed
76
+ # ' before this function is called, it is included as an argument so it does
77
+ # ' not have to be recomputed.
78
+ # ' @return returns `TRUE` if indention is needed, `FALSE` otherwise. Indention
79
+ # ' is needed if and only if:
80
+ # ' * the opening token is not `NA`.
81
+ # ' * if there is a multi-line token before the first line break.
82
+ # ' @return `TRUE` if indention is needed, `FALSE` otherwise.
83
+ needs_indention <- function (pd , opening ) {
84
+ if (is.na(opening )) return (FALSE )
85
+ before_first_break <- which(pd $ lag_newlines > 0 )[1 ] - 1
86
+ if (is.na(before_first_break )) return (FALSE )
87
+ ! any(pd $ multi_line [opening : before_first_break ])
88
+ }
89
+
90
+
91
+
101
92
# ' Set the multi-line column
102
93
# '
103
94
# ' Sets the column `multi_line` in `pd` by checking row-wise whether any child
104
95
# ' of a token is a multi-line token.
105
96
# ' @param pd A parse table.
106
97
# ' @importFrom purrr map_lgl
107
98
set_multi_line <- function (pd ) {
108
- pd % > %
109
- mutate( multi_line = map_lgl( child , token_is_multi_line ))
99
+ pd $ multi_line <- map_lgl( pd $ child , token_is_multi_line )
100
+ pd
110
101
}
111
102
112
103
# ' Check whether a parse table is a multi-line token
@@ -117,7 +108,7 @@ set_multi_line <- function(pd) {
117
108
# ' * it has at least one child that is a multi-line expression itself.
118
109
# ' @param pd A parse table.
119
110
token_is_multi_line <- function (pd ) {
120
- any(pd $ multi_line ) | any( pd $ lag_newlines )
111
+ any(pd $ multi_line , pd $ lag_newlines > 0 )
121
112
}
122
113
123
114
@@ -127,6 +118,7 @@ token_is_multi_line <- function(pd) {
127
118
# ' @param pd_flat A flat parse table.
128
119
# ' @return A nested parse table.
129
120
strip_eol_spaces <- function (pd_flat ) {
130
- pd_flat %> %
131
- mutate(spaces = spaces * (lead(lag_newlines , default = 0 ) == 0 ))
121
+ idx <- lead(pd_flat $ lag_newlines , default = 0 ) != 0
122
+ pd_flat $ spaces [idx ] <- 0
123
+ pd_flat
132
124
}
0 commit comments