use crate::{Mode, expression::evaluate_with_variables};
use std::collections::HashMap;
pub struct App {
pub text_lines: Vec<String>,
pub cursor_line: usize,
pub cursor_col: usize,
pub scroll_offset: usize,
pub results: Vec<Option<String>>,
pub variables: HashMap<String, String>, pub mode: Mode,
}
impl Default for App {
fn default() -> App {
App {
text_lines: vec![String::new()],
cursor_line: 0,
cursor_col: 0,
scroll_offset: 0,
results: vec![None],
variables: HashMap::new(),
mode: Mode::Insert, }
}
}
impl App {
pub fn insert_char(&mut self, c: char) {
if self.cursor_line < self.text_lines.len() {
self.text_lines[self.cursor_line].insert(self.cursor_col, c);
self.cursor_col += 1;
self.update_result(self.cursor_line);
}
}
pub fn delete_char(&mut self) {
if self.cursor_line < self.text_lines.len() {
if self.cursor_col > 0 {
self.text_lines[self.cursor_line].remove(self.cursor_col - 1);
self.cursor_col -= 1;
self.update_result(self.cursor_line);
} else if self.cursor_line > 0 {
let current_line = self.text_lines.remove(self.cursor_line);
self.results.remove(self.cursor_line);
self.cursor_line -= 1;
self.cursor_col = self.text_lines[self.cursor_line].len();
self.text_lines[self.cursor_line].push_str(¤t_line);
self.update_result(self.cursor_line);
}
}
}
pub fn delete_word(&mut self) {
if self.cursor_line < self.text_lines.len() && self.cursor_col > 0 {
let line = &self.text_lines[self.cursor_line];
let mut new_col = self.cursor_col;
while new_col > 0 && line.chars().nth(new_col - 1).unwrap_or(' ').is_whitespace() {
new_col -= 1;
}
while new_col > 0 {
let ch = line.chars().nth(new_col - 1).unwrap_or(' ');
if ch.is_alphanumeric() || ch == '_' {
new_col -= 1;
} else {
break;
}
}
if new_col == self.cursor_col {
while new_col > 0 {
let ch = line.chars().nth(new_col - 1).unwrap_or(' ');
if ch.is_whitespace() || ch.is_alphanumeric() || ch == '_' {
break;
}
new_col -= 1;
}
}
if new_col < self.cursor_col {
self.text_lines[self.cursor_line].drain(new_col..self.cursor_col);
self.cursor_col = new_col;
self.update_result(self.cursor_line);
}
}
}
pub fn new_line(&mut self) {
if self.cursor_line < self.text_lines.len() {
let current_line = self.text_lines[self.cursor_line].clone();
let (left, right) = current_line.split_at(self.cursor_col);
self.text_lines[self.cursor_line] = left.to_string();
self.text_lines
.insert(self.cursor_line + 1, right.to_string());
self.results.insert(self.cursor_line + 1, None);
self.cursor_line += 1;
self.cursor_col = 0;
self.update_result(self.cursor_line - 1);
self.update_result(self.cursor_line);
}
}
pub fn move_cursor_up(&mut self) {
if self.cursor_line > 0 {
self.cursor_line -= 1;
self.cursor_col = self.cursor_col.min(self.text_lines[self.cursor_line].len());
}
}
pub fn move_cursor_down(&mut self) {
if self.cursor_line + 1 < self.text_lines.len() {
self.cursor_line += 1;
self.cursor_col = self.cursor_col.min(self.text_lines[self.cursor_line].len());
}
}
pub fn move_cursor_left(&mut self) {
if self.cursor_col > 0 {
self.cursor_col -= 1;
}
}
pub fn move_cursor_right(&mut self) {
if self.cursor_line < self.text_lines.len() {
self.cursor_col = (self.cursor_col + 1).min(self.text_lines[self.cursor_line].len());
}
}
pub fn update_result(&mut self, line_index: usize) {
if line_index < self.text_lines.len() && line_index < self.results.len() {
let line = &self.text_lines[line_index];
let (result, variable_assignment) = evaluate_with_variables(
line,
&self.variables,
&self.results,
line_index
);
if let Some((var_name, var_value)) = variable_assignment {
self.variables.insert(var_name, var_value);
}
self.results[line_index] = result;
} else {
eprintln!(
"Warning: Attempted to update result for invalid line index {}",
line_index
);
}
}
}