Files
Steckbrett/src/main.rs
2025-11-10 14:19:58 +05:30

209 lines
8.7 KiB
Rust

#![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<B: Backend>(app: &mut AppState, terminal: &mut Terminal<B>) -> Result<usize> {
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)
}