Skip to content

Commit

Permalink
No leading and a single trailing newline for files
Browse files Browse the repository at this point in the history
  • Loading branch information
fredrikekre committed Jul 15, 2024
1 parent 2ddbb38 commit 5766cc9
Show file tree
Hide file tree
Showing 4 changed files with 93 additions and 26 deletions.
12 changes: 7 additions & 5 deletions src/Runic.jl
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ mutable struct Context
debug::Bool
check::Bool
diff::Bool
filemode::Bool
# Global state
indent_level::Int # track (hard) indentation level
call_depth::Int # track call-depth level for debug printing
Expand All @@ -138,7 +139,7 @@ end

function Context(
src_str::String; assert::Bool = true, debug::Bool = false, verbose::Bool = debug,
diff::Bool = false, check::Bool = false, quiet::Bool = false,
diff::Bool = false, check::Bool = false, quiet::Bool = false, filemode::Bool = true,
)
src_io = IOBuffer(src_str)
src_tree = Node(
Expand All @@ -165,7 +166,7 @@ function Context(
lineage_kinds = JuliaSyntax.Kind[]
return Context(
src_str, src_tree, src_io, fmt_io, fmt_tree, quiet, verbose, assert, debug, check,
diff, call_depth, indent_level, prev_sibling, next_sibling, lineage_kinds,
diff, filemode, call_depth, indent_level, prev_sibling, next_sibling, lineage_kinds,
)
end

Expand Down Expand Up @@ -297,9 +298,10 @@ function format_node!(ctx::Context, node::Node)::Union{Node, Nothing, NullNode}

# Go through the runestone and apply transformations.
ctx.call_depth += 1
@return_something no_leading_and_single_trailing_newline(ctx, node)
@return_something max_three_consecutive_newlines(ctx, node)
@return_something insert_delete_mark_newlines(ctx, node)
@return_something trim_trailing_whitespace(ctx, node)
@return_something max_three_consecutive_newlines(ctx, node)
@return_something format_hex_literals(ctx, node)
@return_something format_oct_literals(ctx, node)
@return_something format_float_literals(ctx, node)
Expand Down Expand Up @@ -371,8 +373,8 @@ end
Format string `str` and return the formatted string.
"""
function format_string(str::AbstractString)
ctx = Context(str)
function format_string(str::AbstractString; filemode::Bool = false)
ctx = Context(str; filemode = filemode)
format_tree!(ctx)
return String(take!(ctx.fmt_io))
end
Expand Down
63 changes: 44 additions & 19 deletions src/chisels.jl
Original file line number Diff line number Diff line change
Expand Up @@ -187,32 +187,32 @@ function make_node(node::Node, kids′::Vector{Node}, tags = node.tags)
return Node(head(node), span′, kids′, tags)
end

function first_leaf(node::Node)
if is_leaf(node)
return node
else
return first_leaf(first(verified_kids(node)))
end
end
# TODO: Remove?
first_leaf(node::Node) = nth_leaf(node, 1)

function second_leaf(node::Node)
function nth_leaf(node::Node, nth::Int)
leaf, n_seen = nth_leaf(node, nth, 0)
return n_seen == nth ? leaf : nothing
end
function nth_leaf(node::Node, nth::Int, n_seen::Int)
if is_leaf(node)
return nothing
return node, n_seen + 1
else
kids = verified_kids(node)
if length(kids) == 0
return nothing
elseif !is_leaf(kids[1])
return second_leaf(kids[1])
elseif length(kids) > 1
@assert is_leaf(kids[1])
return first_leaf(kids[2])
else
@assert false
for kid in kids
leaf, n_seen = nth_leaf(kid, nth, n_seen)
if n_seen == nth
return leaf, n_seen
end
end
return nothing, n_seen
end
end

function second_leaf(node::Node)
return nth_leaf(node, 2)
end

# Return number of non-whitespace kids, basically the length the equivalent
# (expr::Expr).args
function meta_nargs(node::Node)
Expand Down Expand Up @@ -258,8 +258,33 @@ function last_leaf(node::Node)
if is_leaf(node)
return node
else
return last_leaf(last(verified_kids(node)))
kids = verified_kids(node)
if length(kids) == 0
return nothing
else
return last_leaf(last(kids))
end
end
end

function second_last_leaf(node::Node)
node, n = second_last_leaf(node, 0)
return n == 2 ? node : nothing
end

function second_last_leaf(node::Node, n_seen::Int)
if is_leaf(node)
return node, n_seen + 1
else
kids = verified_kids(node)
for i in reverse(1:length(kids))
kid, n_seen = second_last_leaf(kids[i], n_seen)
if n_seen == 2
return kid, n_seen
end
end
end
return nothing, n_seen
end

function has_newline_after_non_whitespace(node::Node)
Expand Down
1 change: 0 additions & 1 deletion src/debug.jl
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,3 @@ function macroexpand_assert(expr)
msg = string(expr)
return :($(esc(expr)) || throw(AssertionError($msg)))
end

43 changes: 42 additions & 1 deletion src/runestone.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1316,8 +1316,49 @@ function parens_around_op_calls_in_colon(ctx::Context, node::Node)
end
end

# No newline at the beginning and single newline at the end of the file
function no_leading_and_single_trailing_newline(ctx::Context, node::Node)
if !(ctx.filemode && length(ctx.lineage_kinds) == 0)
return nothing
end
@assert kind(node) === K"toplevel"
@assert !is_leaf(node)
@assert position(ctx.fmt_io) == 0
changed = false
while (l = first_leaf(node); l !== nothing && kind(l) === K"NewlineWs" && length(verified_kids(node)) > 1)
changed = true
replace_bytes!(ctx, "", span(l))
node = replace_first_leaf(node, nullnode)
end
accept_node!(ctx, node)
l = last_leaf(node)
if l === nothing || kind(l) !== K"NewlineWs"
kids′ = copy(verified_kids(node))
push!(kids′, Node(JuliaSyntax.SyntaxHead(K"NewlineWs", JuliaSyntax.TRIVIA_FLAG), 1))
replace_bytes!(ctx, "\n", 0)
changed = true
node = make_node(node, kids′)
else
ll = second_last_leaf(node)
while ll !== nothing && kind(l) === kind(ll) === K"NewlineWs"
changed = true
seek(ctx.fmt_io, position(ctx.fmt_io) - span(l))
# replace_bytes!(ctx, "", span(l))
node = replace_last_leaf(node, nullnode)
@assert last_leaf(node) === ll
l = ll
ll = second_last_leaf(node)
end
end
if changed
return node
else
seek(ctx.fmt_io, 0)
return nothing
end
end

# Remove more than two newlines in a row
# Remove more than three newlines in a row
function max_three_consecutive_newlines(ctx::Context, node::Node)
is_leaf(node) && return nothing
kids = verified_kids(node)
Expand Down

0 comments on commit 5766cc9

Please sign in to comment.