Repository: Deltares/Wflow.jl (julia)

Issue:
provide ANSI aliases for TOML file
We've had several reports of users whose text editors don't like the unicode characters we use here:

https://github.com/Deltares/Wflow.jl/blob/67b44dac62774226feaa014f372de213d8eac071/test/sbm_simple.toml#L36
https://github.com/Deltares/Wflow.jl/blob/67b44dac62774226feaa014f372de213d8eac071/test/sbm_simple.toml#L56-L57

In the code we use this as well, and that is no problem, but for the TOML file it is in hindsight probably better to avoid them. To do this without breaking old TOML files, we could provide ANSI aliases.

`"θᵣ"` could then become `theta_r` for instance.

Pull request description:
Fixes #124.

Patch:
diff --git a/docs/src/changelog.md b/docs/src/changelog.md
index 4d78bcd37..880f7614a 100644
--- a/docs/src/changelog.md
+++ b/docs/src/changelog.md
@@ -17,6 +17,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
 - Multi-threading of vertical SBM concept and lateral kinematic wave components (overland,
   river and subsurface flow) of wflow\_sbm model [SBM + Kinematic wave](@ref).
 - Improved error message for CSV Reducer.
+- The TOML keys `kv₀`, `θᵣ` and `θₛ` have been replaced with the ASCII versions `kv_0`,
+  `θ_r` and `θ_s`, to avoid encoding issues with certain text editors. The old keys still
+  work as well.
 
 ### Fixed
 - Calculation of volumetric water content of vertical SBM (soil layers and root zone).
diff --git a/src/io.jl b/src/io.jl
index 411bedf00..1ef1fc2e8 100644
--- a/src/io.jl
+++ b/src/io.jl
@@ -55,6 +55,10 @@ function Base.setproperty!(config::Config, f::Symbol, x)
     return dict[String(f)] = x
 end
 
+function get_alias(config::Config, key, alias, default)
+    get(Dict(config), key, get(Dict(config), alias, default))
+end
+
 # also used in autocomplete
 Base.propertynames(config::Config) = collect(keys(Dict(config)))
 Base.haskey(config::Config, key) = haskey(Dict(config), key)
@@ -62,7 +66,10 @@ Base.keys(config::Config) = keys(Dict(config))
 Base.values(config::Config) = values(Dict(config))
 Base.pairs(config::Config) = pairs(Dict(config))
 Base.get(config::Config, key, default) = get(Dict(config), key, default)
-Base.getindex(config::Config, i) = getindex(Dict(config), i)
+Base.getindex(config::Config, key) = getindex(Dict(config), key)
+Base.setindex!(config::Config, val, key) = setindex!(Dict(config), val, key)
+Base.pop!(config::Config, key) = pop!(Dict(config), key)
+Base.pop!(config::Config, key, default) = pop!(Dict(config), key, default)
 Base.Dict(config::Config) = getfield(config, :dict)
 Base.pathof(config::Config) = getfield(config, :path)
 Base.dirname(config::Config) = dirname(pathof(config))
diff --git a/src/sbm.jl b/src/sbm.jl
index 214468415..14e308fb3 100644
--- a/src/sbm.jl
+++ b/src/sbm.jl
@@ -364,14 +364,14 @@ function initialize_sbm(nc, config, riverfrac, inds)
     # soil parameters
     θₛ = ncread(
         nc,
-        param(config, "input.vertical.θₛ", nothing);
+        get_alias(config.input.vertical, "theta_s", "θₛ", nothing);
         sel = inds,
         defaults = 0.6,
         type = Float,
     )
     θᵣ = ncread(
         nc,
-        param(config, "input.vertical.θᵣ", nothing);
+        get_alias(config.input.vertical, "theta_r", "θᵣ", nothing);
         sel = inds,
         defaults = 0.01,
         type = Float,
@@ -379,7 +379,7 @@ function initialize_sbm(nc, config, riverfrac, inds)
     kv₀ =
         ncread(
             nc,
-            param(config, "input.vertical.kv₀", nothing);
+            get_alias(config.input.vertical, "kv_0", "kv₀", nothing);
             sel = inds,
             defaults = 3000.0,
             type = Float,


Test patch:
diff --git a/test/io.jl b/test/io.jl
index 744bf379c..6ab82d2f1 100644
--- a/test/io.jl
+++ b/test/io.jl
@@ -22,6 +22,12 @@ config = Wflow.Config(tomlpath)
     @test config.output.path == "data/output_moselle.nc"
     @test config.output isa Wflow.Config
     @test collect(keys(config.output)) == ["lateral", "vertical", "path"]
+
+    # theta_s can also be provided under the alias θₛ
+    Wflow.get_alias(config.input.vertical, "theta_s", "θₛ", nothing) == "thetaR"
+    val = pop!(config.input.vertical, "theta_s")
+    config.input.vertical["θₛ"] = val
+    Wflow.get_alias(config.input.vertical, "theta_s", "θₛ", nothing) == "thetaR"
 end
 
 @testset "Clock constructor" begin
diff --git a/test/sbm_config.toml b/test/sbm_config.toml
index 8630c98f9..3172e4b80 100644
--- a/test/sbm_config.toml
+++ b/test/sbm_config.toml
@@ -69,7 +69,7 @@ f = "f"
 infiltcappath = "InfiltCapPath"
 infiltcapsoil = "InfiltCapSoil"
 kext = "Kext"
-"kv₀" = "KsatVer"
+kv_0 = "KsatVer"
 leaf_area_index = "LAI"
 maxleakage = "MaxLeakage"
 pathfrac = "PathFrac"
@@ -86,8 +86,8 @@ tti = "TTI"
 ttm = "TTM"
 water_holding_capacity = "WHC"
 waterfrac = "WaterFrac"
-"θᵣ" = "thetaR"
-"θₛ" = "thetaS"
+theta_r = "thetaR"
+theta_s = "thetaS"
 
 [input.lateral.river]
 length = "wflow_riverlength"
diff --git a/test/sbm_gw.toml b/test/sbm_gw.toml
index 00d9dc43a..861a0a66a 100644
--- a/test/sbm_gw.toml
+++ b/test/sbm_gw.toml
@@ -66,7 +66,7 @@ f = "f"
 infiltcappath = "InfiltCapPath"
 infiltcapsoil = "InfiltCapSoil"
 kext = "Kext"
-"kv₀" = "KsatVer"
+kv_0 = "KsatVer"
 leaf_area_index = "LAI"
 maxleakage = "MaxLeakage"
 pathfrac = "PathFrac"
@@ -83,8 +83,8 @@ tti = "TTI"
 ttm = "TTM"
 water_holding_capacity = "WHC"
 waterfrac = "WaterFrac"
-"θᵣ" = "thetaR"
-"θₛ" = "thetaS"
+theta_r = "thetaR"
+theta_s = "thetaS"
 
 [input.lateral.river]
 length = "wflow_riverlength"
diff --git a/test/sbm_gwf_config.toml b/test/sbm_gwf_config.toml
index 2f82850c0..748e0e693 100644
--- a/test/sbm_gwf_config.toml
+++ b/test/sbm_gwf_config.toml
@@ -54,15 +54,15 @@ canopygapfraction = "canopygapfraction"
 cmax = "cmax"
 e_r = "EoverR"
 infiltcapsoil = "InfiltCapSoil"
-"kv₀" = "kv"
+kv_0 = "kv"
 m = "M"
 pathfrac = "PathFrac"
 potential_evaporation = "PET"
 precipitation = "P"
 rootingdepth = "rootingdepth"
 soilthickness = "soilthickness"
-"θᵣ" = "thetaR"
-"θₛ" = "thetaS"
+theta_r = "thetaR"
+theta_s = "thetaS"
 
 [input.lateral.river]
 length = "wflow_riverlength"
diff --git a/test/sbm_simple.toml b/test/sbm_simple.toml
index 2e7ba50bf..60d30bb45 100644
--- a/test/sbm_simple.toml
+++ b/test/sbm_simple.toml
@@ -33,7 +33,7 @@ e_r = "EoverR"
 infiltcappath = "InfiltCapPath"
 infiltcapsoil = "InfiltCapSoil"
 kext = "Kext"
-"kv₀" = "KsatVer"
+kv_0 = "KsatVer"
 leaf_area_index = "LAI"
 m = "M"
 maxleakage = "MaxLeakage"
@@ -53,8 +53,8 @@ ttm = "TTM"
 w_soil = "wflow_soil"
 water_holding_capacity = "WHC"
 waterfrac = "WaterFrac"
-"θᵣ" = "thetaR"
-"θₛ" = "thetaS"
+theta_r = "thetaR"
+theta_s = "thetaS"
 
 [input.lateral.river]
 length = "wflow_riverlength"