julia-vscode / DocumentFormat.jl
1
const INDENT = 4
2

3
mutable struct IndentState
4 70
    indent::Int
5
    edits
6
end
7

8 20
function indent_pass(x, state)
9 70
    if headof(x) === :file
10 70
        if length(x) > 0
11 70
            for a in x
12 70
                check_indent(a, state)
13 70
                indent_pass(a, state)
14
            end
15
        end
16 70
    elseif (headof(x) === :block && headof(x[1]) == :BEGIN) || (headof(x) === :quote && headof(x[1]) === :QUOTE)
17 70
        state.offset += x[1].fullspan
18 60
        state.edits.indent += 1
19 70
        if length(x) > 2
20 70
            for i = 2:length(x) - 1
21 70
                a = x[i]
22 70
                check_indent(a, state)
23 70
                indent_pass(a, state)
24
            end
25
        end
26 60
        state.edits.indent -= 1
27 70
        check_indent(x[3], state)
28 70
        state.offset += x[3].fullspan
29 70
    elseif headof(x) == :struct
30 70
        state.offset += x[1].fullspan + x.args[2].fullspan
31 70
        if length(x.trivia) > 2 #mutable
32 70
            state.offset += x.trivia[2].fullspan
33
        end
34 70
        if headof(x.args[3]) === :block && length(x.args[3]) > 0
35 60
            state.edits.indent += 1
36 70
            for a in x.args[3]
37 70
                check_indent(a, state)
38 70
                indent_pass(a, state)
39
            end
40 60
            state.edits.indent -= 1
41 70
            check_indent(last(x.trivia), state)
42 70
            state.offset += last(x.trivia).fullspan
43
        end
44 70
    elseif headof(x) in (:function, :macro, :for, :while)
45 70
        state.offset += x[1].fullspan + x[2].fullspan
46 70
        if headof(x[3]) === :block
47 60
            state.edits.indent += 1
48 70
            if length(x[3]) > 0
49 70
                for a in x[3]
50 70
                    check_indent(a, state)
51 70
                    indent_pass(a, state)
52
                end
53
            end
54 60
            state.edits.indent -= 1
55 70
            check_indent(x[4], state)
56 70
            state.offset += x[4].fullspan
57
        else
58 70
            check_indent(x[3], state)
59 70
            state.offset += x[3].fullspan
60
        end
61 70
    elseif headof(x) === :do
62 70
        state.offset += x[1].fullspan + x[2].fullspan + x[3][1].fullspan
63 70
        if headof(x[3][3]) === :block
64 60
            state.edits.indent += 1
65 70
            if length(x[3][3]) > 0
66 70
                for a in x[3][3]
67 70
                    check_indent(a, state)
68 70
                    indent_pass(a, state)
69
                end
70
            end
71 60
            state.edits.indent -= 1
72 70
            check_indent(x[4], state)
73 70
            state.offset += x[4].fullspan
74
        else
75 0
            check_indent(x[4], state)
76 60
            state.offset += x[4].fullspan
77
        end
78 70
    elseif headof(x) === :macrocall
79 70
        if headof(x[1]) === :globalrefdoc
80 70
            state.offset += x[1].fullspan
81 70
            doc = x.args[3]
82 70
            doc_strs = split(str_value(doc), "\n")
83 60
            state.offset += 4 
84 70
            for (i, s) in enumerate(doc_strs)
85
                # Skip indenting lines of "".
86
                # The final "" is associated with identing the
87
                # trailing docstring triple quote
88 70
                if s == "" && i != length(doc_strs)
89 70
                    state.offset += 1
90
                else
91 70
                    a = EXPR(:STRING, length(s) + 1, length(s), String(s))
92 70
                    check_indent(a, state)
93 70
                    indent_pass(a, state)
94
                end
95
            end
96 60
            state.offset += 3
97

98 70
            check_indent(x.args[4], state)
99 70
            indent_pass(x.args[4], state)
100 0
        elseif length(x) > 0
101 0
            for a in x
102 60
                indent_pass(a, state)
103
            end
104
        end
105 70
    elseif headof(x) === :mutable
106 0
        state.offset += x[1].fullspan + x[2].fullspan + x[3].fullspan
107 0
        if headof(x[4]) === :block
108 0
            state.edits.indent += 1
109 0
            if length(x[4]) > 0
110 0
                for a in x[4]
111 0
                    check_indent(a, state)
112 0
                    indent_pass(a, state)
113
                end
114
            end
115 0
            state.edits.indent -= 1
116 0
            check_indent(x[5], state)
117 0
            state.offset += x[5].fullspan
118
        else
119 0
            check_indent(x[3], state)
120 0
            state.offset += x[4].fullspan
121
        end
122 70
    elseif headof(x) === :try && length(x) > 5
123 70
        state.offset += x[1].fullspan
124 60
        state.edits.indent += 1
125 70
        if length(x[2]) > 0
126 70
            for a in x[2]
127 70
                check_indent(a, state)
128 70
                indent_pass(a, state)
129
            end
130
        end
131 60
        state.edits.indent -= 1
132 70
        check_indent(x[3], state)
133 70
        state.offset += x[3].fullspan + x[4].fullspan
134

135 60
        state.edits.indent += 1
136 70
        if length(x[5]) > 0
137 70
            for a in x[5]
138 70
                check_indent(a, state)
139 70
                indent_pass(a, state)
140
            end
141
        end
142 60
        state.edits.indent -= 1
143 70
        check_indent(x[6], state)
144 70
        state.offset += x[6].fullspan
145

146 70
        if length(x) == 8
147 0
            state.edits.indent += 1
148 0
            if length(x[7]) > 0
149 0
                for a in x[7]
150 0
                    check_indent(a, state)
151 0
                    indent_pass(a, state)
152
                end
153
            end
154 0
            state.edits.indent -= 1
155 0
            check_indent(x[8], state)
156 0
            state.offset += x[8].fullspan
157
        end
158 70
    elseif headof(x) === :if
159 70
        if headof(first(x)) == :IF
160 70
            state.offset += x[1].fullspan + x[2].fullspan
161 60
            state.edits.indent += 1
162 70
            if length(x[3]) > 0
163 70
                for a in x[3]
164 70
                    check_indent(a, state)
165 70
                    indent_pass(a, state)
166
                end
167
            end
168 70
            if length(x) >= 4
169 60
                state.edits.indent -= 1
170 70
                check_indent(x[4], state)
171 70
                state.offset += x[4].fullspan
172
            end
173 70
            if length(x) == 5
174
                # state.edits.indent += 1
175 70
                check_indent(x[5], state)
176 70
                state.offset += x[5].fullspan
177 0
            elseif length(x) == 6
178 0
                state.edits.indent += 1
179 0
                for a in x[5]
180 0
                    check_indent(a, state)
181 0
                    indent_pass(a, state)
182
                end
183 0
                state.edits.indent -= 1
184 0
                check_indent(x[6], state)
185 60
                state.offset += x[6].fullspan
186
            end
187
        else
188 0
            state.offset += x[1].fullspan
189 0
            if length(x[2]) > 0
190 0
                for a in x[2]
191 0
                    check_indent(a, state)
192 0
                    indent_pass(a, state)
193
                end
194
            end
195 0
            if length(x) > 2
196 0
                state.edits.indent -= 1
197 0
                check_indent(x[3], state)
198 0
                state.offset += x[3].fullspan
199 0
                state.edits.indent += 1
200 0
                if length(x[4]) > 0
201 0
                    for a in x[4]
202 0
                        check_indent(a, state)
203 60
                        indent_pass(a, state)
204
                    end
205
                end
206
            end
207
        end
208 70
    elseif headof(x) === :let
209 70
        if length(x) > 3
210 70
            state.offset += x[1].fullspan + x[2].fullspan
211 60
            state.edits.indent += 1
212 70
            if length(x[3]) > 0
213 70
                for a in x[3]
214 70
                    check_indent(a, state)
215 70
                    indent_pass(a, state)
216
                end
217
            end
218 60
            state.edits.indent -= 1
219 70
            check_indent(x[4], state)
220 70
            state.offset += x[4].fullspan
221
        else
222 0
            state.offset += x[1].fullspan
223 0
            state.edits.indent += 1
224 0
            if length(x[2]) > 0
225 0
                for a in x[2]
226 0
                    check_indent(a, state)
227 0
                    indent_pass(a, state)
228
                end
229
            end
230 0
            state.edits.indent -= 1
231 0
            check_indent(x[3], state)
232 60
            state.offset += x[3].fullspan
233
        end
234

235 70
    elseif x.args === nothing
236 70
        state.offset += x.fullspan
237
    else
238 70
        if length(x) > 0
239 70
            for a in x
240 70
                indent_pass(a, state)
241
            end
242
        end
243
    end
244 70
    state
245
end
246

247 20
function check_indent(x, state)
248 70
    for (l, i) in state.lines
249 70
        if state.offset == l + i
250 70
            if state.edits.indent * INDENT != i
251
                #= @info CSTParser.str_value(CSTParser.get_name(x)), state.edits.indent*INDENT, i, state.offset =#
252 70
                push!(state.edits.edits, (l, state.edits.indent * INDENT - i))
253
            end
254
        end
255
    end
256
end
257

258 20
function indents(text, opts)
259 70
    x = CSTParser.parse(text, true)
260

261 70
    state = indent_pass(x, State(0, IndentState(0, []), opts, text, get_lines(text)))
262

263 70
    sort!(state.edits.edits, lt=(a, b) -> a[1] < b[1], rev=true)
264 70
    for (l, d) in state.edits.edits
265 70
        if d > 0
266 70
            text = string(text[1:l], " "^d, text[l + 1:end])
267
        else
268 70
            text = string(text[1:l], text[l + 1 - d:end])
269
        end
270
    end
271 70
    return text
272
end

Read our documentation on viewing source code .

Loading