diff --git a/src/chisels.jl b/src/chisels.jl index 6a89915..09de51f 100644 --- a/src/chisels.jl +++ b/src/chisels.jl @@ -570,6 +570,11 @@ function is_triple_string_macro(node) return false end +function is_triple_thing(node) + return is_triple_string(node) || is_triple_string_macro(node) || + (kind(node) === K"juxtapose" && is_triple_string_macro(verified_kids(node)[1])) +end + ########################## # Utilities for IOBuffer # ########################## diff --git a/src/runestone.jl b/src/runestone.jl index 43b4933..2dd5931 100644 --- a/src/runestone.jl +++ b/src/runestone.jl @@ -2053,10 +2053,18 @@ function indent_newlines_between_indices( if !indent_closing_token && i == close_idx - 1 && kind(kid) === K"NewlineWs" continue end - # Tag all direct NewlineWs kids if kind(kid) === K"NewlineWs" && !has_tag(kid, TAG_LINE_CONT) + # Tag all direct NewlineWs kids kid = add_tag(kid, TAG_LINE_CONT) this_kid_changed = true + elseif is_triple_thing(kid) && (i != open_idx || has_tag(node, TAG_LINE_CONT)) + # TODO: Might be too course to use the tag on the node here... + # Tag triple strings and triple string macros + kid′ = indent_triple_thing(ctx, kid) + if kid′ !== nothing + kid = kid′ + this_kid_changed = true + end end # NewlineWs nodes can also hide as the first or last leaf of a node, tag'em. # Skip leading newline if this kid is the first one @@ -2449,6 +2457,29 @@ function indent_short_circuit(ctx::Context, node::Node) return indent_op_call(ctx, node) end +function indent_triple_thing(ctx::Context, node::Node) + @assert is_triple_thing(node) + if is_triple_string(node) + return has_tag(node, TAG_LINE_CONT) ? nothing : add_tag(node, TAG_LINE_CONT) + elseif is_triple_string_macro(node) + kids = verified_kids(node) + @assert is_triple_string(kids[2]) + kid′ = indent_triple_thing(ctx, kids[2]) + kid′ === nothing && return nothing + kids′ = copy(kids) + kids′[2] = kid′ + return make_node(node, kids′) + else + @assert kind(node) === K"juxtapose" && is_triple_string_macro(verified_kids(node)[1]) + kids = verified_kids(node) + kid′ = indent_triple_thing(ctx, kids[1]) + kid′ === nothing && return nothing + kids′ = copy(kids) + kids′[1] = kid′ + return make_node(node, kids′) + end +end + # TODO: This function can be used for more things than just indent_using I think. Perhaps # with a max_depth parameter. function continue_all_newlines( @@ -2465,6 +2496,13 @@ function continue_all_newlines( else return nothing end + elseif is_triple_thing(node) + # Check skip_first inside to break the recursion and considier triple strings leafs + if !(skip_first && is_first) + return indent_triple_thing(ctx, node) + else + return nothing + end else any_kid_changed = false kids = verified_kids(node) @@ -2508,12 +2546,6 @@ function indent_assignment(ctx::Context, node::Node) rhsidx = findnext(!JuliaSyntax.is_whitespace, kids, eqidx + 1)::Int r = (eqidx + 1):(rhsidx - 1) length(r) == 0 && return nothing - if length(r) == 1 && kind(kids[r[1]]) === K"Whitespace" - return nothing - end - if !any(i -> kind(kids[i]) === K"NewlineWs", r) - return nothing - end rhs = kids[rhsidx] # Some right hand sides have more "inertia" towards indentation. This is so that we # will end up with e.g. @@ -2533,8 +2565,7 @@ function indent_assignment(ctx::Context, node::Node) # x = if cond # end # ``` - blocklike = kind(rhs) in KSet"if try function let" || - is_triple_string(rhs) || is_triple_string_macro(rhs) + blocklike = kind(rhs) in KSet"if try function let" || is_triple_thing(rhs) blocklike && return nothing # TODO: Perhaps delete superfluous newlines? # Continue all newlines between the `=` and the rhs kids′ = kids @@ -2554,9 +2585,20 @@ function indent_assignment(ctx::Context, node::Node) push!(kids′, kid′) end end + # Mark the rhs for line continuation + if !has_tag(rhs, TAG_LINE_CONT) + rhs = add_tag(rhs, TAG_LINE_CONT) + changed = true + if kids′ === kids + kids′ = kids[1:(rhsidx - 1)] + end + push!(kids′, rhs) + else + changed && push!(kids′, rhs) + end if changed @assert kids !== kids′ - for i in rhsidx:length(kids) + for i in (rhsidx + 1):length(kids) push!(kids′, kids[i]) end return make_node(node, kids′) @@ -2786,6 +2828,9 @@ function indent_multiline_strings(ctx::Context, node::Node) triplekind = kind(node) === K"string" ? K"\"\"\"" : K"```" itemkind = kind(node) === K"string" ? K"String" : K"CmdString" indent_span = 4 * ctx.indent_level + if has_tag(node, TAG_LINE_CONT) + indent_span += 4 + end indented = indent_span > 0 pos = position(ctx.fmt_io) diff --git a/test/runtests.jl b/test/runtests.jl index 772fa6f..d73f559 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -735,12 +735,16 @@ end # Blocklike RHS for thing in ( "if c\n x\nend", "try\n x\ncatch\n y\nend", + "let c = 1\n c\nend", "function()\n x\nend", "\"\"\"\nfoo\n\"\"\"", "r\"\"\"\nfoo\n\"\"\"", - "```\nfoo\n```", "r```\nfoo\n```", + "```\nfoo\n```", "r```\nfoo\n```", "```\nfoo\n```x", ) @test format_string("a =$(nl)$(thing)") == "a =$(nl)$(thing)" @test format_string("a =$(nl)# comment$(nl)$(thing)") == "a =$(nl)# comment$(nl)$(thing)" + @test format_string("a = $(thing)") == "a = $(thing)" + @test format_string("a = #=comment=#$(sp)$(thing)") == + "a = #=comment=# $(thing)" end end # using/import @@ -937,6 +941,29 @@ end "$(otriple)\na\\\nb\n$(ctriple)" @test format_string("begin\n$(otriple)\n$(sp)a\\\n$(sp)b\n$(sp)$(ctriple)\nend") === "begin\n $(otriple)\n a\\\n b\n $(ctriple)\nend" + # Triple strings with continuation indent + @test format_string("x = $(otriple)\n$(sp)a\n$(sp)b\n$(sp)$(ctriple)") === + "x = $(otriple)\na\nb\n$(ctriple)" + @test format_string("$(otriple)\n$(sp)a\n$(sp)b\n$(sp)$(ctriple) * $(otriple)\n$(sp)a\n$(sp)b\n$(sp)$(ctriple)") === + "$(otriple)\na\nb\n$(ctriple) * $(otriple)\n a\n b\n $(ctriple)" + @test format_string("$(otriple)\n$(sp)a\n$(sp)b\n$(sp)$(ctriple) *\n$(otriple)\n$(sp)a\n$(sp)b\n$(sp)$(ctriple)") === + "$(otriple)\na\nb\n$(ctriple) *\n $(otriple)\n a\n b\n $(ctriple)" + # Implicit tuple + @test format_string("$(otriple)\nabc\n$(ctriple), $(otriple)\ndef\n$(ctriple)") === + "$(otriple)\nabc\n$(ctriple), $(otriple)\n def\n $(ctriple)" + @test format_string("$(otriple)\nabc\n$(ctriple),\n$(otriple)\ndef\n$(ctriple)") === + "$(otriple)\nabc\n$(ctriple),\n $(otriple)\n def\n $(ctriple)" + # Operator chains + @test format_string("$(otriple)\nabc\n$(ctriple) * $(otriple)\ndef\n$(ctriple)") === + "$(otriple)\nabc\n$(ctriple) * $(otriple)\n def\n $(ctriple)" + @test format_string("$(otriple)\nabc\n$(ctriple) *\n$(otriple)\ndef\n$(ctriple)") === + "$(otriple)\nabc\n$(ctriple) *\n $(otriple)\n def\n $(ctriple)" + @test format_string("x = $(otriple)\nabc\n$(ctriple) *\n$(otriple)\ndef\n$(ctriple)") === + "x = $(otriple)\n abc\n $(ctriple) *\n $(otriple)\n def\n $(ctriple)" + @test format_string("x = $(otriple)\nabc\n$(ctriple) *\n\"def\"") === + "x = $(otriple)\n abc\n $(ctriple) *\n \"def\"" + @test format_string("x = \"abc\" *\n$(otriple)\ndef\n$(ctriple)") === + "x = \"abc\" *\n $(otriple)\n def\n $(ctriple)" end end @@ -961,13 +988,13 @@ end end """, ) == """ - function f() - $off - 1+1 - $on - 1 + 1 - end - """ + function f() + $off + 1+1 + $on + 1 + 1 + end + """ @test format_string( """ function f() @@ -978,13 +1005,13 @@ end end """, ) == """ - function f() - $off - 1 + 1 - $bon - 1 + 1 - end - """ + function f() + $off + 1 + 1 + $bon + 1 + 1 + end + """ @test format_string( """ function f() @@ -994,12 +1021,12 @@ end end """, ) == """ - function f() - $off - 1 + 1 - 1 + 1 - end - """ + function f() + $off + 1 + 1 + 1 + 1 + end + """ end end