Skip to main content

zsh/zle/
move_ops.rs

1//! ZLE movement operations
2//!
3//! Direct port from zsh/Src/Zle/zle_move.c
4
5use super::main::Zle;
6
7impl Zle {
8    /// Move cursor to start of current physical line
9    pub fn move_to_bol(&mut self) {
10        while self.zlecs > 0 && self.zleline[self.zlecs - 1] != '\n' {
11            self.zlecs -= 1;
12        }
13    }
14
15    /// Move cursor to end of current physical line
16    pub fn move_to_eol(&mut self) {
17        while self.zlecs < self.zlell && self.zleline[self.zlecs] != '\n' {
18            self.zlecs += 1;
19        }
20    }
21
22    /// Move cursor up one line
23    pub fn move_up(&mut self) -> bool {
24        let col = self.current_column();
25
26        // Find start of current line
27        let mut line_start = self.zlecs;
28        while line_start > 0 && self.zleline[line_start - 1] != '\n' {
29            line_start -= 1;
30        }
31
32        if line_start == 0 {
33            return false; // Already on first line
34        }
35
36        // Move to end of previous line
37        self.zlecs = line_start - 1;
38
39        // Find start of previous line
40        let mut prev_start = self.zlecs;
41        while prev_start > 0 && self.zleline[prev_start - 1] != '\n' {
42            prev_start -= 1;
43        }
44
45        // Move to same column or end of line
46        self.zlecs = prev_start + col.min(self.zlecs - prev_start);
47
48        true
49    }
50
51    /// Move cursor down one line
52    pub fn move_down(&mut self) -> bool {
53        let col = self.current_column();
54
55        // Find end of current line
56        let mut line_end = self.zlecs;
57        while line_end < self.zlell && self.zleline[line_end] != '\n' {
58            line_end += 1;
59        }
60
61        if line_end >= self.zlell {
62            return false; // Already on last line
63        }
64
65        // Move to start of next line
66        self.zlecs = line_end + 1;
67
68        // Find end of next line
69        let mut next_end = self.zlecs;
70        while next_end < self.zlell && self.zleline[next_end] != '\n' {
71            next_end += 1;
72        }
73
74        // Move to same column or end of line
75        self.zlecs = (self.zlecs + col).min(next_end);
76
77        true
78    }
79
80    /// Get current column (0-indexed)
81    pub fn current_column(&self) -> usize {
82        let mut col = 0;
83        let mut i = self.zlecs;
84        while i > 0 && self.zleline[i - 1] != '\n' {
85            i -= 1;
86            col += 1;
87        }
88        col
89    }
90
91    /// Get current line number (0-indexed)
92    pub fn current_line(&self) -> usize {
93        self.zleline[..self.zlecs]
94            .iter()
95            .filter(|&&c| c == '\n')
96            .count()
97    }
98
99    /// Count total lines
100    pub fn count_lines(&self) -> usize {
101        self.zleline.iter().filter(|&&c| c == '\n').count() + 1
102    }
103}