basho / cuttlefish

never lose your childlike sense of wonder baby cuttlefish, promise me?
Apache License 2.0
205 stars 124 forks source link

Right Hand Side Substitutions #116

Closed joedevivo closed 10 years ago

joedevivo commented 10 years ago

This is the ability to have settings depend on other settings, either explicitly or by default.

Imagine a riak.conf file:

##
## Default: ./data
##
## Acceptable values:
##   - the path to a directory
platform_data_dir = ./lore

## Default location of ringstate
##
## Default: #(platform_data_dir)/ring
##
## Acceptable values:
##   - the path to a directory
ring.state_dir = #(platform_data_dir)/ring

If you change platform_data_dir, ring.state_dir will also change

The effective config will still display the relative value:

...
platform_data_dir = ./lore
ring.state_dir = #(platform_data_dir)/ring
...

But the generated app.config will have a hard substitution

[
  {riak_core, [
    {platform_data_dir, "./lore"},
    {ring_state_dir, "./lore/ring"}
  ]}
].

This will allow for a more consistent experience when sub directories in riak.

Here are some caveats:

I'll open up a PR against riak_core so you can see how this would work in practice.

bookshelfdave commented 10 years ago

eunit tests pass: https://gist.github.com/metadave/8845130

Vagabond commented 10 years ago

+1 from me.

bookshelfdave commented 10 years ago

I EQC'd and found some edge cases where variable names are whitespace or "foo)bar", but it seems like you are asking for trouble and maybe you SHOULD be punished if you do that?

here's my crappy/"cheaty"/incomplete EQC:

not_empty(G) ->
    ?SUCHTHAT(X, G, X /= [] andalso X /= <<>>).
lower_char() ->
    choose(16#20, 16#7f).
non_blank_string() ->
    %% don't allow whitespace at either end, but it's fine in the middle
    ?LET(X, not_empty(list(lower_char())), list_to_binary("X" ++ X ++ "X")).

prop_sub() ->
    ?FORALL({Var0, Val0}, {non_blank_string(), non_blank_string() },
            begin
            Var = erlang:binary_to_list(Var0),
            Val = erlang:binary_to_list(Val0),
    Conf = [
            {[Var,"b","c"], "#(" ++ Var ++ ".b)/c"},
            {[Var,"b"], Val}
           ],
    {NewConf, Errors} = value_sub(Conf),
    ?assertEqual([], Errors),
    ABC = proplists:get_value([Var,"b","c"], NewConf),
    Val ++ "/c" == ABC
            end).

+1, tests pass fine, code reads fine.

gburd commented 10 years ago

+1