tusks_lib/codegen/preparse/tasks/
functions.rs1use syn::{Item, ItemFn, ItemMod, parse_quote};
2use syn::{Attribute, Meta};
3
4use crate::{AttributeValue, attribute::models::TasksConfig};
5
6pub fn add_use_staements(module: &mut ItemMod) {
7 let use_statement: Item = parse_quote! {
8 use ::tusks::clap::{CommandFactory, Parser};
9 };
10
11 if let Some((_, ref mut items)) = module.content {
12 items.insert(0, use_statement);
13 }
14}
15
16pub fn set_allow_external_subcommands(module: &mut ItemMod) {
17 if module.get_attribute_bool("command", "allow_external_subcommands") {
18 return;
19 }
20
21 if let Some(attr) = module.attrs.iter_mut().find(|a| a.path().is_ident("command")) {
23 match &mut attr.meta {
25 Meta::List(list) => {
26 let tokens_str = list.tokens.to_string();
28 let has_trailing_comma = tokens_str.trim_end().ends_with(',');
29
30 let tokens = &list.tokens;
31 if tokens.is_empty() {
32 list.tokens = parse_quote! { allow_external_subcommands = true };
33 } else if has_trailing_comma {
34 list.tokens = parse_quote! { #tokens allow_external_subcommands = true };
36 } else {
37 list.tokens = parse_quote! { #tokens, allow_external_subcommands = true };
39 }
40 }
41 Meta::Path(_) => {
42 *attr = parse_quote! { #[command(allow_external_subcommands = true)] };
44 }
45 Meta::NameValue(_) => {
46 *attr = parse_quote! { #[command(allow_external_subcommands = true)] };
48 }
49 }
50 } else {
51 let new_attr: Attribute = parse_quote! { #[command(allow_external_subcommands = true)] };
53 module.attrs.push(new_attr);
54 }
55}
56
57pub fn add_execute_task_function(module: &mut ItemMod, config: &TasksConfig) {
58 let cmd_name = "tasks"; let separator = &config.separator;
60 let max_groupsize = &config.max_groupsize;
61 let max_depth = &config.max_depth;
62
63 let function: ItemFn = parse_quote! {
64 #[command(about = "Execute a task", hide=true)]
65 #[default]
66 pub fn _execute_task(external_args: Vec<String>) -> Option<u8> {
67 let mut transformed_arguments = Vec::new();
68 if let Some(first) = external_args.first() {
69 transformed_arguments.push(#cmd_name.to_string());
70 transformed_arguments.extend(first.split(#separator).map(|s| s.to_string()));
71 transformed_arguments.extend_from_slice(&external_args[1..]);
72 let cli = __internal_tusks_module::cli::Cli::parse_from(
73 transformed_arguments
74 );
75 __internal_tusks_module::handle_matches(&cli)
76 }
77 else {
78 let command = __internal_tusks_module::cli::Cli::command();
79 if external_args.len() == 0 {
80 let task_list = ::tusks::tasks::task_list::models::TaskList::from_command(
81 &command,
82 #separator.to_string(),
83 #max_groupsize,
84 #max_depth
85 );
86 task_list.to_list().print(&::tusks::tasks::list::models::RenderConfig::default());
87 }
88 else {
89 let cli = __internal_tusks_module::cli::Cli::parse_from(
90 std::iter::once(#cmd_name).chain(external_args.iter().map(String::as_str))
91 );
92 __internal_tusks_module::handle_matches(&cli);
93 }
94 Some(0)
95 }
96 }
97 };
98
99 if let Some((_, ref mut items)) = module.content {
100 items.push(Item::Fn(function));
101 }
102}
103
104pub fn add_show_help_for_task(module: &mut ItemMod, config: &TasksConfig) {
105 let cmd_name = "tasks"; let separator = &config.separator;
107 let max_groupsize = &config.max_groupsize;
108 let max_depth = &config.max_depth;
109
110 let function: ItemFn = parse_quote! {
111 #[command(about = "Show the help for a task", name="h", hide=true)]
112 pub fn _show_help_for_task(#[arg()] task: Option<String>) {
113 if let Some(task) = task {
114 let parts: Vec<&str> = task.split(#separator).collect();
115
116 let args: Vec<&str> = std::iter::once(#cmd_name)
117 .chain(parts.iter().copied())
118 .chain(std::iter::once("--help"))
119 .collect();
120
121 let cli = __internal_tusks_module::cli::Cli::parse_from(args);
122 __internal_tusks_module::handle_matches(&cli);
123 }
124 else {
125 let command = __internal_tusks_module::cli::Cli::command();
126 let task_list = ::tusks::tasks::task_list::models::TaskList::from_command(
127 &command,
128 #separator.to_string(),
129 #max_groupsize,
130 #max_depth
131 );
132 task_list.to_list().print(&::tusks::tasks::list::models::RenderConfig::default());
133 }
134 }
135 };
136
137 if let Some((_, ref mut items)) = module.content {
138 items.push(Item::Fn(function));
139 }
140}