Skip to content

Commit

Permalink
refactor: extract resolvers to single module (#51)
Browse files Browse the repository at this point in the history
  • Loading branch information
fu050409 authored Jul 22, 2024
1 parent fa1b5c6 commit be34ebc
Show file tree
Hide file tree
Showing 7 changed files with 136 additions and 131 deletions.
5 changes: 5 additions & 0 deletions .changeset/brave-horses-grow.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'archons': patch
---

Refactor codes to extract resolvers to single module
2 changes: 0 additions & 2 deletions index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,6 @@ export interface CommandOption {
parser?:
| 'string'
| 'str'
| 'string[]'
| 'str[]'
| 'number'
| 'boolean'
| 'bool'
Expand Down
3 changes: 2 additions & 1 deletion src/command.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
use napi::{bindgen_prelude::*, JsNull};
use napi_derive::napi;

use crate::resolver::{resolve_command, resolve_option_args};
use crate::types::{Command, Context};
use crate::utils::{merge_args_matches, resolve_command, resolve_option_args};
use crate::utils::merge_args_matches;

#[napi]
pub fn define_command(options: Command) -> Command {
Expand Down
3 changes: 1 addition & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
#![deny(clippy::all)]

pub mod command;
pub mod resolver;
pub mod types;
pub mod utils;
127 changes: 127 additions & 0 deletions src/resolver.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
use std::collections::HashMap;

use crate::{
types::{Command, CommandMeta, CommandOption},
utils::{leak_borrowed_str, leak_borrowed_str_or_default, leak_str},
};

pub(crate) fn resolve_option_args(args: Option<Vec<String>>) -> Vec<String> {
let mut args = args.unwrap_or(std::env::args().collect());
args.remove(0); // remove `node.exe`
args
}

pub(crate) fn resolve_command_meta(
mut clap: clap::Command,
bin_name: Option<String>,
meta: &CommandMeta,
) -> clap::Command {
let name: &'static str = if let Some(name) = &meta.name {
leak_borrowed_str(name)
} else {
leak_str(bin_name.unwrap())
};
clap = clap.name(name);
if let Some(version) = &meta.version {
clap = clap.version(leak_borrowed_str(version));
}
if let Some(about) = &meta.about {
clap = clap.about(leak_borrowed_str(about));
}
if meta.styled.is_some() && meta.styled.unwrap() {
use clap::builder::styling;
let styles = styling::Styles::styled()
.header(styling::AnsiColor::Green.on_default() | styling::Effects::BOLD)
.usage(styling::AnsiColor::Green.on_default() | styling::Effects::BOLD)
.literal(styling::AnsiColor::Cyan.on_default() | styling::Effects::BOLD)
.placeholder(styling::AnsiColor::Cyan.on_default());
clap = clap.styles(styles);
}
clap
}

pub(crate) fn resolve_action(_type: &str, parser: Option<&str>) -> Option<clap::ArgAction> {
match _type {
"positional" | "option" => {
if parser.is_some() && parser.unwrap().ends_with("[]") {
Some(clap::ArgAction::Append)
} else {
None
}
}
"flag" => match parser {
Some("bool" | "boolean") | None => Some(clap::ArgAction::SetTrue),
Some("number") => Some(clap::ArgAction::Count),
_ => panic!("Invalid flag parser: `{:?}`", parser),
},
_ => panic!("Unsupported option type: `{}`", _type),
}
}

pub(crate) fn resolve_command_options(
clap: clap::Command,
meta: &HashMap<String, CommandOption>,
) -> clap::Command {
clap.args(
meta
.iter()
.map(|(name, opt)| {
let mut arg = clap::Arg::new(leak_borrowed_str(name));
arg = arg.action(resolve_action(
opt._type.as_deref().unwrap_or("option"),
opt.parser.as_deref(),
));
if opt._type.as_deref() != Some("positional") {
let long = leak_borrowed_str_or_default(opt.long.as_ref(), name);
arg = arg.long(long).short(
leak_borrowed_str_or_default(opt.short.as_ref(), long)
.chars()
.next(),
);
}
if let Some(alias) = &opt.alias {
let alias = alias.iter().map(leak_borrowed_str).collect::<Vec<&str>>();
arg = arg.visible_aliases(alias);
}
if let Some(hidden_alias) = &opt.hidden_alias {
let hidden_alias = hidden_alias
.iter()
.map(leak_borrowed_str)
.collect::<Vec<&str>>();
arg = arg.aliases(hidden_alias);
}
if let Some(help) = &opt.help {
arg = arg.help(leak_borrowed_str(help));
}
if let Some(required) = opt.required {
arg = arg.required(required);
}
if let Some(default) = &opt.default {
arg = arg.default_value(leak_borrowed_str(default));
}
if let Some(hidden) = opt.hidden {
arg = arg.hide(hidden);
}
arg
})
.collect::<Vec<clap::Arg>>(),
)
}

pub(crate) fn resolve_command(
mut clap: clap::Command,
name: String,
cmd: &Command,
) -> clap::Command {
clap = resolve_command_meta(clap, Some(name), &cmd.meta);
clap = resolve_command_options(clap, &cmd.options);
if let Some(subcommands) = &cmd.subcommands {
clap = clap.subcommands(
subcommands
.iter()
.map(|(name, sub_cmd)| resolve_command(clap::Command::default(), name.clone(), sub_cmd))
.collect::<Vec<clap::Command>>(),
);
}
clap
}
2 changes: 0 additions & 2 deletions src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,6 @@ pub struct CommandOption {
#[napi(ts_type = r#"
| 'string'
| 'str'
| 'string[]'
| 'str[]'
| 'number'
| 'boolean'
| 'bool'"#)]
Expand Down
125 changes: 1 addition & 124 deletions src/utils.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
use std::collections::HashMap;

use napi::{JsObject, Result};

use crate::types::{Command, CommandMeta, CommandOption};
use crate::types::Command;

pub(crate) fn leak_str(s: String) -> &'static str {
s.leak()
Expand All @@ -16,127 +14,6 @@ pub(crate) fn leak_borrowed_str(s: &String) -> &'static str {
s.to_owned().leak()
}

pub(crate) fn resolve_option_args(args: Option<Vec<String>>) -> Vec<String> {
let mut args = args.unwrap_or(std::env::args().collect());
args.remove(0); // remove `node.exe`
args
}

pub(crate) fn resolve_command_meta(
mut clap: clap::Command,
bin_name: Option<String>,
meta: &CommandMeta,
) -> clap::Command {
let name: &'static str = if let Some(name) = &meta.name {
leak_borrowed_str(name)
} else {
leak_str(bin_name.unwrap())
};
clap = clap.name(name);
if let Some(version) = &meta.version {
clap = clap.version(leak_borrowed_str(version));
}
if let Some(about) = &meta.about {
clap = clap.about(leak_borrowed_str(about));
}
if meta.styled.is_some() && meta.styled.unwrap() {
use clap::builder::styling;
let styles = styling::Styles::styled()
.header(styling::AnsiColor::Green.on_default() | styling::Effects::BOLD)
.usage(styling::AnsiColor::Green.on_default() | styling::Effects::BOLD)
.literal(styling::AnsiColor::Cyan.on_default() | styling::Effects::BOLD)
.placeholder(styling::AnsiColor::Cyan.on_default());
clap = clap.styles(styles);
}
clap
}

pub(crate) fn resolve_action(_type: &str, parser: Option<&str>) -> Option<clap::ArgAction> {
match _type {
"positional" | "option" => {
if parser.is_some() && parser.unwrap().ends_with("[]") {
Some(clap::ArgAction::Append)
} else {
None
}
}
"flag" => match parser {
Some("bool" | "boolean") | None => Some(clap::ArgAction::SetTrue),
Some("number") => Some(clap::ArgAction::Count),
_ => panic!("Invalid flag parser: `{:?}`", parser),
},
_ => panic!("Unsupported option type: `{}`", _type),
}
}

pub(crate) fn resolve_command_options(
clap: clap::Command,
meta: &HashMap<String, CommandOption>,
) -> clap::Command {
clap.args(
meta
.iter()
.map(|(name, opt)| {
let mut arg = clap::Arg::new(leak_borrowed_str(name));
arg = arg.action(resolve_action(
opt._type.as_deref().unwrap_or("option"),
opt.parser.as_deref(),
));
if opt._type.as_deref() != Some("positional") {
let long = leak_borrowed_str_or_default(opt.long.as_ref(), name);
arg = arg.long(long).short(
leak_borrowed_str_or_default(opt.short.as_ref(), long)
.chars()
.next(),
);
}
if let Some(alias) = &opt.alias {
let alias = alias.iter().map(leak_borrowed_str).collect::<Vec<&str>>();
arg = arg.visible_aliases(alias);
}
if let Some(hidden_alias) = &opt.hidden_alias {
let hidden_alias = hidden_alias
.iter()
.map(leak_borrowed_str)
.collect::<Vec<&str>>();
arg = arg.aliases(hidden_alias);
}
if let Some(help) = &opt.help {
arg = arg.help(leak_borrowed_str(help));
}
if let Some(required) = opt.required {
arg = arg.required(required);
}
if let Some(default) = &opt.default {
arg = arg.default_value(leak_borrowed_str(default));
}
if let Some(hidden) = opt.hidden {
arg = arg.hide(hidden);
}
arg
})
.collect::<Vec<clap::Arg>>(),
)
}

pub(crate) fn resolve_command(
mut clap: clap::Command,
name: String,
cmd: &Command,
) -> clap::Command {
clap = resolve_command_meta(clap, Some(name), &cmd.meta);
clap = resolve_command_options(clap, &cmd.options);
if let Some(subcommands) = &cmd.subcommands {
clap = clap.subcommands(
subcommands
.iter()
.map(|(name, sub_cmd)| resolve_command(clap::Command::default(), name.clone(), sub_cmd))
.collect::<Vec<clap::Command>>(),
);
}
clap
}

pub(crate) fn merge_args_matches(
parsed_args: &mut JsObject,
cmd: &Command,
Expand Down

0 comments on commit be34ebc

Please sign in to comment.