1use clap::Parser;
2use core::panic;
3use flams_system::settings::{BuildQueueSettings, ServerSettings, SettingsSpec};
4use flams_utils::settings::GitlabSettings;
5use std::path::{Path, PathBuf};
6
7#[derive(Parser, Debug)]
8#[command(propagate_version = true, version, about, long_about = Some(
9"𝖥𝖫∀𝖬∫ - Flexiformal Annotation Management System\n\
10--------------------------------------------------------------------\n\
11See the \u{1b}]8;;https://github.com/UniFormal/MMT\u{1b}\\documentation\u{1b}]8;;\u{1b}\\ for details"
12))]
13struct Cli {
14 #[arg(short, long)]
17 pub(crate) mathhubs: Option<String>,
18
19 #[arg(short, long)]
21 pub(crate) debug: Option<bool>,
22
23 #[arg(short, long)]
24 pub(crate) config_file: Option<PathBuf>,
26
27 #[arg(short, long)]
28 pub(crate) log_dir: Option<PathBuf>,
30
31 #[arg(long)]
32 pub(crate) stack_size: Option<u8>,
34
35 #[arg(long)]
36 pub(crate) temp_dir: Option<PathBuf>,
38
39 #[arg(short, long)]
40 pub(crate) admin_pwd: Option<String>,
42
43 #[arg(long,value_parser = clap::value_parser!(u16).range(1..))]
45 pub(crate) port: Option<u16>,
46
47 #[arg(long)]
49 pub(crate) ip: Option<String>,
50
51 #[arg(long)]
52 pub(crate) external_url: Option<String>,
53
54 #[arg(long)]
55 pub(crate) db: Option<PathBuf>,
57
58 #[arg(long)]
59 pub(crate) rdf_database: Option<PathBuf>,
61
62 #[arg(short, long)]
64 pub(crate) threads: Option<u8>,
65
66 #[arg(long)]
68 pub(crate) lsp: bool,
69
70 #[arg(long)]
71 pub(crate) gitlab_url: Option<String>,
72
73 #[arg(long)]
74 pub(crate) gitlab_token: Option<String>,
75 #[arg(long)]
76 pub(crate) gitlab_app_id: Option<String>,
77 #[arg(long)]
78 pub(crate) gitlab_app_secret: Option<String>,
79 #[arg(long)]
80 pub(crate) gitlab_redirect_url: Option<String>,
81}
82impl From<Cli> for (Option<PathBuf>, SettingsSpec) {
83 fn from(cli: Cli) -> Self {
85 let settings = SettingsSpec {
86 mathhubs: cli
87 .mathhubs
88 .map(|s| s.split(',').map(|s| PathBuf::from(s.trim())).collect())
89 .unwrap_or_default(),
90 debug: cli.debug,
91 stack_size: cli.stack_size,
92 database: cli.db.map(PathBuf::into_boxed_path),
93 rdf_database: cli.rdf_database.map(PathBuf::into_boxed_path),
94 log_dir: cli.log_dir.map(PathBuf::into_boxed_path),
95 temp_dir: cli.temp_dir.map(PathBuf::into_boxed_path),
96 server: ServerSettings {
97 port: cli.port.unwrap_or_default(),
98 ip: cli.ip.map(|s| s.parse().expect("Illegal ip")),
99 admin_pwd: cli.admin_pwd,
100 external_url: cli.external_url,
101 },
102 buildqueue: BuildQueueSettings {
103 num_threads: cli.threads,
104 },
105 gitlab: GitlabSettings {
106 url: cli.gitlab_url.map(|s| s.parse().expect("Illegal url")),
107 token: cli.gitlab_token.map(Into::into),
108 app_id: cli.gitlab_app_id.map(Into::into),
109 app_secret: cli.gitlab_app_secret.map(Into::into),
110 redirect_url: cli.gitlab_redirect_url.map(Into::into),
111 },
112 lsp: cli.lsp,
113 };
114 (cli.config_file, settings)
115 }
116}
117
118impl Cli {
119 #[must_use]
120 #[inline]
121 fn get() -> Self {
122 Self::parse()
123 }
124}
125
126#[must_use]
127#[allow(clippy::missing_panics_doc)]
128pub fn get_settings() -> SettingsSpec {
129 fn from_file(cfg_file: &Path) -> SettingsSpec {
130 let cfg = std::fs::read_to_string(cfg_file)
131 .unwrap_or_else(|e| panic!("Could not read config file {}: {e}", cfg_file.display()));
132 let cfg: SettingsSpec = toml::from_str(&cfg)
133 .unwrap_or_else(|e| panic!("Could not parse config file {}: {e}", cfg_file.display()));
134 cfg
135 }
136 let cli = Cli::get();
137 let (cfg, mut settings) = cli.into();
138 settings += SettingsSpec::from_envs();
139 if let Some(cfg_file) = cfg {
140 if cfg_file.exists() {
141 settings += from_file(&cfg_file);
142 } else {
143 panic!("Could not find config file {}", cfg_file.display());
144 }
145 } else if let Ok(path) = std::env::current_exe() {
146 if let Some(path) = path.parent() {
147 let path = path.join("settings.toml");
148 if path.exists() {
149 settings += from_file(&path);
150 }
151 }
152 }
153 settings
154}