209 lines
8.7 KiB
Rust
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)
|
|
}
|