css_variable_lsp/
flags.rs1use std::collections::HashMap;
2
3pub fn get_arg_value(args: &[String], name: &str) -> Option<String> {
4 let flag = format!("--{name}");
5 if let Some(idx) = args.iter().position(|arg| arg == &flag) {
6 if let Some(candidate) = args.get(idx + 1) {
7 if !candidate.starts_with('-') {
8 return Some(candidate.to_string());
9 }
10 }
11 return None;
12 }
13
14 let prefix = format!("{}=", flag);
15 for arg in args {
16 if arg.starts_with(&prefix) {
17 return Some(arg[prefix.len()..].to_string());
18 }
19 }
20 None
21}
22
23pub fn parse_optional_int(value: Option<&str>) -> Option<i64> {
24 let raw = value?.trim();
25 if raw.is_empty() {
26 return None;
27 }
28 raw.parse::<i64>().ok()
29}
30
31pub fn split_list(value: &str) -> Vec<String> {
32 value
33 .split(',')
34 .map(|s| s.trim().to_string())
35 .filter(|s| !s.is_empty())
36 .collect()
37}
38
39pub fn flag_bool(
40 args: &[String],
41 env: &HashMap<String, String>,
42 _name: &str,
43 env_key: &str,
44 cli_disable: &str,
45 default: bool,
46) -> bool {
47 if args.iter().any(|arg| arg == cli_disable) {
48 return false;
49 }
50 if let Some(v) = env.get(env_key) {
51 return v != "0";
52 }
53 default
54}
55
56pub fn flag_bool_simple(
57 args: &[String],
58 env: &HashMap<String, String>,
59 env_key: &str,
60 cli_flag: &str,
61 default: bool,
62) -> bool {
63 if args.iter().any(|arg| arg == cli_flag) {
64 return true;
65 }
66 if let Some(v) = env.get(env_key) {
67 return v != "0";
68 }
69 default
70}
71
72pub fn flag_opt<T: From<Vec<String>>>(
73 args: &[String],
74 env: &HashMap<String, String>,
75 name: &str,
76 env_key: &str,
77 default: Option<T>,
78) -> Option<T> {
79 let singular_names = ["lookup-files", "ignore-globs"];
80 let use_singular = singular_names.contains(&name);
81
82 let mut names: Vec<String> = vec![name.to_string()];
83 if use_singular {
84 if let Some(singular) = name.strip_suffix('s') {
85 names.push(singular.to_string());
86 }
87 }
88
89 let mut values = Vec::new();
90
91 let mut i = 0;
92 while i < args.len() {
93 let arg = &args[i];
94 for n in &names {
95 if arg == &format!("--{n}") {
96 if let Some(next) = args.get(i + 1) {
97 if !next.starts_with('-') {
98 values.extend(split_list(next));
99 i += 1;
100 }
101 }
102 } else if let Some(rest) = arg.strip_prefix(&format!("--{n}=")) {
103 values.extend(split_list(rest));
104 }
105 }
106 i += 1;
107 }
108
109 if !values.is_empty() {
110 return Some(T::from(values));
111 }
112
113 if let Some(v) = env.get(env_key) {
114 let env_values = split_list(v);
115 if !env_values.is_empty() {
116 return Some(T::from(env_values));
117 }
118 }
119
120 default
121}
122
123pub fn flag_enum<T: Clone + Default>(
124 args: &[String],
125 env: &HashMap<String, String>,
126 name: &str,
127 env_key: &str,
128 cli_name: Option<&str>,
129 normalizer: fn(Option<&str>) -> Option<T>,
130 default: T,
131) -> T {
132 let cli_name = cli_name.unwrap_or(name);
133
134 if let Some(cli_val) = get_arg_value(args, cli_name) {
135 if let Some(normalized) = normalizer(Some(&cli_val)) {
136 return normalized;
137 }
138 }
139
140 if let Some(v) = env.get(env_key) {
141 if let Some(normalized) = normalizer(Some(v.as_str())) {
142 return normalized;
143 }
144 }
145
146 default
147}
148
149pub fn flag_usize(
150 args: &[String],
151 env: &HashMap<String, String>,
152 name: &str,
153 env_key: &str,
154 default: usize,
155) -> usize {
156 let arg_value = get_arg_value(args, name);
157 if let Some(v) = parse_optional_int(arg_value.as_deref()) {
158 return v.max(0) as usize;
159 }
160
161 if let Some(v) = env.get(env_key) {
162 if let Some(n) = parse_optional_int(Some(v)) {
163 return n.max(0) as usize;
164 }
165 }
166
167 default
168}