custom_cli

This commit is contained in:
Aiden McClelland
2021-08-31 11:42:31 -06:00
parent 9aae157d60
commit ee9b302ecd
3 changed files with 180 additions and 36 deletions

View File

@@ -493,7 +493,14 @@ fn rpc_handler(
method: &str,
args: Params#param_ty_generics,
) -> Result<::rpc_toolkit::command_helpers::prelude::Value, ::rpc_toolkit::command_helpers::prelude::RpcError> {
Ok(::rpc_toolkit::command_helpers::prelude::to_value(#invocation)?)
if method.is_empty() {
Ok(::rpc_toolkit::command_helpers::prelude::to_value(#invocation)?)
} else {
Err(::rpc_toolkit::command_helpers::prelude::RpcError {
data: Some(method.into()),
..::rpc_toolkit::command_helpers::prelude::yajrc::METHOD_NOT_FOUND_ERROR
})
}
}
}
}
@@ -818,44 +825,91 @@ fn cli_handler(
}
}
Options::Leaf(opt) => {
let invocation = if opt.is_async {
if let ExecutionContext::CustomCli {
ref cli, is_async, ..
} = opt.exec_ctx
{
let fn_path = cli;
let invocation = if is_async {
quote! {
rt_ref.block_on(#fn_path(#(#param),*))?
}
} else {
quote! {
#fn_path(#(#param),*)?
}
};
let display_res = if let Some(display_fn) = &opt.display {
quote! {
#display_fn(#invocation, matches)
}
} else {
quote! {
::rpc_toolkit::command_helpers::prelude::default_display(#invocation, matches)
}
};
let rt_action = if is_async {
create_rt
} else {
quote! {
drop(rt);
}
};
quote! {
rt_ref.block_on(#fn_path(#(#param),*))?
}
} else {
quote! {
#fn_path(#(#param),*)?
}
};
let display_res = if let Some(display_fn) = &opt.display {
quote! {
#display_fn(#invocation, matches)
}
} else {
quote! {
::rpc_toolkit::command_helpers::prelude::default_display(#invocation, matches)
}
};
let rt_action = if opt.is_async {
create_rt
} else {
quote! {
drop(rt);
}
};
quote! {
pub fn cli_handler#generics(
ctx: #ctx_ty,
mut rt: Option<::rpc_toolkit::command_helpers::prelude::Runtime>,
matches: &::rpc_toolkit::command_helpers::prelude::ArgMatches<'_>,
_method: ::rpc_toolkit::command_helpers::prelude::Cow<'_, str>,
parent_params: ParentParams
) -> Result<(), ::rpc_toolkit::command_helpers::prelude::RpcError> {
#param_struct_def
pub fn cli_handler#generics(
ctx: #ctx_ty,
mut rt: Option<::rpc_toolkit::command_helpers::prelude::Runtime>,
matches: &::rpc_toolkit::command_helpers::prelude::ArgMatches<'_>,
_method: ::rpc_toolkit::command_helpers::prelude::Cow<'_, str>,
parent_params: ParentParams
) -> Result<(), ::rpc_toolkit::command_helpers::prelude::RpcError> {
#param_struct_def
#rt_action
#rt_action
Ok(#display_res)
Ok(#display_res)
}
}
} else {
let invocation = if opt.is_async {
quote! {
rt_ref.block_on(#fn_path(#(#param),*))?
}
} else {
quote! {
#fn_path(#(#param),*)?
}
};
let display_res = if let Some(display_fn) = &opt.display {
quote! {
#display_fn(#invocation, matches)
}
} else {
quote! {
::rpc_toolkit::command_helpers::prelude::default_display(#invocation, matches)
}
};
let rt_action = if opt.is_async {
create_rt
} else {
quote! {
drop(rt);
}
};
quote! {
pub fn cli_handler#generics(
ctx: #ctx_ty,
mut rt: Option<::rpc_toolkit::command_helpers::prelude::Runtime>,
matches: &::rpc_toolkit::command_helpers::prelude::ArgMatches<'_>,
_method: ::rpc_toolkit::command_helpers::prelude::Cow<'_, str>,
parent_params: ParentParams
) -> Result<(), ::rpc_toolkit::command_helpers::prelude::RpcError> {
#param_struct_def
#rt_action
Ok(#display_res)
}
}
}
}

View File

@@ -10,6 +10,11 @@ pub enum ExecutionContext {
CliOnly(Path),
RpcOnly(Path),
Local(Path),
CustomCli {
custom: Path,
cli: Path,
is_async: bool,
},
}
impl Default for ExecutionContext {
fn default() -> Self {

View File

@@ -126,6 +126,73 @@ pub fn parse_command_attr(args: AttributeArgs) -> Result<Options> {
"`display` cannot be assigned to",
));
}
NestedMeta::Meta(Meta::List(list)) if list.path.is_ident("custom_cli") => {
if list.nested.len() == 1 {
match &opt.common().exec_ctx {
ExecutionContext::Standard => match &list.nested[0] {
NestedMeta::Meta(Meta::Path(custom_cli_impl)) => {
opt.common().exec_ctx = ExecutionContext::CustomCli {
custom: list.path,
cli: custom_cli_impl.clone(),
is_async: false,
}
}
NestedMeta::Meta(Meta::List(custom_cli_impl)) if custom_cli_impl.nested.len() == 1 => {
let is_async = match custom_cli_impl.nested.first().unwrap() {
NestedMeta::Meta(Meta::Path(p)) if p.is_ident("async") => false,
arg => return Err(Error::new(arg.span(), "unknown argument")),
};
opt.common().exec_ctx = ExecutionContext::CustomCli {
custom: list.path,
cli: custom_cli_impl.path.clone(),
is_async,
};
}
a => {
return Err(Error::new(
a.span(),
"`custom_cli` implementation must be a path, or a list with 1 argument",
))
}
},
ExecutionContext::CliOnly(_) => {
return Err(Error::new(list.span(), "duplicate argument: `cli_only`"))
}
ExecutionContext::RpcOnly(_) => {
return Err(Error::new(
list.span(),
"`cli_only` and `rpc_only` are mutually exclusive",
))
}
ExecutionContext::Local(_) => {
return Err(Error::new(
list.span(),
"`cli_only` and `local` are mutually exclusive",
))
}
ExecutionContext::CustomCli { .. } => {
return Err(Error::new(
list.span(),
"`cli_only` and `custom_cli` are mutually exclusive",
))
}
}
} else {
return Err(Error::new(
list.nested.span(),
"`custom_cli` can only have one implementation",
));
}
}
NestedMeta::Meta(Meta::Path(p)) if p.is_ident("custom_cli") => {
return Err(Error::new(p.span(), "`custom_cli` requires an argument"));
}
NestedMeta::Meta(Meta::NameValue(nv)) if nv.path.is_ident("custom_cli") => {
return Err(Error::new(
nv.path.span(),
"`custom_cli` cannot be assigned to",
));
}
NestedMeta::Meta(Meta::List(list)) if list.path.is_ident("aliases") => {
if !opt.common().aliases.is_empty() {
return Err(Error::new(list.span(), "duplicate argument `alias`"));
@@ -170,6 +237,12 @@ pub fn parse_command_attr(args: AttributeArgs) -> Result<Options> {
"`cli_only` and `local` are mutually exclusive",
))
}
ExecutionContext::CustomCli { .. } => {
return Err(Error::new(
p.span(),
"`cli_only` and `custom_cli` are mutually exclusive",
))
}
}
}
NestedMeta::Meta(Meta::List(list)) if list.path.is_ident("cli_only") => {
@@ -204,6 +277,12 @@ pub fn parse_command_attr(args: AttributeArgs) -> Result<Options> {
"`rpc_only` and `local` are mutually exclusive",
))
}
ExecutionContext::CustomCli { .. } => {
return Err(Error::new(
p.span(),
"`rpc_only` and `custom_cli` are mutually exclusive",
))
}
}
}
NestedMeta::Meta(Meta::List(list)) if list.path.is_ident("rpc_only") => {
@@ -238,6 +317,12 @@ pub fn parse_command_attr(args: AttributeArgs) -> Result<Options> {
"`local` and `cli_only` are mutually exclusive",
))
}
ExecutionContext::CustomCli { .. } => {
return Err(Error::new(
p.span(),
"`local` and `custom_cli` are mutually exclusive",
))
}
}
}
NestedMeta::Meta(Meta::List(list)) if list.path.is_ident("local") => {