1use super::main::{ModifierFlags, Zle};
6
7#[derive(Debug, Clone, Copy, PartialEq, Eq)]
9pub enum ViPendingOp {
10 None,
11 Delete,
12 Change,
13 Yank,
14 ShiftLeft,
15 ShiftRight,
16 Filter,
17 Case,
18}
19
20#[derive(Debug, Default)]
22pub struct ViState {
23 pub pending_op: Option<ViPendingOp>,
25 pub find_char: Option<char>,
27 pub find_forward: bool,
29 pub find_skip: bool,
31 pub last_change: Option<ViChange>,
33 pub arg: Option<i32>,
35}
36
37#[derive(Debug, Clone)]
39pub struct ViChange {
40 pub keys: Vec<u8>,
42 pub start_cs: usize,
44}
45
46impl Zle {
47 pub fn vi_get_arg(&self) -> i32 {
49 if self.zmod.flags.contains(ModifierFlags::MULT) {
50 self.zmod.mult
51 } else {
52 1
53 }
54 }
55
56 pub fn vi_find_char(&mut self, forward: bool, skip: bool) {
58 let c = match self.getfullchar(true) {
60 Some(c) => c,
61 None => return,
62 };
63
64 let count = self.vi_get_arg();
65
66 for _ in 0..count {
67 if forward {
68 let mut pos = self.zlecs + 1;
70 while pos < self.zlell {
71 if self.zleline[pos] == c {
72 self.zlecs = if skip { pos - 1 } else { pos };
73 break;
74 }
75 pos += 1;
76 }
77 } else {
78 if self.zlecs > 0 {
80 let mut pos = self.zlecs - 1;
81 loop {
82 if self.zleline[pos] == c {
83 self.zlecs = if skip { pos + 1 } else { pos };
84 break;
85 }
86 if pos == 0 {
87 break;
88 }
89 pos -= 1;
90 }
91 }
92 }
93 }
94
95 self.resetneeded = true;
96 }
97
98 pub fn vi_match_bracket(&mut self) {
100 let c = if self.zlecs < self.zlell {
101 self.zleline[self.zlecs]
102 } else {
103 return;
104 };
105
106 let (target, forward) = match c {
107 '(' => (')', true),
108 ')' => ('(', false),
109 '[' => (']', true),
110 ']' => ('[', false),
111 '{' => ('}', true),
112 '}' => ('{', false),
113 '<' => ('>', true),
114 '>' => ('<', false),
115 _ => return,
116 };
117
118 let mut depth = 1;
119 let mut pos = self.zlecs;
120
121 if forward {
122 pos += 1;
123 while pos < self.zlell && depth > 0 {
124 if self.zleline[pos] == c {
125 depth += 1;
126 } else if self.zleline[pos] == target {
127 depth -= 1;
128 }
129 if depth > 0 {
130 pos += 1;
131 }
132 }
133 } else {
134 if pos > 0 {
135 pos -= 1;
136 loop {
137 if self.zleline[pos] == c {
138 depth += 1;
139 } else if self.zleline[pos] == target {
140 depth -= 1;
141 }
142 if depth == 0 || pos == 0 {
143 break;
144 }
145 pos -= 1;
146 }
147 }
148 }
149
150 if depth == 0 {
151 self.zlecs = pos;
152 self.resetneeded = true;
153 }
154 }
155
156 pub fn vi_replace_mode(&mut self) {
158 self.keymaps.select("viins");
159 self.insmode = false; }
161
162 pub fn vi_swap_case(&mut self) {
164 let count = self.vi_get_arg() as usize;
165
166 for _ in 0..count {
167 if self.zlecs < self.zlell {
168 let c = self.zleline[self.zlecs];
169 self.zleline[self.zlecs] = if c.is_uppercase() {
170 c.to_lowercase().next().unwrap_or(c)
171 } else if c.is_lowercase() {
172 c.to_uppercase().next().unwrap_or(c)
173 } else {
174 c
175 };
176 self.zlecs += 1;
177 }
178 }
179
180 if self.zlecs > 0 && self.zlecs == self.zlell {
182 self.zlecs -= 1;
183 }
184
185 self.resetneeded = true;
186 }
187
188 pub fn vi_undo(&mut self) {
190 }
192
193 pub fn vi_visual_mode(&mut self) {
195 self.mark = self.zlecs;
196 }
198
199 pub fn vi_visual_line_mode(&mut self) {
201 self.mark = self.zlecs;
202 }
204
205 pub fn vi_visual_block_mode(&mut self) {
207 self.mark = self.zlecs;
208 }
210
211 pub fn vi_set_mark(&mut self, name: char) {
213 let _ = name;
215 self.mark = self.zlecs;
216 }
217
218 pub fn vi_goto_mark(&mut self, name: char) {
220 let _ = name;
222 }
223
224 pub fn vi_record_change(&mut self, key: u8) {
226 let _ = key;
228 }
229
230 pub fn vi_repeat_change(&mut self) {
232 }
234}