[tui] Add more logging.

This commit is contained in:
Shaun Reed 2026-01-25 09:07:41 -05:00
parent 711f92b7dd
commit 01eeb9f0ac
8 changed files with 54 additions and 18 deletions

View File

@ -7,7 +7,7 @@ mod logger;
mod menu_bar;
use anyhow::{Context, Result};
use log::{LevelFilter, debug, info};
use log::{LevelFilter, debug, info, trace};
use ratatui::Terminal;
use ratatui::backend::CrosstermBackend;
use ratatui::crossterm::event::{
@ -28,10 +28,15 @@ pub struct Tui {
}
impl Tui {
pub fn id() -> &'static str {
"Tui"
}
pub fn new(root_path: std::path::PathBuf) -> Result<Self> {
trace!(target:Self::id(), "Building {}", Self::id());
init_logger(LevelFilter::Trace)?;
set_default_level(LevelFilter::Trace);
debug!(target:"Tui", "Logging initialized");
debug!(target:Self::id(), "Logging initialized");
let mut dir = env::temp_dir();
dir.push("clide.log");
@ -43,7 +48,7 @@ impl Tui {
.output_file(false)
.output_separator(':');
set_log_file(file_options);
debug!(target:"Tui", "Logging to file: {dir:?}");
debug!(target:Self::id(), "Logging to file: {dir:?}");
Ok(Self {
terminal: Terminal::new(CrosstermBackend::new(stdout()))?,
@ -52,7 +57,7 @@ impl Tui {
}
pub fn start(self) -> Result<()> {
info!(target:"Tui", "Starting the TUI editor at {:?}", self.root_path);
info!(target:Self::id(), "Starting the TUI editor at {:?}", self.root_path);
ratatui::crossterm::execute!(
stdout(),
EnterAlternateScreen,
@ -69,7 +74,7 @@ impl Tui {
}
fn stop() -> Result<()> {
info!(target:"Tui", "Stopping the TUI editor");
info!(target:Self::id(), "Stopping the TUI editor");
disable_raw_mode()?;
ratatui::crossterm::execute!(
stdout(),

View File

@ -6,7 +6,7 @@ use crate::tui::logger::Logger;
use crate::tui::menu_bar::MenuBar;
use AppComponent::AppMenuBar;
use anyhow::{Context, Result};
use log::error;
use log::{error, info, trace, warn};
use ratatui::DefaultTerminal;
use ratatui::buffer::Buffer;
use ratatui::crossterm::event;
@ -22,7 +22,7 @@ use std::time::Duration;
// TODO: Need a way to dynamically run Widget::render on all widgets.
// TODO: + Need a way to map Rect to Component::id() to position each widget?
// TODO: Need a good way to dynamically run Component methods on all widgets.
#[derive(PartialEq)]
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum AppComponent {
AppEditor,
AppExplorer,
@ -44,6 +44,7 @@ impl<'a> App<'a> {
}
pub fn new(root_path: PathBuf) -> Result<Self> {
trace!(target:Self::id(), "Building {}", Self::id());
let app = Self {
editor_tabs: EditorTab::new(&root_path),
explorer: Explorer::new(&root_path)?,
@ -56,6 +57,7 @@ impl<'a> App<'a> {
/// Logic that should be executed once on application startup.
pub fn start(&mut self) -> Result<()> {
trace!(target:Self::id(), "Starting App");
let root_path = self.explorer.root_path.clone();
let editor = self
.editor_tabs
@ -72,10 +74,8 @@ impl<'a> App<'a> {
pub fn run(mut self, mut terminal: DefaultTerminal) -> Result<()> {
self.start()?;
trace!(target:Self::id(), "Entering App run loop");
loop {
self.refresh_editor_contents()
.context("Failed to refresh editor contents.")?;
terminal.draw(|f| {
f.render_widget(&mut self, f.area());
})?;
@ -122,6 +122,7 @@ impl<'a> App<'a> {
}
fn change_focus(&mut self, focus: AppComponent) {
info!(target:Self::id(), "Changing widget focus to {:?}", focus);
match focus {
AppEditor => match self.editor_tabs.current_editor_mut() {
None => {
@ -138,6 +139,7 @@ impl<'a> App<'a> {
/// Refresh the contents of the editor to match the selected TreeItem in the file Explorer.
/// If the selected item is not a file, this does nothing.
#[allow(unused)]
fn refresh_editor_contents(&mut self) -> Result<()> {
// TODO: This may be useful for a preview mode of the selected file prior to opening a tab.
// Use the currently selected TreeItem or get an absolute path to this source file.
@ -242,8 +244,8 @@ impl<'a> Component for App<'a> {
Action::Quit | Action::Handled => Ok(action),
Action::Save => match editor.save() {
Ok(_) => Ok(Action::Handled),
Err(_) => {
error!(target:Self::id(), "Failed to save editor contents");
Err(e) => {
error!(target:Self::id(), "Failed to save editor contents: {e}");
Ok(Action::Noop)
}
},

View File

@ -1,6 +1,7 @@
#![allow(dead_code, unused_variables)]
use anyhow::Result;
use log::trace;
use ratatui::crossterm::event::{Event, KeyEvent, MouseEvent};
pub enum Action {
@ -55,7 +56,12 @@ pub struct ComponentState {
}
impl ComponentState {
pub fn id() -> &'static str {
"ComponentState"
}
fn new() -> Self {
trace!(target:Self::id(), "Building {}", Self::id());
Self {
focus: Focus::Active,
help_text: String::new(),

View File

@ -3,6 +3,7 @@ use anyhow::{Context, Result, bail};
use edtui::{
EditorEventHandler, EditorState, EditorTheme, EditorView, LineNumbers, Lines, SyntaxHighlighter,
};
use log::{error, trace};
use ratatui::buffer::Buffer;
use ratatui::crossterm::event::{Event, KeyCode, KeyEvent, KeyModifiers};
use ratatui::layout::{Alignment, Rect};
@ -25,6 +26,7 @@ impl Editor {
// TODO: You shouldnt be able to construct the editor without a path?
pub fn new() -> Self {
trace!(target:Self::id(), "Building {}", Self::id());
Editor {
state: EditorState::default(),
event_handler: EditorEventHandler::default(),
@ -38,6 +40,7 @@ impl Editor {
}
pub fn set_contents(&mut self, path: &std::path::PathBuf) -> Result<()> {
trace!(target:Self::id(), "Setting Editor contents from path {:?}", path);
if let Ok(contents) = std::fs::read_to_string(path) {
let lines: Vec<_> = contents
.lines()
@ -53,8 +56,10 @@ impl Editor {
pub fn save(&self) -> Result<()> {
if let Some(path) = &self.file_path {
trace!(target:Self::id(), "Saving Editor contents {:?}", path);
return std::fs::write(path, self.state.lines.to_string()).map_err(|e| e.into());
};
error!(target:Self::id(), "Failed saving Editor contents; file_path was None");
bail!("File not saved. No file path set.")
}
}

View File

@ -1,7 +1,7 @@
use crate::tui::component::{Action, Component};
use crate::tui::editor::Editor;
use anyhow::{Context, Result};
use log::trace;
use log::{trace, warn};
use ratatui::buffer::Buffer;
use ratatui::crossterm::event::{Event, KeyCode, KeyEvent, KeyModifiers};
use ratatui::layout::Rect;
@ -24,7 +24,7 @@ impl EditorTab {
}
pub fn new(path: &std::path::PathBuf) -> Self {
trace!(target:Self::id(), "Building EditorTab with path '{path:?}'");
trace!(target:Self::id(), "Building EditorTab with path {path:?}");
let tab_order = vec![path.to_string_lossy().to_string()];
Self {
editors: HashMap::from([(tab_order.first().unwrap().to_owned(), Editor::new())]),
@ -34,14 +34,18 @@ impl EditorTab {
}
pub fn next_editor(&mut self) {
self.current_editor = (self.current_editor + 1) % self.tab_order.len();
let next = (self.current_editor + 1) % self.tab_order.len();
trace!(target:Self::id(), "Moving from {} to next editor tab at {}", self.current_editor, next);
self.current_editor = next;
}
pub fn prev_editor(&mut self) {
self.current_editor = self
let prev = self
.current_editor
.checked_sub(1)
.unwrap_or(self.tab_order.len() - 1);
trace!(target:Self::id(), "Moving from {} to previous editor tab at {}", self.current_editor, prev);
self.current_editor = prev;
}
pub fn current_editor(&self) -> Option<&Editor> {
@ -53,10 +57,12 @@ impl EditorTab {
}
pub fn open_tab(&mut self, path: &std::path::PathBuf) -> Result<()> {
trace!(target:Self::id(), "Opening new EditorTab with path {:?}", path);
if self
.editors
.contains_key(&path.to_string_lossy().to_string())
{
warn!(target:Self::id(), "EditorTab already opened with this file");
return Ok(());
}

View File

@ -1,5 +1,6 @@
use crate::tui::component::{Action, Component, ComponentState, Focus};
use anyhow::{Context, Result, bail};
use log::trace;
use ratatui::buffer::Buffer;
use ratatui::crossterm::event::{Event, KeyCode, KeyEvent, MouseEvent, MouseEventKind};
use ratatui::layout::{Alignment, Position, Rect};
@ -24,6 +25,7 @@ impl<'a> Explorer<'a> {
}
pub fn new(path: &PathBuf) -> Result<Self> {
trace!(target:Self::id(), "Building {}", Self::id());
let explorer = Explorer {
root_path: path.to_owned(),
tree_items: Self::build_tree_from_path(path.to_owned())?,

View File

@ -1,4 +1,5 @@
use crate::tui::component::{Action, Component, ComponentState, Focus};
use log::trace;
use ratatui::buffer::Buffer;
use ratatui::crossterm::event::{Event, KeyCode, KeyEvent};
use ratatui::layout::Rect;
@ -19,6 +20,7 @@ impl Logger {
}
pub fn new() -> Self {
trace!(target:Self::id(), "Building {}", Self::id());
let state = TuiWidgetState::new();
state.transition(TuiWidgetEvent::HideKey);
Self {

View File

@ -2,6 +2,7 @@ use crate::tui::component::{Action, Component, ComponentState};
use crate::tui::menu_bar::MenuBarItemOption::{
About, Exit, Reload, Save, ShowHideExplorer, ShowHideLogger,
};
use log::trace;
use ratatui::buffer::Buffer;
use ratatui::crossterm::event::{KeyCode, KeyEvent};
use ratatui::layout::Rect;
@ -80,8 +81,13 @@ pub struct MenuBar {
}
impl MenuBar {
pub fn id() -> &'static str {
"MenuBar"
}
const DEFAULT_HELP: &str = "(←/h)/(→/l): Select option | Enter: Choose selection";
pub fn new() -> Self {
trace!(target:Self::id(), "Building {}", Self::id());
Self {
selected: MenuBarItem::File,
opened: None,
@ -136,12 +142,14 @@ impl MenuBar {
fn rect_under_option(anchor: Rect, area: Rect, width: u16, height: u16) -> Rect {
// TODO: X offset for item option? It's fine as-is, but it might look nicer.
Rect {
let rect = Rect {
x: anchor.x,
y: anchor.y + anchor.height,
width: width.min(area.width),
height,
}
};
trace!(target:Self::id(), "Building Rect under MenuBar popup {}", rect);
rect
}
}