wifui 0.3.0

A lightweight, keyboard-driven Terminal User Interface (TUI) for managing Wi-Fi connections on Windows.
#[derive(Debug, Default, Clone)]
pub struct InputState {
    pub value: String,
    pub cursor: usize,
}

impl InputState {
    pub fn new() -> Self {
        Self::default()
    }

    pub fn clear(&mut self) {
        self.value.clear();
        self.cursor = 0;
    }

    pub fn insert(&mut self, c: char) {
        let byte_idx = self
            .value
            .chars()
            .take(self.cursor)
            .map(|c| c.len_utf8())
            .sum();
        self.value.insert(byte_idx, c);
        self.cursor += 1;
    }

    pub fn backspace(&mut self) {
        if self.cursor > 0 {
            let byte_idx = self
                .value
                .chars()
                .take(self.cursor - 1)
                .map(|c| c.len_utf8())
                .sum();
            self.value.remove(byte_idx);
            self.cursor -= 1;
        }
    }

    pub fn backspace_word(&mut self) {
        if self.cursor > 0 {
            let chars: Vec<char> = self.value.chars().collect();
            let mut idx = self.cursor;
            // Skip trailing whitespace
            while idx > 0 && idx <= chars.len() && chars[idx - 1].is_whitespace() {
                idx -= 1;
            }
            // Skip word characters
            while idx > 0 && !chars[idx - 1].is_whitespace() {
                idx -= 1;
            }

            let start_byte = chars.iter().take(idx).map(|c| c.len_utf8()).sum::<usize>();
            let end_byte = chars
                .iter()
                .take(self.cursor)
                .map(|c| c.len_utf8())
                .sum::<usize>();

            self.value.replace_range(start_byte..end_byte, "");
            self.cursor = idx;
        }
    }

    pub fn move_left(&mut self) {
        if self.cursor > 0 {
            self.cursor -= 1;
        }
    }

    pub fn move_word_left(&mut self) {
        let chars: Vec<char> = self.value.chars().collect();
        let mut idx = self.cursor;
        while idx > 0 && idx <= chars.len() && chars[idx - 1].is_whitespace() {
            idx -= 1;
        }
        while idx > 0 && !chars[idx - 1].is_whitespace() {
            idx -= 1;
        }
        self.cursor = idx;
    }

    pub fn move_right(&mut self) {
        if self.cursor < self.value.chars().count() {
            self.cursor += 1;
        }
    }

    pub fn move_word_right(&mut self) {
        let chars: Vec<char> = self.value.chars().collect();
        let mut idx = self.cursor;
        let len = chars.len();
        while idx < len && !chars[idx].is_whitespace() {
            idx += 1;
        }
        while idx < len && chars[idx].is_whitespace() {
            idx += 1;
        }
        self.cursor = idx;
    }

    pub fn move_home(&mut self) {
        self.cursor = 0;
    }

    pub fn move_end(&mut self) {
        self.cursor = self.value.chars().count();
    }
}