TUI #1

Merged
shaunrd0 merged 73 commits from ui into master 2026-01-25 20:57:37 +00:00
2 changed files with 32 additions and 14 deletions
Showing only changes of commit bccc5a35e2 - Show all commits

View File

@ -8,6 +8,7 @@ use ratatui::layout::{Constraint, Direction, Layout, Rect};
use ratatui::prelude::{Color, Style, Widget}; use ratatui::prelude::{Color, Style, Widget};
use ratatui::widgets::{Block, Borders, Padding, Paragraph, Tabs, Wrap}; use ratatui::widgets::{Block, Borders, Padding, Paragraph, Tabs, Wrap};
use ratatui::{DefaultTerminal, symbols}; use ratatui::{DefaultTerminal, symbols};
use std::path::PathBuf;
use std::time::Duration; use std::time::Duration;
pub struct App<'a> { pub struct App<'a> {
@ -16,7 +17,7 @@ pub struct App<'a> {
} }
impl<'a> App<'a> { impl<'a> App<'a> {
pub(crate) fn new(root_path: std::path::PathBuf) -> Self { pub(crate) fn new(root_path: PathBuf) -> Self {
let mut app = Self { let mut app = Self {
explorer: Explorer::new(&root_path), explorer: Explorer::new(&root_path),
editor: Editor::new(), editor: Editor::new(),
@ -90,6 +91,21 @@ impl<'a> App<'a> {
.wrap(Wrap { trim: false }) .wrap(Wrap { trim: false })
.render(area, buf); .render(area, buf);
} }
/// 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.
fn refresh_editor_contents(&mut self) {
if let Some(current_file_path) = self.editor.file_path.clone() {
if let Some(selected_path_string) = self.explorer.selected() {
let selected_pathbuf = PathBuf::from(selected_path_string);
if std::path::absolute(&selected_pathbuf).unwrap().is_file()
&& selected_pathbuf != current_file_path
{
self.editor.set_contents(&selected_pathbuf.into()).ok();
}
}
}
}
} }
// TODO: Separate complex components into their own widgets. // TODO: Separate complex components into their own widgets.
@ -129,16 +145,7 @@ impl<'a> Widget for &mut App<'a> {
self.explorer.render(horizontal[0], buf); self.explorer.render(horizontal[0], buf);
self.draw_tabs(editor_layout[0], buf); self.draw_tabs(editor_layout[0], buf);
self.refresh_editor_contents();
if let Some(editor) = self.editor.file_path.clone() {
let editor_abs = std::path::absolute(editor).unwrap();
if let Some(selected) = self.explorer.selected() {
let selected_abs = std::path::absolute(selected).unwrap();
if selected_abs.is_file() && selected_abs != editor_abs {
self.editor.set_contents(&selected_abs).ok();
}
}
}
self.editor.render(editor_layout[1], buf); self.editor.render(editor_layout[1], buf);
} }
} }

View File

@ -9,6 +9,7 @@ use ratatui::crossterm::event::{Event, KeyCode, KeyEvent, KeyModifiers};
use ratatui::layout::{Alignment, Rect}; use ratatui::layout::{Alignment, Rect};
use ratatui::prelude::{Color, Style}; use ratatui::prelude::{Color, Style};
use ratatui::widgets::{Block, Borders, Padding, Widget}; use ratatui::widgets::{Block, Borders, Padding, Widget};
use syntect::parsing::SyntaxSet;
// TODO: Consider using editor-command https://docs.rs/editor-command/latest/editor_command/ // TODO: Consider using editor-command https://docs.rs/editor-command/latest/editor_command/
// TODO: Title should be detected programming language name // TODO: Title should be detected programming language name
@ -52,20 +53,30 @@ impl Editor {
impl Widget for &mut Editor { impl Widget for &mut Editor {
fn render(self, area: Rect, buf: &mut Buffer) { fn render(self, area: Rect, buf: &mut Buffer) {
// TODO: Use current file extension for syntax highlighting here. let lang = self
.file_path
.as_ref()
.and_then(|p| p.extension())
.map(|e| e.to_str().unwrap_or("md"))
.unwrap_or("md");
let lang_name = SyntaxSet::load_defaults_nonewlines()
.find_syntax_by_extension(lang)
.map(|s| s.name.to_string())
.unwrap_or_else(|| "Unknown".to_string());
EditorView::new(&mut self.state) EditorView::new(&mut self.state)
.wrap(true) .wrap(true)
.theme( .theme(
EditorTheme::default().block( EditorTheme::default().block(
Block::default() Block::default()
.title("Rust") .title(lang_name.to_owned())
.title_style(Style::default().fg(Color::Yellow)) .title_style(Style::default().fg(Color::Yellow))
.title_alignment(Alignment::Right) .title_alignment(Alignment::Right)
.borders(Borders::ALL) .borders(Borders::ALL)
.padding(Padding::new(0, 0, 0, 1)), .padding(Padding::new(0, 0, 0, 1)),
), ),
) )
.syntax_highlighter(SyntaxHighlighter::new("dracula", "rs").ok()) .syntax_highlighter(SyntaxHighlighter::new("dracula", lang).ok())
.tab_width(2) .tab_width(2)
.line_numbers(LineNumbers::Absolute) .line_numbers(LineNumbers::Absolute)
.render(area, buf); .render(area, buf);