What is in your startup.jl?

I now have a fair bit in my startup.jl
I am wondering if anyone else also has cool things.


What mine does:

  • Load Revise and OhMyRepl.
    - installing them if they are not already installed
  • Update all packages
    - It does this in a silenced worker processes, so as not to waste time
    - it is supposed to remove that worker afterwards but I am not sure that it does
    - My packages are now evergreen, like a webbrowser.

I used to do stuff with setting stacktrace colors to not uses bold, because bold was not differentiable from white on my old terminal emulator,
but it is on my new setup so I don’t have it anymore


# Setup OhMyREPL and Revise
import Pkg
let
    pkgs = ["Revise", "OhMyREPL"]
    for pkg in pkgs
    if Base.find_package(pkg) === nothing
        Pkg.add(pkg)
    end
    end
end

using Revise
using OhMyREPL


# Update all packages, but do so in a worker process
import Distributed
let
    pkg_worker = Distributed.addprocs(1)[end]
    Distributed.remotecall(pkg_worker) do
        redirect_stdout() # silence everything, only on this worker
        Pkg.update()

        # now remove this worker and say we are done
        remotecall(1) do
            eval(quote
                Distributed.rmprocs($(pkg_worker))
                printstyled("\n Pkg.update() complete \n"; color=:light_black)
            end)
        end
    end
end
38 Likes

Here is mine

ENV["JULIA_NUM_THREADS"] = 8
ENV["EDITOR"] = "vim"
ENV["PYTHON"] = "python"
#using Reduce
#@force using Reduce.Algebra
#using OhMyREPL
#using Revise
using BenchmarkTools, SyntaxTree

cdpkg(pkg) = cd(dirname(Base.find_package(string(pkg))))

macro cdpkg(pkg)
    cdpkg(pkg)
    return nothing
end

usually I have some of my startup packages commented and disabled, such as OhMyREPL and Revise, since I want the REPL to startup as fast as possible, I enable and uncomment them only sometimes.

The macro and cdpkg function are used to cd to a package without having to import it.

3 Likes

That’s very nice @oxinabox. I definitely would not want all dependencies of projects I’m working on to update every time I start Julia. It’s great for the main project (labelled (1.0) but no project I’m developing seriously.

I thought you had to do some more eval magic for Revise and Rebugger to really do their thing?
Mine is

ENV["EDITOR"] = "atom"
const PLOTS_DEFAULTS = Dict(:theme => :wong)

 try
     @eval using Revise
     # Turn on Revise's automatic-evaluation behavior
     Revise.async_steal_repl_backend()

     @eval using Rebugger
     # Activate Rebugger's key bindings
     atreplinit(Rebugger.repl_init)

     using OhMyREPL
     colorscheme!("Monokai24bit")

 catch err
     @warn "Could not load startup packages."
 end

 showall(x) = show(stdout, "text/plain", x)

The showall function is particularly nice when you things like keys(somedict) to get a list of the keys to use etc.
The :wong theme is nicer than Plots’s default IMHO.

4 Likes

Thanks for sharing these tips !
BTW is it possible to configure startup.jl to make an automatic cd() to the last used directory ?

1 Like

Yes, that’s possible by adding this to your startup.jl file

try
    open(joinpath(homedir(),".julia","config","dir"),"r") do f
        cd(read(f,String))
    end
catch
end
atexit(() -> begin
    try
        open(joinpath(homedir(),".julia","config","dir"),"w") do f
            write(f,pwd())
        end
    catch
    end
end)
13 Likes

Thank you very much… It’s added !

Nice. Thanks.

Does anyone know a decent way to work in a call to load precompiled modules (from package compiler) in the startup file? I.e. Start Julia within Julia with the precompiled modules from an image, but only doing this once.

1 Like

Being new to and super excited by julia, I find these config tips so inspirational that I can’t help bumping this thread by my two cents:

The following config allows individual startup.jl per project.

 using Pkg

let proj = Pkg.project()
  startupfile = joinpath(dirname(proj.path), "startup.jl")
  isfile(startupfile) && include(startupfile)
end

This comes handy when starting julia into a project with julia --project=<dir>

9 Likes

I use tmux to manage my projects:

## ... to test if environment is OK
# Do I have a session $PROJECT
tmux has-session -t $PROJECT 2>/dev/null
if [ $? = 0 ]; then
    tmux attach-session -t $1
else
    if [ $TERM = "screen" ]; then # in a tmux session
        echo You are now in a tmux session which will be detached.
        echo Please run the command again.
        tmux detach-client
    else
        tmux new-session -d -s $PROJECT \; \
             splitw -h -p 66 \; \
             splitw -h \; \
             splitw -v -p 24 \; \
             attach-session \; \
             select-pane -t 0 \;  \
             splitw -v -p 89 \; \
             send-keys -t 1 cd\ $ddat Enter \; \
             send-keys -t 0 figlet\ -cw\ 99\ $PROJECT Enter \; \
             send-keys -t 2 cd\ $dprj/src Enter \; \
             send-keys -t 3 cd\ $dprj/src Enter \; \
             send-keys -t 3 ec\ $PROJECT.jl Enter \; \
             send-keys -t 4 cd\ $dprj Enter \; \
             send-keys -t 4 julia Enter \; \
             send-keys -t 4 ] \; \
             send-keys -t 4 update Enter \; \
             send-keys -t 4 activate\ . Enter \; \
             send-keys -t 4 update Enter \; \
             send-keys -t 4 ^h \; \
             send-keys -t 4 using\ Revise Enter \; \
             send-keys -t 4 using\ $PROJECT Enter \; \
             select-pane -t 2
    fi
fi

can of course be improved. tmux grammer is not very good. This is also for a 32’’ screen. I can then have a project title, a data, 2 editor, and 1 repl panes.

I’d been a Julia user for less than a week before the REPL default format for floats drove me insane. So I put this Google search result in my startup.jl and became less insane. I had no idea what these four lines were really doing for several months after that, but they solved my problem.

using Printf 
Base.show(io::IO, f::Float64) = @printf(io, "%1.5e", f)
Base.show(io::IO, f::Float32) = @printf(io, "%1.5e", f)
Base.show(io::IO, f::Float16) = @printf(io, "%1.5e", f)
13 Likes

Here is my updated one.
I gave up on updating all packages

# Disable updating registry on `add` (still runs on `up`), as it is slow
using Pkg: Pkg
Pkg.UPDATED_REGISTRY_THIS_SESSION[] = true

# use more colors for displaying Pkg conflicts
if isdefined(Pkg.Resolve, :CONFLICT_COLORS)
    append!(Pkg.Resolve.CONFLICT_COLORS,  [21:51; 55:119; 124:142; 160:184; 196:220])
end

# Setup Revise.jl
atreplinit() do repl
    try
        @eval using Revise
        @async Revise.wait_steal_repl_backend()
    catch err
        println("Error starting Revise $err")
    end
end
6 Likes

Nowadays you can just do using Revise.

4 Likes

Has anyone configured ENV[EDITOR"] in their startup.jl to use Visual Studio Code as their editor?

Yes I use ENV["JULIA_EDITOR"] = "code" and works ok

2 Likes

Other than starting Revise and setting the editor I have a macro for partial application:

module My_partial
export @p
function count_(expr::Expr)
    count = 0
    for arg in expr.args
        count += count_(arg)
    end
    count
end
function count_(expr)
            convert(Int64,expr == :_)::Int64
end

function subst_!(expr::Expr,slist)
    for i in eachindex(expr.args)
        expr.args[i]= subst_!(expr.args[i],slist)
    end
    expr
end
function subst_!(sym,slist)
    if (sym == :_) & (!isempty(slist))
        sym = popfirst!(slist) 
else
        return esc(sym)
    end
end
macro p(expr::Expr)
    fname = gensym()
    symnames = [gensym() for i in 1:My_partial.count_(expr)]
    args = copy(symnames)
    My_partial.subst_!(expr,symnames)
    (quote $fname($(args...)) = $expr end)
end
end

using Main.My_partial

and the obligatory (for me) definitions to stack array of arrays to a matrix:

vstack(v) = permutedims(reduce(hcat,v))
hstack(v) = hcat(v...)
2 Likes

I set the environment variable for my editor in ~/.bashrc, and I generally launch Julia from bash, so I don’t use startup.jl to set environment variables like this.

But I think the name code is absolutely absurd, and it’s not on my PATH. I use the symlink vscode, and so my startup.jl contains:

# `vscode` is my symlink to the Visual Studio Code executable.
# Tell Julia how to open files with `vscode`, modified from: `InteractiveUtils/src/editless.jl`
using InteractiveUtils # `using` instead of `import` due to https://github.com/JuliaLang/julia/issues/40192
InteractiveUtils.define_editor(["vscode"]) do cmd, path, line
    `$cmd -g $path:$line`
end

Along the same lines of making things prettier, I keep a pretty_rational function in my startup to change the default printing of Rational numbers when I want to. I’m not brave enough to make it my default setting, though.

function pretty_rational()
    @eval Base.show(io::IO, x::Rational) =
	    x.den==1 ? print(io, x.num) : print(io, "$(x.num)/$(x.den)")
end

Now this

julia> a = [x//y for x in 1:10, y in 1:10]
10×10 Matrix{Rational{Int64}}:
  1//1  1//2   1//3  1//4  1//5  1//6   1//7  1//8   1//9  1//10
  2//1  1//1   2//3  1//2  2//5  1//3   2//7  1//4   2//9  1//5
  3//1  3//2   1//1  3//4  3//5  1//2   3//7  3//8   1//3  3//10
  4//1  2//1   4//3  1//1  4//5  2//3   4//7  1//2   4//9  2//5
  5//1  5//2   5//3  5//4  1//1  5//6   5//7  5//8   5//9  1//2
  6//1  3//1   2//1  3//2  6//5  1//1   6//7  3//4   2//3  3//5
  7//1  7//2   7//3  7//4  7//5  7//6   1//1  7//8   7//9  7//10
  8//1  4//1   8//3  2//1  8//5  4//3   8//7  1//1   8//9  4//5
  9//1  9//2   3//1  9//4  9//5  3//2   9//7  9//8   1//1  9//10
 10//1  5//1  10//3  5//2  2//1  5//3  10//7  5//4  10//9  1//1

becomes

julia> pretty_rational()

julia> a
10×10 Matrix{Rational{Int64}}:
  1  1/2   1/3  1/4  1/5  1/6   1/7  1/8   1/9  1/10
  2    1   2/3  1/2  2/5  1/3   2/7  1/4   2/9   1/5
  3  3/2     1  3/4  3/5  1/2   3/7  3/8   1/3  3/10
  4    2   4/3    1  4/5  2/3   4/7  1/2   4/9   2/5
  5  5/2   5/3  5/4    1  5/6   5/7  5/8   5/9   1/2
  6    3     2  3/2  6/5    1   6/7  3/4   2/3   3/5
  7  7/2   7/3  7/4  7/5  7/6     1  7/8   7/9  7/10
  8    4   8/3    2  8/5  4/3   8/7    1   8/9   4/5
  9  9/2     3  9/4  9/5  3/2   9/7  9/8     1  9/10
 10    5  10/3  5/2    2  5/3  10/7  5/4  10/9     1
11 Likes

On Windows 10, in my case, I need ENV["JULIA_EDITOR"] = "code.cmd -g".

Details:

julia> ENV["JULIA_EDITOR"] = "code "

julia> edit("test_4.jl", 7)
ERROR: IOError: could not spawn `code -g test_4.jl:7`: no such file or directory (ENOENT)

julia> ENV["JULIA_EDITOR"] = "code.cmd -g"
"code.cmd -g"

julia> edit("test_4.jl", 7)

julia> split(ENV["PATH"], ';')
12-element Vector{SubString{String}}:
...
 "C:\\Users\\f\\AppData\\Local\\Programs\\Microsoft VS Code\\bin"
...
`
4 Likes

I like automatically activating local envs when they exist

if isfile("Project.toml") && isfile("Manifest.toml")
    Pkg.activate(".")
end
17 Likes