what the hell

This commit is contained in:
ldlda committed 2025-07-02 21:16:20 +07:00
commit b34f32310c
5 files changed
+1380

No files matched your search

+1
View File
@@ -0,0 +1 @@
/target
Generated
+1058
View File
File diff suppressed because it is too large. Load diff
+11
View File
@@ -0,0 +1,11 @@
[package]
name = "lda-thp"
version = "0.1.0"
edition = "2024"
publish = ["gitea"]
[dependencies]
color-eyre = "0.6.5"
crossterm = "0.29.0"
ratatui = { version = "0.29.0", features = ["all-widgets", "macros"] }
ratatui-explorer = "0.2.1"
+291
View File
@@ -0,0 +1,291 @@
use crossterm::event::{self, KeyCode, KeyEvent, KeyEventKind, KeyModifiers, MouseEvent};
use ratatui::crossterm;
use ratatui::crossterm::event::Event;
use ratatui::widgets::Clear;
use ratatui::{
Frame, Terminal,
layout::{Constraint, Layout, Spacing},
prelude::Backend,
style::{Style, Stylize},
text::{Line, Span, Text},
widgets::{Block, BorderType, Padding, Paragraph},
};
use ratatui_explorer::{FileExplorer, Input};
use std::{
fmt::Debug,
fs::{File, read_to_string},
io::{self, Read},
path::PathBuf,
};
pub struct DocCache {
doc: PathBuf,
cache: String,
offset: (u16, u16),
}
impl Debug for DocCache {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("DocCache")
.field("doc", &self.doc)
.field("cache", &format!("{:.20}", &self.cache))
.finish()
}
}
#[derive(Debug, Clone, PartialEq, Eq, Default)]
enum AppState {
#[default]
Main,
Quit,
DocSwitcher,
FileError, // file open error. file read error. whatever error.
}
/// model
#[derive(Debug, Default)]
pub struct App<'a> {
doc: Option<DocCache>,
state: AppState,
explorer: Option<&'a mut FileExplorer>,
}
impl<'a> App<'a> {
pub fn new() -> Self {
Default::default()
}
pub fn with_doc(self, doc: impl Into<PathBuf>) -> io::Result<Self> {
let doc = Some(DocCache::new(doc)?);
Ok(Self { doc, ..self })
}
pub fn with_explorer(self, explorer: &'a mut FileExplorer) -> Self {
explorer.set_theme(
explorer
.theme()
.clone()
.with_title_bottom(|_| Line::from("press enter to select ig idk")),
);
Self {
explorer: Some(explorer),
..self
}
}
}
#[derive(Debug, Default, PartialEq, Eq, Clone)]
enum Message {
#[default]
Main,
Quit,
ReloadDoc,
OpenDocSwitcher,
CloseDocSwitcher,
}
impl App<'_> {
pub fn run<B: Backend>(&mut self, term: &mut Terminal<B>) -> io::Result<()> {
while self.state != AppState::Quit {
term.draw(|frame| self.view(frame))?;
let mut event = self.event()?;
while let Some(ev) = event {
event = self.update(ev);
}
}
Ok(())
}
fn view(&self, frame: &mut Frame) {
let [header, main] = Layout::vertical([Constraint::Length(3), Constraint::Min(2)])
.split(frame.area())[..]
.try_into()
.expect("Layout::split / Rc problem");
let header_box = Block::bordered()
.border_type(BorderType::Rounded)
.padding(Padding::horizontal(1));
let [lda, space] = Layout::horizontal([Constraint::Length(3), Constraint::Min(0)])
.spacing(Spacing::Space(1))
.split(header_box.inner(header))[..]
.try_into()
.expect("Layout::split / Rc problem");
let lda_text =
Span::from("lda").style(Style::new().fg(ratatui::style::Color::Indexed(202)));
frame.render_widget(lda_text, lda);
let content_block = Block::bordered().title(Line::from(" file content ").left_aligned());
let mut file_name = Text::default().blue().centered();
let content;
//wtf
if let Some(doc) = &self.doc {
file_name.push_span(doc.doc.display().to_string());
content = Paragraph::new(doc.cache.as_str())
.scroll(doc.offset)
.block(content_block);
} else {
file_name.push_span("no file");
content = Paragraph::new("no idea").block(content_block)
}
frame.render_widget(file_name, space);
frame.render_widget(header_box, header);
frame.render_widget(content, main);
let bij = Layout::horizontal([
Constraint::Fill(1),
Constraint::Max(120),
Constraint::Fill(1),
])
.split(frame.area())[1];
let real = Layout::vertical([
Constraint::Fill(1),
Constraint::Max(30),
Constraint::Fill(1),
])
.split(bij)[1];
if self.state == AppState::DocSwitcher {
frame.render_widget(Clear, real);
let Some(ref exp) = self.explorer else {
let widget = Paragraph::new("you dont have shit on buh what fuck")
.block(Block::bordered().title("shit cuh"));
frame.render_widget(widget, real);
return;
};
frame.render_widget_ref(exp.widget(), real);
}
if self.state == AppState::FileError {
frame.render_widget(Clear, real);
frame.render_widget(
Paragraph::new("file error bihfhahf (if you select with the thing how could it be file error i wonder")
.centered()
.block(Block::bordered().padding(Padding::proportional(5))),
real,
);
}
}
fn update(&mut self, message: Message) -> Option<Message> {
match message {
Message::Main => {
// tf do here
// good. reset
self.state = AppState::Main;
return None;
}
Message::Quit => {
self.state = AppState::Quit;
}
Message::ReloadDoc => {
let Some(doc) = &mut self.doc else {
return Some(Message::Main);
};
match doc.reload_doc() {
Ok(_) => return Some(Message::Main),
Err(_e) => self.state = AppState::FileError,
};
}
Message::OpenDocSwitcher => self.state = AppState::DocSwitcher,
Message::CloseDocSwitcher => {
let Some(ref mut expl) = self.explorer else {
// no way bro doesnt have this and then close doc
unreachable!()
};
if let Some(file_name) = {
let maybe = expl.current();
(maybe.is_file()).then(|| maybe.path())
} {
if let Some(ref mut doc) = self.doc {
// get cur file if
{
if file_name != &doc.doc {
doc.doc.clear();
doc.doc.push(file_name);
return Some(Message::ReloadDoc); // ohoho i can do this
}
}
} else {
match DocCache::new(file_name.clone()) {
Ok(f) => {
self.doc = Some(f);
return Some(Message::Main);
}
Err(_e) => self.state = AppState::FileError,
}
}
}
}
};
None
}
fn event(&mut self) -> io::Result<Option<Message>> {
let ev = ratatui::crossterm::event::read()?;
if self.state == AppState::DocSwitcher {
if let Some(ref mut exp) = self.explorer {
if matches!(
ev,
Event::Key(
KeyEvent {
code,..
}
) if code == KeyCode::Char('q') || code == KeyCode::Esc
) {
return Ok(Some(Message::Main));
}
if matches!(
ev,
event::Event::Key(KeyEvent {
code: KeyCode::Enter,
..
})
) && exp.current().is_file()
{
return Ok(Some(Message::CloseDocSwitcher));
};
exp.handle(Input::from(&ev))?;
return Ok(None);
}
};
match ev {
event::Event::Key(KeyEvent {
code,
modifiers,
kind,
state: _,
}) => {
if kind == KeyEventKind::Release {
return Ok(None);
}
if code == KeyCode::Char('q') || code == KeyCode::Esc {
return Ok(Some(Message::Quit));
} else if code == KeyCode::Char('r') && modifiers.contains(KeyModifiers::CONTROL) {
return Ok(Some(Message::ReloadDoc));
} else if code == KeyCode::Enter {
return Ok(Some(Message::OpenDocSwitcher));
}
Ok(None)
}
event::Event::Mouse(MouseEvent {
kind: _,
column: _,
row: _,
modifiers: _,
}) => Ok(None),
_ => Ok(None),
}
}
}
impl DocCache {
pub fn new(doc: impl Into<PathBuf>) -> io::Result<Self> {
let doc = doc.into();
let cache = read_to_string(&doc)?;
Ok(Self {
doc,
cache,
offset: (0, 0),
})
}
fn reload_doc(&mut self) -> io::Result<()> {
self.cache.clear();
File::open(&self.doc)?.read_to_string(&mut self.cache)?;
Ok(())
}
}
+19
View File
@@ -0,0 +1,19 @@
//! im going to fucking ELM
//! ima view event update
use ratatui_explorer::FileExplorer;
mod app;
fn main() -> color_eyre::Result<()> {
color_eyre::install()?;
let mut r = ratatui::init();
let mut exp = FileExplorer::new()?;
app::App::new()
.with_doc("src/main.rs")?
.with_explorer(&mut exp)
.run(&mut r)?;
ratatui::restore();
Ok(())
}