Add a prefix to every `println()` output

And, I have found a solution, which is to use closures:
Here is the code:

function get_printinfo(prefix::String="", prefix_arr::Vector=[""])::Function
    if prefix != ""
        push!(prefix_arr, prefix)
    end
    function printinfo(s::String=""; prefix::String="", pop::Bool=false)::Function
        if pop
            pop!(prefix_arr)
        end
        if s != ""
            fullprefix = join(prefix_arr, "")
            print(fullprefix)
            println(s)
        end
        return get_printinfo(prefix, prefix_arr)
    end
    return printinfo
end

This function returns a closure function that, when called, prints the string with the given prefix (implicitly passed).
The new function can also be used to recursively add more prefixes on top or pop the last one.
Note that when the prefix and pop arguments are used, they actually modify the existing function itself, and also return itself. prefix argument takes effect in next call, while pop argument takes effect in current one.

An example on how to print repl-like output with this (repl> lines are actually printed output not actual an repl prompt):

julia> replprint=get_printinfo("repl> ")
(::var"#printinfo#13"{var"#printinfo#10#14"{Vector{String}}}) (generic function with 2 methods)

julia> replprint("@time somefunc(arg1, arg2)")
repl> @time somefunc(arg1, arg2)
(::var"#printinfo#13"{var"#printinfo#10#14"{Vector{String}}}) (generic function with 2 methods)

julia> timereplprint=replprint(prefix="@time ")  # `replprint` itself is also modified
(::var"#printinfo#13"{var"#printinfo#10#14"{Vector{String}}}) (generic function with 2 methods)

julia> timereplprint("somefunc(arg1, arg2)")
repl> @time somefunc(arg1, arg2)
(::var"#printinfo#13"{var"#printinfo#10#14"{Vector{String}}}) (generic function with 2 methods)

julia> # new prefix takes effect in next call, but pop takes effect in current one
julia> whichreplprint=timereplprint("somefunc(arg1, arg2)", prefix="@which ", pop=true)
repl> somefunc(arg1, arg2)
(::var"#printinfo#13"{var"#printinfo#10#14"{Vector{String}}}) (generic function with 2 methods)

julia> timereplprint("somefunc(arg1, arg2)")  # `timereplprint` itself was also modified
repl> @which somefunc(arg1, arg2)
(::var"#printinfo#13"{var"#printinfo#10#14"{Vector{String}}}) (generic function with 2 methods)

julia> whichreplprint("somefunc(arg1, arg2)")
repl> @which somefunc(arg1, arg2)
(::var"#printinfo#13"{var"#printinfo#10#14"{Vector{String}}}) (generic function with 2 methods)