Hey friends!
I’m new to Julia, but I’ve been programming for a bit now. I’m mostly used to Common Lisp, Java, Kotlin, Elixir, Python, Javascript/Typescript, pretty much all shell scripting languages.
Part of my interest in Julia is the potential to use it at work, as well as general use for data analysis.
My question is regarding setting up a more “sane” development environment for working with Julia. I’ve used Emacs for several years now, mostly with Org-Mode as there’s quite a bit of finagling you have to do with Emacs to get a decent programming experience. If you want to dig around my Emacs configuration I can post it in the comments as I cannot put links in my posts yet.
So what I have so far for Emacs at least is the following:
;;;;; Julia
;;;;;
;; `ob-julia' needs this variable to be defined
;;;###autoload (defvar inferior-julia-program-name (or (executable-find "julia-basic") "julia"))
(use-package julia-ts-mode
:interpreter "julia"
:mode "\\.jl\\'"
:config
(setq-mode-local julia-ts-mode
lsp-enable-folding t
lsp-folding-range-limit 100)
;; Borrow matlab.el's fontification of math operators. From
;; <https://web.archive.org/web/20170326183805/https://ogbe.net/emacsconfig.html>
(font-lock-add-keywords
'julia-mode
`((,(let ((OR "\\|"))
(concat "\\(" ; stolen `matlab.el' operators first
;; `:` defines a symbol in Julia and must not be highlighted
;; as an operator. The only operators that start with `:` are
;; `:<` and `::`. This must be defined before `<`.
"[:<]:" OR
"[<>]=?" OR
"\\.[/*^']" OR
"===" OR
"==" OR
"=>" OR
"\\<xor\\>" OR
"[-+*\\/^&|$]=?" OR ; this has to come before next (updating operators)
"[-^&|*+\\/~]" OR
;; Julia variables and names can have `!`. Thus, `!` must be
;; highlighted as a single operator only in some
;; circumstances. However, full support can only be
;; implemented by a full parser. Thus, here, we will handle
;; only the simple cases.
"[[:space:]]!=?=?" OR "^!=?=?" OR
;; The other math operators that starts with `!`.
;; more extra julia operators follow
"[%$]" OR
;; bitwise operators
">>>" OR ">>" OR "<<" OR
">>>=" OR ">>" OR "<<" OR
"\\)"))
1 font-lock-type-face))))
;;;;;; Inferior Julia REPL
;;;;;;
(use-package julia-snail
:requires vterm
:hook (julia-ts-mode . julia-snail-mode)
:custom
(julia-snail-terminal-type :vterm))
;;;;;; For the LSP support for Julia
;;;;;;
(use-package lsp-julia
:after lsp-mode
:hook (julia-ts-mode . lsp-deferred)
:preface
(defconst lsp-julia:emacs-env
(expand-file-name "~/.julia/environment/emacs/")
"The julia environment for install LanguageServer.jl.")
:init
(make-directory lsp-julia:emacs-env t)
(general-setq lsp-julia-default-environment nil)
:custom
(lsp-julia-flags '("--startup-file=no" "--history-file=no" "--color=no"))
(lsp-julia-default-environment (string-trim
(shell-command-to-string
"julia --startup-file=no --history-file=no --color=no -e 'print(dirname(Base.active_project()))'")))
:config
(add-to-list 'lsp-language-id-configuration '(julia-ts-mode . "julia")))
Some of the stuff for lsp-julia I pulled from issue no. 49 on the lsp-julia Github. Obviously it’s not entirely finished. One thing I would recommend for anyone using lsp-mode or eglot in emacs is to check out emacs-lsp-booster which I’ve heard good things about and if you use eglot you can check out eglot-booster.
Now here’s a few questions I have. For lsp-julia, it’s recommended that:
Additionally because JIT compilation of
LanguageServer.jl
can cause a long delay which may cause issues withlsp-mode
, I recommend usingPackageCompiler.jl
to AOT compileLanguageServer.jl
into your julia image.
So in order to streamline this process, I thought I’d write a script. Not sure if it’s entirely correct, but it’s what I have so far:
#!/usr/bin/env julia --startup-file=no --history-file=no --color=no
using Pkg
const pkg_name = ARGS[1]
const img_output = ARGS[2] # the path to output the image to
Pkg.add("PackageCompiler")
Pkg.update()
using PackageCompiler
# This is where is gets funky
create_sysimage(
# Figure how to intern a string into an atom like :LanguageServer or whatever
sysimage_path=dirname(img_output * "figure out how to create the name of the *.so file")
)
Not sophisticated, but if I can figure out a few other things it’ll be good for my uses as well as have it be generic to use for potentially compiling an image for other packages in the future if need be.
Now comes using the script and running the lsp server, and this is where it gets a little funky. I could follow what’s mentioned in that previously mentioned Github issue on lsp-julia, which would be fine, but I’d like to actually understand some things about how it all works together, if anyone is willing to explain.
I have only two other things to ask:
- Is all of the above really “sane”?
- How do you setup your development environment?