Emacs-based workflow

I couldn’t agree more with this.

It looks like upstream issues with LanguageServer are currently affecting eglot-jl (and probably lsp-julia in the same way). Since these issues appear to have been fixed in LanguageServer#master, the most straightforward workaround that I can think of (while waiting for a new release of LanguageServer) is to indeed use a custom version of LanguageServer. The following github issue contains a ste-by-step guide on how to do this without messing with the default environment:

If this is useful and clear enough, I’m considering adding this as an entry in eglot-jl’s FAQ.

1 Like

Each time I try to set Language server I see this

[stderr] nil
[stderr]   No Changes to `~/.doom.d/julia-lsp/Project.toml`
[stderr]   No Changes to `~/.doom.d/julia-lsp/Manifest.toml`
[stderr] [ Info: Environment successfully resolved
[stderr] ┌ Info: Running language server
[stderr] │   env = "/home/username/.doom.d/julia-lsp/Project.toml"
[stderr] │   src_path = "/home/username/aoc2021/src/"
[stderr] │   project_path = "/home/username/aoc2021"
[stderr] └   depot_path = ""
[internal] Mon Dec 20 13:59:04 2021:
(:message "Connection state changed" :change "killed\n")

----------b---y---e---b---y---e----------
[stderr] 
[stderr] 
[stderr] nil
[stderr] nil
[stderr] Process EGLOT (aoc2021/julia-mode) stderr finished

Specifically depot_path is missing, should it?

I’m running LanguageServer#master branch with eglot jl, should I bump eglot ?

No, it’s expected that depot_path is empty if you’re using the default depot (i.e. “~/.julia”).

The env=... line is what you should be looking at to debug issues related to the version of LanguageServer you’re using. Currently, eglot is using the version specified in:

/home/username/.doom.d/julia-lsp/Project.toml

Is that the environment in which you Pkg.added the latest master version of LanguageServer?

Yes, for some reason it started working now :man_shrugging:. I decided to keep a separate environment for Language server there as suggested before.

I tried to get Emacs+Julia to work on Windows platform, but no joy so far. At the moment, my issue is to get REPL to work. See julia-repl does not launch in Windows 7 · Issue #20 · tpapp/julia-repl (github.com) and Windows support · Issue #44 · gcv/julia-snail (github.com).

If you have working (REPL + debug + plot) Emacs+Julia+Windows, please share your workflow. Thanks.

Edit: Emacs with Julia on Windows - Tooling - JuliaLang. This is using Cygwin. I am looking for vanilla Emacs Win solution.

I’m not aware of a way to get a working Julia session running under native Windows emacs. I work around this limitation by installing emacs and Julia under WSL2. There, snail, eglot, etc. all work perfectly.

Thanks @PeterSimon for your feedback. Much appreciated.

Probably a simpe question, but is there anything we have to do in order to see plots with the Plots package?
Just running a script on the regular REPL works, but when I run it inside the REPL of julia-repl-mode in emacs there’s no graphical output.
In this case, I’m writting a script with a plot command at the end, so I send the whole script to the emacs REPL by C-c C-b (which is include(“/blablabla/script.jl”), but there’s no graphical output.
Running the same script in the regular REPL by using include(“/blablabla/script.jl”) works.

Both julia-snail and emacs-jupyter support rich output types. See the documentation for how to do so. I’m guessing Plots or whatever Plots backend you’re using is looking for some environment variable that emacs modifies in order to tell whether to display immediately or not, but I’m not familiar enough to say exactly what.

EDIT: glancing through the Plots.jl source code really quick, I’m guessing that something is going wrong with this __init__() code. Try comparing Base.Multimedia.displays after running using Plots from julia-repl and julia running in a regular REPL in the terminal. Maybe functions registered with atreplinit aren’t getting run with julia-repl?

EDIT2: I can’t replicate after installing julia-repl Can you post a MWE?

Thanks for taking the time, here’s a simple example where this happens.
I use the DifferentialEquations package because I’m having this problem when plotting the solution object. Once again, works in the REPL run from the terminal, no graphical output when run in julia-repl in emacs.

using DifferentialEquations, Plots


exp_growth(u,p,t) = 0.95u

solution = solve(ODEProblem(exp_growth,
                            1.0,
                            (0.0,1.0)
                            )
                 )

plot(solution)

EDIT: I also checked Base.Multimedia.displays, but I’m in over my head on this, I’m going to copy both here anyway.

Terminal:

3-element Vector{AbstractDisplay}:
 TextDisplay(Base.TTY(RawFD(13) open, 0 bytes waiting))
 REPL.REPLDisplay{REPL.LineEditREPL}(REPL.LineEditREPL(REPL.Terminals.TTYTerminal("xterm-256color", Base.TTY(RawFD(10) paused, 0 bytes waiting), Base.TTY(RawFD(13) open, 0 bytes waiting), Base.TTY(RawFD(15) open, 0 bytes waiting)), true, "\e[32m", "\e[0m", "\e[0m", "\e[31m", "\e[33m", true, false, false, true, false, nothing, REPL.Options(true, Dict{Any, Any}[], 8, 100, 0.2, 0.2, 0.2, 1.0, ["\e[90m"], true, true, true, false, true, false, false, 0.005, 0.0, Dict{Symbol, Any}()), MI State ("Prompt(\"julia> \",...)" active), [("./Base.jl", 35), ("REPL[7]", 1)], REPL.LineEdit.ModalInterface(REPL.LineEdit.TextInterface["Prompt(\"julia> \",...)", "Prompt(\"shell> \",...)", "Prompt(\"help?> \",...)", REPL.LineEdit.HistoryPrompt(REPL.REPLHistoryProvider([**history array here, I erased it**], IOStream(<file /home/tomas/.julia/logs/repl_history.jl>), 314, 322, 320, IOBuffer(data=UInt8[...], readable=true, writable=true, seekable=true, append=false, size=0, maxsize=Inf, ptr=1, mark=-1), "Prompt(\"julia> \",...)", Dict{Symbol, REPL.LineEdit.Prompt}(:julia => "Prompt(\"julia> \",...)", :help => "Prompt(\"help?> \",...)", :pkg => "Prompt(\"(@v1.7) pkg> \",...)", :shell => "Prompt(\"shell> \",...)"), [:pkg, :julia, :julia, :julia, :julia, :julia, :pkg, :julia, :julia, :julia  …  :julia, :julia, :julia, :julia, :julia, :julia, :julia, :julia, :julia, :julia]), "Prompt(\"julia> \",...)", REPL.LineEdit.EmptyCompletionProvider(), Dict{Char, Any}('\x0e' => REPL.LineEdit.var"#239#247"(), '\x10' => REPL.LineEdit.var"#238#246"(), '\U10f7ff' => REPL.LineEdit.var"#242#250"(), '\e' => Dict{Char, Any}('[' => Dict{Char, Any}('1' => Dict{Char, Any}('1' => Dict{Char, Any}('h' => REPL.LineEdit.var"#242#250"(), 'l' => REPL.LineEdit.var"#242#250"()), '7' => Dict{Char, Any}('h' => REPL.LineEdit.var"#242#250"(), 'l' => REPL.LineEdit.var"#242#250"()), '6' => Dict{Char, Any}('h' => REPL.LineEdit.var"#242#250"(), 'l' => REPL.LineEdit.var"#242#250"()), '5' => Dict{Char, Any}('h' => REPL.LineEdit.var"#242#250"(), 'l' => REPL.LineEdit.var"#242#250"()), 'h' => REPL.LineEdit.var"#242#250"(), '4' => Dict{Char, Any}('h' => REPL.LineEdit.var"#242#250"(), 'l' => REPL.LineEdit.var"#242#250"()), '8' => Dict{Char, Any}('h' => REPL.LineEdit.var"#242#250"(), 'l' => REPL.LineEdit.var"#242#250"()), '~' => REPL.LineEdit.var"#242#250"(), ';' => Dict{Char, Any}('2' => Dict{Char, Any}('\U10f7ff' => REPL.LineEdit.var"#242#250"()), '3' => Dict{Char, Any}('\U10f7ff' => REPL.LineEdit.var"#242#250"()), '5' => Dict{Char, Any}('\U10f7ff' => REPL.LineEdit.var"#242#250"())), '9' => Dict{Char, Any}('h' => REPL.LineEdit.var"#242#250"(), 'l' => REPL.LineEdit.var"#242#250"())…), '7' => Dict{Char, Any}('~' => REPL.LineEdit.var"#242#250"(), 'h' => REPL.LineEdit.var"#242#250"(), 'l' => REPL.LineEdit.var"#242#250"()), '6' => Dict{Char, Any}('~' => REPL.LineEdit.var"#242#250"(), 'h' => REPL.LineEdit.var"#242#250"(), 'l' => REPL.LineEdit.var"#242#250"()), '5' => Dict{Char, Any}('~' => REPL.LineEdit.var"#242#250"(), 'h' => REPL.LineEdit.var"#242#250"(), 'l' => REPL.LineEdit.var"#242#250"()), 'B' => REPL.LineEdit.var"#241#249"(), 'A' => REPL.LineEdit.var"#240#248"(), '4' => Dict{Char, Any}('~' => REPL.LineEdit.var"#242#250"(), 'h' => REPL.LineEdit.var"#242#250"(), 'l' => REPL.LineEdit.var"#242#250"()), '8' => Dict{Char, Any}('~' => REPL.LineEdit.var"#242#250"(), 'h' => REPL.LineEdit.var"#242#250"(), 'l' => REPL.LineEdit.var"#242#250"()), '\U10f7ff' => REPL.LineEdit.var"#242#250"(), '9' => Dict{Char, Any}('h' => REPL.LineEdit.var"#242#250"(), 'l' => REPL.LineEdit.var"#242#250"())…), '\U10f7ff' => REPL.LineEdit.var"#242#250"(), 'O' => Dict{Char, Any}('\U10f7ff' => REPL.LineEdit.var"#242#250"())), '\x18' => Dict{Char, Any}('\U10f7ff' => REPL.LineEdit.var"#242#250"()))), "Prompt(\"(@v1.7) pkg> \",...)"]), REPL.REPLBackendRef(Channel{Any}(1), Channel{Any}(1))))
 Plots.PlotsDisplay()

Emacs:

3-element Vector{AbstractDisplay}:
 TextDisplay(Base.TTY(RawFD(13) open, 0 bytes waiting))
 REPL.REPLDisplay{REPL.LineEditREPL}(REPL.LineEditREPL(REPL.Terminals.TTYTerminal("eterm-color", Base.TTY(RawFD(10) paused, 0 bytes waiting), Base.TTY(RawFD(13) open, 0 bytes waiting), Base.TTY(RawFD(15) open, 0 bytes waiting)), true, "\e[32m", "\e[0m", "\e[0m", "\e[31m", "\e[33m", true, false, false, true, false, nothing, REPL.Options(true, Dict{Any, Any}[], 8, 100, 0.2, 0.2, 0.2, 1.0, ["\e[90m"], true, true, true, false, true, false, true, 0.005, 0.0, Dict{Symbol, Any}()), MI State ("Prompt(\"julia> \",...)" active), Tuple{String, Int64}[], REPL.LineEdit.ModalInterface(REPL.LineEdit.TextInterface["Prompt(\"julia> \",...)", "Prompt(\"shell> \",...)", "Prompt(\"help?> \",...)", REPL.LineEdit.HistoryPrompt(REPL.REPLHistoryProvider([**history array here, I erased it**], IOStream(<file /home/tomas/.julia/logs/repl_history.jl>), 313, 316, -1, IOBuffer(data=UInt8[...], readable=true, writable=true, seekable=true, append=false, size=0, maxsize=Inf, ptr=1, mark=-1), nothing, Dict{Symbol, REPL.LineEdit.Prompt}(:julia => "Prompt(\"julia> \",...)", :help => "Prompt(\"help?> \",...)", :pkg => "Prompt(\"(@v1.7) pkg> \",...)", :shell => "Prompt(\"shell> \",...)"), [:pkg, :julia, :julia, :julia, :julia, :julia, :pkg, :julia, :julia, :julia  …  :julia, :julia, :julia, :julia, :julia, :julia, :julia, :julia, :julia, :julia]), REPL.LatexCompletions(), Dict{Char, Any}('\x10' => REPL.LineEdit.var"#74#105"(), '\x1f' => nothing, '\x0e' => REPL.LineEdit.var"#73#104"(), '\x13' => REPL.LineEdit.var"#49#80"(), '\0' => nothing, '\b' => REPL.LineEdit.var"#53#84"(), '\x7f' => REPL.LineEdit.KeyAlias("\b"), '\x1d' => nothing, '\f' => REPL.LineEdit.var"#52#83"(), '\n' => REPL.LineEdit.var"#50#81"{REPL.LineEdit.HistoryPrompt}(REPL.LineEdit.HistoryPrompt(#= circular reference @-3 =#))…)), REPL.LineEdit.PrefixHistoryPrompt(REPL.REPLHistoryProvider([**history array here, I erased it**], IOStream(<file /home/tomas/.julia/logs/repl_history.jl>), 313, 316, -1, IOBuffer(data=UInt8[...], readable=true, writable=true, seekable=true, append=false, size=0, maxsize=Inf, ptr=1, mark=-1), nothing, Dict{Symbol, REPL.LineEdit.Prompt}(:julia => "Prompt(\"julia> \",...)", :help => "Prompt(\"help?> \",...)", :pkg => "Prompt(\"(@v1.7) pkg> \",...)", :shell => "Prompt(\"shell> \",...)"), [:pkg, :julia, :julia, :julia, :julia, :julia, :pkg, :julia, :julia, :julia  …  :julia, :julia, :julia, :julia, :julia, :julia, :julia, :julia, :julia, :julia]), "Prompt(\"julia> \",...)", REPL.LineEdit.EmptyCompletionProvider(), Dict{Char, Any}('\x0e' => REPL.LineEdit.var"#239#247"(), '\x10' => REPL.LineEdit.var"#238#246"(), '\U10f7ff' => REPL.LineEdit.var"#242#250"(), '\e' => Dict{Char, Any}('[' => Dict{Char, Any}('1' => Dict{Char, Any}('1' => Dict{Char, Any}('h' => REPL.LineEdit.var"#242#250"(), 'l' => REPL.LineEdit.var"#242#250"()), '7' => Dict{Char, Any}('h' => REPL.LineEdit.var"#242#250"(), 'l' => REPL.LineEdit.var"#242#250"()), '6' => Dict{Char, Any}('h' => REPL.LineEdit.var"#242#250"(), 'l' => REPL.LineEdit.var"#242#250"()), '5' => Dict{Char, Any}('h' => REPL.LineEdit.var"#242#250"(), 'l' => REPL.LineEdit.var"#242#250"()), 'h' => REPL.LineEdit.var"#242#250"(), '4' => Dict{Char, Any}('h' => REPL.LineEdit.var"#242#250"(), 'l' => REPL.LineEdit.var"#242#250"()), '8' => Dict{Char, Any}('h' => REPL.LineEdit.var"#242#250"(), 'l' => REPL.LineEdit.var"#242#250"()), '~' => REPL.LineEdit.var"#242#250"(), ';' => Dict{Char, Any}('2' => Dict{Char, Any}('\U10f7ff' => REPL.LineEdit.var"#242#250"()), '3' => Dict{Char, Any}('\U10f7ff' => REPL.LineEdit.var"#242#250"()), '5' => Dict{Char, Any}('\U10f7ff' => REPL.LineEdit.var"#242#250"())), '9' => Dict{Char, Any}('h' => REPL.LineEdit.var"#242#250"(), 'l' => REPL.LineEdit.var"#242#250"())…), '7' => Dict{Char, Any}('~' => REPL.LineEdit.var"#242#250"(), 'h' => REPL.LineEdit.var"#242#250"(), 'l' => REPL.LineEdit.var"#242#250"()), '6' => Dict{Char, Any}('~' => REPL.LineEdit.var"#242#250"(), 'h' => REPL.LineEdit.var"#242#250"(), 'l' => REPL.LineEdit.var"#242#250"()), '5' => Dict{Char, Any}('~' => REPL.LineEdit.var"#242#250"(), 'h' => REPL.LineEdit.var"#242#250"(), 'l' => REPL.LineEdit.var"#242#250"()), 'B' => REPL.LineEdit.var"#241#249"(), 'A' => REPL.LineEdit.var"#240#248"(), '4' => Dict{Char, Any}('~' => REPL.LineEdit.var"#242#250"(), 'h' => REPL.LineEdit.var"#242#250"(), 'l' => REPL.LineEdit.var"#242#250"()), '8' => Dict{Char, Any}('~' => REPL.LineEdit.var"#242#250"(), 'h' => REPL.LineEdit.var"#242#250"(), 'l' => REPL.LineEdit.var"#242#250"()), '\U10f7ff' => REPL.LineEdit.var"#242#250"(), '9' => Dict{Char, Any}('h' => REPL.LineEdit.var"#242#250"(), 'l' => REPL.LineEdit.var"#242#250"())…), '\U10f7ff' => REPL.LineEdit.var"#242#250"(), 'O' => Dict{Char, Any}('\U10f7ff' => REPL.LineEdit.var"#242#250"())), '\x18' => Dict{Char, Any}('\U10f7ff' => REPL.LineEdit.var"#242#250"()))), "Prompt(\"(@v1.7) pkg> \",...)"]), REPL.REPLBackendRef(Channel{Any}(1), Channel{Any}(1))))
 Plots.PlotsDisplay()

I struggling using MELPA to install packages, in my minimal init.el I have:

;;; --- MELPA repository interface, source: https://melpa.org/#/getting-started
;;  MELPA "bleeding-edge" (default)
;;  Remark: "package.el" is the built-in package manager in Emacs v > v24.
(require 'package)
(add-to-list 'package-archives '("melpa" . "https://melpa.org/packages/") t)
(package-initialize)

My expectation was that this enables the installation of packages hosted by “Melpa”.
But I have the impression that something is still missing. My emacs version is: v28.2
Do I need to trigger something like: update-package-list?

Hi,

It should definitely be enough to activate Melpa. Is your init.el file at the right location?
(In Emacs, see the value of the variable user-init-file, for instance by typing C-h v user-init-file. Its value must match the location of your init.el file.)

1 Like

In addition to what @fsantos said: what do you see when you run M-xpackage-list-packages?

Unrelated, but I just thought I would mention that I no longer have any problems with REPL output in emacs, I switched to using vterm for the julia repl and everything just works.

3 Likes

I haven’t found a package “s”, is this a typo?
Could it be the package s-buffer?

No, it’s a package literally named “s”, written by Magnar Sveen

Thanks for the immediate reply! :slight_smile:
After a second attempt, I understood how to check, which packages are installed via

M-x package-list-packages

And I saw the package: julia-vterm.el
Is this a useful package?

I found something interesting regarding vterm:
emacs-libvterm
I hope this helps others to get started, but I do not know how to install vterm on MS Windows :frowning:

It’s my understanding that vterm doesn’t work in Windows. I run emacs under WSL2 to circumvent this limitation. Under WSL2, vterm and snail make a powerful combination for Julia development.