text:
@with_kw struct IZParameter
    a::SNNFloat = 0.01
    b::SNNFloat = 0.2
    c::SNNFloat = -65
    d::SNNFloat = 2
end

@with_kw mutable struct IZ{VF,VB}
    param::IZParameter = IZParameter()
    N::SNNInt = 100
    v::VF = fill(-65.0, N)
    u::VF = param.b * v
    fire::VB = zeros(eltype(VB), N)
    I::VF = zeros(eltype(VF), N)
    records::Dict = Dict()
end
IZ(x;kwargs...) = IZ{Vector{SNNFloat},Vector{Bool}}(;kwargs...)

function integrate!(p::IZ, param::IZParameter, dt::SNNFloat)
    @unpack N, v, u, fire, I = p
    @unpack a, b, c, d = param
    @inbounds for i = 1:N
        v[i] += 0.5f0dt * (0.04f0v[i]^2 + 5f0v[i] + 140f0 - u[i] + I[i])
        v[i] += 0.5f0dt * (0.04f0v[i]^2 + 5f0v[i] + 140f0 - u[i] + I[i])
        u[i] += dt * (a * (b * v[i] - u[i]))
    end
    @inbounds for i = 1:N
        fire[i] = v[i] > 30f0
        v[i] = ifelse(fire[i], c, v[i])
        u[i] += ifelse(fire[i], d, 0f0)
    end
end


text:
"""
    AlignedSpans.indices(span::AlignedSpan) -> UnitRange{Int64}

Returns the sample indices associated to an `AlignedSpan`.
"""
indices(span::AlignedSpan) = (span.first_index):(span.last_index)

"""
    n_samples(aligned::AlignedSpan)

Returns the number of samples present in the span `aligned`.
"""
n_samples(aligned::AlignedSpan) = length(indices(aligned))

"""
    consecutive_subspans(span::AlignedSpan, duration::Period)

Creates an iterator of `AlignedSpan` such that each `AlignedSpan` has consecutive indices
which cover all of the original `span`'s indices. In particular,

* Each span has `n = n_samples(span.sample_rate, duration)` samples, except possibly
the last one, which may have fewer.
* The number of subspans is given by `cld(n_samples(span), n)`
* The number of samples in the last subspan is `r = rem(n_samples(span), n)` unless `r=0`, in which
  case the the last subspan has the same number of samples as the rest, namely `n`.
"""
function consecutive_subspans(span::AlignedSpan, duration::Period)
    n = n_samples(span.sample_rate, duration)
    return consecutive_subspans(span::AlignedSpan, n)
end

function consecutive_subspans(span::AlignedSpan, n::Int)
    index_groups = Iterators.partition((span.first_index):(span.last_index), n)
    return (AlignedSpan(span.sample_rate, first(I), last(I)) for I in index_groups)
end

ext: jl


text:
__precompile__(true)

module MarkovChainExperiment

using Reproduce
using JLD2
using Resampling
import Resampling.ExpUtils: algorithm_settings!, build_algorithm_dict
using Resampling.ExpUtils.MarkovChainUtil
using Random
using Statistics
import Flux: Descent
import ProgressMeter
import StatsBase

function exp_settings(as::ArgParseSettings = ArgParseSettings(exc_handler=Reproduce.ArgParse.debug_handler))
    @add_arg_table as begin
        # Basic Experiment Arguments
        "--exp_loc"
        arg_type=String
        required=true
        "--numruns"
        arg_type=Int64
        required=true
        "--seed"
        help = "Starting seed (initialize seed + run)"
        default = 0
        arg_type = Int64
        "--numiter"
        help = "Number of training iterations"
        default = 1000
        arg_type = Int64
        "--buffersize"
        help = "Size of buffer"
        default = 15000
        arg_type = Int64
        "--batchsize"
        help = "Size of batch"
        default = 16
        arg_type = Int64
        "--onpolicy"
        action=:store_true
        "--working"
        action=:store_true
    end

    @add_arg_table as begin
        "--alphas"
        arg_type=Float64
        nargs='+'
        required=true
    end

    algorithm_settings!(as)
    env_settings!(as)

    return as
end

function mave(model::Resampling.TabularLayer{Array{Float64, 1}}, truth, args...)
    return mean(abs.(model.W .- truth))
end

function mave(model::Resampling.TabularLayer{Array{Float64, 2}}, truth, target_policy)
    return mean(abs.(model.W'*target_policy  .- truth))
end

function main_experiment(args::Vector{String})

    as = exp_settings()
    parsed = parse_args(args, as)
    save_loc=""
    if !parsed["working"]
        create_info!(parsed, parsed["exp_loc"]; filter_keys=["verbose", "working", "exp_loc"])
        save_loc = Reproduce.get_save_dir(parsed)
        if isfile(joinpath(save_loc, "results.jld2"))
            return
        end
    end

    num_runs = parsed["numruns"]
    chain_size = parsed["chainsize"]
    num_iterations = parsed["numiter"]
    buffer_size = parsed["buffersize"]
    batch_size = parsed["batchsize"]
    α_arr = parsed["alphas"]

    μ, π = get_policies(parsed)
    if parsed["onpolicy"]
        μ = π
    end

    truth = Resampling.DynamicProgramming(MarkovChain(chain_size), π, 0.9)
    println(truth)

    algo_dict, sample_dict, value_type_dict = build_algorithm_dict(parsed; max_is=max_is_dict[parsed["policy"]])

    # value_dict = Dict{String, Array{Resampling.TabularLayer, 1}}()
    error_dict = Dict{String, Array{Float64}}()
    for key in keys(algo_dict)
        error_dict[key] = zeros(num_runs, length(α_arr), num_iterations)
    end

    p_run = ProgressMeter.Progress(num_runs, "Runs: ", 1)
    prog_mutex = Threads.Mutex()
    err_mutex = Threads.Mutex()

    local_err_iddict = IdDict()
    value_iddict = IdDict()

    for run in 1:num_runs
        value_dict = Dict{String, Array{Resampling.TabularLayer, 1}}()
        local_error_dict = Dict{String, Array{Float64}}()
        for key in keys(algo_dict)
            if value_type_dict[key] == "State"
                value_dict[key] = [Tabular(chain_size) for α in α_arr]
            else
                value_dict[key] = [Tabular(2, chain_size) for α in α_arr]
            end
            local_error_dict[key] = zeros(length(α_arr), num_iterations)
        end

        rng = MersenneTwister(parsed["seed"] + run)
        # for vf in values(value_dict)
        #     for v in vf
        #         fill!(v.W, 0.0)
        #     end
        # end
        ER, WER = get_experience(buffer_size, μ, π; rng=rng, chain_size=chain_size)
        avg_is = Resampling.total(WER.sumtree)/buffer_size

        for iter in 1:num_iterations
            samp_er = sample(ER, batch_size; rng=rng)
            samp_wer = sample(WER, batch_size; rng=rng)

            action_tp1 = StatsBase.sample(rng, [1, 2], StatsBase.weights(π), batch_size)

            arg_er = (samp_er[:ρ], samp_er[:s_t], samp_er[:s_tp1],
                      samp_er[:r], samp_er[:γ_tp1], samp_er[:terminal], samp_er[:a_t], action_tp1, π)
            arg_wer = (ones(length(samp_wer[:ρ])), samp_wer[:s_t], samp_wer[:s_tp1],
                       samp_wer[:r], samp_wer[:γ_tp1], samp_wer[:terminal], samp_er[:a_t], action_tp1, π)

            for (α_idx, α) in enumerate(α_arr)
                opt = Descent(α)
                for key in keys(algo_dict)
                    if sample_dict[key] == "IR"
                        corr_term = 1.0
                        if key == "BCIR"
                            corr_term = avg_is
                        end
                        update!(value_dict[key][α_idx], opt, algo_dict[key], arg_wer...; corr_term=corr_term)
                    elseif sample_dict[key] == "ER"
                        update!(value_dict[key][α_idx], opt, algo_dict[key], arg_er...;)
                    elseif sample_dict[key] == "Optimal"
                        samp_opt = ER.buffer
                        arg_opt = (samp_opt[:ρ], samp_opt[:s_t], samp_opt[:s_tp1],
                                  samp_opt[:r], samp_opt[:γ_tp1], samp_opt[:terminal])
                        update!(value_dict[key][α_idx], opt, algo_dict[key], arg_opt...;)
                    end
                    local_error_dict[key][α_idx, iter] = mave(value_dict[key][α_idx], truth, π)
                end
            end
        end
        Threads.lock(prog_mutex)
        ProgressMeter.next!(p_run)
        for key in keys(local_error_dict)
            error_dict[key][run, :, :] .= local_error_dict[key]
        end
        Threads.unlock(prog_mutex)
    end

    # println(value_function)

    if parsed["working"]
        return error_dict
    else
        results = error_dict
        @save joinpath(save_loc, "results.jld2") results
    end

end

Base.@ccallable function julia_main(ARGS::Vector{String})::Cint
    main_experiment(ARGS)
    return 0
end

end


text:
"""
A package for best subset selection for binary prediction.
"""
module BSBP

include("MaxScore.jl")
include("CVMaxScore.jl")
include("WarmStartMaxScore.jl")
export MaxScore, CVMaxScore, WarmStartMaxScore

include("simulation.jl")
include("transportationMode.jl")
include("transportationModeCV.jl")
using .transportationMode
using .transportationModeCV
using .simulation
export Simulation, TransportationMode, TransportationModeCV

end # module


text:
#== MFDFA1.jl  by Tehran Davis, 2020

This is an Julia-based translation of the Matlab script based on EAF Ihlen:
Front. Physiol., 04 June 2012 | https://doi.org/10.3389/fphys.2012.00141

==#

using StatsBase, Polynomials, DataFrames, GLM, Polynomials.PolyCompat

function MFDFA(signal, scale, q, m)

#== Multifractal detrended fluctuation analysis (MFDFA)
[Hq,tq,hq,Dq,Fq]=MFDFA(signal,scale,q,m);
INPUT PARAMETERS---------------------------------------------------------
signal:       input signal
scale:        vector of scales
q:            q-order that weights the local variations
m:            polynomial order for the detrending

OUTPUT VARIABLES---------------------------------------------------------
Hq:           q-order Hurst exponent
tq:           q-order mass exponent
hq:           q-order singularity exponent
Dq:           q-order dimension
Fq:           q-order scaling function
--------------------------------------------------------------------==#

    X=cumsum(signal.-mean(signal), dims=1);

    RMS_scale = [Float64[] for i=1:length(scale)]
    qRMS = [Float64[] for i=1:length(q),j=1:length(scale)]
    Fq = Array{Float64}(undef, length(q), length(scale))
    Hq = Float64[]
    Hq_r2 = Float64[]
    qRegLine = []

    # if minimum(size(X))!=1||minimum(size(scale))!=1||minimum(size(q))!=1;
    #     error("Input arguments signal, scale and q must be a vector");
    # end
    # if size(X,2)==1;
    #    X=transpose(X);
    # end
    # if min(scale)<m+1
    #    error('The minimum scale must be larger than trend order m+1')
    # end

    for ns=1:length(scale)
        # segments[ns]=floor(length(X)/scale[ns]);
        segments = floor(length(X)/scale[ns])
        for v=1:segments
            Index=Int.([(((v-1)*scale[ns])+1):v*scale[ns];])
            C=Polynomials.PolyCompat.polyfit(Index,X[Index],m);
            pfit = Polynomials.PolyCompat.polyval(C,Index)
            push!(RMS_scale[ns],sqrt(mean((X[Index]-pfit).^2)))
        end
        for nq=1:length(q)
            qRMS[nq,ns] = RMS_scale[ns].^q[nq]
            Fq[nq,ns]=mean(qRMS[nq,ns]) .^(1/q[nq])
        end
        Fq[findall(x->x==0,q),ns].=exp(0.5*mean(log.(RMS_scale[ns].^2)));
    end
    for nq=1:length(q)

        # using Polynomials - old method
        # C = polyfit(log2.(scale),log2.(Fq[nq,:]),1)
        # push!(Hq,C[1])
        # push!(qRegLine,polyval(C,log2.(scale)))

        # using GLM: benefit we get R-squared
        C = GLM.lm(@formula(y~x),DataFrame(y=log2.(Fq[nq,:]),x=log2.(scale)))
        push!(Hq,GLM.coef(C)[2])
        push!(qRegLine,GLM.predict(C))
        push!(Hq_r2, GLM.r²(C))

    end

    tq = (Hq.*q).-1
    hq = diff(tq)./(q[2]-q[1])
    Dq = q[1:(length(q)-1)].*hq-tq[1:(length(tq)-1)]

    mfw = maximum(hq) - minimum(hq);

    output = Dict("Hq" => Hq,
                    "Hq_r2" => Hq_r2,
                    "tq" => tq,
                    "hq" => hq,
                    "Dq" => Dq,
                    "Fq" => Fq,
                    "q" => q,
                    "mfw" => mfw
                    )

    return output

end


text:
#using JuMP, CPLEX
using JuMP, GLPK

function jobshop(n, m, p, r)
  #model = Model(CPLEX.Optimizer)
  model = Model(GLPK.Optimizer)
  set_optimizer_attribute(model, "msg_lev", GLPK.GLP_MSG_ALL)
  @variable(model,s[1:n,1:m]>=0)
  @variable(model,C>=0)
  @objective(model, Min, C)
  M=sum(p)
  #print(M,"\n")

  for i in 1:n
    for j in 1:m-1
      @constraint(model,s[i,j]+p[i,j]<=s[i,j+1])
    end
    @constraint(model,s[i,m]+p[i,m]<=C)
  end
  for i in 1:n
    for ii in i+1:n
      for j in 1:m
        for jj in 1:m
          if ruta[i,j]==ruta[ii,jj]
            z=@variable(model,base_name ="z_$(i)_$(ii)_$(j)",binary=true)
            @constraint(model,s[i,j]+p[i,j]-s[ii,jj]<=z*M)
            @constraint(model,s[ii,jj]+p[ii,jj]-s[i,j]<=(1-z)*M)
          end
        end
      end
    end
  end
  #println(model)
  optimize!(model)
  println("Objective: ",objective_value(model))
#  for i in 1:n
#    for j in 1:m
#      println(i,"\t",j,"\t",value(s[i,j]))
#    end
#  end
end

## leo archivo y guardo datos
f = open(ARGS[1], "r")
s = readlines(f)
print("filename:", s)
n=parse(Int,s[2])
m=parse(Int,s[4])
ruta=zeros(Int, n, m)
processing=zeros(Int,n,m)
print("número piezas ",n,"\nnúmero de máquinas ",m,"\n")
print("ruta:\n")
for i in 1:n
  divided=split(s[5+i])
  for j in 1:m
    ruta[i,j]=parse(Int,divided[j])
    print(ruta[i,j],"\t")
  end
  print("\n")
end
print("duraciones:\n")
for i in 1:n
  divided=split(s[6+n+i])
  for j in 1:m
    processing[i,j]=parse(Int,divided[j])
    print(processing[i,j],"\t")
  end
  print("\n")
end
close(f)
jobshop(n,m,processing,ruta)


text:
using FileIO
include("julia2ims.jl")

field = ["s1-1"  "s4-3"  "s4-6"  "s5-6"  "s9-5"  "s9-4"  "s10-2" "s11-4" "s12-1" "s13-3" "s13-1" "s14-1" "s14-6" "s14-4" "s14-8" "s16-5" "s16-1" "s21-1" "s22-8" "s23-1" "s27-5" "s34-3"  ]
data_dir = "/datahub/rawdata/tandeng/mRNA_imaging/mRNA_confocal_hamamatsu-60X-TIRF/20200315";
output_dir = "$(data_dir)_visualization"

try
    mkdir("$output_dir")
catch
end

function max_projection(cell)
    println("Processing $cell")
    #raw_img = load(File(format"TIFF", "$data_dir/HE7-11-1-80uw-const_3_$pos.ome.tiff"));
    raw_img = loadims2("$(data_dir)_result/output/d15$cell.ims");
    img_size = size(raw_img);
    img_max = zeros(N0f16, img_size[1], img_size[2], Int(img_size[3]/20));
    for i in 1:Int(img_size[3]/20)
        img_max[:, :, i] = maximum(raw_img[:, :, (i-1)*20+1:i*20], dims=3);
    end
    save("$output_dir/$cell.tiff", img_max);
end

for cell in field
    max_projection(cell)
end


text:
using StringBuilders
using Test

@testset "StringBuilders" begin
    sb = StringBuilder()
    append!(sb, "First string.")
    append!(sb, "Second string.")
    append!(sb, "Third string.")

    s = String(sb)
    @test s == "First string.Second string.Third string."
    s2 = String(sb)
    @test s2 == "First string.Second string.Third string."

    append!(sb, "Fourth string.")
    s3 = String(sb)

    @test s3 == "First string.Second string.Third string.Fourth string."

    b = StringBuilder()
    append!(b, "1", "2", "3")
    @test String(b) == "123"

    sb = StringBuilder()
    @test isempty(String(sb))
end


text:
# b-splines

using Plots, LaTeXStrings

function b_spline_basis(i,r,t,u)
    u_i = u[i+1]
    u_i1 = u[i+2]
    u_ir = u[i+r+1]
    u_i1r = u[i+r+2]

    if r == 0
        if u_i <= t <= u_i1
            return 1
        else
            return 0
        end
    else
        N = b_spline_basis
        left = 0
        if (u_ir-u_i) != 0
            left = (t-u_i)/(u_ir-u_i) * N(i,r-1,t,u)
        end

        right = 0
        if (u_i1r-u_i1) != 0
            right = (u_i1r-t)/(u_i1r-u_i1) * N(i+1,r-1,t,u)
        end
        return left + right
    end
end

function b_spline(dBx,dBy, n, knot_vector; steps=200)
    m = length(dBx)-1
    if length(knot_vector) != m+1+n+1
        println("The knot vector has the wrong length it should have m+1+n+1 = ", m+1+n+1, " components.")
        println("But it has ", length(knot_vector), " components")
        return
    end
    plot(;size=(700,500), axisratio=:equal, legend=false)
    u_min = knot_vector[1]
    u_max = knot_vector[end]
    step_size = (u_max-u_min)/(steps-1)

    curve = zeros(steps,2)
    N = (i,r,t)->b_spline_basis(i,r,t,knot_vector)
    c = 1
    for t=u_min:step_size:u_max
        pos = zeros(2)
        for i=0:m
            if knot_vector[i+1] != knot_vector[i+1+n]
                pos = pos .+ [dBx[i+1],dBy[i+1]].*N(i,n,t)
            end
        end
        curve[c,:] .= pos
        c += 1
    end
    plot!(curve[:,1],curve[:,2])
    plot!(dBx,dBy, linetype=:scatter, color=:springgreen)
    plot!(dBx,dBy, color=:springgreen)
    for i in 0:length(dBx)-1
        annotate!(dBx[i+1]+0.2,dBy[i+1]+0.35, latexstring("d_"*string(i)))
    end

    png("b_spline")
end

dBx = [0.0,-1,5,7, 9,13]
dBy = [0.0, 3,5,4,-2, 1]
@time b_spline(dBx, dBy, 2, [0,0,0,1,2,3,4,4,4])

max_stars_repo_name: Ellon-M/visualizations

max_issues_repo_name: Ellon-M/visualizations

max_forks_repo_name: Ellon-M/visualizations


text:
"""
    KR13(X_cr::T=0.05, η_max::T=0.0348) where T

Efficiency model by Kang&Ryu 2013: ApJ, 764, 95.

## Values
- `X_cr`: P_cr / P_th defined in model for re-acceleration. Basis for interpolation between acceleration and re-acceleration efficiency.
- `η_max`: Maximum efficiency defined in the model
"""
struct KR13{T} <: AbstractShockAccelerationEfficiency
    X_cr::T
    η_max::T

    KR13(X_cr::T = 0.05, η_max::T = 0.2055) where {T} = new{T}(X_cr, η_max)
end

"""
    η_Ms_acc(η_model::KR13, M::T) where T

Efficiency model from Kang&Ryu 2013, doi:10.1088/0004-637X/764/1/95
"""
function η_Ms_acc(η_model::KR13, M::Real)

    if M < 2
        return 0.0
    elseif 2 <= M <= 5
        return -0.0005950569221922047 + 1.880258286365841e-5 * M^5.334076006529829
    elseif 5 < M <= 15
        return kr_fitting_function(M, -2.8696966498579606, 9.667563166507879,
            -8.877138312318019, 1.938386688261113, 0.1806112438315771)
    else
        return 0.21152
    end
end

"""
    η_Ms_reacc(η_model::KR13, M::T) where T

Efficiency model from Kang&Ryu 2013, doi:10.1088/0004-637X/764/1/95
"""
function η_Ms_reacc(η_model::KR13, M::Real)

    if M < 2
        return 0.0
    elseif M <= 17.7
        return kr_fitting_function(M, -0.722, 2.7307, -3.2854, 1.3428, 0.1901)
    else
        return 0.2055
    end
end


text:
#! format: off
using JuliaFormatter
using CSTParser
using Test

fmt1(s, i, m, always_for_in) = JuliaFormatter.format_text(s, indent = i, margin = m, always_for_in = always_for_in)

# Verifies formatting the formatted text
# results in the same output
function fmt(s; i = 4, m = 80,
             always_for_in = false)
    s1 = fmt1(s, i, m, always_for_in)
    fmt1(s1, i, m, always_for_in)
end
fmt(s, i, m) = fmt(s; i = i, m = m)
fmt1(s, i, m) = fmt1(s; i = i, m = m)

function run_pretty(text::String, print_width::Int)
    d = JuliaFormatter.Document(text)
    s = JuliaFormatter.State(d, 4, print_width)
    x = CSTParser.parse(text, true)
    t = JuliaFormatter.pretty(x, s)
    t
end

function run_nest(text::String, print_width::Int)
    d = JuliaFormatter.Document(text)
    s = JuliaFormatter.State(d, 4, print_width)
    x = CSTParser.parse(text, true)
    t = JuliaFormatter.pretty(x, s)
    JuliaFormatter.nest!(t, s)
    s
end

@testset "All" begin

    @testset "basic" begin
        @test fmt("") == ""
        @test fmt("a") == "a"
        @test fmt("a  #foo") == "a  #foo"
        @test fmt("#foo") == "#foo"

        str = """
        #=
        Hello, world!
        =#"""
        @test fmt(str) == str

        str = """
        #=
        Hello, world!
        =#
        a"""
        @test fmt(str) == str
    end

    @testset "format toggle" begin
        str = "#! format: off\n module Foo a \n end"
        @test fmt(str) == str

        str = "#! format: off\n#! format: on"
        @test fmt(str) == str

        str = """
        # this should be formatted
        a = f(aaa, bbb, ccc)

        #! format: off
        # anything past this point should not be formatted !!!
        a = f(aaa,
            bbb,ccc)

        c = 102000

        d = @foo 10 20
        #! format: onono

        e = "what the foocho"

        # comment"""
        str_ = """
        # this should be formatted
        a = f(aaa,
            bbb,ccc)

        #! format: off
        # anything past this point should not be formatted !!!
        a = f(aaa,
            bbb,ccc)

        c = 102000

        d = @foo 10 20
        #! format: onono

        e = "what the foocho"

        # comment"""
        @test fmt(str_) == str

        str = """
        # this should be formatted
        a = f(aaa, bbb, ccc)

        #! format: off
        # this section is not formatted !!!
        a = f(aaa,
            bbb,ccc)

        c = 102000

        d = @foo 10 20
        # turning formatting back on
        #! format: on
        # back in business !!!

        e = "what the foocho"
        a = f(aaa, bbb, ccc)

        #! format: off
        b = 10*20
        #! format: on
        b = 10 * 20

        # comment"""
        str_ = """
        # this should be formatted
        a = f(aaa, bbb, ccc)

        #! format: off
        # this section is not formatted !!!
        a = f(aaa,
            bbb,ccc)

        c = 102000

        d = @foo 10 20
        # turning formatting back on
        #! format: on
        # back in business !!!

        e = "what the foocho"
        a = f(aaa,
            bbb,      ccc)

        #! format: off
        b = 10*20
        #! format: on
        b = 10*20

        # comment"""
        @test fmt(str_) == str

        str = """
        # this should be formatted
        a = f(aaa, bbb, ccc)

        #! format: off
        # this section is not formatted !!!
        a = f(aaa,
            bbb,ccc)

        c = 102000

        #=
        α
        =#
        x =      1

        d = @foo 10 20"""
        @test fmt(str) == str
    end

    @testset "dot op" begin
        @test fmt("10 .^ a") == "10 .^ a"
        @test fmt("10.0 .^ a") == "10.0 .^ a"
        @test fmt("a.^b") == "a .^ b"
        @test fmt("a.^10.") == "a .^ 10.0"
    end

    @testset "toplevel" begin
        str = """

        hello = "string";

        a = 10;

        c = 50;

        #comment"""
        str_ = """

        hello = "string";

        a = 10
        ;

        c = 50;

        #comment"""
        @test fmt(str_) == str
        t = run_pretty(str, 80)
        @test length(t) == 17
    end

    @testset "for = vs in normalization" begin
        str = """
        for i = 1:n
            println(i)
        end"""
        @test fmt(str) == str

        str = """
        for i in itr
            println(i)
        end"""
        @test fmt(str) == str

        str = """
        for i = 1:n
            println(i)
        end"""
        str_ = """
        for i in 1:n
            println(i)
        end"""
        @test fmt(str) == str

        str = """
        for i in itr
            println(i)
        end"""
        str_ = """
        for i = itr
            println(i)
        end"""
        @test fmt(str_) == str

        str_ = """
        for i = I1, j in I2
            println(i, j)
        end"""
        str = """
        for i in I1, j in I2
            println(i, j)
        end"""
        @test fmt(str_) == str

        str = """
        for i = 1:30, j = 100:-2:1
            println(i, j)
        end"""
        str_ = """
        for i = 1:30, j in 100:-2:1
            println(i, j)
        end"""
        @test fmt(str) == str

        str_ = "[(i,j) for i=I1,j=I2]"
        str = "[(i, j) for i in I1, j in I2]"
        @test fmt(str_) == str

        str_ = "((i,j) for i=I1,j=I2)"
        str = "((i, j) for i in I1, j in I2)"
        @test fmt(str_) == str

        str_ = "[(i,j) for i in 1:2:10,j  in 100:-1:10]"
        str = "[(i, j) for i = 1:2:10, j = 100:-1:10]"
        @test fmt(str_) == str

        str_ = "((i,j) for i in 1:2:10,j  in 100:-1:10)"
        str = "((i, j) for i = 1:2:10, j = 100:-1:10)"
        @test fmt(str_) == str
    end

    @testset "always eq to in" begin
        str_ = """
        for i = 1:n
            println(i)
        end"""
        str = """
        for i in 1:n
            println(i)
        end"""
        @test fmt(str_, always_for_in = true) == str
        @test fmt(str, always_for_in = true) == str

        str_ = """
        for i = I1, j in I2
            println(i, j)
        end"""
        str = """
        for i in I1, j in I2
            println(i, j)
        end"""
        @test fmt(str_, always_for_in = true) == str
        @test fmt(str, always_for_in = true) == str

        str_ = """
        for i = 1:30, j = 100:-2:1
            println(i, j)
        end"""
        str = """
        for i in 1:30, j in 100:-2:1
            println(i, j)
        end"""
        @test fmt(str_, always_for_in = true) == str
        @test fmt(str, always_for_in = true) == str

        str_ = "[(i,j) for i=I1,j=I2]"
        str = "[(i, j) for i in I1, j in I2]"
        @test fmt(str_, always_for_in = true) == str
        @test fmt(str, always_for_in = true) == str

        str_ = "((i,j) for i=I1,j=I2)"
        str = "((i, j) for i in I1, j in I2)"
        @test fmt(str_, always_for_in = true) == str
        @test fmt(str, always_for_in = true) == str

        str_ = "[(i, j) for i = 1:2:10, j = 100:-1:10]"
        str = "[(i, j) for i in 1:2:10, j in 100:-1:10]"
        @test fmt(str_, always_for_in = true) == str
        @test fmt(str, always_for_in = true) == str
    end

    @testset "tuples" begin
        @test fmt("a,b") == "a, b"
        @test fmt("a ,b") == "a, b"
        @test fmt("(a,b)") == "(a, b)"
        @test fmt("(a ,b)") == "(a, b)"
        @test fmt("( a, b)") == "(a, b)"
        @test fmt("(a, b )") == "(a, b)"
        @test fmt("(a, b ,)") == "(a, b)"
        @test fmt("""(a,    b ,
                            c)""") == "(a, b, c)"
    end

    @testset "curly" begin
        @test fmt("X{a,b}") == "X{a,b}"
        @test fmt("X{ a,b}") == "X{a,b}"
        @test fmt("X{a ,b}") == "X{a,b}"
        @test fmt("X{a, b}") == "X{a,b}"
        @test fmt("X{a,b }") == "X{a,b}"
        @test fmt("X{a,b }") == "X{a,b}"

        str = """
        mutable struct Foo{A<:Bar,Union{B<:Fizz,C<:Buzz},<:Any}
            a::A
        end"""
        @test fmt(str) == str
        t = run_pretty(str, 80)
        @test length(t) == 55

        str = """
        struct Foo{A<:Bar,Union{B<:Fizz,C<:Buzz},<:Any}
            a::A
        end"""
        @test fmt(str) == str
        t = run_pretty(str, 80)
        @test length(t) == 47
    end

    @testset "where op" begin
        str = "Atomic{T}(value) where {T<:AtomicTypes} = new(value)"
        str_ = "Atomic{T}(value) where T <: AtomicTypes = new(value)"
        @test fmt(str) == str
        @test fmt(str_) == str

        str = "Vector{Vector{T} where T}"
        @test fmt(str) == str

        str_ = "Vector{Vector{T}} where T"
        str = "Vector{Vector{T}} where {T}"
        @test fmt(str_) == str
        @test fmt(str) == str
    end

    @testset "unary ops" begin
        @test fmt("! x") == "!x"
        @test fmt("x ...") == "x..."
    end

    @testset "binary ops" begin
        @test fmt("a+b*c") == "a + b * c"
        @test fmt("a +b*c") == "a + b * c"
        @test fmt("a+ b*c") == "a + b * c"
        @test fmt("a+b *c") == "a + b * c"
        @test fmt("a+b* c") == "a + b * c"
        @test fmt("a+b*c ") == "a + b * c"
        @test fmt("a:b") == "a:b"
        @test fmt("a : b") == "a:b"
        @test fmt("a: b") == "a:b"
        @test fmt("a :b") == "a:b"
        @test fmt("a +1 :b -1") == "a+1:b-1"
        @test fmt("a:b:c") == "a:b:c"
        @test fmt("a :b:c") == "a:b:c"
        @test fmt("a: b:c") == "a:b:c"
        @test fmt("a:b :c") == "a:b:c"
        @test fmt("a:b: c") == "a:b:c"
        @test fmt("a:b:c ") == "a:b:c"
        @test fmt("a::b:: c") == "a::b::c"
        @test fmt("a :: b::c") == "a::b::c"
        # issue #74
        @test fmt("0:1/3:2") == "0:1/3:2"
        @test fmt("2a") == "2a"
        @test fmt("2(a+1)") == "2 * (a + 1)"

        str_ = "a[1:2 * num_source * num_dump-1]"
        str = "a[1:2*num_source*num_dump-1]"
        @test fmt(str_, 4, 1) == str

        str_ = "a[2 * num_source * num_dump-1:1]"
        str = "a[2*num_source*num_dump-1:1]"
        @test fmt(str_, 4, 1) == str

        str = "!(typ <: ArithmeticTypes)"
        @test fmt(str) == str

        # Function def

        str_ = """foo() = if cond a else b end"""
        str = """
        foo() =
            if cond
                a
            else
                b
            end"""
        @test fmt(str_) == str

        str_ = """
        foo() = begin
            body
        end"""
        str = """
        foo() =
            begin
                body
            end"""
        @test fmt(str_) == str_
        @test fmt(str_, 4, 1) == str

        str_ = """
        foo() = quote
            body
        end"""
        str = """
        foo() =
            quote
                body
            end"""
        @test fmt(str_) == str_
        @test fmt(str_, 4, 1) == str

        str = """foo() = :(Union{})"""
        @test fmt(str) == str

        str_ = """foo() = for i=1:10 body end"""
        str = """
        foo() =
            for i = 1:10
                body
            end"""
        @test fmt(str_) == str

        str_ = """foo() = while cond body end"""
        str = """
        foo() =
            while cond
                body
            end"""
        @test fmt(str_) == str

        str_ = """foo() = try body1 catch e body2 finally body3 end"""
        str = """
        foo() =
            try
                body1
            catch e
                body2
            finally
                body3
            end"""
        @test fmt(str_) == str

        str_ = """foo() = let var1=value1,var2,var3=value3 body end"""
        str = """
        foo() =
            let var1 = value1, var2, var3 = value3
                body
            end"""
        @test fmt(str_) == str

        # Assignment op

        str_ = """foo = if cond a else b end"""
        str = """
        foo =
          if cond
            a
          else
            b
          end"""
        @test fmt(str_, 2, 1) == str

        str_ = """foo = begin body end"""
        str = """
        foo = begin
          body
        end"""
        @test fmt(str_, 2, 1) == str

        str_ = """foo = quote body end"""
        str = """
        foo = quote
          body
        end"""
        @test fmt(str_, 2, 1) == str

        str_ = """foo = for i=1:10 body end"""
        str = """
        foo =
          for i = 1:10
            body
          end"""
        @test fmt(str_, 2, 1) == str

        str_ = """foo = while cond body end"""
        str = """
        foo =
          while cond
            body
          end"""
        @test fmt(str_, 2, 1) == str

        str_ = """foo = try body1 catch e body2 finally body3 end"""
        str = """
        foo =
          try
            body1
          catch e
            body2
          finally
            body3
          end"""
        @test fmt(str_, 2, 1) == str

        str_ = """foo = let var1=value1,var2,var3=value3 body end"""
        str = """
        foo =
          let var1 = value1, var2, var3 = value3
            body
          end"""
        @test fmt(str_, 2, 1) == str

        str = """
        foo = let
          body
        end"""
        @test fmt(str, 2, 1) == str

        str_ = """a, b = cond ? e1 : e2"""
        str = """
        a, b = cond ?
               e1 :
               e2"""
        @test fmt(str_, 4, 13) == str

        str = """
        a,
        b = cond ?
            e1 : e2"""
        @test fmt(str_, 4, 12) == str
    end

    @testset "op chain" begin
        @test fmt("a+b+c+d") == "a + b + c + d"
    end

    @testset "comparison chain" begin
        @test fmt("a<b==c≥d") == "a < b == c ≥ d"
    end

    @testset "single line block" begin
        @test fmt("(a;b;c)") == "(a; b; c)"
    end

    @testset "func call" begin
        @test fmt("func(a, b, c)") == "func(a, b, c)"
        @test fmt("func(a,b,c)") == "func(a, b, c)"
        @test fmt("func(a,b,c,)") == "func(a, b, c)"
        @test fmt("func(a,b,c, )") == "func(a, b, c)"
        @test fmt("func( a,b,c    )") == "func(a, b, c)"
        @test fmt("func(a, b, c) ") == "func(a, b, c)"
        @test fmt("func(a, b; c)") == "func(a, b; c)"
        @test fmt("func(  a, b; c)") == "func(a, b; c)"
        @test fmt("func(a  ,b; c)") == "func(a, b; c)"
        @test fmt("func(a=1,b; c=1)") == "func(a = 1, b; c = 1)"
        @test fmt("func(; c = 1)", 4, 1) == "func(; c = 1)"
        @test fmt("func(; c = 1,)") == "func(; c = 1)"
    end

    @testset "begin" begin
        str = """
        begin
            arg
        end"""
        @test fmt("""
                    begin
                    arg
                    end""") == str
        @test fmt("""
                    begin
                        arg
                    end""") == str
        @test fmt("""
                    begin
                        arg
                    end""") == str
        @test fmt("""
                    begin
                            arg
                    end""") == str
        str = """
        begin
            begin
                arg
            end
        end"""
        @test fmt("""
                    begin
                    begin
                    arg
                    end
                    end""") == str
        @test fmt("""
                    begin
                                begin
                    arg
                    end
                    end""") == str
        @test fmt("""
                    begin
                                begin
                    arg
                            end
                    end""") == str

        str = """
        begin
            s = foo(aaa, bbbb, cccc)
            s = foo(
                aaaa,
                bbbb,
                cccc,
            )
        end"""
        @test fmt(str, 4, 28) == str

    end

    @testset "quote" begin
        str = """
        quote
            arg
        end"""
        @test fmt("""
        quote
            arg
        end""") == str
        @test fmt("""
        quote
        arg
        end""") == str
        @test fmt("""
        quote
                arg
            end""") == str

        str = """:(a = 10; b = 20; c = a * b)"""
        @test fmt(":(a = 10; b = 20; c = a * b)") == str

        str = """
        :(endidx = ndigits;
        while endidx > 1 && digits[endidx] == UInt8('0')
            endidx -= 1
        end;
        if endidx > 1
            print(out, '.')
            unsafe_write(out, pointer(digits) + 1, endidx - 1)
        end)"""

        str_ = """
    :(endidx = ndigits;
                while endidx > 1 && digits[endidx] == UInt8('0')
                    endidx -= 1
                end;
                if endidx > 1
                    print(out, '.')
                    unsafe_write(out, pointer(digits) + 1, endidx - 1)
                end)"""
        @test fmt(str_) == str
        @test fmt(str) == str

        str = """
        quote
            s = foo(aaa, bbbb, cccc)
            s = foo(
                aaaa,
                bbbb,
                cccc,
            )
        end"""
        @test fmt(str, 4, 28) == str

    end

    @testset "do" begin
        str = """
        map(args) do x
            y = 20
            return x * y
        end"""

        @test fmt("""
        map(args) do x
          y = 20
                            return x * y
            end""") == str

        str = """
        map(1:10, 11:20) do x, y
            x + y
        end"""
        t = run_pretty(str, 80)
        @test length(t) == 24

        str = """
        map(1:10, 11:20) do x, y
            x + y + foo + bar + ba
            x + y + foo + bar +
            baz
        end"""
        t = run_pretty(str, 80)
        @test length(t) == 27
        @test fmt(str, 4, 26) == str

        # issue #58

        str_ = """
        model = SDDP.LinearPolicyGraph(stages = 2, lower_bound = 1, direct_mode = false) do (subproblem1, subproblem2, subproblem3, subproblem4, subproblem5, subproblem6, subproblem7, subproblem8)
            body
        end"""
        str = """
        model = SDDP.LinearPolicyGraph(
            stages = 2,
            lower_bound = 1,
            direct_mode = false,
        ) do (
            subproblem1,
            subproblem2,
            subproblem3,
            subproblem4,
            subproblem5,
            subproblem6,
            subproblem7,
            subproblem8,
        )
            body
        end"""
        @test fmt(str_) == str

        str_ = """
        model = SDDP.LinearPolicyGraph(stages = 2, lower_bound = 1, direct_mode = false) do subproblem1, subproblem2
            body
        end"""
        str = """
        model = SDDP.LinearPolicyGraph(
            stages = 2,
            lower_bound = 1,
            direct_mode = false,
        ) do subproblem1, subproblem2
            body
        end"""
        @test fmt(str_) == str

    end

    @testset "for" begin
        str = """
        for iter in I
            arg
        end"""
        @test fmt("""
        for iter in I
            arg
        end""") == str
        @test fmt("""
        for iter in I
        arg
        end""") == str
        @test fmt("""
        for iter in I
          arg
        end""") == str

        str = """
        for iter in I, iter2 in I2
            arg
        end"""
        @test fmt("""
        for iter = I, iter2= I2
            arg
        end""") == str
        @test fmt("""
        for iter= I, iter2=I2
        arg
        end""") == str
        @test fmt("""
        for iter    = I, iter2 = I2
                arg
            end""") == str

        str = """
        for i = 1:10
            body
        end"""
        t = run_pretty(str, 80)
        @test length(t) == 12

        str = """
        for i in 1:10
            bodybodybodybody
        end"""
        t = run_pretty(str, 80)
        @test length(t) == 20

    end

    @testset "while" begin
        str = """
        while cond
            arg
        end"""
        @test fmt("""
        while cond
            arg
        end""") == str
        @test fmt("""
        while cond
        arg
        end""") == str
        @test fmt("""
        while cond
                arg
            end""") == str

        # This will be a FileH header
        # with no blocks
        str = """
        a = 1
        while a < 100
            a += 1
        end"""
        t = run_pretty(str, 80)
        @test length(t) == 13

        str = """
        a = 1
        while a < 100
            a += 1
            thisisalongnameforabody
        end"""
        t = run_pretty(str, 80)
        @test length(t) == 27
    end

    @testset "let" begin
        str = """
        let x = X
            arg
        end"""
        @test fmt("""
        let x=X
            arg
        end""") == str
        @test fmt("""
        let x=X
        arg
        end""") == str
        @test fmt("""
        let x=X
            arg
        end""") == str

        str = """
        let x = X, y = Y
            arg
        end"""
        @test fmt("""
        let x = X, y = Y
            arg
        end""") == str
        @test fmt("""
        let x = X, y = Y
        arg
        end""") == str

        str = """
        y, back = let
            body
        end"""
        @test fmt("""
        y,back = let
          body
        end""") == str

        # TODO: This should probably be aligned to match up with `a` ?
        str = """
        let x = a,
            # comment
        b,
        c
            body
        end"""
        @test fmt("""
        let x = a,
            # comment
               b,
              c
           body
           end""") == str

        str = """
        let x = X, y = Y
            body
        end"""
        t = run_pretty(str, 80)
        @test length(t) == 16

        str = """
        let x = X, y = Y
        letthebodieshitthefloor
        end"""
        t = run_pretty(str, 80)
        @test length(t) == 27
    end

    @testset "structs" begin
        str = """
        struct name
            arg
        end"""
        @test fmt("""
        struct name
            arg
        end""") == str
        @test fmt("""
        struct name
        arg
        end""") == str
        @test fmt("""
        struct name
                arg
            end""") == str

        str = """
        mutable struct name
            arg
        end"""
        @test fmt("""
        mutable struct name
            arg
        end""") == str
        @test fmt("""
        mutable struct name
        arg
        end""") == str
        @test fmt("""
        mutable struct name
                arg
            end""") == str
    end

    @testset "try" begin
        str = """
        try
            arg
        catch
            arg
        end"""
        @test fmt("""
        try
            arg
        catch
            arg
        end""") == str

        @test fmt("""
        try
        arg
        catch
        arg
        end""") == str

        @test fmt("""
        try
                arg
            catch
                arg
            end""") == str

        str = """
        try
            arg
        catch
            arg
        end"""
        @test fmt("""
        try
            arg
        catch
            arg
        end""") == str

        @test fmt("""
        try
        arg
        catch
        arg
        end""") == str

        @test fmt("""
        try
                arg
            catch
                arg
            end""") == str

        str = """
        try
            arg
        catch err
            arg
        end"""

        @test fmt("""
        try
            arg
        catch err
            arg
        end""") == str

        @test fmt("""
        try
        arg
        catch err
        arg
        end""") == str

        @test fmt("""
        try
                arg
            catch err
                arg
            end""") == str

        str = """
        try
            a111111
            a2
        catch error123
            b1
            b2
        finally
            c1
            c2
        end"""
        t = run_pretty(str, 80)
        @test length(t) == 14

        str = """
        try
            a111111
            a2
        catch erro
            b1
            b2
        finally
            c1
            c2
        end"""
        t = run_pretty(str, 80)
        @test length(t) == 11

    end

    @testset "if" begin
        str = """
        if cond1
            e1
            e2
        elseif cond2
            e3
            e4
        elseif cond33
            e5
            e6
        else
            e7
            e88888
        end"""
        t = run_pretty(str, 80)
        @test length(t) == 13

        str = """
        if cond1
            e1
            e2
        elseif cond2
            e3
            e4
        elseif cond33
            e5
            e6
        else
            e7
            e888888888
        end"""
        t = run_pretty(str, 80)
        @test length(t) == 14

    end

    @testset "docs" begin
        str = """
        \"""
        doc
        \"""
        function f()
            20
        end"""
        t = run_pretty(str, 80)
        @test length(t) == 12

        str = """
        \"""doc
        \"""
        function f()
            20
        end"""
        @test fmt(str) == str

        str = """
        \"""
        doc\"""
        function f()
            20
        end"""
        @test fmt(str) == str

        str = """
        \"""doc\"""
        function f()
            20
        end"""
        @test fmt(str) == str

        str = """
        "doc
        "
        function f()
            20
        end"""
        @test fmt(str) == str

        str = """
        "
        doc"
        function f()
            20
        end"""
        @test fmt(str) == str

        str = """
        "doc"
        function f()
            20
        end"""
        @test fmt(str) == str

        # test aligning to function identation
        str_ = """
            "doc"
        function f()
            20
        end"""
        str = """
        "doc"
        function f()
            20
        end"""
        @test fmt(str_) == str

        str = """\"""
                 doc for Foo
                 \"""
                 Foo"""
        @test fmt(str) == str
        t = run_pretty(str, 80)
        @test length(t) == 11

        str = """
        \"""
        doc
        \"""
        function f()    #  comment
            20
        end"""
        @test fmt(str) == str
    end

    @testset "strings" begin
        str = """
        \"""
        Interpolate using `\\\$`
        \"""
        a"""
        @test fmt(str) == str

        str = """error("foo\\n\\nbar")"""
        @test fmt(str) == str

        str = """
        \"""
        \\\\
        \"""
        x"""
        @test fmt(str) == str

        str = """
        begin
            s = \"\"\"This is a multiline string.
                    This is another line.
                          Look another 1 that is indented a bit.

                          cool!\"\"\"
        end"""
        str_ = """
        begin
        s = \"\"\"This is a multiline string.
                This is another line.
                      Look another 1 that is indented a bit.

                      cool!\"\"\"
        end"""
        @test fmt(str_) == str

        str = """
        begin
            begin
                throw(ErrorException(\"""An error occured formatting \$filename. :-(

                                     Please file an issue at https://github.com/domluna/JuliaFormatter.jl/issues
                                     with a link to a gist containing the contents of the file. A gist
                                     can be created at https://gist.github.com/.\"""))
            end
        end"""
        str_ = """
        begin
        begin
           throw(ErrorException(\"""An error occured formatting \$filename. :-(

                                Please file an issue at https://github.com/domluna/JuliaFormatter.jl/issues
                                with a link to a gist containing the contents of the file. A gist
                                can be created at https://gist.github.com/.\"""))
           end
        end"""
        @test fmt(str_) == str

        str = """
        foo() = llvmcall(\"""
                         llvm1
                         llvm2
                         \""")"""
        @test fmt(str) == str

        str_ = """
        foo() =
          llvmcall(\"""
                   llvm1
                   llvm2
                   \""")"""
        @test fmt(str, 2, 10) == str_

        str = """
        str = \"""
        begin
            arg
        end\"""
        """
        @test fmt(str) == str

        str = """
        str = \"""
              begin
                  arg
              end\"""
        """
        @test fmt(str) == str
    end

    @testset "comments" begin
        str = """
        module Foo
        # comment 0
        # comment 1
        begin

            # comment 2
            # comment 3

            begin

                # comment 4
                # comment 5
                a = 10
            end

        end

        end"""
        @test fmt(str) == str
        t = run_pretty(str, 80)
        @test length(t) == 14

        str_ = """
        module Foo
        # comment 0
        # comment 1
        begin

        # comment 2
        # comment 3

        begin

        # comment 4
        # comment 5
        a = 10
        end

        end

        end"""
        str = """
        module Foo
        # comment 0
        # comment 1
        begin

        # comment 2
        # comment 3

            begin

        # comment 4
        # comment 5
                a = 10
            end

        end

        end"""

        @test fmt(str_) == str

        str = "# comment 0\n\n\n\n\na = 1\n\n# comment 1\n\n\n\n\nb = 2\n\n\nc = 3\n\n# comment 2\n\n"
        @test fmt(str) == str

        str = """
        #=
        hello
        world
        =#
        const a = \"hi there\""""
        @test fmt(str) == str

        str = """
        if a
            # comment above var
            var = 10
            # comment below var
        else
            something_else()
        end"""
        @test fmt(str) == str

        str = """
        begin
            a = 10 # foo
            b = 20           # foo
        end    # trailing comment"""
        str_ = """
        begin
        a = 10 # foo
        b = 20           # foo
        end    # trailing comment"""
        @test fmt(str_) == str

        str = """
        function bar(x, y)
            # single comment ending in a subscriptₙ
            x - y
        end"""
        @test fmt("""
        function bar(x, y)
            # single comment ending in a subscriptₙ
            x- y
        end""") == str

        str_ = """
        var = foo(      # eat
            a, b, # comment 1
            c, # comment 2
            # in between comment
            d # comment 3
        )        # pancakes"""
        str = """
        var = foo(      # eat
            a,
            b, # comment 1
            c, # comment 2
            # in between comment
            d, # comment 3
        )        # pancakes"""
        @test fmt(str_) == str

        str_ = """
        var = foo(      # eat
            a, b, # comment 1
            c, # comment 2
            d # comment 3
        )        # pancakes"""
        str = """
        var = foo(      # eat
            a,
            b, # comment 1
            c, # comment 2
            d, # comment 3
        )        # pancakes"""
        @test fmt(str_) == str

        str = """
        A ? # foo
        # comment 1

        B :    # bar
        # comment 2
        C"""
        @test fmt(str) == str

        str = """
        A ? B :
         # comment

        C"""
        @test fmt(str) == str

        str = """
        A ? # foo
        # comment 1

        B : C"""
        @test fmt(str) == str

        str = """
        begin
            var = a +
                # comment
                  b
        end
        """
        @test fmt(str) == str

        str = """
        begin
            var = a +  # inline
            # comment

                  b
        end
        """
        @test fmt(str) == str

        str = """
        begin
            var = a +  # inline
                  b
        end
        """
        @test fmt(str) == str

        str_ = """
        foo() = 10 where {
            # comment
            A,
                # comment
            B
            # comment
        }"""
        str = """
        foo() = 10 where {
            # comment
            A,
                # comment
            B,
            # comment
        }"""
        @test fmt(str_) == str

        str_ = """
        foo() = 10 where Foo{
            # comment
            A,
                # comment
            B
            # comment
        }"""
        str = """
        foo() = 10 where Foo{
            # comment
            A,
                # comment
            B,
            # comment
        }"""
        @test fmt(str_) == str

        str_ = """
        foo() = Foo(
            # comment
            A,
                # comment
            B
            # comment
        )"""
        str = """
        foo() = Foo(
            # comment
            A,
                # comment
            B,
            # comment
        )"""
        @test fmt(str_) == str

        str = """
        foo(
            # comment
            ;
            # comment
            a = b, # comment
            c = d,
            # comment
        )"""
        @test fmt(str) == str

        str = """
        foo(
            ;
            a = b, # comment
            c = d,
            # comment
        )"""
        @test fmt(str) == str

        str_ = """
        foo(
            ;
            ;a = b, # comment
            c = d,
            # comment
        )"""
        @test fmt(str_) == str

        str_ = """
        foo( ;
            ;a = b, # comment
            c = d,
            # comment
        )"""
        @test fmt(str_) == str

        # str = """
        # [
        #  a b Expr();
        #  d e Expr()
        # ]"""
        # str_ = """
        # [
        # ;
        # ;
        # ;
        #  a b Expr();
        #  ;
        #  d e Expr();
        #  ;
        # ]"""
        # @test fmt(str_) == str
        #

        # Issue #51
        # NOTE: `str_` has extra whitespace after
        # keywords on purpose
        str_ = "begin \n # comment\n end"
        str = """
        begin
         # comment
        end"""
        @test fmt(str_) == str

        str_ = "try \n # comment\n catch \n # comment\n finally \n # comment\n end"
        str = """
        try
         # comment
        catch
         # comment
        finally
         # comment
        end"""
        @test fmt(str_) == str

        str = """a = "hello ##" # # # α"""
        @test fmt(str) == str

        # issue #65
        str = "1 # α"
        @test fmt(str) == str

        str = "# α"
        @test fmt(str) == str

        str = """
        #=
        α
        =#
        x = 1
        """
        @test fmt(str) == str

    end

    @testset "pretty" begin
        str = """function foo end"""
        @test fmt("""
            function  foo
            end""") == str
        t = run_pretty(str, 80)
        @test length(t) == 16

        str = """function foo() end"""
        @test fmt("""
                     function  foo()
            end""") == str
        t = run_pretty(str, 80)
        @test length(t) == 18

        str = """function foo()
                     10
                     20
                 end"""
        @test fmt("""function foo() 10;  20 end""") == str
        t = run_pretty(str, 80)
        @test length(t) == 14

        str = """abstract type AbstractFoo end"""
        @test fmt("""abstract type
                     AbstractFoo
                end""") == str

        str = """for i = 1:10
                     1
                     2
                     3
                 end"""
        @test fmt("""for i=1:10 1; 2; 3 end""") == str

        str = """while true
                     1
                     2
                     3
                 end"""
        @test fmt("""while true 1; 2; 3 end""") == str

        str = """try
                     a
                 catch e
                     b
                 end"""
        @test fmt("""try a catch e b end""") == str

        str = """try
                     a1
                     a2
                 catch e
                     b1
                     b2
                 finally
                     c1
                     c2
                 end"""
        @test fmt("""try a1;a2 catch e b1;b2 finally c1;c2 end""") == str

        str = """map(a) do b, c
                     e
                 end"""
        @test fmt("""map(a) do b,c
                     e end""") == str

        str = """let a = b, c = d
                     e1
                     e2
                     e3
                 end"""
        @test fmt("""let a=b,c=d\ne1; e2; e3 end""") == str

        str = """let a, b
                     e
                 end"""
        @test fmt("""let a,b
                     e end""") == str

        str = """return a, b, c"""
        @test fmt("""return a,b,
                     c""") == str

        str = """begin
                     a
                     b
                     c
                 end"""
        @test fmt("""begin a; b; c end""") == str

        str = """begin end"""
        @test fmt("""begin \n            end""") == str

        str = """quote
                     a
                     b
                     c
                 end"""
        @test fmt("""quote a; b; c end""") == str

        str = """quote end"""
        @test fmt("""quote \n end""") == str

        str = """if cond1
                     e1
                     e2
                 end"""
        @test fmt("if cond1 e1;e2 end") == str

        str = """if cond1
                     e1
                     e2
                 else
                     e3
                     e4
                 end"""
        @test fmt("if cond1 e1;e2 else e3;e4 end") == str

        str = """begin
                     if cond1
                         e1
                         e2
                     elseif cond2
                         e3
                         e4
                     elseif cond3
                         e5
                         e6
                     else
                         e7
                         e8
                     end
                 end"""
        @test fmt("begin if cond1 e1; e2 elseif cond2 e3; e4 elseif cond3 e5;e6 else e7;e8  end end") == str

        str = """if cond1
                     e1
                     e2
                 elseif cond2
                     e3
                     e4
                 end"""
        @test fmt("if cond1 e1;e2 elseif cond2 e3; e4 end") == str

        str = """
        [a b c]"""
        @test fmt("[a   b         c   ]") == str

        str = """
        [a; b; c]"""
        @test fmt("[a;   b;         c;   ]") == str

        str = """
        T[a b c]"""
        @test fmt("T[a   b         c   ]") == str

        str = """
        T[a; b; c]"""
        @test fmt("T[a;   b;         c;   ]") == str

        str = """
        T[a; b; c; e d f]"""
        @test fmt("T[a;   b;         c;   e  d    f   ]") == str

        str = """
        T[a; b; c; e d f]"""
        @test fmt("T[a;   b;         c;   e  d    f    ;   ]") == str

        str = "T[a;]"
        @test fmt(str) == str

        str = "[a;]"
        @test fmt(str) == str

        str = """T[e for e in x]"""
        @test fmt("T[e  for e= x  ]") == str

        str = """T[e for e = 1:2:50]"""
        @test fmt("T[e  for e= 1:2:50  ]") == str

        str = """struct Foo end"""
        @test fmt("struct Foo\n      end") == str

        str = """
        struct Foo
            body
        end"""
        @test fmt("struct Foo\n    body  end") == str

        str = """macro foo() end"""
        @test fmt("macro foo()\n      end") == str

        str = """macro foo end"""
        @test fmt("macro foo\n      end") == str

        str = """
        macro foo()
            body
        end"""
        @test fmt("macro foo()\n    body  end") == str

        str = """mutable struct Foo end"""
        @test fmt("mutable struct Foo\n      end") == str

        str = """
        mutable struct Foo
            body
        end"""
        @test fmt("mutable struct Foo\n    body  end") == str

        str = """
        module A
        bodybody
        end"""
        @test fmt("module A\n    bodybody  end") == str
        t = run_pretty(str, 80)
        @test length(t) == 8

        str = """
        module Foo end"""
        @test fmt("module Foo\n    end") == str
        t = run_pretty(str, 80)
        @test length(t) == 14

        str = """
        baremodule A
        bodybody
        end"""
        @test fmt("baremodule A\n    bodybody  end") == str
        t = run_pretty(str, 80)
        @test length(t) == 12

        str = """
        baremodule Foo end"""
        @test fmt("baremodule Foo\n    end") == str
        t = run_pretty(str, 80)
        @test length(t) == 18

        str = """
        if cond1
        elseif cond2
        elseif cond3
        elseif cond4
        elseif cond5
        elseif cond6
        elseif cond7
        else
        end"""
        @test fmt(str) == str

        str = """
        try
        catch
        finally
        end"""
        @test fmt(str) == str

        str = """
        (args...; kwargs) -> begin
            body
        end"""
        @test fmt(str) == str

        @test fmt("ref[a: (b + c)]") == "ref[a:(b+c)]"
        @test fmt("ref[a in b]") == "ref[a in b]"
    end

    @testset "nesting" begin
        str = """
        function f(
            arg1::A,
            key1 = val1;
            key2 = val2,
        ) where {
            A,
            F{
              B,
              C,
            },
        }
            10
            20
        end"""
        str_ = "function f(arg1::A,key1=val1;key2=val2) where {A,F{B,C}} 10; 20 end"
        @test fmt(str_, 4, 1) == str

        str = """
        function f(
            arg1::A,
            key1 = val1;
            key2 = val2,
        ) where {
            A,
            F{B,C},
        }
            10
            20
        end"""
        @test fmt(str_, 4, 17) == str

        str = """
        function f(
            arg1::A,
            key1 = val1;
            key2 = val2,
        ) where {A,F{B,C}}
            10
            20
        end"""
        @test fmt(str_, 4, 18) == str

        str = """
        a |
        b |
        c |
        d"""
        @test fmt("a | b | c | d", 4, 1) == str

        str = """
        a, b, c, d"""
        @test fmt("a, b, c, d", 4, 10) == str

        str = """a,\nb,\nc,\nd"""
        @test fmt("a, b, c, d", 4, 9) == str

        str = """(a, b, c, d)"""
        @test fmt("(a, b, c, d)", 4, 12) == str

        str = """
        (
         a,
         b,
         c,
         d,
        )"""
        @test fmt("(a, b, c, d)", 4, 11) == str

        str = """{a, b, c, d}"""
        @test fmt("{a, b, c, d}", 4, 12) == str

        str = """
        {
         a,
         b,
         c,
         d,
        }"""
        @test fmt("{a, b, c, d}", 4, 11) == str

        str = """[a, b, c, d]"""
        @test fmt("[a, b, c, d]", 4, 12) == str

        str = """
        [
         a,
         b,
         c,
         d,
        ]"""
        @test fmt("[a, b, c, d]", 4, 11) == str

        str = """
        cond ?
        e1 :
        e2"""
        @test fmt("cond ? e1 : e2", 4, 1) == str

        str = """
        cond ? e1 :
        e2"""
        @test fmt("cond ? e1 : e2", 4, 12) == str

        str = """
        cond1 ? e1 :
        cond2 ? e2 :
        cond3 ? e3 :
        e4"""
        @test fmt("cond1 ? e1 : cond2 ? e2 : cond3 ? e3 : e4", 4, 13) == str

        # I'm an importer/exporter
        str = """
        export a,
               b"""
        @test fmt("export a,b", 4, 1) == str

        str = """
        using a,
              b"""
        @test fmt("using a,b", 4, 1) == str

        str = """
        using M: a,
                 b"""
        @test fmt("using M:a,b", 4, 1) == str

        str = """
        import M1.M2.M3: a,
                         b"""
        @test fmt("import M1.M2.M3:a,b", 4, 1) == str

        str = """
        foo() =
            (one, x -> (true, false))"""
        @test fmt("foo() = (one, x -> (true, false))", 4, 30) == str

        str = """
        foo() = (
            one,
            x -> (
                true,
                false,
            ),
        )"""
        @test fmt("foo() = (one, x -> (true, false))", 4, 20) == str

        str = """
        foo() = (
                 one,
                 x -> (
                       true,
                       false,
                 ),
        )"""
        @test fmt("foo() = (one, x -> (true, false))", 10, 20) == str

        str = """
        @somemacro function (fcall_ | fcall_)
            body_
        end"""
        @test fmt("@somemacro function (fcall_ | fcall_) body_ end", 4, 37) == str

        str = """
        @somemacro function (fcall_ |
                             fcall_)
            body_
        end"""
        @test fmt("@somemacro function (fcall_ | fcall_) body_ end", 4, 36) == str

        str = "Val(x) = (@_pure_meta; Val{x}())"
        @test fmt("Val(x) = (@_pure_meta ; Val{x}())", 4, 80) == str

        str = "(a; b; c)"
        @test fmt("(a;b;c)", 4, 100) == str
        @test fmt("(a;b;c)", 4, 1) == str

        str = "(x for x = 1:10)"
        @test fmt("(x   for x  in  1 : 10)", 4, 100) == str
        @test fmt("(x   for x  in  1 : 10)", 4, 1) == str

        # indent for TupleH with no parens
        str = """
        function foo()
            arg1,
            arg2
        end"""
        @test fmt("function foo() arg1, arg2 end", 4, 1) == str

        str = """
        function foo()
            # comment
            arg
        end"""
        @test fmt(str, 4, 1) == str

        # don't nest < 2 args

        str = "A where {B}"
        @test fmt(str, 4, 1) == str

        str = "foo(arg1)"
        @test fmt(str, 4, 1) == str

        str = "[arg1]"
        @test fmt(str, 4, 1) == str

        str = "{arg1}"
        @test fmt(str, 4, 1) == str

        str = "(arg1)"
        @test fmt(str, 4, 1) == str

        str_ = """
        begin
        if foo
        elseif baz
        elseif (a || b) && c
        elseif bar
        else
        end
        end"""

        str = """
        begin
            if foo
            elseif baz
            elseif (a ||
                    b) && c
            elseif bar
            else
            end
        end"""
        @test fmt(str_, 4, 21) == str
        @test fmt(str_, 4, 19) == str

        str = """
        begin
            if foo
            elseif baz
            elseif (a ||
                    b) &&
                   c
            elseif bar
            else
            end
        end"""
        @test fmt(str_, 4, 18) == str

        str = """
        begin
            if foo
            elseif baz
            elseif (a || b) &&
                   c
            elseif bar
            else
            end
        end"""
        @test fmt(str_, 4, 23) == str
        @test fmt(str_, 4, 22) == str

        str = """
        begin
            if foo
            elseif baz
            elseif (a || b) && c
            elseif bar
            else
            end
        end"""
        @test fmt(str_, 4, 24) == str

        # https://github.com/domluna/JuliaFormatter.jl/issues/9#issuecomment-481607068
        str = """
        this_is_a_long_variable_name = Dict{Symbol,Any}(
            :numberofpointattributes => NAttributes,
            :numberofpointmtrs => NMTr,
            :numberofcorners => NSimplex,
            :firstnumber => Cint(1),
            :mesh_dim => Cint(3),
        )"""

        str_ = """this_is_a_long_variable_name = Dict{Symbol,Any}(:numberofpointattributes => NAttributes,
               :numberofpointmtrs => NMTr, :numberofcorners => NSimplex, :firstnumber => Cint(1),
               :mesh_dim => Cint(3),)"""
        @test fmt(str_, 4, 80) == str

        str = """this_is_a_long_variable_name = Dict{
             Symbol,
             Any,
        }(
             :numberofpointattributes => NAttributes,
             :numberofpointmtrs => NMTr,
             :numberofcorners => NSimplex,
             :firstnumber => Cint(1),
             :mesh_dim => Cint(3),
        )"""
        @test fmt(str_, 5, 1) == str

        str = """
        this_is_a_long_variable_name = (
            :numberofpointattributes => NAttributes,
            :numberofpointmtrs => NMTr,
            :numberofcorners => NSimplex,
            :firstnumber => Cint(1),
            :mesh_dim => Cint(3),
        )"""

        str_ = """this_is_a_long_variable_name = (:numberofpointattributes => NAttributes,
               :numberofpointmtrs => NMTr, :numberofcorners => NSimplex, :firstnumber => Cint(1),
               :mesh_dim => Cint(3),)"""
        @test fmt(str_, 4, 80) == str

        str = """
        begin
            a && b
            a || b
        end"""
        @test fmt(str, 4, 1) == str

        str = """
        begin
            a &&
            b ||
            c &&
            d
        end"""
        @test fmt("begin\n a && b || c && d\nend", 4, 1) == str

        str = """
        func(a, \"""this
                is another
                multi-line
                string.
                Longest line
                \""", foo(b, c))"""
        @test fmt(str, 4, 100) == str

        str_ = """
        func(
            a,
            \"""this
            is another
            multi-line
            string.
            Longest line
            \""",
            foo(
                b,
                c,
            ),
        )"""
        @test fmt(str, 4, 1) == str_

        str = """
        func(
            a,
            \"""this
            is another
            multi-line
            string.
            Longest line
            \""",
            foo(b, c),
        )"""
        @test fmt(str, 4, 31) == str

        # Ref
        str = "a[1+2]"
        @test fmt("a[1 + 2]", 4, 1) == str

        str = "a[(1+2)]"
        @test fmt("a[(1 + 2)]", 4, 1) == str

        str_ = "(a + b + c + d)"
        @test fmt(str_, 4, 15) == str_

        str = "(a + b + c +\n d)"
        @test fmt(str_, 4, 14) == str
        @test fmt(str_, 4, 12) == str

        str = "(a + b +\n c + d)"
        @test fmt(str_, 4, 11) == str
        @test fmt(str_, 4, 8) == str

        str = "(a +\n b +\n c + d)"
        @test fmt(str_, 4, 7) == str

        str = "(a +\n b +\n c +\n d)"
        @test fmt(str_, 4, 1) == str

        str_ = "(a <= b <= c <= d)"
        @test fmt(str_, 4, 18) == str_

        str = "(a <= b <= c <=\n d)"
        @test fmt(str_, 4, 17) == str
        @test fmt(str_, 4, 15) == str

        str = "(a <= b <=\n c <= d)"
        @test fmt(str_, 4, 14) == str
        @test fmt(str_, 4, 10) == str

        str = "(a <=\n b <=\n c <= d)"
        @test fmt(str_, 4, 9) == str
        @test fmt(str_, 4, 8) == str

        str = "(a <=\n b <=\n c <=\n d)"
        @test fmt(str_, 4, 7) == str
        @test fmt(str_, 4, 1) == str

        # https://github.com/domluna/JuliaFormatter.jl/issues/60
        str_ = """
        function write_subproblem_to_file(
                node::Node, filename::String;
                format::Symbol=:both, throw_error::Bool = false)
            body
        end"""
        str = """
        function write_subproblem_to_file(
            node::Node,
            filename::String;
            format::Symbol = :both,
            throw_error::Bool = false,
        )
            body
        end"""
        @test fmt(str_) == str

        # single function kwarg or param should not nest
        @test fmt("f(;a=1)", 4, 1) == "f(; a = 1)"
        @test fmt("f(a=1)", 4, 1) == "f(a = 1)"

        # any pairing of argument, kawrg, or param should nest
        str = """
        f(
          arg;
          a = 1,
        )"""
        @test fmt("f(arg;a=1)", 4, 1) == str

        str = """
        f(
          arg,
          a = 1,
        )"""
        @test fmt("f(arg,a=1)", 4, 1) == str

        str = """
        f(
          a = 1;
          b = 2,
        )"""
        @test fmt("f(a=1; b=2)", 4, 1) == str
    end

    @testset "nesting line offset" begin
        str = "a - b + c * d"
        s = run_nest(str, 100)
        @test s.line_offset == length(str)
        s = run_nest(str, length(str) - 1)
        @test s.line_offset == 5
        s = run_nest(str, 1)
        @test s.line_offset == 1

        str = "c ? e1 : e2"
        s = run_nest(str, 100)
        @test s.line_offset == length(str)
        s = run_nest(str, length(str) - 1)
        @test s.line_offset == 2
        s = run_nest(str, 8)
        @test s.line_offset == 2
        s = run_nest(str, 1)
        @test s.line_offset == 2

        str = "c1 ? e1 : c2 ? e2 : c3 ? e3 : c4 ? e4 : e5"
        s = run_nest(str, 100)
        @test s.line_offset == length(str)
        s = run_nest(str, length(str) - 1)
        @test s.line_offset == 32
        s = run_nest(str, 30)
        @test s.line_offset == 22
        s = run_nest(str, 20)
        @test s.line_offset == 12
        s = run_nest(str, 10)
        @test s.line_offset == 2
        s = run_nest(str, 1)
        @test s.line_offset == 2

        str = "f(a, b, c) where {A,B,C}"
        s = run_nest(str, 100)
        @test s.line_offset == length(str)
        s = run_nest(str, length(str) - 1)
        @test s.line_offset == 15
        s = run_nest(str, 14)
        @test s.line_offset == 1
        s = run_nest(str, 1)
        @test s.line_offset == 1

        str = "f(a, b, c) where Union{A,B,C}"
        s = run_nest(str, 100)
        @test s.line_offset == length(str)
        s = run_nest(str, length(str) - 1)
        @test s.line_offset == 20
        s = run_nest(str, 19)
        @test s.line_offset == 1
        s = run_nest(str, 1)
        @test s.line_offset == 1

        str = "f(a, b, c) where {A}"
        s = run_nest(str, 100)
        # adds surrounding {...} after `where`
        @test s.line_offset == length(str)
        s = run_nest(str, 1)
        @test s.line_offset == 11

        str = "f(a, b, c) where {A<:S}"
        s = run_nest(str, 100)
        @test s.line_offset == length(str)
        s = run_nest(str, 1)
        @test s.line_offset == 14

        str = "f(a, b, c) where Union{A,B,Union{C,D,E}}"
        s = run_nest(str, 100)
        @test s.line_offset == length(str)
        s = run_nest(str, length(str) - 1)
        @test s.line_offset == 31
        s = run_nest(str, 30)
        @test s.line_offset == 1
        s = run_nest(str, 1)
        @test s.line_offset == 1

        str = "f(a, b, c) where {A,{B, C, D},E}"
        s = run_nest(str, 100)
        @test s.line_offset == length(str)
        s = run_nest(str, 1)
        @test s.line_offset == 1

        str = "(a, b, c, d)"
        s = run_nest(str, 100)
        @test s.line_offset == length(str)
        s = run_nest(str, length(str) - 1)
        @test s.line_offset == 1

        str = "a, b, c, d"
        s = run_nest(str, 100)
        @test s.line_offset == length(str)
        s = run_nest(str, length(str) - 1)
        @test s.line_offset == 1

        str = """
        splitvar(arg) =
            @match arg begin
                ::T_ => (nothing, T)
                name_::T_ => (name, T)
                x_ => (x, :Any)
            end"""
        s = run_nest(str, 96)
        @test s.line_offset == 3
        s = run_nest(str, 1)
        @test s.line_offset == 7

        str = "prettify(ex; lines = false) = ex |> (lines ? identity : striplines) |> flatten |> unresolve |> resyntax |> alias_gensyms"
        s = run_nest(str, 80)
        @test s.line_offset == 17

        str = "foo() = a + b"
        s = run_nest(str, length(str))
        @test s.line_offset == length(str)
        s = run_nest(str, length(str) - 1)
        @test s.line_offset == 9
        s = run_nest(str, 1)
        @test s.line_offset == 5

        str_ = """
        @Expr(:scope_block, begin
                    body1
                    @Expr :break loop_cont
                    body2
                    @Expr :break loop_exit2
                    body3
                end)"""

        str = """
        @Expr(:scope_block, begin
            body1
            @Expr :break loop_cont
            body2
            @Expr :break loop_exit2
            body3
        end)"""
        @test fmt(str_, 4, 100) == str

        str = """
        @Expr(
            :scope_block,
            begin
                body1
                @Expr :break loop_cont
                body2
                @Expr :break loop_exit2
                body3
            end,
        )"""
        @test fmt(str_, 4, 20) == str

        str = "export @esc, isexpr, isline, iscall, rmlines, unblock, block, inexpr, namify, isdef"
        s = run_nest(str, length(str))
        @test s.line_offset == length(str)
        s = run_nest(str, length(str) - 1)
        @test s.line_offset == 12

        # https://github.com/domluna/JuliaFormatter.jl/issues/9#issuecomment-481607068
        str = """this_is_a_long_variable_name = Dict{Symbol,Any}(:numberofpointattributes => NAttributes,
               :numberofpointmtrs => NMTr, :numberofcorners => NSimplex, :firstnumber => Cint(1),
               :mesh_dim => Cint(3),)"""
        s = run_nest(str, 80)
        @test s.line_offset == 1

        str = """this_is_a_long_variable_name = (:numberofpointattributes => NAttributes,
               :numberofpointmtrs => NMTr, :numberofcorners => NSimplex, :firstnumber => Cint(1),
               :mesh_dim => Cint(3),)"""
        s = run_nest(str, 80)
        @test s.line_offset == 1
    end

    @testset "additional length" begin
        str_ = "f(a, @g(b, c), d)"
        str = """
        f(
          a,
          @g(b, c),
          d,
        )"""
        @test fmt(str_, 4, 11) == str
        @test fmt(str, 4, length(str)) == str_

        str_ = "f(a, @g(b, c), d)"
        str = """
        f(
          a,
          @g(
             b,
             c,
          ),
          d,
        )"""
        @test fmt(str_, 4, 10) == str
        @test fmt(str, 4, length(str)) == str_

        str_ = "(a, (b, c), d)"
        str = """
        (
         a,
         (
          b,
          c,
         ),
         d,
        )"""
        @test fmt(str_, 4, 7) == str
        @test fmt(str, 4, length(str)) == str_

        str_ = "(a, {b, c}, d)"
        str = """
        (
         a,
         {
          b,
          c,
         },
         d,
        )"""
        @test fmt(str_, 4, 6) == str
        @test fmt(str, 4, length(str)) == str_

        str_ = "(a, [b, c], d)"
        str = """
        (
         a,
         [
          b,
          c,
         ],
         d,
        )"""
        @test fmt(str_, 4, 6) == str
        @test fmt(str, 4, length(str)) == str_

        str_ = "a, (b, c), d"
        str = """
        a,
        (
         b,
         c,
        ),
        d"""
        @test fmt(str_, 4, 6) == str
        @test fmt(str, 4, length(str)) == str_

        str_ = "a, (b, c), d"
        str = """
        a,
        (b, c),
        d"""
        @test fmt(str_, 4, 7) == str
        @test fmt(str, 4, length(str)) == str_

        str = """
        (
         var1,
         var2,
        ) && var3"""
        @test fmt("(var1,var2) && var3", 4, 10) == str

        str = """
        (
         var1,
         var2,
        ) && var3"""
        @test fmt("(var1,var2) && var3", 4, 19) == str

        str = """
        (var1, var2) ?
        (var3, var4) :
        var5"""
        @test fmt("(var1,var2) ? (var3,var4) : var5", 4, 14) == str

        str = """
        (
         var1,
         var2,
        ) ?
        (
         var3,
         var4,
        ) :
        var5"""
        @test fmt("(var1,var2) ? (var3,var4) : var5", 4, 13) == str

        str = """
        (var1, var2) ? (var3, var4) :
        var5"""
        @test fmt("(var1,var2) ? (var3,var4) : var5", 4, 29) == str

        str = """
        (var1, var2) ?
        (var3, var4) : var5"""
        @test fmt("(var1,var2) ? (var3,var4) : var5", 4, 28) == str

        str = """
        f(
          var1::A,
          var2::B,
        ) where {A,B}"""
        @test fmt("f(var1::A, var2::B) where {A,B}", 4, 30) == str

        str = """
        f(
          var1::A,
          var2::B,
        ) where {
            A,
            B,
        }"""
        @test fmt("f(var1::A, var2::B) where {A,B}", 4, 12) == str

        str = "foo(a, b, c)::Rtype where {A,B} = 10"
        str_ = "foo(a, b, c)::Rtype where {A,B,} = 10"
        @test fmt(str, 4, length(str)) == str
        @test fmt(str_, 4, length(str_)) == str

        str_ = """
        foo(a, b, c)::Rtype where {A,B} =
            10"""
        @test fmt(str, 4, 35) == str_
        @test fmt(str, 4, 33) == str_

        str_ = """
        foo(a, b, c)::Rtype where {
            A,
            B,
        } = 10"""
        @test fmt(str, 4, 32) == str_
        @test fmt(str, 4, 19) == str_

        str_ = """
        foo(
            a,
            b,
            c,
        )::Rtype where {
            A,
            B,
        } = 10"""
        @test fmt(str, 4, 18) == str_

        str = "keytype(::Type{<:AbstractDict{K,V}}) where {K,V} = K"
        @test fmt(str, 4, 52) == str

        str_ = "transcode(::Type{THISISONESUPERLONGTYPE1234567}) where {T<:Union{Int32,UInt32}} = transcode(T, String(Vector(src)))"
        str = """
        transcode(::Type{THISISONESUPERLONGTYPE1234567}) where {T<:Union{
          Int32,
          UInt32,
        }} = transcode(T, String(Vector(src)))"""
        @test fmt(str_, 2, 80) == str
        @test fmt(str_, 2, 38) == str

        str = """
        transcode(::Type{THISISONESUPERLONGTYPE1234567}) where {T<:Union{
          Int32,
          UInt32,
        }} =
          transcode(T, String(Vector(src)))"""
        @test fmt(str_, 2, 37) == str

        str_ = "transcode(::Type{T}, src::AbstractVector{UInt8}) where {T<:Union{Int32,UInt32}} = transcode(T, String(Vector(src)))"
        str = """
        transcode(
          ::Type{T},
          src::AbstractVector{UInt8},
        ) where {T<:Union{Int32,UInt32}} = transcode(T, String(Vector(src)))"""
        @test fmt(str_, 2, 80) == str
        @test fmt(str_, 2, 68) == str

        str = """
        transcode(
          ::Type{T},
          src::AbstractVector{UInt8},
        ) where {T<:Union{Int32,UInt32}} =
          transcode(T, String(Vector(src)))"""
        @test fmt(str_, 2, 67) == str

        # issue 56
        str_ = "a_long_function_name(Array{Float64,2}[[1.0], [0.5 0.5], [0.5 0.5; 0.5 0.5], [0.5 0.5; 0.5 0.5]])"
        str = """
        a_long_function_name(Array{Float64,2}[
            [1.0],
            [0.5 0.5],
            [0.5 0.5; 0.5 0.5],
            [0.5 0.5; 0.5 0.5],
        ])"""
        @test fmt(str, 4, length(str)) == str_
        @test fmt(str_) == str

        # unary op
        str_ = "[1, 1]'"
        str = """
        [
         1,
         1,
        ]'"""
        @test fmt(str, 4, length(str)) == str_
        @test fmt(str_, 4, length(str_) - 1) == str
    end

    @testset "Trailing zeros" begin
        @test fmt("1.") == "1.0"
        @test fmt("a * 1. + b") == "a * 1.0 + b"
        @test fmt("1. + 2. * im") == "1.0 + 2.0 * im"
        @test fmt("[1., 2.]") == "[1.0, 2.0]"
        @test fmt("""
        1. +
            2.
        """) == "1.0 + 2.0\n"
    end

    @testset "Leading zeros" begin
        @test fmt(".1") == "0.1"
        @test fmt("a * .1 + b") == "a * 0.1 + b"
        @test fmt(".1 + .2 * im") == "0.1 + 0.2 * im"
        @test fmt("[.1, .2]") == "[0.1, 0.2]"
        @test fmt("""
        .1 +
            .2
        """) == "0.1 + 0.2\n"
    end

    # https://github.com/domluna/JuliaFormatter.jl/issues/77
    @testset "issue 77" begin
        str_ = """
        [ a b Expr()
        d e Expr()]"""
        str = """
        [
         a b Expr()
         d e Expr()
        ]"""
        @test fmt(str_) == str

        str_ = """
        T[ a b Expr()
        d e Expr()]"""
        str = """
        T[
          a b Expr()
          d e Expr()
        ]"""
        @test fmt(str_) == str

        str_ = """
        [ a b Expr();
        d e Expr();]"""
        str = """
        [
         a b Expr()
         d e Expr()
        ]"""
        @test fmt(str_) == str
        str_ = "[a b Expr(); d e Expr()]"
        @test fmt(str_) == str_
        @test fmt(str_, 4, 1) == str

        str_ = """
        T[ a b Expr();
        d e Expr();]"""
        str = """
        T[
          a b Expr()
          d e Expr()
        ]"""
        @test fmt(str_) == str

        str_ = "T[a b Expr(); d e Expr()]"
        @test fmt(str_) == str_
        @test fmt(str_, 4, 1) == str

        str = """
        [
         0.0 0.0 0.0 1.0
         0.0 0.0 0.1 1.0
         0.0 0.0 0.2 1.0
         0.0 0.0 0.3 1.0
         0.0 0.0 0.4 1.0
         0.0 0.0 0.5 1.0
         0.0 0.0 0.6 1.0
         0.0 0.0 0.7 1.0
         0.0 0.0 0.8 1.0
         0.0 0.0 0.9 1.0
         0.0 0.0 1.0 1.0
         0.0 0.0 0.0 1.0
         0.0 0.1 0.1 1.0
         0.0 0.2 0.2 1.0
         0.0 0.3 0.3 1.0
         0.0 0.4 0.4 1.0
         0.0 0.5 0.5 1.0
         0.0 0.6 0.6 1.0
         0.0 0.7 0.7 1.0
         0.0 0.8 0.8 1.0
         0.0 0.9 0.9 1.0
         0.0 1.0 1.0 1.0
         0.0 0.0 0.0 1.0
         0.1 0.1 0.1 1.0
         0.2 0.2 0.2 1.0
         0.3 0.3 0.3 1.0
         0.4 0.4 0.4 1.0
         0.5 0.5 0.5 1.0
        ]"""
        @test fmt(str) == str
    end

end


text:
const root = RectanglePacker(SimpleRectangle(0,0,1024,1024))
push!(root, SimpleRectangle(0,0,20,20))
push!(root, SimpleRectangle(0,0,20,20))
push!(root, [SimpleRectangle(0,0,rand(5:50), rand(5:50)) for i=1:20])


text:
import Cxx
import DifferentialDynamicProgramming
import MuJoCo
using Cxx
using MuJoCo

include("simenvi.jl")

function SetSimState(sim::MJSimEnv, xi)
    offset = 1
    for i=1:sim.data.nq
        sim.data.qpos.mat[i] = xi[offset]
        offset += 1
    end
    for i=1:sim.data.nv
        sim.data.qvel.mat[i] = xi[offset]
        offset += 1
    end
    for i=1:sim.data.nsite
        sim.data.site_xpos.mat[:, i] = xi[offset:(offset + 2)]
        offset += 3
    end
end

function SetSimControls(sim::MJSimEnv, ui)
    SetSimControls(sim.controls, ui)
    SetControls(sim)
end

function GetSimState(sim::MJSimEnv)
    xi = Vector{mjtNum}(sim.data.nq + sim.data.nv + sim.data.nsite * 3)
    offset = 1
    for i=1:sim.data.nq
        xi[offset] = sim.data.qpos[i, 1]
        offset += 1
    end
    for i=1:sim.data.nv
        xi[offset] = sim.data.qvel[i, 1]
        offset += 1
    end
    for i=1:sim.data.nsite
        xi[offset:(offset + 2)] = sim.data.site_xpos.mat[:, i]
        offset += 3
    end
    return xi
end

function GetSimControls(sim::MJSimEnv)
    u = zeros(sim.data.nu, 1)
    for i=1:sim.data.nu
        u[i] = sim.data.ctrl[i, 1]
    end
    return u
end

#transition
function mjDynamicsF(xi, ui, i, sim, intermediateCost)
    SetSimState(sim, xi)
    SetSimControls(sim, ui)
    mj_forward(sim.model, sim.data)
    xnew = GetSimState(sim)
    cost = intermediateCost(xnew, ui, sim)
    return (xnew, cost)
end

#compute jacobian along each point in the given trajectory
#time invariant, can drop I??
function mjDynamicsFx(x, u, I, sim, costx, costu, costxx, costuu)
    #compute derivatives:
    nx = size(x, 1)
    #fx, fu, fxx, fuu, fxu, cx, cu, cxx, cxu, cuu
    fx = zeros(nx, nx, length(I) + 1)
    fu = zeros(nx, sim.data.nu, length(I) + 1)
    cx = zeros(nx, length(I) + 1)
    cu = zeros(sim.data.nu, length(I))
    cxx = zeros(nx, nx)
    cxu = zeros(nx, sim.data.nu)
    cuu = zeros(sim.data.nu, sim.data.nu)

    #fxx = zeros()

    #for every point on trajectory
    for t in I
        #set states
        SetSimState(sim, x[:, t])
        SetSimControls(sim, u[:, t])
        mj_forward(sim.model, sim.data)

        defaultSim = MJSimEnv(sim.model, s -> (0), s -> (false))
        SetSimState(defaultSim, x[:, t])
        SetSimControls(defaultSim, u[:, t])
        mj_forward(defaultSim.model, defaultSim.data)
        for i=1:3
            mj_forwardSkip(defaultSim.model, defaultSim.data, icxx"mjSTAGE_VEL;", 1)
        end

        ###DYNAMICS MODEL DERIVATIVES these top level loops can be parallelized

        #fu
        offset1 = 1
        for nu1=1:sim.data.nu
            sim.data.ctrl.mat[1, nu1] += 1.0e-4

            icxx"""
            mju_copy($(sim.data.d)->qacc_warmstart, $(defaultSim.data.d)->qacc_warmstart, $(sim.model.m)->nv);
            """

            for k in 1:1
                mj_step(sim.model, sim.data)
            end

            #set column values (observed derivs wrt modified value in the row)
            offset2 = 1
            for nq2=1:sim.data.nq
                fu[offset2, offset1, t] = (sim.data.qpos[nq2, 1] - defaultSim.data.qpos[nq2, 1]) / 2 / 1.0e-4
                offset2 += 1
            end
            for nv2=1:sim.data.nv
                fu[offset2, offset1, t] = (sim.data.qvel[nv2, 1] - defaultSim.data.qvel[nv2, 1]) / 2 / 1.0e-4
                offset2 += 1
            end
            for nsite2=1:sim.data.nsite
                for j=1:3
                    fu[offset2, offset1, t] = (sim.data.site_xpos[nsite2, j] - defaultSim.data.site_xpos[nsite2, j]) / 2 / 1.0e-4
                    offset2 += 1
                end
            end
            icxx"""
            //reset
            mju_copy($(sim.data.d)->qpos, $(defaultSim.data.d)->qpos, $(sim.model.m)->nq);
            mju_copy($(sim.data.d)->qvel, $(defaultSim.data.d)->qvel, $(sim.model.m)->nv);
            mju_copy($(sim.data.d)->qacc, $(defaultSim.data.d)->qacc, $(sim.model.m)->nv);
            mju_copy($(sim.data.d)->qacc_warmstart, $(defaultSim.data.d)->qacc_warmstart, $(sim.model.m)->nv);
            mju_copy($(sim.data.d)->qfrc_applied, $(defaultSim.data.d)->qfrc_applied, $(sim.model.m)->nv);
            mju_copy($(sim.data.d)->xfrc_applied, $(defaultSim.data.d)->xfrc_applied, 6*$(sim.model.m)->nsite);
            mju_copy($(sim.data.d)->ctrl, $(defaultSim.data.d)->ctrl, $(sim.model.m)->nu);
            mj_forward($(sim.model.m), $(sim.data.d));
            """
            offset1 += 1
        end

        #fx
        offset1 = 1
        for nq1=1:sim.data.nq
            sim.data.qpos.mat[1, nq1] += 1.0e-4

            icxx"""
            mju_copy($(sim.data.d)->qacc_warmstart, $(defaultSim.data.d)->qacc_warmstart, $(sim.model.m)->nv);
            """

            for k in 1:1
                mj_step(sim.model, sim.data)
            end

            #set column values (observed derivs wrt modified value in the row)
            offset2 = 1
            for nq2=1:sim.data.nq
                fx[offset2, offset1, t] = (sim.data.qpos[nq2, 1] - defaultSim.data.qpos[nq2, 1]) / 2 / 1.0e-4
                offset2 += 1
            end
            for nv2=1:sim.data.nv
                fx[offset2, offset1, t] = (sim.data.qvel[nv2, 1] - defaultSim.data.qvel[nv2, 1]) / 2 / 1.0e-4
                offset2 += 1
            end
            for nsite2=1:sim.data.nsite
                for j=1:3
                    fx[offset2, offset1, t] = (sim.data.site_xpos[nsite2, j] - defaultSim.data.site_xpos[nsite2, j]) / 2 / 1.0e-4
                    offset2 += 1
                end
            end

            icxx"""
            //reset
            mju_copy($(sim.data.d)->qpos, $(defaultSim.data.d)->qpos, $(sim.model.m)->nq);
            mju_copy($(sim.data.d)->qvel, $(defaultSim.data.d)->qvel, $(sim.model.m)->nv);
            mju_copy($(sim.data.d)->qacc, $(defaultSim.data.d)->qacc, $(sim.model.m)->nv);
            mju_copy($(sim.data.d)->qacc_warmstart, $(defaultSim.data.d)->qacc_warmstart, $(sim.model.m)->nv);
            mju_copy($(sim.data.d)->qfrc_applied, $(defaultSim.data.d)->qfrc_applied, $(sim.model.m)->nv);
            mju_copy($(sim.data.d)->xfrc_applied, $(defaultSim.data.d)->xfrc_applied, 6*$(sim.model.m)->nsite);
            mju_copy($(sim.data.d)->ctrl, $(defaultSim.data.d)->ctrl, $(sim.model.m)->nu);
            mj_forward($(sim.model.m), $(sim.data.d));
            """
            offset1 += 1
        end
        for nv1=1:sim.data.nv
            sim.data.qvel.mat[1, nv1] += 1.0e-4

            icxx"""
            mju_copy($(sim.data.d)->qacc_warmstart, $(defaultSim.data.d)->qacc_warmstart, $(sim.model.m)->nv);
            """

            for k in 1:1
                mj_step(sim.model, sim.data)
            end

            #set column values (observed derivs wrt modified value in the row)
            offset2 = 1
            for nq2=1:sim.data.nq
                fx[offset2, offset1, t] = (sim.data.qpos[nq2, 1] - defaultSim.data.qpos[nq2, 1]) / 2 / 1.0e-4
                offset2 += 1
            end
            for nv2=1:sim.data.nv
                fx[offset2, offset1, t] = (sim.data.qvel[nv2, 1] - defaultSim.data.qvel[nv2, 1]) / 2 / 1.0e-4
                offset2 += 1
            end
            for nsite2=1:sim.data.nsite
                for j=1:3
                    fx[offset2, offset1, t] = (sim.data.site_xpos[nsite2, j] - defaultSim.data.site_xpos[nsite2, j]) / 2 / 1.0e-4
                    offset2 += 1
                end
            end

            icxx"""
            //reset
            mju_copy($(sim.data.d)->qpos, $(defaultSim.data.d)->qpos, $(sim.model.m)->nq);
            mju_copy($(sim.data.d)->qvel, $(defaultSim.data.d)->qvel, $(sim.model.m)->nv);
            mju_copy($(sim.data.d)->qacc, $(defaultSim.data.d)->qacc, $(sim.model.m)->nv);
            mju_copy($(sim.data.d)->qacc_warmstart, $(defaultSim.data.d)->qacc_warmstart, $(sim.model.m)->nv);
            mju_copy($(sim.data.d)->qfrc_applied, $(defaultSim.data.d)->qfrc_applied, $(sim.model.m)->nv);
            mju_copy($(sim.data.d)->xfrc_applied, $(defaultSim.data.d)->xfrc_applied, 6*$(sim.model.m)->nsite);
            mju_copy($(sim.data.d)->ctrl, $(defaultSim.data.d)->ctrl, $(sim.model.m)->nu);
            mj_forward($(sim.model.m), $(sim.data.d));
            """
            offset1 += 1
        end
        for nsite1=1:sim.data.nsite#don't do, doesn't make sense
            for j1=1:3

                sim.data.site_xpos.mat[j1, nsite1] += 1.0e-4

                icxx"""
                mju_copy($(sim.data.d)->qacc_warmstart, $(defaultSim.data.d)->qacc_warmstart, $(sim.model.m)->nv);
                """

                for k in 1:1
                    mj_step(sim.model, sim.data)
                end

                #set column values (observed derivs wrt modified value in the row)
                offset2 = 1
                for nq2=1:sim.data.nq
                    fx[offset2, offset1, t] = (sim.data.qpos[nq2, 1] - defaultSim.data.qpos[nq2, 1]) / 2 / 1.0e-4
                    offset2 += 1
                end
                for nv2=1:sim.data.nv
                    fx[offset2, offset1, t] = (sim.data.qvel[nv2, 1] - defaultSim.data.qvel[nv2, 1]) / 2 / 1.0e-4
                    offset2 += 1
                end
                for nsite2=1:sim.data.nsite
                    for j=1:3
                        fx[offset2, offset1, t] = (sim.data.site_xpos[nsite2, j] - defaultSim.data.site_xpos[nsite2, j]) / 2 / 1.0e-4
                        offset2 += 1
                    end
                end
            end

            icxx"""
            //reset
            mju_copy($(sim.data.d)->qpos, $(defaultSim.data.d)->qpos, $(sim.model.m)->nq);
            mju_copy($(sim.data.d)->qvel, $(defaultSim.data.d)->qvel, $(sim.model.m)->nv);
            mju_copy($(sim.data.d)->qacc, $(defaultSim.data.d)->qacc, $(sim.model.m)->nv);
            mju_copy($(sim.data.d)->qacc_warmstart, $(defaultSim.data.d)->qacc_warmstart, $(sim.model.m)->nv);
            mju_copy($(sim.data.d)->qfrc_applied, $(defaultSim.data.d)->qfrc_applied, $(sim.model.m)->nv);
            mju_copy($(sim.data.d)->xfrc_applied, $(defaultSim.data.d)->xfrc_applied, 6*$(sim.model.m)->nsite);
            mju_copy($(sim.data.d)->ctrl, $(defaultSim.data.d)->ctrl, $(sim.model.m)->nu);
            mj_forward($(sim.model.m), $(sim.data.d));
            """
            offset1 += 1
        end

        ###COST FUNCTION DERIVATIVES
        cu[:, t] = costu(u[:, t], sim)
        cx[:, t] = costx(x[:, t], sim)
    end

    cuu = costuu(u, sim)
    cxx = costxx(x, sim)
    cxu = cx * transpose(hcat(cu, ones(sim.data.nu)))

    #assume linear?
    fxx = fxu = fuu = []

    return (fx, fu, fxx, fxu, fuu, cx, cu, cxx, cxu, cuu)
end

#get cost of being in a state
function mjDynamicsFT(xi, sim, finalCost)
    return finalCost(xi, sim)
end


text:
module PicoScope

@windows? begin const ps4000driver = "ps4000.dll" end : nothing
@windows? begin const ps3000driver = "ps3000.dll" end : nothing

include("checkstatus.jl")
include("ps4000.jl")
include("ps3000.jl")

end # module


text:
# This file is part of the StateMachines.jl Julia package
#
# Paul Bayer
# MIT License
# Github: https://github.com/pbayer/StateMachines.jl
#

"""
    StateMachines

A Julia package for state machines.

It can (after registration) be installed with:
```julia
] add StateMachines
```

The development version can be installed with:
```julia
] add("https://github.com/pbayer/StateMachines.jl")
```
"""
module StateMachines

using Simulate

include("types.jl")
include("box.jl")
include("block.jl")
include("statemachine.jl")
include("state.jl")
include("event.jl")
include("transition.jl")
include("action.jl")

export  AbstractEvent, MessageEvent, ChangeEvent, TimeEvent,
        AbstractState, SimpleState, CompositeState, OrthogonalState,
        SubmachineState, PseudoState,
        System, Behavior, StateMachine, step!

"""
    trace

a module variable used for debugging state machines.
Set `StateMachines.trace = true` if you want to have messages for
undefined transitions.
"""
trace = false

end # module