最近Pluto.jlをPlots.jlのお試し用に色々使っているのだが, そういやPlutoPlotly.jl ってあったよなぁと思ってPluto.jl上で,
using PlutoPlotly
とするといきなりエラー。まる一日かかってようやく原因が分かる。
最初はよく分からなかったのだが,エラーメッセージのプ
'が'原因を解く鍵だった。
julia> using PlutoPlotly Precompiling PlutoPlotly Info Given PlutoPlotly was explicitly requested, output will be shown live ERROR: LoadError: InitError: StringIndexError: invalid index [41], valid nearby indices [39]=>'プ', [42]=>'\"' Stacktrace: [1] string_index_err(s::String, i::Int64) @ Base ./strings/string.jl:12 [2] SubString{String}(s::String, i::Int64, j::Int64) @ Base ./strings/substring.jl:35 [3] SubString @ ./strings/substring.jl:41 [inlined] [4] SubString @ ./strings/substring.jl:47 [inlined] [5] SubString @ ./strings/substring.jl:43 [inlined] [6] getindex @ ./strings/substring.jl:292 [inlined] [7] parseuserdirs(configdir::String) @ BaseDirs ~/.julia/packages/BaseDirs/tgw06/src/unix.jl:23 [8] reload() @ BaseDirs ~/.julia/packages/BaseDirs/tgw06/src/unix.jl:56 [9] __init__() @ BaseDirs ~/.julia/packages/BaseDirs/tgw06/src/BaseDirs.jl:38
まず答えから言うと,BaseDirs/src/unix.jlの23行目 が原因で,そのまま原因の関数のソースを抜粋してみる。
function parseuserdirs(configdir::String) validnames = ("XDG_DESKTOP_DIR", "XDG_DOWNLOAD_DIR", "XDG_TEMPLATES_DIR", "XDG_PUBLICSHARE_DIR", "XDG_DOCUMENTS_DIR", "XDG_MUSIC_DIR", "XDG_PICTURES_DIR", "XDG_VIDEOS_DIR") userdirsfile = joinpath(configdir, "user-dirs.dirs") if isfile(userdirsfile) keys = Symbol[] values = String[] for line in Iterators.map(strip, eachline(userdirsfile)) if !startswith(line, '#') && occursin('=', line) key, value = split(line, '=', limit=2) if key in validnames if startswith(value, '"') && endswith(value, '"') value = unescape_string(value[2:end-1]) # 23行目 end if startswith(value, "\$HOME") value = string(homedir(), value[6:end]) end if startswith(value, '/') push!(keys, Symbol(key)) push!(values, value) end end end end NamedTuple{Tuple(keys)}(values) else (;) end end
ソースの中身としてはuserdirsfile
の設定ファイルを読み込んでvalue
を加工してキー・バリューのNamedTupleを作ろうとしているのだが,
一目value[2:end-1]
が原因というのが分かる。utf-8でマルチバイト文字がある時,1文字のうちの2byte目以降のインデックスを
参照すると一発エラーとなるからだ。
ちなみにuserdirsfile
はだいたい~/.config/user-dirs.dirs
で,コメント行を除くと私の使っている
ubuntu 23.10では次のような感じ。
XDG_DESKTOP_DIR="$HOME/デスクトップ" XDG_DOWNLOAD_DIR="$HOME/ダウンロード" XDG_TEMPLATES_DIR="$HOME/テンプレート" XDG_PUBLICSHARE_DIR="$HOME/公開" XDG_DOCUMENTS_DIR="$HOME/ドキュメント" XDG_MUSIC_DIR="$HOME/ミュージック" XDG_PICTURES_DIR="$HOME/ピクチャ" XDG_VIDEOS_DIR="$HOME/ビデオ"
大体ubuntu Desktopで日本語インストールしてそのままならこういう設定になっている。エラーに「プ」があるので,この一行目でエラーになっているらしい。再現するのも簡単で,Replで次のようにして再現できた。
julia> line="XDG_DESKTOP_DIR=\"\$HOME/デスクトップ\"" "XDG_DESKTOP_DIR=\"\$HOME/デスクトップ\"" julia> key, value = split(line, '=', limit=2) 2-element Vector{SubString{String}}: "XDG_DESKTOP_DIR" "\"\$HOME/デスクトップ\"" julia> value[2:end-1] ERROR: StringIndexError: invalid index [41], valid nearby indices [39]=>'プ', [42]=>'\"' Stacktrace: [1] string_index_err(s::String, i::Int64) @ Base ./strings/string.jl:12 [2] SubString{String}(s::String, i::Int64, j::Int64) @ Base ./strings/substring.jl:35 [3] SubString @ ./strings/substring.jl:41 [inlined] [4] SubString @ ./strings/substring.jl:47 [inlined] [5] SubString @ ./strings/substring.jl:43 [inlined] [6] getindex(s::SubString{String}, r::UnitRange{Int64}) @ Base ./strings/substring.jl:292 [7] top-level scope @ REPL[4]:1
まぁindexを使わずに先頭と最後の"
をとってしまえばいいので,
厳密に直すならreplace(value, r"^\"" => "", r"\"$" => "")
とか 少し横着するなら strip(value, '"')
ぐらいでもOKか。
julia> replace(value, r"^\"" => "", r"\"$" => "") "\$HOME/デスクトップ" julia> strip(value, '"') "\$HOME/デスクトップ"
プルリクを出すか,イシューを上げるか…
どちらで直すかよく分からないので,イシューかな?
一応,暫定でLinux側の設定を修正しない時は
(@v1.10) pkg> dev BaseDirs
から,~/.julia/dev/BaseDirs/src/unix.jl
を次のような感じで修正した後,
パッケージモードからadd PlutoPlotly
ができるようになるのでやっておく。
index 3f10214..d31aab8 100644 --- a/src/unix.jl +++ b/src/unix.jl @@ -20,7 +20,7 @@ function parseuserdirs(configdir::String) key, value = split(line, '=', limit=2) if key in validnames if startswith(value, '"') && endswith(value, '"') - value = unescape_string(value[2:end-1]) + value = unescape_string(strip(value, ['"'])) end if startswith(value, "\$HOME") value = string(homedir(), value[6:end])
Plutoのノートブックからは最初の方のセルに
begin use Pkg Pkg.develop("BaseDirs") using PlutoPlotly end
とかやると,Plutoのパッケージ管理から外れた状態で実行可能となる。
まぁ修正依頼かけるしかないよなぁ…めんどい。
追記(2/17 18:00過ぎ)
イシュー投げたら速攻で対応 され,しかもindexアクセスしていた他のソースも修正され,テストも追加されていました。 私と違って全然仕事早いっすわ。こんな人になりたかった。
chop関数
知らんかったっす。また参考にします。