2026-01-31 08:02:16 -05:00
|
|
|
// SPDX-FileCopyrightText: 2026, Shaun Reed <shaunrd0@gmail.com>
|
|
|
|
|
//
|
|
|
|
|
// SPDX-License-Identifier: GNU General Public License v3.0 or later
|
|
|
|
|
|
2026-01-25 20:57:36 +00:00
|
|
|
mod about;
|
|
|
|
|
mod app;
|
|
|
|
|
mod component;
|
|
|
|
|
mod editor;
|
|
|
|
|
mod editor_tab;
|
|
|
|
|
mod explorer;
|
|
|
|
|
mod logger;
|
|
|
|
|
mod menu_bar;
|
|
|
|
|
|
2026-01-31 04:25:14 +00:00
|
|
|
use crate::AppContext;
|
2026-01-25 20:57:36 +00:00
|
|
|
use anyhow::{Context, Result};
|
|
|
|
|
use log::{LevelFilter, debug, info, trace};
|
|
|
|
|
use ratatui::Terminal;
|
|
|
|
|
use ratatui::backend::CrosstermBackend;
|
|
|
|
|
use ratatui::crossterm::event::{
|
|
|
|
|
DisableBracketedPaste, DisableMouseCapture, EnableBracketedPaste, EnableMouseCapture,
|
|
|
|
|
};
|
|
|
|
|
use ratatui::crossterm::terminal::{
|
|
|
|
|
EnterAlternateScreen, LeaveAlternateScreen, disable_raw_mode, enable_raw_mode,
|
|
|
|
|
};
|
|
|
|
|
use std::env;
|
|
|
|
|
use std::io::{Stdout, stdout};
|
|
|
|
|
use tui_logger::{
|
|
|
|
|
TuiLoggerFile, TuiLoggerLevelOutput, init_logger, set_default_level, set_log_file,
|
|
|
|
|
};
|
|
|
|
|
|
2026-01-31 04:25:14 +00:00
|
|
|
struct Tui {
|
2026-01-25 20:57:36 +00:00
|
|
|
terminal: Terminal<CrosstermBackend<Stdout>>,
|
|
|
|
|
root_path: std::path::PathBuf,
|
|
|
|
|
}
|
|
|
|
|
|
2026-01-31 04:25:14 +00:00
|
|
|
pub fn run(app_context: AppContext) -> Result<()> {
|
|
|
|
|
trace!(target:Tui::ID, "Starting TUI");
|
|
|
|
|
Tui::new(app_context)?.start()
|
|
|
|
|
}
|
|
|
|
|
|
2026-01-25 20:57:36 +00:00
|
|
|
impl Tui {
|
2026-01-31 04:25:14 +00:00
|
|
|
pub const ID: &str = "Tui";
|
2026-01-25 20:57:36 +00:00
|
|
|
|
2026-01-31 04:25:14 +00:00
|
|
|
fn new(app_context: AppContext) -> Result<Self> {
|
|
|
|
|
trace!(target:Self::ID, "Building {}", Self::ID);
|
2026-01-25 20:57:36 +00:00
|
|
|
init_logger(LevelFilter::Trace)?;
|
|
|
|
|
set_default_level(LevelFilter::Trace);
|
2026-01-31 04:25:14 +00:00
|
|
|
debug!(target:Self::ID, "Logging initialized");
|
2026-01-25 20:57:36 +00:00
|
|
|
|
|
|
|
|
let mut dir = env::temp_dir();
|
|
|
|
|
dir.push("clide.log");
|
|
|
|
|
let file_options = TuiLoggerFile::new(
|
|
|
|
|
dir.to_str()
|
|
|
|
|
.context("Failed to set temp directory for file logging")?,
|
|
|
|
|
)
|
|
|
|
|
.output_level(Some(TuiLoggerLevelOutput::Abbreviated))
|
|
|
|
|
.output_file(false)
|
|
|
|
|
.output_separator(':');
|
|
|
|
|
set_log_file(file_options);
|
2026-01-31 04:25:14 +00:00
|
|
|
debug!(target:Self::ID, "Logging to file: {dir:?}");
|
2026-01-25 20:57:36 +00:00
|
|
|
|
|
|
|
|
Ok(Self {
|
|
|
|
|
terminal: Terminal::new(CrosstermBackend::new(stdout()))?,
|
2026-01-31 04:25:14 +00:00
|
|
|
root_path: app_context.path,
|
2026-01-25 20:57:36 +00:00
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
2026-01-31 04:25:14 +00:00
|
|
|
fn start(self) -> Result<()> {
|
|
|
|
|
info!(target:Self::ID, "Starting the TUI editor at {:?}", self.root_path);
|
2026-01-25 20:57:36 +00:00
|
|
|
ratatui::crossterm::execute!(
|
|
|
|
|
stdout(),
|
|
|
|
|
EnterAlternateScreen,
|
|
|
|
|
EnableMouseCapture,
|
|
|
|
|
EnableBracketedPaste
|
|
|
|
|
)?;
|
|
|
|
|
enable_raw_mode()?;
|
|
|
|
|
|
|
|
|
|
let app_result = app::App::new(self.root_path)?
|
|
|
|
|
.run(self.terminal)
|
|
|
|
|
.context("Failed to start the TUI editor.");
|
|
|
|
|
Self::stop()?;
|
|
|
|
|
app_result
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn stop() -> Result<()> {
|
2026-01-31 04:25:14 +00:00
|
|
|
info!(target:Self::ID, "Stopping the TUI editor");
|
2026-01-25 20:57:36 +00:00
|
|
|
disable_raw_mode()?;
|
|
|
|
|
ratatui::crossterm::execute!(
|
|
|
|
|
stdout(),
|
|
|
|
|
LeaveAlternateScreen,
|
|
|
|
|
DisableMouseCapture,
|
|
|
|
|
DisableBracketedPaste
|
|
|
|
|
)?;
|
|
|
|
|
Ok(())
|
|
|
|
|
}
|
|
|
|
|
}
|