5 warnings
This commit is contained in:
1 parent
c165b3fa94
commit
a4cafc0ef9
2 files changed
+212
-74
No files matched your search
+211
-73
@@ -1,29 +1,31 @@
|
||||
use crossterm::event::Event;
|
||||
use crossterm::event::{self, KeyCode, KeyEvent, KeyEventKind, KeyModifiers, MouseEvent};
|
||||
use ratatui::text::{ToLine, ToSpan};
|
||||
use ratatui::widgets::Clear;
|
||||
use crossterm::event::{
|
||||
self, Event, KeyCode, KeyEvent, KeyEventKind, KeyModifiers, MouseEvent, MouseEventKind,
|
||||
};
|
||||
use ratatui::{
|
||||
Frame, Terminal,
|
||||
layout::{Constraint, Layout, Spacing},
|
||||
layout::{Constraint, Layout, Position, Rect, Size, Spacing},
|
||||
prelude::Backend,
|
||||
style::{Style, Stylize},
|
||||
text::{Line, Span, Text},
|
||||
widgets::{Block, BorderType, Padding, Paragraph},
|
||||
text::{Line, Span, Text, ToLine, ToSpan},
|
||||
widgets::{Block, BorderType, Clear, Padding, Paragraph, Wrap},
|
||||
};
|
||||
use ratatui_explorer::{FileExplorer, Input};
|
||||
use std::io::{BufRead, BufReader};
|
||||
use std::path::Path;
|
||||
use std::{
|
||||
fmt::Debug,
|
||||
fs::File,
|
||||
io::{self},
|
||||
path::PathBuf,
|
||||
io::{self, BufRead, BufReader},
|
||||
path::{Path, PathBuf},
|
||||
};
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct DocCache {
|
||||
content: String,
|
||||
/// height - width. up down first, left right second.
|
||||
offset: (u16, u16),
|
||||
length_hint: u16,
|
||||
/// same format as offset
|
||||
screen: Rect,
|
||||
/// is also lines - max len, which means height width.
|
||||
length_hint: (u16, u16),
|
||||
}
|
||||
pub struct Doc {
|
||||
doc: PathBuf,
|
||||
@@ -95,6 +97,23 @@ impl<'a> App<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Clone)]
|
||||
enum TextScroll {
|
||||
UpOne,
|
||||
DownOne,
|
||||
UpHalf,
|
||||
DownHalf,
|
||||
UpFull,
|
||||
DownFull,
|
||||
Up(u16),
|
||||
Down(u16),
|
||||
// not when i Wrap.
|
||||
Left(u16),
|
||||
Right(u16),
|
||||
LeftOne,
|
||||
RightOne,
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, PartialEq, Eq, Clone)]
|
||||
enum Message {
|
||||
#[default]
|
||||
@@ -105,7 +124,7 @@ enum Message {
|
||||
DocSwitcherAction(Input),
|
||||
/// close doc switcher because there is a new file coming
|
||||
NewDoc,
|
||||
TextScroll(Option<bool>, Option<bool>),
|
||||
TextScroll(TextScroll),
|
||||
}
|
||||
impl App<'_> {
|
||||
pub fn run<B: Backend>(&mut self, term: &mut Terminal<B>) -> io::Result<()> {
|
||||
@@ -118,7 +137,7 @@ impl App<'_> {
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
fn view(&self, frame: &mut Frame) {
|
||||
fn view(&mut self, frame: &mut Frame) {
|
||||
frame.render_widget(Clear, frame.area()); // tf this about
|
||||
|
||||
let [header, main, foot] = Layout::vertical([
|
||||
@@ -142,6 +161,14 @@ impl App<'_> {
|
||||
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());
|
||||
// NOOOO this is only reason self is mut
|
||||
if let Some(Doc {
|
||||
cache: Some(DocCache { ref mut screen, .. }),
|
||||
..
|
||||
}) = self.doc
|
||||
{
|
||||
*screen = content_block.inner(main);
|
||||
}
|
||||
|
||||
let mut file_name = Text::default().blue().centered();
|
||||
let content;
|
||||
@@ -150,7 +177,9 @@ impl App<'_> {
|
||||
file_name.push_span(doc.doc.display().to_string());
|
||||
if let Some(cache) = &doc.cache {
|
||||
let text = Text::from(cache.content.as_str());
|
||||
content = Paragraph::new(text).scroll(cache.offset);
|
||||
content = Paragraph::new(text)
|
||||
.wrap(Wrap { trim: false })
|
||||
.scroll(cache.offset); // pronblem
|
||||
} else {
|
||||
content = Paragraph::new("errored buhhhhhh".to_line().centered())
|
||||
}
|
||||
@@ -162,10 +191,14 @@ impl App<'_> {
|
||||
frame.render_widget(header_box, header);
|
||||
frame.render_widget(content, main);
|
||||
frame.render_widget(
|
||||
Line::from_iter([
|
||||
Span::from("enter to choose file, "),
|
||||
Span::from("esc or q to quit"),
|
||||
]),
|
||||
{
|
||||
let mut line = Line::default();
|
||||
if self.explorer.is_some() {
|
||||
line.push_span(Span::from("enter to choose file, "));
|
||||
};
|
||||
line.push_span(Span::from("esc or q to quit"));
|
||||
line
|
||||
},
|
||||
foot,
|
||||
);
|
||||
{
|
||||
@@ -232,7 +265,11 @@ impl App<'_> {
|
||||
Err(_e) => self.state = AppState::FileError,
|
||||
};
|
||||
}
|
||||
Message::OpenDocSwitcher => self.state = AppState::DocSwitcher,
|
||||
Message::OpenDocSwitcher => {
|
||||
if self.explorer.is_some() {
|
||||
self.state = AppState::DocSwitcher
|
||||
};
|
||||
}
|
||||
Message::NewDoc => {
|
||||
let Some(ref mut expl) = self.explorer else {
|
||||
// no way bro doesnt have this and then close doc
|
||||
@@ -250,6 +287,9 @@ impl App<'_> {
|
||||
{
|
||||
self.doc = Some(Doc::new(file_name));
|
||||
return Some(Message::ReloadDoc);
|
||||
} else if let Some(Doc { cache: None, .. }) = self.doc {
|
||||
self.state = AppState::FileError;
|
||||
return None;
|
||||
}
|
||||
}
|
||||
return Some(Message::Main);
|
||||
@@ -280,20 +320,21 @@ impl App<'_> {
|
||||
}; // noooo
|
||||
}
|
||||
|
||||
Message::TextScroll(up, right) => {
|
||||
if let Some(ref mut doc) = self.doc {
|
||||
if let Some(up) = up {
|
||||
let bij = if up { -1 } else { 1 }; // fuck is this about
|
||||
if let Some(ref mut cache) = doc.cache {
|
||||
cache.offset.0 = cache.offset.0.saturating_add_signed(bij);
|
||||
}
|
||||
};
|
||||
if let Some(right) = right {
|
||||
let bij = if right { 1 } else { -1 };
|
||||
if let Some(ref mut cache) = doc.cache {
|
||||
cache.offset.1 = cache.offset.1.saturating_add_signed(bij);
|
||||
}
|
||||
};
|
||||
Message::TextScroll(thing) => {
|
||||
if let Some(Doc {
|
||||
cache: Some(ref mut cache),
|
||||
..
|
||||
}) = self.doc
|
||||
&& !matches!(
|
||||
// disabled here
|
||||
thing,
|
||||
TextScroll::Left(_)
|
||||
| TextScroll::Right(_)
|
||||
| TextScroll::LeftOne
|
||||
| TextScroll::RightOne
|
||||
)
|
||||
{
|
||||
cache.update_scroll(thing);
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -336,7 +377,13 @@ impl App<'_> {
|
||||
|
||||
Ok(None)
|
||||
}
|
||||
_ => match ev {
|
||||
_ => {
|
||||
macro_rules! osScroll {
|
||||
($this:expr) => {
|
||||
Ok(Some(Message::TextScroll($this)))
|
||||
};
|
||||
}
|
||||
match ev {
|
||||
event::Event::Key(KeyEvent {
|
||||
code,
|
||||
modifiers,
|
||||
@@ -346,6 +393,7 @@ impl App<'_> {
|
||||
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')
|
||||
@@ -357,44 +405,84 @@ impl App<'_> {
|
||||
}
|
||||
// no what is this code block
|
||||
if self.doc.is_some() {
|
||||
let updown = tri_state(
|
||||
code.is_up() || code.is_char('k'),
|
||||
code.is_down() || code.is_char('j'),
|
||||
);
|
||||
let leftright = tri_state(
|
||||
code.is_right() || code.is_char('l'),
|
||||
code.is_left() || code.is_char('h'),
|
||||
);
|
||||
return Ok(Some(Message::TextScroll(updown, leftright)));
|
||||
match code {
|
||||
KeyCode::Up | KeyCode::Char('k') => {
|
||||
return osScroll!(TextScroll::UpOne);
|
||||
}
|
||||
KeyCode::Down | KeyCode::Char('j') => {
|
||||
return osScroll!(TextScroll::DownOne);
|
||||
}
|
||||
KeyCode::Right | KeyCode::Char('l') => {
|
||||
return osScroll!(TextScroll::RightOne);
|
||||
}
|
||||
KeyCode::Left | KeyCode::Char('h') => {
|
||||
return osScroll!(TextScroll::LeftOne);
|
||||
}
|
||||
KeyCode::Char('u') => return osScroll!(TextScroll::UpHalf),
|
||||
KeyCode::Char('d') => return osScroll!(TextScroll::DownHalf),
|
||||
KeyCode::Char('f') => return osScroll!(TextScroll::UpFull),
|
||||
KeyCode::Char('b') => return osScroll!(TextScroll::DownFull),
|
||||
_ => (),
|
||||
};
|
||||
};
|
||||
Ok(None)
|
||||
}
|
||||
event::Event::Mouse(MouseEvent {
|
||||
Event::Mouse(MouseEvent {
|
||||
kind,
|
||||
column: _,
|
||||
row: _,
|
||||
column,
|
||||
row,
|
||||
modifiers,
|
||||
}) => {
|
||||
if self.doc.is_some() {
|
||||
eprintln!("{modifiers}");
|
||||
let updown = tri_state(
|
||||
kind.is_scroll_up() && !modifiers.contains(KeyModifiers::SHIFT),
|
||||
kind.is_scroll_down() && !modifiers.contains(KeyModifiers::SHIFT),
|
||||
);
|
||||
let leftright = tri_state(
|
||||
kind.is_scroll_right()
|
||||
|| (kind.is_scroll_down()
|
||||
&& modifiers.contains(KeyModifiers::SHIFT)),
|
||||
kind.is_scroll_left()
|
||||
|| (kind.is_scroll_up()
|
||||
&& modifiers.contains(KeyModifiers::SHIFT)),
|
||||
);
|
||||
return Ok(Some(Message::TextScroll(updown, leftright)));
|
||||
if let Some(Doc {
|
||||
cache: Some(DocCache { screen, .. }),
|
||||
..
|
||||
}) = self.doc
|
||||
&& screen.contains(Position::new(column, row))
|
||||
{
|
||||
match kind {
|
||||
MouseEventKind::ScrollDown
|
||||
if !modifiers.contains(KeyModifiers::SHIFT) =>
|
||||
{
|
||||
return osScroll!(TextScroll::Down(
|
||||
TextScroll::SCROLL_STEPS
|
||||
));
|
||||
}
|
||||
MouseEventKind::ScrollUp
|
||||
if !modifiers.contains(KeyModifiers::SHIFT) =>
|
||||
{
|
||||
return osScroll!(TextScroll::Up(TextScroll::SCROLL_STEPS));
|
||||
}
|
||||
MouseEventKind::ScrollLeft => {
|
||||
return osScroll!(TextScroll::Left(
|
||||
TextScroll::SCROLL_STEPS
|
||||
));
|
||||
}
|
||||
MouseEventKind::ScrollUp
|
||||
if modifiers.contains(KeyModifiers::SHIFT) =>
|
||||
{
|
||||
return osScroll!(TextScroll::Left(
|
||||
TextScroll::SCROLL_STEPS
|
||||
));
|
||||
}
|
||||
MouseEventKind::ScrollRight => {
|
||||
return osScroll!(TextScroll::Right(
|
||||
TextScroll::SCROLL_STEPS
|
||||
));
|
||||
}
|
||||
MouseEventKind::ScrollDown
|
||||
if modifiers.contains(KeyModifiers::SHIFT) => {}
|
||||
_ => {
|
||||
return osScroll!(TextScroll::Right(
|
||||
TextScroll::SCROLL_STEPS
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(None)
|
||||
}
|
||||
_ => Ok(None),
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -421,25 +509,67 @@ impl Doc {
|
||||
}
|
||||
impl DocCache {
|
||||
pub fn new(doc: impl AsRef<Path>) -> io::Result<Self> {
|
||||
read_lines(&doc).map(|(l, content)| Self {
|
||||
read_lines(&doc).map(|((l, m), content)| Self {
|
||||
content,
|
||||
offset: (0, 0),
|
||||
length_hint: l as _,
|
||||
length_hint: (l as _, m as _),
|
||||
..Default::default()
|
||||
})
|
||||
}
|
||||
pub fn reload_doc(&mut self, doc: impl AsRef<Path>) -> io::Result<()> {
|
||||
let a = read_lines(doc)?; // bail as early as possible
|
||||
self.content.clear();
|
||||
let lh;
|
||||
(lh, self.content) = a;
|
||||
self.length_hint = lh as _;
|
||||
let (lh, m);
|
||||
((lh, m), self.content) = a;
|
||||
self.length_hint = (lh as _, m as _);
|
||||
Ok(())
|
||||
}
|
||||
fn update_scroll(&mut self, update: TextScroll) {
|
||||
{
|
||||
let bih = get_size_as_ldaformat(&self.screen);
|
||||
let (up, right) = update.to_two_numbers(bih);
|
||||
if up != 0 {
|
||||
self.offset.0 = self
|
||||
.offset
|
||||
.0
|
||||
.saturating_add_signed(-up) // real
|
||||
.min(self.length_hint.0.saturating_sub(bih.0));
|
||||
};
|
||||
if right != 0 {
|
||||
unreachable!("disabled left right handling from update");
|
||||
self.offset.1 = self
|
||||
.offset
|
||||
.1
|
||||
.saturating_add_signed(right)
|
||||
.min(self.length_hint.1.saturating_sub(bih.1));
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
impl TextScroll {
|
||||
const SCROLL_STEPS: u16 = 3;
|
||||
pub fn to_two_numbers(&self, (height, _width): (u16, u16)) -> (i16, i16) {
|
||||
match self {
|
||||
TextScroll::UpOne => (1, 0),
|
||||
TextScroll::DownOne => (-1, 0),
|
||||
TextScroll::UpHalf => ((height / 2) as _, 0),
|
||||
TextScroll::DownHalf => (-((height / 2) as i16), 0),
|
||||
TextScroll::UpFull => (height as _, 0),
|
||||
TextScroll::DownFull => (-(height as i16), 0),
|
||||
TextScroll::Up(r) => (*r as _, 0),
|
||||
TextScroll::Down(r) => (-(*r as i16), 0),
|
||||
// not ever getting it
|
||||
_ => unreachable!("disabled left right handling from update"),
|
||||
TextScroll::Left(r) => (0, -(*r as i16)),
|
||||
TextScroll::Right(r) => (0, (*r as i16)),
|
||||
TextScroll::LeftOne => (0, -1),
|
||||
TextScroll::RightOne => (0, 1),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// returns some true if real, some false if fake, none if neither,
|
||||
/// idk what happens if both
|
||||
fn tri_state(real: bool, fake: bool) -> Option<bool> {
|
||||
fn _tri_state(real: bool, fake: bool) -> Option<bool> {
|
||||
if real {
|
||||
Some(true)
|
||||
} else if fake {
|
||||
@@ -449,20 +579,28 @@ fn tri_state(real: bool, fake: bool) -> Option<bool> {
|
||||
}
|
||||
}
|
||||
|
||||
fn get_size_as_ldaformat(r: &Rect) -> (u16, u16) {
|
||||
let Size { height, width } = r.as_size();
|
||||
(height, width)
|
||||
}
|
||||
/// this works for now
|
||||
fn read_lines(doc: impl AsRef<Path>) -> io::Result<(usize, String)> {
|
||||
fn read_lines(doc: impl AsRef<Path>) -> io::Result<((usize, usize), String)> {
|
||||
let file = File::open(doc)?;
|
||||
let lenf = file.metadata()?.len() as _;
|
||||
let mut strg = String::with_capacity(lenf);
|
||||
let mut fuek = BufReader::with_capacity(lenf, file);
|
||||
let mut c = 0;
|
||||
let mut m = 0;
|
||||
loop {
|
||||
let r = fuek.read_line(&mut strg)?;
|
||||
let mut str_new = String::new();
|
||||
let r = fuek.read_line(&mut str_new)?;
|
||||
if r > 0 {
|
||||
c += 1;
|
||||
m = m.max(str_new.len());
|
||||
strg.push_str(&str_new);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
Ok((c, strg))
|
||||
Ok(((c, m), strg))
|
||||
}
|
||||
+1
-1
@@ -12,7 +12,7 @@ fn main() -> color_eyre::Result<()> {
|
||||
let mut r = ratatui::init();
|
||||
let mut exp = FileExplorer::new()?;
|
||||
app::App::new()
|
||||
.with_doc("src/main.rs")?
|
||||
.with_doc("src/app.rs")?
|
||||
.with_explorer(&mut exp)
|
||||
.run(&mut r)?;
|
||||
ratatui::restore();
|
||||
|
||||
Reference in new issue
Block a user