|
@@ -10,56 +10,107 @@ use super::{CLIError, CLIObject};
|
|
use clap::{FromArgMatches, Subcommand};
|
|
use clap::{FromArgMatches, Subcommand};
|
|
|
|
|
|
/// iterate across the list of key parts (E::Keys) and add args for each
|
|
/// iterate across the list of key parts (E::Keys) and add args for each
|
|
-fn add_keys<E: Entity>(mut cmd: clap::Command) -> clap::Command {
|
|
|
|
- struct UVisitor<'a>(&'a mut clap::Command);
|
|
|
|
- impl<'a> EntityPartVisitor for UVisitor<'a> {
|
|
|
|
|
|
+fn add_keys<E: Entity, IC: InterfaceCustomization>(
|
|
|
|
+ mut cmd: clap::Command,
|
|
|
|
+ role: ValueRole,
|
|
|
|
+) -> clap::Command {
|
|
|
|
+ struct UVisitor<'a, IC: InterfaceCustomization>(
|
|
|
|
+ &'a mut clap::Command,
|
|
|
|
+ ValueRole,
|
|
|
|
+ std::marker::PhantomData<IC>,
|
|
|
|
+ );
|
|
|
|
+ impl<'a, IC: InterfaceCustomization> EntityPartVisitor for UVisitor<'a, IC> {
|
|
fn visit<EP: microrm::schema::entity::EntityPart>(&mut self) {
|
|
fn visit<EP: microrm::schema::entity::EntityPart>(&mut self) {
|
|
- let arg = clap::Arg::new(EP::part_name())
|
|
|
|
- .required(true)
|
|
|
|
- .help(EP::desc());
|
|
|
|
- *self.0 = self.0.clone().arg(arg);
|
|
|
|
|
|
+ if !IC::has_value_for(EP::Entity::entity_name(), EP::part_name(), self.1) {
|
|
|
|
+ let arg = clap::Arg::new(EP::part_name())
|
|
|
|
+ .required(true)
|
|
|
|
+ .help(EP::desc());
|
|
|
|
+ *self.0 = self.0.clone().arg(arg);
|
|
|
|
+ }
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
- <E::Keys as EntityPartList>::accept_part_visitor(&mut UVisitor(&mut cmd));
|
|
|
|
|
|
+ <E::Keys as EntityPartList>::accept_part_visitor(&mut UVisitor::<IC>(
|
|
|
|
+ &mut cmd,
|
|
|
|
+ role,
|
|
|
|
+ Default::default(),
|
|
|
|
+ ));
|
|
|
|
|
|
cmd
|
|
cmd
|
|
}
|
|
}
|
|
|
|
|
|
-fn collect_keys<E: Entity>(matches: &clap::ArgMatches) -> Vec<String> {
|
|
|
|
- struct UVisitor<'a>(&'a clap::ArgMatches, &'a mut Vec<String>);
|
|
|
|
- impl<'a> EntityPartVisitor for UVisitor<'a> {
|
|
|
|
|
|
+fn collect_keys<E: Entity, IC: InterfaceCustomization>(
|
|
|
|
+ matches: &clap::ArgMatches,
|
|
|
|
+ role: ValueRole,
|
|
|
|
+) -> Vec<EntityKey> {
|
|
|
|
+ struct UVisitor<'a, IC: InterfaceCustomization>(
|
|
|
|
+ &'a clap::ArgMatches,
|
|
|
|
+ &'a mut Vec<EntityKey>,
|
|
|
|
+ ValueRole,
|
|
|
|
+ std::marker::PhantomData<IC>,
|
|
|
|
+ );
|
|
|
|
+ impl<'a, IC: InterfaceCustomization> EntityPartVisitor for UVisitor<'a, IC> {
|
|
fn visit<EP: microrm::schema::entity::EntityPart>(&mut self) {
|
|
fn visit<EP: microrm::schema::entity::EntityPart>(&mut self) {
|
|
- self.1.push(
|
|
|
|
- self.0
|
|
|
|
- .get_one::<std::string::String>(EP::part_name())
|
|
|
|
- .unwrap()
|
|
|
|
- .clone(),
|
|
|
|
- );
|
|
|
|
|
|
+ if !IC::has_value_for(EP::Entity::entity_name(), EP::part_name(), self.2) {
|
|
|
|
+ self.1.push(EntityKey::UserInput(
|
|
|
|
+ self.0
|
|
|
|
+ .get_one::<std::string::String>(EP::part_name())
|
|
|
|
+ .unwrap()
|
|
|
|
+ .clone(),
|
|
|
|
+ ));
|
|
|
|
+ } else {
|
|
|
|
+ self.1.push(EntityKey::Placeholder(
|
|
|
|
+ EP::Entity::entity_name(),
|
|
|
|
+ EP::part_name(),
|
|
|
|
+ self.2,
|
|
|
|
+ ));
|
|
|
|
+ }
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
let mut key_values = vec![];
|
|
let mut key_values = vec![];
|
|
- <E::Keys as EntityPartList>::accept_part_visitor(&mut UVisitor(matches, &mut key_values));
|
|
|
|
|
|
+ <E::Keys as EntityPartList>::accept_part_visitor(&mut UVisitor::<IC>(
|
|
|
|
+ matches,
|
|
|
|
+ &mut key_values,
|
|
|
|
+ role,
|
|
|
|
+ Default::default(),
|
|
|
|
+ ));
|
|
key_values
|
|
key_values
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+#[derive(Debug, Clone)]
|
|
|
|
+pub enum EntityKey {
|
|
|
|
+ Placeholder(&'static str, &'static str, ValueRole),
|
|
|
|
+ UserInput(String),
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+impl EntityKey {
|
|
|
|
+ fn to_string_vec(vec: &Vec<Self>, ic: &impl InterfaceCustomization) -> Vec<String> {
|
|
|
|
+ vec.iter()
|
|
|
|
+ .map(|v| match v {
|
|
|
|
+ EntityKey::UserInput(s) => s.to_owned(),
|
|
|
|
+ EntityKey::Placeholder(entity, field, role) => ic.value_for(entity, field, *role),
|
|
|
|
+ })
|
|
|
|
+ .collect()
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
#[derive(Clone, Debug)]
|
|
#[derive(Clone, Debug)]
|
|
pub enum InterfaceVerb<O: CLIObject> {
|
|
pub enum InterfaceVerb<O: CLIObject> {
|
|
Attach {
|
|
Attach {
|
|
- local_keys: Vec<String>,
|
|
|
|
|
|
+ local_keys: Vec<EntityKey>,
|
|
relation: String,
|
|
relation: String,
|
|
- remote_keys: Vec<String>,
|
|
|
|
|
|
+ remote_keys: Vec<EntityKey>,
|
|
},
|
|
},
|
|
Create(O::CreateParameters),
|
|
Create(O::CreateParameters),
|
|
- Delete(Vec<String>),
|
|
|
|
|
|
+ Delete(Vec<EntityKey>),
|
|
Detach {
|
|
Detach {
|
|
- local_keys: Vec<String>,
|
|
|
|
|
|
+ local_keys: Vec<EntityKey>,
|
|
relation: String,
|
|
relation: String,
|
|
- remote_keys: Vec<String>,
|
|
|
|
|
|
+ remote_keys: Vec<EntityKey>,
|
|
},
|
|
},
|
|
ListAll,
|
|
ListAll,
|
|
- Inspect(Vec<String>),
|
|
|
|
|
|
+ Inspect(Vec<EntityKey>),
|
|
Extra(O::ExtraCommands),
|
|
Extra(O::ExtraCommands),
|
|
}
|
|
}
|
|
|
|
|
|
@@ -67,22 +118,23 @@ pub enum InterfaceVerb<O: CLIObject> {
|
|
type UniqueList<E> = <<E as Entity>::Keys as EntityPartList>::DatumList;
|
|
type UniqueList<E> = <<E as Entity>::Keys as EntityPartList>::DatumList;
|
|
|
|
|
|
impl<O: CLIObject> InterfaceVerb<O> {
|
|
impl<O: CLIObject> InterfaceVerb<O> {
|
|
- fn parse_attachment(
|
|
|
|
|
|
+ fn parse_attachment<IC: InterfaceCustomization>(
|
|
matches: &clap::ArgMatches,
|
|
matches: &clap::ArgMatches,
|
|
- ) -> Result<(Vec<String>, String, Vec<String>), clap::Error> {
|
|
|
|
- let local_keys = collect_keys::<O>(matches);
|
|
|
|
|
|
+ ) -> Result<(Vec<EntityKey>, String, Vec<EntityKey>), clap::Error> {
|
|
|
|
+ let local_keys = collect_keys::<O, IC>(matches, ValueRole::BaseTarget);
|
|
|
|
|
|
let (subcommand, submatches) = matches
|
|
let (subcommand, submatches) = matches
|
|
.subcommand()
|
|
.subcommand()
|
|
.ok_or(clap::Error::new(clap::error::ErrorKind::MissingSubcommand))?;
|
|
.ok_or(clap::Error::new(clap::error::ErrorKind::MissingSubcommand))?;
|
|
|
|
|
|
// find the relevant relation
|
|
// find the relevant relation
|
|
- struct RelationFinder<'l> {
|
|
|
|
|
|
+ struct RelationFinder<'l, IC: InterfaceCustomization> {
|
|
subcommand: &'l str,
|
|
subcommand: &'l str,
|
|
submatches: &'l clap::ArgMatches,
|
|
submatches: &'l clap::ArgMatches,
|
|
- keys: &'l mut Vec<String>,
|
|
|
|
|
|
+ keys: &'l mut Vec<EntityKey>,
|
|
|
|
+ _ghost: std::marker::PhantomData<IC>,
|
|
}
|
|
}
|
|
- impl<'l> EntityPartVisitor for RelationFinder<'l> {
|
|
|
|
|
|
+ impl<'l, IC: InterfaceCustomization> EntityPartVisitor for RelationFinder<'l, IC> {
|
|
fn visit<EP: microrm::schema::entity::EntityPart>(&mut self) {
|
|
fn visit<EP: microrm::schema::entity::EntityPart>(&mut self) {
|
|
if EP::part_name() != self.subcommand {
|
|
if EP::part_name() != self.subcommand {
|
|
return;
|
|
return;
|
|
@@ -94,31 +146,34 @@ impl<O: CLIObject> InterfaceVerb<O> {
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
- impl<'l> EntityVisitor for RelationFinder<'l> {
|
|
|
|
|
|
+ impl<'l, IC: InterfaceCustomization> EntityVisitor for RelationFinder<'l, IC> {
|
|
fn visit<E: Entity>(&mut self) {
|
|
fn visit<E: Entity>(&mut self) {
|
|
println!("\trelationfinder visiting entity {}", E::entity_name());
|
|
println!("\trelationfinder visiting entity {}", E::entity_name());
|
|
- *self.keys = collect_keys::<E>(self.submatches);
|
|
|
|
|
|
+ *self.keys = collect_keys::<E, IC>(self.submatches, ValueRole::AttachmentTarget);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
let mut remote_keys = vec![];
|
|
let mut remote_keys = vec![];
|
|
- O::accept_part_visitor(&mut RelationFinder {
|
|
|
|
|
|
+ O::accept_part_visitor(&mut RelationFinder::<IC> {
|
|
subcommand,
|
|
subcommand,
|
|
submatches,
|
|
submatches,
|
|
keys: &mut remote_keys,
|
|
keys: &mut remote_keys,
|
|
|
|
+ _ghost: Default::default(),
|
|
});
|
|
});
|
|
|
|
|
|
Ok((local_keys, subcommand.into(), remote_keys))
|
|
Ok((local_keys, subcommand.into(), remote_keys))
|
|
}
|
|
}
|
|
|
|
|
|
- fn from_matches(parent_matches: &clap::ArgMatches) -> Result<Self, clap::Error> {
|
|
|
|
|
|
+ fn from_matches<IC: InterfaceCustomization>(
|
|
|
|
+ parent_matches: &clap::ArgMatches,
|
|
|
|
+ ) -> Result<Self, clap::Error> {
|
|
let (subcommand, matches) = parent_matches
|
|
let (subcommand, matches) = parent_matches
|
|
.subcommand()
|
|
.subcommand()
|
|
.ok_or(clap::Error::new(clap::error::ErrorKind::MissingSubcommand))?;
|
|
.ok_or(clap::Error::new(clap::error::ErrorKind::MissingSubcommand))?;
|
|
|
|
|
|
Ok(match subcommand {
|
|
Ok(match subcommand {
|
|
"attach" => {
|
|
"attach" => {
|
|
- let (local_keys, relation, remote_keys) = Self::parse_attachment(matches)?;
|
|
|
|
|
|
+ let (local_keys, relation, remote_keys) = Self::parse_attachment::<IC>(matches)?;
|
|
InterfaceVerb::Attach {
|
|
InterfaceVerb::Attach {
|
|
local_keys,
|
|
local_keys,
|
|
relation,
|
|
relation,
|
|
@@ -128,9 +183,11 @@ impl<O: CLIObject> InterfaceVerb<O> {
|
|
"create" => InterfaceVerb::Create(
|
|
"create" => InterfaceVerb::Create(
|
|
<O::CreateParameters as clap::FromArgMatches>::from_arg_matches(matches)?,
|
|
<O::CreateParameters as clap::FromArgMatches>::from_arg_matches(matches)?,
|
|
),
|
|
),
|
|
- "delete" => InterfaceVerb::Delete(collect_keys::<O>(matches)),
|
|
|
|
|
|
+ "delete" => {
|
|
|
|
+ InterfaceVerb::Delete(collect_keys::<O, IC>(matches, ValueRole::BaseTarget))
|
|
|
|
+ }
|
|
"detach" => {
|
|
"detach" => {
|
|
- let (local_keys, relation, remote_keys) = Self::parse_attachment(matches)?;
|
|
|
|
|
|
+ let (local_keys, relation, remote_keys) = Self::parse_attachment::<IC>(matches)?;
|
|
InterfaceVerb::Detach {
|
|
InterfaceVerb::Detach {
|
|
local_keys,
|
|
local_keys,
|
|
relation,
|
|
relation,
|
|
@@ -138,7 +195,9 @@ impl<O: CLIObject> InterfaceVerb<O> {
|
|
}
|
|
}
|
|
}
|
|
}
|
|
"list" => InterfaceVerb::ListAll,
|
|
"list" => InterfaceVerb::ListAll,
|
|
- "inspect" => InterfaceVerb::Inspect(collect_keys::<O>(matches)),
|
|
|
|
|
|
+ "inspect" => {
|
|
|
|
+ InterfaceVerb::Inspect(collect_keys::<O, IC>(matches, ValueRole::BaseTarget))
|
|
|
|
+ }
|
|
cmd => {
|
|
cmd => {
|
|
if <O::ExtraCommands>::has_subcommand(cmd) {
|
|
if <O::ExtraCommands>::has_subcommand(cmd) {
|
|
InterfaceVerb::Extra(<O::ExtraCommands>::from_arg_matches(parent_matches)?)
|
|
InterfaceVerb::Extra(<O::ExtraCommands>::from_arg_matches(parent_matches)?)
|
|
@@ -154,7 +213,7 @@ impl<O: CLIObject> InterfaceVerb<O> {
|
|
struct Attacher<'l, Error: CLIError> {
|
|
struct Attacher<'l, Error: CLIError> {
|
|
do_attach: bool,
|
|
do_attach: bool,
|
|
relation: &'l str,
|
|
relation: &'l str,
|
|
- remote_keys: &'l Vec<String>,
|
|
|
|
|
|
+ remote_keys: Vec<String>,
|
|
err: Option<Error>,
|
|
err: Option<Error>,
|
|
}
|
|
}
|
|
|
|
|
|
@@ -233,16 +292,43 @@ impl<'l, Error: CLIError> DatumDiscriminatorRef for Attacher<'l, Error> {
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+#[derive(Debug, Clone, Copy, Hash, Eq, PartialEq)]
|
|
|
|
+pub enum ValueRole {
|
|
|
|
+ BaseTarget,
|
|
|
|
+ AttachmentTarget,
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+pub trait InterfaceCustomization {
|
|
|
|
+ fn has_value_for(entity: &'static str, field: &'static str, role: ValueRole) -> bool;
|
|
|
|
+ fn value_for(&self, entity: &'static str, field: &'static str, role: ValueRole) -> String;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+impl InterfaceCustomization for () {
|
|
|
|
+ fn has_value_for(_entity: &'static str, _field: &'static str, _role: ValueRole) -> bool {
|
|
|
|
+ false
|
|
|
|
+ }
|
|
|
|
+ fn value_for(&self, _: &'static str, _: &'static str, _: ValueRole) -> String {
|
|
|
|
+ unreachable!()
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
#[derive(Debug)]
|
|
#[derive(Debug)]
|
|
-pub struct ClapInterface<O: CLIObject> {
|
|
|
|
|
|
+/// Type implementing `Subcommand` for a given CLIObject and specialization.
|
|
|
|
+///
|
|
|
|
+///
|
|
|
|
+pub struct ClapInterface<O: CLIObject, IC: InterfaceCustomization> {
|
|
verb: InterfaceVerb<O>,
|
|
verb: InterfaceVerb<O>,
|
|
- _ghost: std::marker::PhantomData<O>,
|
|
|
|
|
|
+ _ghost: std::marker::PhantomData<IC>,
|
|
}
|
|
}
|
|
|
|
|
|
-impl<O: CLIObject> ClapInterface<O> {
|
|
|
|
|
|
+impl<O: CLIObject, IC: InterfaceCustomization> ClapInterface<O, IC> {
|
|
|
|
+ /// Execute the action that this ClapInterface instance describes. Note that if `Spec` is
|
|
|
|
+ /// chosen as [`EmptyList`](../schema/entity/struct.EmptyList.html), the value passed for the
|
|
|
|
+ /// `spec` parameter should be the unit type, `()`.
|
|
pub fn perform(
|
|
pub fn perform(
|
|
&self,
|
|
&self,
|
|
- data: &O::ExtraCommandData,
|
|
|
|
|
|
+ data: &O::CommandData,
|
|
|
|
+ ic: &IC,
|
|
query_ctx: impl microrm::prelude::Queryable<EntityOutput = O>,
|
|
query_ctx: impl microrm::prelude::Queryable<EntityOutput = O>,
|
|
insert_ctx: &impl microrm::prelude::Insertable<O>,
|
|
insert_ctx: &impl microrm::prelude::Insertable<O>,
|
|
) -> Result<(), O::Error> {
|
|
) -> Result<(), O::Error> {
|
|
@@ -252,6 +338,8 @@ impl<O: CLIObject> ClapInterface<O> {
|
|
relation,
|
|
relation,
|
|
remote_keys,
|
|
remote_keys,
|
|
} => {
|
|
} => {
|
|
|
|
+ let local_keys = EntityKey::to_string_vec(local_keys, ic);
|
|
|
|
+ let remote_keys = EntityKey::to_string_vec(remote_keys, ic);
|
|
let outer_obj = query_ctx
|
|
let outer_obj = query_ctx
|
|
.keyed(
|
|
.keyed(
|
|
UniqueList::<O>::build_equivalent(local_keys.iter().map(String::as_str))
|
|
UniqueList::<O>::build_equivalent(local_keys.iter().map(String::as_str))
|
|
@@ -283,9 +371,10 @@ impl<O: CLIObject> ClapInterface<O> {
|
|
}
|
|
}
|
|
}
|
|
}
|
|
InterfaceVerb::Create(params) => {
|
|
InterfaceVerb::Create(params) => {
|
|
- insert_ctx.insert(O::create_from_params(params)?)?;
|
|
|
|
|
|
+ insert_ctx.insert(O::create_from_params(data, params)?)?;
|
|
}
|
|
}
|
|
InterfaceVerb::Delete(keys) => {
|
|
InterfaceVerb::Delete(keys) => {
|
|
|
|
+ let keys = EntityKey::to_string_vec(keys, ic);
|
|
query_ctx
|
|
query_ctx
|
|
.keyed(
|
|
.keyed(
|
|
UniqueList::<O>::build_equivalent(keys.iter().map(String::as_str)).unwrap(),
|
|
UniqueList::<O>::build_equivalent(keys.iter().map(String::as_str)).unwrap(),
|
|
@@ -297,6 +386,8 @@ impl<O: CLIObject> ClapInterface<O> {
|
|
relation,
|
|
relation,
|
|
remote_keys,
|
|
remote_keys,
|
|
} => {
|
|
} => {
|
|
|
|
+ let local_keys = EntityKey::to_string_vec(local_keys, ic);
|
|
|
|
+ let remote_keys = EntityKey::to_string_vec(remote_keys, ic);
|
|
let outer_obj = query_ctx
|
|
let outer_obj = query_ctx
|
|
.keyed(
|
|
.keyed(
|
|
UniqueList::<O>::build_equivalent(local_keys.iter().map(String::as_str))
|
|
UniqueList::<O>::build_equivalent(local_keys.iter().map(String::as_str))
|
|
@@ -338,6 +429,7 @@ impl<O: CLIObject> ClapInterface<O> {
|
|
}
|
|
}
|
|
}
|
|
}
|
|
InterfaceVerb::Inspect(keys) => {
|
|
InterfaceVerb::Inspect(keys) => {
|
|
|
|
+ let keys = EntityKey::to_string_vec(keys, ic);
|
|
let obj = query_ctx
|
|
let obj = query_ctx
|
|
.keyed(
|
|
.keyed(
|
|
UniqueList::<O>::build_equivalent(keys.iter().map(String::as_str)).unwrap(),
|
|
UniqueList::<O>::build_equivalent(keys.iter().map(String::as_str)).unwrap(),
|
|
@@ -413,12 +505,19 @@ impl<O: CLIObject> ClapInterface<O> {
|
|
fn make_relation_subcommands() -> impl Iterator<Item = clap::Command> {
|
|
fn make_relation_subcommands() -> impl Iterator<Item = clap::Command> {
|
|
let mut out = vec![];
|
|
let mut out = vec![];
|
|
|
|
|
|
- struct PartVisitor<'l>(&'l mut Vec<clap::Command>);
|
|
|
|
- impl<'l> EntityPartVisitor for PartVisitor<'l> {
|
|
|
|
|
|
+ struct PartVisitor<'l, IC: InterfaceCustomization>(
|
|
|
|
+ &'l mut Vec<clap::Command>,
|
|
|
|
+ std::marker::PhantomData<IC>,
|
|
|
|
+ );
|
|
|
|
+ impl<'l, IC: InterfaceCustomization> EntityPartVisitor for PartVisitor<'l, IC> {
|
|
fn visit<EP: microrm::schema::entity::EntityPart>(&mut self) {
|
|
fn visit<EP: microrm::schema::entity::EntityPart>(&mut self) {
|
|
- struct Discriminator<'l>(&'l mut Vec<clap::Command>, &'static str);
|
|
|
|
|
|
+ struct Discriminator<'l, IC: InterfaceCustomization>(
|
|
|
|
+ &'l mut Vec<clap::Command>,
|
|
|
|
+ &'static str,
|
|
|
|
+ std::marker::PhantomData<IC>,
|
|
|
|
+ );
|
|
|
|
|
|
- impl<'l> DatumDiscriminator for Discriminator<'l> {
|
|
|
|
|
|
+ impl<'l, IC: InterfaceCustomization> DatumDiscriminator for Discriminator<'l, IC> {
|
|
fn visit_entity_id<E: Entity>(&mut self) {}
|
|
fn visit_entity_id<E: Entity>(&mut self) {}
|
|
fn visit_serialized<T: serde::Serialize + serde::de::DeserializeOwned>(
|
|
fn visit_serialized<T: serde::Serialize + serde::de::DeserializeOwned>(
|
|
&mut self,
|
|
&mut self,
|
|
@@ -426,34 +525,42 @@ impl<O: CLIObject> ClapInterface<O> {
|
|
}
|
|
}
|
|
fn visit_bare_field<T: Datum>(&mut self) {}
|
|
fn visit_bare_field<T: Datum>(&mut self) {}
|
|
fn visit_assoc_map<E: Entity>(&mut self) {
|
|
fn visit_assoc_map<E: Entity>(&mut self) {
|
|
- self.0.push(add_keys::<E>(clap::Command::new(self.1)));
|
|
|
|
|
|
+ self.0.push(add_keys::<E, IC>(
|
|
|
|
+ clap::Command::new(self.1),
|
|
|
|
+ ValueRole::AttachmentTarget,
|
|
|
|
+ ));
|
|
}
|
|
}
|
|
fn visit_assoc_domain<R: microrm::schema::Relation>(&mut self) {
|
|
fn visit_assoc_domain<R: microrm::schema::Relation>(&mut self) {
|
|
- self.0
|
|
|
|
- .push(add_keys::<R::Range>(clap::Command::new(self.1)));
|
|
|
|
|
|
+ self.0.push(add_keys::<R::Range, IC>(
|
|
|
|
+ clap::Command::new(self.1),
|
|
|
|
+ ValueRole::AttachmentTarget,
|
|
|
|
+ ));
|
|
}
|
|
}
|
|
fn visit_assoc_range<R: microrm::schema::Relation>(&mut self) {
|
|
fn visit_assoc_range<R: microrm::schema::Relation>(&mut self) {
|
|
- self.0
|
|
|
|
- .push(add_keys::<R::Domain>(clap::Command::new(self.1)));
|
|
|
|
|
|
+ self.0.push(add_keys::<R::Domain, IC>(
|
|
|
|
+ clap::Command::new(self.1),
|
|
|
|
+ ValueRole::AttachmentTarget,
|
|
|
|
+ ));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
- <EP::Datum as Datum>::accept_discriminator(&mut Discriminator(
|
|
|
|
|
|
+ <EP::Datum as Datum>::accept_discriminator(&mut Discriminator::<IC>(
|
|
self.0,
|
|
self.0,
|
|
EP::part_name(),
|
|
EP::part_name(),
|
|
|
|
+ Default::default(),
|
|
));
|
|
));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
- O::accept_part_visitor(&mut PartVisitor(&mut out));
|
|
|
|
|
|
+ O::accept_part_visitor(&mut PartVisitor::<IC>(&mut out, Default::default()));
|
|
|
|
|
|
out.into_iter()
|
|
out.into_iter()
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
-impl<O: CLIObject> FromArgMatches for ClapInterface<O> {
|
|
|
|
|
|
+impl<O: CLIObject, IC: InterfaceCustomization> FromArgMatches for ClapInterface<O, IC> {
|
|
fn from_arg_matches(matches: &clap::ArgMatches) -> Result<Self, clap::Error> {
|
|
fn from_arg_matches(matches: &clap::ArgMatches) -> Result<Self, clap::Error> {
|
|
- let verb = InterfaceVerb::from_matches(matches);
|
|
|
|
|
|
+ let verb = InterfaceVerb::from_matches::<IC>(matches);
|
|
|
|
|
|
Ok(Self {
|
|
Ok(Self {
|
|
verb: verb?,
|
|
verb: verb?,
|
|
@@ -466,7 +573,7 @@ impl<O: CLIObject> FromArgMatches for ClapInterface<O> {
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
-impl<O: CLIObject> Subcommand for ClapInterface<O> {
|
|
|
|
|
|
+impl<O: CLIObject, IC: InterfaceCustomization> Subcommand for ClapInterface<O, IC> {
|
|
fn has_subcommand(_name: &str) -> bool {
|
|
fn has_subcommand(_name: &str) -> bool {
|
|
todo!()
|
|
todo!()
|
|
}
|
|
}
|
|
@@ -474,18 +581,24 @@ impl<O: CLIObject> Subcommand for ClapInterface<O> {
|
|
fn augment_subcommands(cmd: clap::Command) -> clap::Command {
|
|
fn augment_subcommands(cmd: clap::Command) -> clap::Command {
|
|
let cmd = cmd
|
|
let cmd = cmd
|
|
.subcommand(
|
|
.subcommand(
|
|
- add_keys::<O>(clap::Command::new("attach"))
|
|
|
|
|
|
+ add_keys::<O, IC>(clap::Command::new("attach"), ValueRole::BaseTarget)
|
|
.subcommands(Self::make_relation_subcommands())
|
|
.subcommands(Self::make_relation_subcommands())
|
|
.subcommand_required(true),
|
|
.subcommand_required(true),
|
|
)
|
|
)
|
|
.subcommand(
|
|
.subcommand(
|
|
- add_keys::<O>(clap::Command::new("detach"))
|
|
|
|
|
|
+ add_keys::<O, IC>(clap::Command::new("detach"), ValueRole::BaseTarget)
|
|
.subcommands(Self::make_relation_subcommands())
|
|
.subcommands(Self::make_relation_subcommands())
|
|
.subcommand_required(true),
|
|
.subcommand_required(true),
|
|
)
|
|
)
|
|
.subcommand(<O::CreateParameters as clap::CommandFactory>::command().name("create"))
|
|
.subcommand(<O::CreateParameters as clap::CommandFactory>::command().name("create"))
|
|
- .subcommand(add_keys::<O>(clap::Command::new("delete")))
|
|
|
|
- .subcommand(add_keys::<O>(clap::Command::new("inspect")))
|
|
|
|
|
|
+ .subcommand(add_keys::<O, IC>(
|
|
|
|
+ clap::Command::new("delete"),
|
|
|
|
+ ValueRole::BaseTarget,
|
|
|
|
+ ))
|
|
|
|
+ .subcommand(add_keys::<O, IC>(
|
|
|
|
+ clap::Command::new("inspect"),
|
|
|
|
+ ValueRole::BaseTarget,
|
|
|
|
+ ))
|
|
.subcommand(clap::Command::new("list"));
|
|
.subcommand(clap::Command::new("list"));
|
|
|
|
|
|
<O::ExtraCommands>::augment_subcommands(cmd)
|
|
<O::ExtraCommands>::augment_subcommands(cmd)
|