#![allow(non_snake_case)] mod app; mod ui; use crate::app::status::{ AppStatus, CurrentScreen, EditingField, EntryValError, entryValError2Field, }; use crate::ui::ui; use app::AppState; use color_eyre::Result; use ratatui::Terminal; use ratatui::crossterm::event::{ self, DisableMouseCapture, EnableMouseCapture, Event, KeyCode, KeyModifiers, }; use ratatui::crossterm::execute; use ratatui::crossterm::terminal::{ EnterAlternateScreen, LeaveAlternateScreen, disable_raw_mode, enable_raw_mode, }; use ratatui::prelude::{Backend, CrosstermBackend}; use std::env::var; use std::io; fn main() -> Result<()> { enable_raw_mode()?; let mut stderr = io::stderr(); // This is a special case. Normally using stdout is fine execute!(stderr, EnterAlternateScreen, EnableMouseCapture)?; let backend = CrosstermBackend::new(stderr); let mut terminal = Terminal::new(backend)?; let configHome = var("XDG_CONFIG_HOME") .or_else(|_| var("HOME").map(|home| format!("{home}/.config"))) .unwrap_or("~/.config".to_string()); // create app and run it let mut appSettings = AppState::new(format!("{configHome}/steckbrett.conf")); // app.load(); let _ = runApp(&mut appSettings, &mut terminal); disable_raw_mode()?; execute!( terminal.backend_mut(), LeaveAlternateScreen, DisableMouseCapture )?; terminal.show_cursor()?; // match res { // Ok(ent) => println!("{ent} entries "), // _ => {} // } Ok(()) } fn runApp(app: &mut AppState, terminal: &mut Terminal) -> Result { loop { terminal.draw(|f| ui(f, app))?; // from ui.rs if let Event::Key(key) = event::read()? { // println!("{key:?}"); if key.kind == event::KeyEventKind::Release { continue; } match app.screen { CurrentScreen::Settings => match key.code { KeyCode::Home | KeyCode::Char('m') | KeyCode::Esc => { app.screen = CurrentScreen::Main; } _ => {} }, CurrentScreen::Delete => match key.code { KeyCode::Up => app.prevRow(), KeyCode::Down => app.nextRow(), KeyCode::Enter => app.delCur(), KeyCode::Esc => app.screen = CurrentScreen::Main, _ => {} }, CurrentScreen::Main => match key.code { KeyCode::Char('a') => { app.screen = CurrentScreen::Add; app.currentlyEditing = Some(EditingField::FromIP); app.appStatus = AppStatus::Editing; } KeyCode::Char('q') | KeyCode::F(10) | KeyCode::Esc => { app.screen = CurrentScreen::Exit } KeyCode::Char('s') => { if app.isHashDifferent() { app.screen = CurrentScreen::SaveConfirm; } } KeyCode::F(2) => app.screen = CurrentScreen::Settings, KeyCode::Char('d') => app.screen = CurrentScreen::Delete, KeyCode::Up => app.prevRow(), KeyCode::Down => app.nextRow(), _ => {} }, CurrentScreen::Add => match (key.modifiers, key.code) { (KeyModifiers::NONE, KeyCode::Enter) => { if let Some(eF) = &app.currentlyEditing { match eF { EditingField::ToPort => { let res = app.store(); match res { EntryValError::None => { app.screen = CurrentScreen::Main; app.currentlyEditing = None; app.appStatus = AppStatus::Added; } _ => { app.currentlyEditing = Some(entryValError2Field(&res)); app.appStatus = AppStatus::Error(res); } } } _ => app.nextField(), } } } (KeyModifiers::NONE, KeyCode::Backspace) => { if let Some(eF) = &app.currentlyEditing { match eF { EditingField::FromIP => { app.fromIP.pop(); } EditingField::FromPort => { app.fromPort.pop(); } EditingField::ToIP => { app.toIP.pop(); } EditingField::ToPort => { app.toPort.pop(); } }; } } (KeyModifiers::NONE, KeyCode::Esc) => { app.screen = CurrentScreen::Main; app.currentlyEditing = None; } (KeyModifiers::NONE, KeyCode::Tab | KeyCode::Right) => app.nextField(), (KeyModifiers::NONE, KeyCode::Left) => app.prevField(), (KeyModifiers::SHIFT, KeyCode::Tab) => app.prevField(), (_, KeyCode::Char(v)) => { if let Some(e) = &app.currentlyEditing { let mut isIP = false; let opField = match e { EditingField::FromIP => { isIP = true; &mut app.fromIP } EditingField::FromPort => &mut app.fromPort, EditingField::ToIP => { isIP = true; &mut app.toIP } EditingField::ToPort => &mut app.toPort, }; match v { 'l' => { if isIP { opField.clear(); opField.push_str("127.0.0.1"); } } 'o' => { if isIP { opField.clear(); opField.push_str("0.0.0.0"); } } 'c' => opField.clear(), 'C' => { app.fromIP.clear(); app.toIP.clear(); app.fromPort.clear(); app.toPort.clear(); } _ => opField.push(v), } } } _ => {} }, CurrentScreen::SaveConfirm => match key.code { KeyCode::Enter => { app.saveConfigToScript(); app.saveConfigToSettingsFile(); app.appStatus = AppStatus::Saved; terminal.clear()?; app.screen = CurrentScreen::Main; } KeyCode::Esc => app.screen = CurrentScreen::Main, _ => {} }, CurrentScreen::Exit => match key.code { KeyCode::Enter => { // app.saveConfigToSettingsFile(); // app.saveConfigToScript(); return Ok(app.settings.entries.len()); } KeyCode::Esc | KeyCode::Char('m') => app.screen = CurrentScreen::Main, _ => {} }, } } } // app.run(terminal) }