diff --git a/src/tui/app.rs b/src/tui/app.rs index 90e37c3..67b0bd5 100644 --- a/src/tui/app.rs +++ b/src/tui/app.rs @@ -8,6 +8,7 @@ use ratatui::layout::{Constraint, Direction, Layout, Rect}; use ratatui::prelude::{Color, Style, Widget}; use ratatui::widgets::{Block, Borders, Padding, Paragraph, Tabs, Wrap}; use ratatui::{DefaultTerminal, symbols}; +use std::path::PathBuf; use std::time::Duration; pub struct App<'a> { @@ -16,7 +17,7 @@ pub struct 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 { explorer: Explorer::new(&root_path), editor: Editor::new(), @@ -90,6 +91,21 @@ impl<'a> App<'a> { .wrap(Wrap { trim: false }) .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. @@ -129,16 +145,7 @@ impl<'a> Widget for &mut App<'a> { self.explorer.render(horizontal[0], buf); self.draw_tabs(editor_layout[0], buf); - - 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.refresh_editor_contents(); self.editor.render(editor_layout[1], buf); } } diff --git a/src/tui/editor.rs b/src/tui/editor.rs index 2ff4f8c..3677f3b 100644 --- a/src/tui/editor.rs +++ b/src/tui/editor.rs @@ -9,6 +9,7 @@ use ratatui::crossterm::event::{Event, KeyCode, KeyEvent, KeyModifiers}; use ratatui::layout::{Alignment, Rect}; use ratatui::prelude::{Color, Style}; 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: Title should be detected programming language name @@ -52,20 +53,30 @@ impl Editor { impl Widget for &mut Editor { 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) .wrap(true) .theme( EditorTheme::default().block( Block::default() - .title("Rust") + .title(lang_name.to_owned()) .title_style(Style::default().fg(Color::Yellow)) .title_alignment(Alignment::Right) .borders(Borders::ALL) .padding(Padding::new(0, 0, 0, 1)), ), ) - .syntax_highlighter(SyntaxHighlighter::new("dracula", "rs").ok()) + .syntax_highlighter(SyntaxHighlighter::new("dracula", lang).ok()) .tab_width(2) .line_numbers(LineNumbers::Absolute) .render(area, buf);