Skip to content

Commit

Permalink
Add Julia formatter (#230)
Browse files Browse the repository at this point in the history
This formatter uses a script wrapping the [JuliaFormatter.jl library](https://github.com/domluna/JuliaFormatter.jl).  This "formatter script in the plugin" approach hasn't been taken before in `vim-codefmt`, so let me know if you'd prefer a different approach or to reorganize things.  (The JuliaFormatter.jl library ships with an executable script, but it only works on file paths (not stdin) and can't handle line ranges.  I'm also not sure how to get the path of a bin directory in your Julia environment, which doesn't work like executables in a package management system like npm.)

If the user hasn't installed the `JuliaFormatter` package, instructions will point to an `install` script in the same directory as the formatter script.  I've tested the shell version of this script, but don't have a Windows machine to test the `.cmd` version.

The line-range handling is a bit of a hack: the underlying library doesn't expose this functionality, so I used comments to enable/disable the formatter around relevant blocks.  I found some edge case behaviors that I've hopefully documented clearly.

The script will use the same `.JuliaFormatter.toml` files in the parent directory hierarchy of the source file being edited to determine the formatter options like style, indent, and line width.  This is the same behavior that running the executable from JuliaFormatter.
  • Loading branch information
dbarnett authored Nov 24, 2023
2 parents 03b8f30 + ae8bd7a commit 22e551a
Show file tree
Hide file tree
Showing 11 changed files with 662 additions and 0 deletions.
76 changes: 76 additions & 0 deletions autoload/codefmt/juliaformatter.vim
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
" Copyright 2023 Google LLC
"
" Licensed under the Apache License, Version 2.0 (the "License");
" you may not use this file except in compliance with the License.
" You may obtain a copy of the License at
"
" http://www.apache.org/licenses/LICENSE-2.0
"
" Unless required by applicable law or agreed to in writing, software
" distributed under the License is distributed on an "AS IS" BASIS,
" WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
" See the License for the specific language governing permissions and
" limitations under the License.

let s:plugin = maktaba#plugin#Get('codefmt')

let s:checkedInstall = 0

""
" @private
" Formatter: JuliaFormatter
function! codefmt#juliaformatter#GetFormatter() abort
let l:installer =
\ maktaba#path#Join([s:plugin.location, 'bin', 'julia', 'install'])
let l:formatter = {
\ 'name': 'JuliaFormatter', 'setup_instructions': 'Run ' . l:installer}

function l:formatter.IsAvailable() abort
let l:cmd = codefmt#formatterhelpers#ResolveFlagToArray('julia_format_executable')
if codefmt#ShouldPerformIsAvailableChecks()
if !executable(l:cmd[0])
return 0
endif
if !s:checkedInstall
let s:checkedInstall = 1
let l:syscall = maktaba#syscall#Create([cmd[0], "--check-install"])
call l:syscall.Call(0)
if v:shell_error != 0
return 0
endif
endif
endif
return 1
endfunction

function l:formatter.AppliesToBuffer() abort
return codefmt#formatterhelpers#FiletypeMatches(&filetype, 'julia')
endfunction

""
" Reformat the current buffer using formatjulia.jl, only targeting {ranges}.
function l:formatter.FormatRanges(ranges) abort
if empty(a:ranges)
return
endif
for [l:startline, l:endline] in a:ranges
call maktaba#ensure#IsNumber(l:startline)
call maktaba#ensure#IsNumber(l:endline)
endfor
let l:exec = s:plugin.Flag('julia_format_executable')
if empty(l:exec)
let l:cmd = [maktaba#path#Join(
\ [s:plugin.location, 'bin', 'julia', 'formatjulia.jl'])]
else
" Split the command on spaces, unless preceeded by a backslash
let l:cmd = split(l:exec, '\\\@<! ')
endif
" JuliaFormatter looks up .JuliaFormatter.toml settings based on file tree
let l:cmd += ['--file-path', @%]
let l:cmd += ['--lines']
let l:cmd += maktaba#function#Map(a:ranges, {x -> x[0] . ':' . x[1]})
call codefmt#formatterhelpers#Format(l:cmd)
endfunction

return l:formatter
endfunction
18 changes: 18 additions & 0 deletions bin/julia/.JuliaFormatter.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Copyright 2023 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

indent = 2
margin = 80
trailing_comma = false
whitespace_in_kwargs = false
232 changes: 232 additions & 0 deletions bin/julia/Manifest.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,232 @@
# This file is machine-generated - editing it directly is not advised

julia_version = "1.9.3"
manifest_format = "2.0"
project_hash = "93e024a7bf6c9615a79c4b80b3a014b0f1f744c9"

[[deps.ArgParse]]
deps = ["Logging", "TextWrap"]
git-tree-sha1 = "3102bce13da501c9104df33549f511cd25264d7d"
uuid = "c7e460c6-2fb9-53a9-8c5b-16f535851c63"
version = "1.1.4"

[[deps.ArgTools]]
uuid = "0dad84c5-d112-42e6-8d28-ef12dabb789f"
version = "1.1.1"

[[deps.Artifacts]]
uuid = "56f22d72-fd6d-98f1-02f0-08ddc0907c33"

[[deps.Base64]]
uuid = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f"

[[deps.CSTParser]]
deps = ["Tokenize"]
git-tree-sha1 = "3ddd48d200eb8ddf9cb3e0189fc059fd49b97c1f"
uuid = "00ebfdb7-1f24-5e51-bd34-a7502290713f"
version = "3.3.6"

[[deps.CommonMark]]
deps = ["Crayons", "JSON", "PrecompileTools", "URIs"]
git-tree-sha1 = "532c4185d3c9037c0237546d817858b23cf9e071"
uuid = "a80b9123-70ca-4bc0-993e-6e3bcb318db6"
version = "0.8.12"

[[deps.Compat]]
deps = ["UUIDs"]
git-tree-sha1 = "8a62af3e248a8c4bad6b32cbbe663ae02275e32c"
uuid = "34da2185-b29b-5c13-b0c7-acf172513d20"
version = "4.10.0"

[deps.Compat.extensions]
CompatLinearAlgebraExt = "LinearAlgebra"

[deps.Compat.weakdeps]
Dates = "ade2ca70-3891-5945-98fb-dc099432e06a"
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"

[[deps.Crayons]]
git-tree-sha1 = "249fe38abf76d48563e2f4556bebd215aa317e15"
uuid = "a8cc5b0e-0ffa-5ad4-8c14-923d3ee1735f"
version = "4.1.1"

[[deps.DataStructures]]
deps = ["Compat", "InteractiveUtils", "OrderedCollections"]
git-tree-sha1 = "3dbd312d370723b6bb43ba9d02fc36abade4518d"
uuid = "864edb3b-99cc-5e75-8d2d-829cb0a9cfe8"
version = "0.18.15"

[[deps.Dates]]
deps = ["Printf"]
uuid = "ade2ca70-3891-5945-98fb-dc099432e06a"

[[deps.Downloads]]
deps = ["ArgTools", "FileWatching", "LibCURL", "NetworkOptions"]
uuid = "f43a241f-c20a-4ad4-852c-f6b1247861c6"
version = "1.6.0"

[[deps.FileWatching]]
uuid = "7b1f6079-737a-58dc-b8bc-7a2ca5c1b5ee"

[[deps.Glob]]
git-tree-sha1 = "97285bbd5230dd766e9ef6749b80fc617126d496"
uuid = "c27321d9-0574-5035-807b-f59d2c89b15c"
version = "1.3.1"

[[deps.InteractiveUtils]]
deps = ["Markdown"]
uuid = "b77e0a4c-d291-57a0-90e8-8db25a27a240"

[[deps.JSON]]
deps = ["Dates", "Mmap", "Parsers", "Unicode"]
git-tree-sha1 = "31e996f0a15c7b280ba9f76636b3ff9e2ae58c9a"
uuid = "682c06a0-de6a-54ab-a142-c8b1cf79cde6"
version = "0.21.4"

[[deps.JuliaFormatter]]
deps = ["CSTParser", "CommonMark", "DataStructures", "Glob", "Pkg", "PrecompileTools", "Tokenize"]
git-tree-sha1 = "3d5b5b539e4606dcca0e6a467b98a64c8da4850b"
uuid = "98e50ef6-434e-11e9-1051-2b60c6c9e899"
version = "1.0.42"

[[deps.LibCURL]]
deps = ["LibCURL_jll", "MozillaCACerts_jll"]
uuid = "b27032c2-a3e7-50c8-80cd-2d36dbcbfd21"
version = "0.6.3"

[[deps.LibCURL_jll]]
deps = ["Artifacts", "LibSSH2_jll", "Libdl", "MbedTLS_jll", "Zlib_jll", "nghttp2_jll"]
uuid = "deac9b47-8bc7-5906-a0fe-35ac56dc84c0"
version = "7.84.0+0"

[[deps.LibGit2]]
deps = ["Base64", "NetworkOptions", "Printf", "SHA"]
uuid = "76f85450-5226-5b5a-8eaa-529ad045b433"

[[deps.LibSSH2_jll]]
deps = ["Artifacts", "Libdl", "MbedTLS_jll"]
uuid = "29816b5a-b9ab-546f-933c-edad1886dfa8"
version = "1.10.2+0"

[[deps.Libdl]]
uuid = "8f399da3-3557-5675-b5ff-fb832c97cbdb"

[[deps.Logging]]
uuid = "56ddb016-857b-54e1-b83d-db4d58db5568"

[[deps.Markdown]]
deps = ["Base64"]
uuid = "d6f4376e-aef5-505a-96c1-9c027394607a"

[[deps.MbedTLS_jll]]
deps = ["Artifacts", "Libdl"]
uuid = "c8ffd9c3-330d-5841-b78e-0817d7145fa1"
version = "2.28.2+0"

[[deps.Mmap]]
uuid = "a63ad114-7e13-5084-954f-fe012c677804"

[[deps.MozillaCACerts_jll]]
uuid = "14a3606d-f60d-562e-9121-12d972cd8159"
version = "2022.10.11"

[[deps.NetworkOptions]]
uuid = "ca575930-c2e3-43a9-ace4-1e988b2c1908"
version = "1.2.0"

[[deps.OrderedCollections]]
git-tree-sha1 = "2e73fe17cac3c62ad1aebe70d44c963c3cfdc3e3"
uuid = "bac558e1-5e72-5ebc-8fee-abe8a469f55d"
version = "1.6.2"

[[deps.Parsers]]
deps = ["Dates", "PrecompileTools", "UUIDs"]
git-tree-sha1 = "716e24b21538abc91f6205fd1d8363f39b442851"
uuid = "69de0a69-1ddd-5017-9359-2bf0b02dc9f0"
version = "2.7.2"

[[deps.Pkg]]
deps = ["Artifacts", "Dates", "Downloads", "FileWatching", "LibGit2", "Libdl", "Logging", "Markdown", "Printf", "REPL", "Random", "SHA", "Serialization", "TOML", "Tar", "UUIDs", "p7zip_jll"]
uuid = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f"
version = "1.9.2"

[[deps.PrecompileTools]]
deps = ["Preferences"]
git-tree-sha1 = "03b4c25b43cb84cee5c90aa9b5ea0a78fd848d2f"
uuid = "aea7be01-6a6a-4083-8856-8a6e6704d82a"
version = "1.2.0"

[[deps.Preferences]]
deps = ["TOML"]
git-tree-sha1 = "00805cd429dcb4870060ff49ef443486c262e38e"
uuid = "21216c6a-2e73-6563-6e65-726566657250"
version = "1.4.1"

[[deps.Printf]]
deps = ["Unicode"]
uuid = "de0858da-6303-5e67-8744-51eddeeeb8d7"

[[deps.REPL]]
deps = ["InteractiveUtils", "Markdown", "Sockets", "Unicode"]
uuid = "3fa0cd96-eef1-5676-8a61-b3b8758bbffb"

[[deps.Random]]
deps = ["SHA", "Serialization"]
uuid = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"

[[deps.SHA]]
uuid = "ea8e919c-243c-51af-8825-aaa63cd721ce"
version = "0.7.0"

[[deps.Serialization]]
uuid = "9e88b42a-f829-5b0c-bbe9-9e923198166b"

[[deps.Sockets]]
uuid = "6462fe0b-24de-5631-8697-dd941f90decc"

[[deps.TOML]]
deps = ["Dates"]
uuid = "fa267f1f-6049-4f14-aa54-33bafae1ed76"
version = "1.0.3"

[[deps.Tar]]
deps = ["ArgTools", "SHA"]
uuid = "a4e569a6-e804-4fa4-b0f3-eef7a1d5b13e"
version = "1.10.0"

[[deps.TextWrap]]
git-tree-sha1 = "9250ef9b01b66667380cf3275b3f7488d0e25faf"
uuid = "b718987f-49a8-5099-9789-dcd902bef87d"
version = "1.0.1"

[[deps.Tokenize]]
git-tree-sha1 = "0454d9a9bad2400c7ccad19ca832a2ef5a8bc3a1"
uuid = "0796e94c-ce3b-5d07-9a54-7f471281c624"
version = "0.5.26"

[[deps.URIs]]
git-tree-sha1 = "67db6cc7b3821e19ebe75791a9dd19c9b1188f2b"
uuid = "5c2747f8-b7ea-4ff2-ba2e-563bfd36b1d4"
version = "1.5.1"

[[deps.UUIDs]]
deps = ["Random", "SHA"]
uuid = "cf7118a7-6976-5b1a-9a39-7adc72f591a4"

[[deps.Unicode]]
uuid = "4ec0a83e-493e-50e2-b9ac-8f72acf5a8f5"

[[deps.Zlib_jll]]
deps = ["Libdl"]
uuid = "83775a58-1f1d-513f-b197-d71354ab007a"
version = "1.2.13+0"

[[deps.nghttp2_jll]]
deps = ["Artifacts", "Libdl"]
uuid = "8e850ede-7688-5339-a07c-302acd2aaf8d"
version = "1.48.0+0"

[[deps.p7zip_jll]]
deps = ["Artifacts", "Libdl"]
uuid = "3f19e933-33d8-53b3-aaab-bd5110c3b7a0"
version = "17.4.0+0"
8 changes: 8 additions & 0 deletions bin/julia/Project.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
name = "julia"
uuid = "f7e72769-0d4f-4e1c-bb39-275b23f83607"
authors = ["Trevor Stone <github@trevorstone.org>"]
version = "0.1.0"

[deps]
ArgParse = "c7e460c6-2fb9-53a9-8c5b-16f535851c63"
JuliaFormatter = "98e50ef6-434e-11e9-1051-2b60c6c9e899"
Loading

0 comments on commit 22e551a

Please sign in to comment.