Comments (12)
@dhruvkb There isn't currently. I'll be getting to a version of what I posted above soon.
from figment.
I went ahead and hard-coded adjoin
, which provides the requested functionality. It would be nice to get the generic version in, but hopefully this suffices for now. If someone else comes across this issue with a use-case for the generic version, I'd be really interesting in hearing it!
from figment.
@SergioBenitez I'm actually looking for a function where the latter values overwrites the former value (like
merge
), except in the case of vectors where they are concatenated (likeadjoin
)... anadmerge
, if you will.I made the changes I need in a fork as a demo. I'd be happy to open a PR if you would consider merging this.
Sure, let's get it merged!
from figment.
It's an interesting concept, but I'm not sure how this would really work. What kind of API are you envisioning? Do you have a use-case motivating the idea?
from figment.
My usecase is a list of saved objects (In my case search and replace filters). My goal is that I as Developer do some prebuild ones, the OS maintaers or package maintainers can provide some and the user can save them.
How I would mark this when defining the struct
#[derive(Serialize, Desearialize)]
#[figment]
struct Config {
#[figment(append_vec)]
presets: Vec<Preset>
// Treat this vector like you do now
other_vec: Vec<String>
}
#[derive(Serialize, Desearialize)]
struct Preset {
name: String,
search: String,
replace: String
}
from figment.
I thought about this some more today. One idea is to make join
and merge
configurable.
Internally, Figment has a provide
method on Figment
that switches between joining and merging. We could expose this method and make it easier to use. We would still provide join
and merge
, but we'd also allow completely custom conflict-resolution via provide
. I think this would be awesome.
I'd be open to API ideas here. I don't have any specific ideas in mind. We obviously want it to be simple to implement the merge
, join
, and append
strategy you've specified above. I'd be totally open to design ideas.
from figment.
That would be great, so we can handle special cases/needs like this without having to work around the existing implementation.
There should be an easy way to only overwrite it for specific fields though:
#[derive(Serialize, Desearialize, Figment)]
struct Config {
#[figment(custom_parser)]
presets: Vec<Preset>
// Treat this vector like you do now
other_vec: Vec<String>
}
#[derive(Serialize, Desearialize)]
struct Preset {
name: String,
search: String,
replace: String
}
That way the default one should just skip the field, but parse all other ones, and panic (if possible, send a compiler error) when there is no custom parser for the fields marked.
Maybe it makes sense, to do this specific thing build in, since I assume what I am doing is rather common. But custom parsers would make it more flexible for others.
from figment.
Figment doesn't have a custom derive now, and I don't think we should add one. It adds a lot of complexity to the codebase, especially in terms of publishing and testing, and it adds a whole layer of compatibility issues with user's code. Plus, there's really no need for it in this case.
The approach I want to take, and the one I was alluding to, is to make the aforementioned provide()
method generic on the conflict resolution mechanism:
fn provide<T: Provider, R: Resolver>(self, provider: T, resolver: R) -> Self;
The question is what the Resolver
trait should look like. The current implementation of something similar in Figment is pretty complex, and it's probably not what we want to expose. But something like it would be nice. I'll think about this a bit more now and report back when I have something.
from figment.
Update: I have a working implementation of the idea that I'm not yet quite happy enough with. Implementing the "join vector" strategy looks like this:
/// ```rust
/// use figment::Figment;
/// use figment::coalesce::JoinVecs;
///
/// let vec: Vec<u8> = Figment::new()
/// .join(("k", vec![1, 2, 3]))
/// .provide(("k", vec![4, 5, 6]), JoinVecs)
/// .extract_inner("k")
/// .unwrap();
///
/// assert_eq!(vec, vec![1, 2, 3, 4, 5, 6]);
/// ```
pub struct JoinVecs;
impl Coalescer for JoinVecs {
fn coalesce_selection(&mut self, first: Profile, second: Profile) -> Profile {
first.join_with(second, self)
}
fn coalesce_data(&mut self, first: Data, second: Data) -> Data {
first.join_with(second, self)
}
fn coalesce_value(&mut self, first: Value, second: Value) -> Value {
first.join_with(second, self)
}
fn coalesce_dict(&mut self, first: Dict, second: Dict) -> Dict {
first.join_with(second, self)
}
fn coalesce_array(&mut self, mut first: Vec<Value>, mut second: Vec<Value>) -> Vec<Value> {
first.extend(second.drain(..));
first
}
}
from figment.
I need this feature. Is there a workaround to have vectors being appended instead of overwritten before this feature is included to the library?
from figment.
My current woraround is using custom code that reads a conf.d type of dir and replacing the value Figment generated.
let global_sets_dir = PathBuf::from("/etc/renameplus/sets.d");
let user_sets_dir = {
let mut out = dirs::config_dir().context("Failed to get config dir")?;
out.push("renameplus");
out.push("sets.d");
out
};
if !user_sets_dir.exists() {
err_log +=
std::fs::create_dir_all(&user_sets_dir).context("Failed to create user sets.d");
}
let global_config_path = "/etc/renameplus.toml";
let user_config_path: PathBuf = {
let mut out = dirs::config_dir().context("Failed to get config dir")?;
out.push("renameplus");
out.push("config.toml");
out
};
let mut conf: Self = err_log
.push_result(
Figment::new()
.merge(Toml::file(global_config_path))
.merge(Toml::file(user_config_path))
.merge(Env::prefixed("renameplus_"))
.extract()
.context("Failed to parse config"),
)
.unwrap_or_default();
let sets: Vec<ReplaceSetData> = {
let mut out: Vec<ReplaceSetData> = Self::builtin_sets()
.into_iter()
.map(|set| ReplaceSetData {
used: conf.is_set_default(&set.name),
set,
editable: false,
})
.collect();
err_log += conf.find_sets(&mut out, global_sets_dir, false);
err_log += conf.find_sets(&mut out, user_sets_dir, true);
out
};
conf.sets = Some(sets);
from figment.
@SergioBenitez I'm actually looking for a function where the latter values overwrites the former value (like merge
), except in the case of vectors where they are concatenated (like adjoin
)... an admerge
, if you will.
I made the changes I need in a fork as a demo. I'd be happy to open a PR if you would consider merging this.
from figment.
Related Issues (20)
- Support YAML aliases/anchors HOT 2
- Is this abandoned? HOT 1
- `serde_yaml` version range HOT 1
- Reading single line from file HOT 5
- Unable to prioritise clap arguments over environment variables HOT 2
- How to handle replacement of single config entries inside a nested configuration? HOT 2
- Feature - set config values by path HOT 4
- Strange behavior with figment.join HOT 1
- Question: Iterator over values and best practices for modification of config HOT 2
- Question: How can I load string vectors from the environment? HOT 2
- Improve clap support recipes HOT 5
- Defaults for list of nested objects HOT 2
- Default value not being loaded HOT 4
- `Env` provider deserializes into unsigned int by force HOT 2
- Get names of expected environment variables HOT 1
- INI format support HOT 3
- Expose coalesce module HOT 3
- kebab-case environment variable fails to be used HOT 5
- Question: Serialize the profile name when extracting HOT 5
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from figment.