2026-01-31 04:25:14 +00:00
|
|
|
use anyhow::{Context, Result, anyhow};
|
2026-01-25 20:57:36 +00:00
|
|
|
use clap::Parser;
|
|
|
|
|
use log::{info, trace};
|
|
|
|
|
use std::process::{Command, Stdio};
|
2025-03-29 08:01:13 -04:00
|
|
|
|
2026-01-25 20:57:36 +00:00
|
|
|
pub mod gui;
|
|
|
|
|
pub mod tui;
|
|
|
|
|
/// Extendable command-line driven development environment written in Rust using the Qt UI framework.
|
|
|
|
|
/// If no flags are provided, the GUI editor is launched in a separate process.
|
|
|
|
|
/// If no path is provided, the current directory is used.
|
|
|
|
|
#[derive(Parser, Debug)]
|
|
|
|
|
#[structopt(name = "clide", verbatim_doc_comment)]
|
|
|
|
|
struct Cli {
|
|
|
|
|
/// The root directory for the project to open with the clide editor.
|
|
|
|
|
#[arg(value_parser = clap::value_parser!(std::path::PathBuf))]
|
|
|
|
|
pub path: Option<std::path::PathBuf>,
|
2025-03-29 08:01:13 -04:00
|
|
|
|
2026-01-25 20:57:36 +00:00
|
|
|
/// Run clide in headless mode.
|
|
|
|
|
#[arg(value_name = "tui", short, long)]
|
|
|
|
|
pub tui: bool,
|
2025-03-29 08:01:13 -04:00
|
|
|
|
2026-01-25 20:57:36 +00:00
|
|
|
/// Run the clide GUI in the current process, blocking the terminal and showing all output streams.
|
|
|
|
|
#[arg(value_name = "gui", short, long)]
|
|
|
|
|
pub gui: bool,
|
2025-03-29 08:01:13 -04:00
|
|
|
}
|
|
|
|
|
|
2026-01-31 04:25:14 +00:00
|
|
|
impl Cli {
|
|
|
|
|
fn run_mode(&self) -> Result<RunMode> {
|
|
|
|
|
let mut modes = Vec::new();
|
|
|
|
|
self.tui.then(|| modes.push(RunMode::Tui));
|
|
|
|
|
self.gui.then(|| modes.push(RunMode::GuiAttached));
|
|
|
|
|
match &modes[..] {
|
|
|
|
|
[] => Ok(RunMode::Gui),
|
|
|
|
|
[mode] => Ok(*mode),
|
|
|
|
|
multiple => Err(anyhow!(
|
|
|
|
|
"More than one run mode found {multiple:?} please select one."
|
|
|
|
|
)),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub struct AppContext {
|
|
|
|
|
pub path: std::path::PathBuf,
|
|
|
|
|
pub run_mode: RunMode,
|
|
|
|
|
}
|
2025-03-29 08:01:13 -04:00
|
|
|
|
2026-01-31 04:25:14 +00:00
|
|
|
impl AppContext {
|
|
|
|
|
fn new(cli: Cli) -> Result<Self> {
|
|
|
|
|
let path = match &cli.path {
|
|
|
|
|
// If the CLI was provided a directory, convert it to absolute.
|
|
|
|
|
Some(path) => std::path::absolute(path)?,
|
|
|
|
|
// If no path was provided, use the current directory.
|
|
|
|
|
None => std::env::current_dir().context("Failed to obtain current directory")?,
|
|
|
|
|
};
|
|
|
|
|
info!(target:"main()", "Root path detected: {path:?}");
|
2025-03-29 08:01:13 -04:00
|
|
|
|
2026-01-31 04:25:14 +00:00
|
|
|
Ok(Self {
|
|
|
|
|
path,
|
|
|
|
|
run_mode: cli.run_mode()?,
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[derive(Copy, Clone, Debug, Default)]
|
|
|
|
|
pub enum RunMode {
|
|
|
|
|
#[default]
|
|
|
|
|
Gui,
|
|
|
|
|
GuiAttached,
|
|
|
|
|
Tui,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn main() -> Result<()> {
|
|
|
|
|
let args = Cli::parse();
|
|
|
|
|
let app_context = AppContext::new(args)?;
|
|
|
|
|
match app_context.run_mode {
|
|
|
|
|
RunMode::GuiAttached => gui::run(app_context),
|
|
|
|
|
RunMode::Tui => tui::run(app_context),
|
|
|
|
|
RunMode::Gui => {
|
|
|
|
|
trace!(target:"main()", "Starting GUI in a new process");
|
|
|
|
|
Command::new(std::env::current_exe()?)
|
|
|
|
|
.args(&["--gui", app_context.path.to_str().unwrap()])
|
|
|
|
|
.stdout(Stdio::null())
|
|
|
|
|
.stderr(Stdio::null())
|
|
|
|
|
.stdin(Stdio::null())
|
|
|
|
|
.spawn()
|
|
|
|
|
.context("Failed to start GUI")
|
|
|
|
|
.map(|_| ())
|
2025-03-29 08:01:13 -04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|