1use super::main::{Zle, ZleChar, ZleString};
15
16impl Zle {
17 pub fn insert_str(&mut self, s: &str) {
19 for c in s.chars() {
20 self.zleline.insert(self.zlecs, c);
21 self.zlecs += 1;
22 self.zlell += 1;
23 }
24 self.resetneeded = true;
25 }
26
27 pub fn insert_chars(&mut self, chars: &[ZleChar]) {
29 for &c in chars {
30 self.zleline.insert(self.zlecs, c);
31 self.zlecs += 1;
32 self.zlell += 1;
33 }
34 self.resetneeded = true;
35 }
36
37 pub fn delete_chars(&mut self, n: usize) {
39 let n = n.min(self.zlell - self.zlecs);
40 for _ in 0..n {
41 if self.zlecs < self.zlell {
42 self.zleline.remove(self.zlecs);
43 self.zlell -= 1;
44 }
45 }
46 self.resetneeded = true;
47 }
48
49 pub fn backspace_chars(&mut self, n: usize) {
51 let n = n.min(self.zlecs);
52 for _ in 0..n {
53 if self.zlecs > 0 {
54 self.zlecs -= 1;
55 self.zleline.remove(self.zlecs);
56 self.zlell -= 1;
57 }
58 }
59 self.resetneeded = true;
60 }
61
62 pub fn get_line(&self) -> String {
64 self.zleline.iter().collect()
65 }
66
67 pub fn set_line(&mut self, s: &str) {
69 self.zleline = s.chars().collect();
70 self.zlell = self.zleline.len();
71 self.zlecs = self.zlecs.min(self.zlell);
72 self.resetneeded = true;
73 }
74
75 pub fn clear_line(&mut self) {
77 self.zleline.clear();
78 self.zlell = 0;
79 self.zlecs = 0;
80 self.mark = 0;
81 self.resetneeded = true;
82 }
83
84 pub fn get_region(&self) -> &[ZleChar] {
86 let (start, end) = if self.zlecs < self.mark {
87 (self.zlecs, self.mark)
88 } else {
89 (self.mark, self.zlecs)
90 };
91 &self.zleline[start..end]
92 }
93
94 pub fn cut_to_buffer(&mut self, buf: usize, append: bool) {
96 if buf < self.vibuf.len() {
97 let (start, end) = if self.zlecs < self.mark {
98 (self.zlecs, self.mark)
99 } else {
100 (self.mark, self.zlecs)
101 };
102
103 let text: ZleString = self.zleline[start..end].to_vec();
104
105 if append {
106 self.vibuf[buf].extend(text);
107 } else {
108 self.vibuf[buf] = text;
109 }
110 }
111 }
112
113 pub fn paste_from_buffer(&mut self, buf: usize, after: bool) {
115 if buf < self.vibuf.len() {
116 let text = self.vibuf[buf].clone();
117 if !text.is_empty() {
118 if after && self.zlecs < self.zlell {
119 self.zlecs += 1;
120 }
121 self.insert_chars(&text);
122 }
123 }
124 }
125}
126
127pub fn metafy(s: &str) -> String {
129 s.to_string()
132}
133
134pub fn unmetafy(s: &str) -> String {
135 s.to_string()
136}
137
138pub fn strwidth(s: &str) -> usize {
140 s.chars().count()
142}
143
144pub fn is_printable(c: char) -> bool {
146 !c.is_control() && c != '\x7f'
147}
148
149pub fn escape_for_display(c: char) -> String {
151 if c.is_control() {
152 if c as u32 <= 26 {
153 format!("^{}", (c as u8 + b'@') as char)
154 } else {
155 format!("\\x{:02x}", c as u32)
156 }
157 } else if c == '\x7f' {
158 "^?".to_string()
159 } else {
160 c.to_string()
161 }
162}
163
164#[derive(Debug, Clone)]
167pub struct UndoEntry {
168 pub start: usize,
170 pub end: usize,
172 pub text: ZleString,
174 pub cursor: usize,
176 pub group_start: bool,
178}
179
180#[derive(Debug, Default)]
182pub struct UndoState {
183 pub history: Vec<UndoEntry>,
185 pub current: usize,
187 pub limit: usize,
189 pub recording: bool,
191 pub merge_inserts: bool,
193}
194
195impl UndoState {
196 pub fn new() -> Self {
197 UndoState {
198 recording: true,
199 merge_inserts: true,
200 ..Default::default()
201 }
202 }
203
204 pub fn init(&mut self) {
207 self.history.clear();
208 self.current = 0;
209 self.limit = 0;
210 self.recording = true;
211 }
212
213 pub fn free(&mut self) {
216 self.history.clear();
217 self.current = 0;
218 }
219
220 pub fn make_entry(&mut self, start: usize, end: usize, text: ZleString, cursor: usize) {
223 if !self.recording {
224 return;
225 }
226
227 self.history.truncate(self.current);
229
230 let entry = UndoEntry {
231 start,
232 end,
233 text,
234 cursor,
235 group_start: false,
236 };
237
238 self.history.push(entry);
239 self.current = self.history.len();
240 }
241
242 pub fn split(&mut self) {
245 if let Some(entry) = self.history.last_mut() {
246 entry.group_start = true;
247 }
248 }
249
250 pub fn merge(&mut self) {
253 if self.history.len() >= 2 {
255 let last = self.history.len() - 1;
256 let prev = last - 1;
257
258 if self.history[prev].end == self.history[last].start
260 && self.history[prev].text.is_empty()
261 && self.history[last].text.is_empty()
262 {
263 self.history[prev].end = self.history[last].end;
264 self.history.pop();
265 self.current = self.history.len();
266 }
267 }
268 }
269
270 pub fn get_current(&self) -> Option<&UndoEntry> {
273 if self.current > 0 {
274 self.history.get(self.current - 1)
275 } else {
276 None
277 }
278 }
279
280 pub fn set_limit(&mut self) {
283 self.limit = self.current;
284 }
285
286 pub fn get_limit(&self) -> usize {
289 self.limit
290 }
291}
292
293impl Zle {
294 fn apply_change(&mut self, entry: &UndoEntry, reverse: bool) {
297 if reverse {
298 let removed: ZleString = self.zleline.drain(entry.start..entry.end).collect();
300 for (i, &c) in entry.text.iter().enumerate() {
301 self.zleline.insert(entry.start + i, c);
302 }
303 self.zlell = self.zleline.len();
304 self.zlecs = entry.cursor;
305
306 let _ = removed;
308 } else {
309 let end = entry.start + entry.text.len();
311 self.zleline.drain(entry.start..end.min(self.zleline.len()));
312 for (i, &c) in entry.text.iter().enumerate() {
313 self.zleline.insert(entry.start + i, c);
314 }
315 self.zlell = self.zleline.len();
316 self.zlecs = entry.cursor;
317 }
318 self.resetneeded = true;
319 }
320
321 pub fn find_bol(&self, pos: usize) -> usize {
324 let mut p = pos;
325 while p > 0 && self.zleline.get(p - 1) != Some(&'\n') {
326 p -= 1;
327 }
328 p
329 }
330
331 pub fn find_eol(&self, pos: usize) -> usize {
334 let mut p = pos;
335 while p < self.zlell && self.zleline.get(p) != Some(&'\n') {
336 p += 1;
337 }
338 p
339 }
340
341 pub fn find_line(&self, pos: usize) -> usize {
344 self.zleline[..pos].iter().filter(|&&c| c == '\n').count()
345 }
346
347 pub fn size_line(&mut self, needed: usize) {
350 if self.zleline.capacity() < needed {
351 self.zleline.reserve(needed - self.zleline.len());
352 }
353 }
354
355 pub fn space_in_line(&mut self, pos: usize, count: usize) {
358 for _ in 0..count {
359 self.zleline.insert(pos, ' ');
360 }
361 self.zlell += count;
362 if self.zlecs >= pos {
363 self.zlecs += count;
364 }
365 }
366
367 pub fn shift_chars(&mut self, from: usize, count: i32) {
370 if count > 0 {
371 for _ in 0..count {
372 self.zleline.insert(from, ' ');
373 }
374 self.zlell += count as usize;
375 } else if count < 0 {
376 let to_remove = (-count) as usize;
377 for _ in 0..to_remove.min(self.zlell - from) {
378 self.zleline.remove(from);
379 }
380 self.zlell = self.zleline.len();
381 }
382 }
383
384 pub fn fore_del(&mut self, count: usize, flags: CutFlags) {
387 let count = count.min(self.zlell - self.zlecs);
388 if count == 0 {
389 return;
390 }
391
392 if flags.contains(CutFlags::KILL) {
394 let text: ZleString = self.zleline[self.zlecs..self.zlecs + count].to_vec();
395 self.killring.push_front(text);
396 if self.killring.len() > self.killringmax {
397 self.killring.pop_back();
398 }
399 }
400
401 for _ in 0..count {
403 self.zleline.remove(self.zlecs);
404 }
405 self.zlell -= count;
406 self.resetneeded = true;
407 }
408
409 pub fn back_del(&mut self, count: usize, flags: CutFlags) {
412 let count = count.min(self.zlecs);
413 if count == 0 {
414 return;
415 }
416
417 if flags.contains(CutFlags::KILL) {
419 let text: ZleString = self.zleline[self.zlecs - count..self.zlecs].to_vec();
420 self.killring.push_front(text);
421 if self.killring.len() > self.killringmax {
422 self.killring.pop_back();
423 }
424 }
425
426 self.zlecs -= count;
428 for _ in 0..count {
429 self.zleline.remove(self.zlecs);
430 }
431 self.zlell -= count;
432 self.resetneeded = true;
433 }
434
435 pub fn fore_kill(&mut self, count: usize, append: bool) {
438 let count = count.min(self.zlell - self.zlecs);
439 if count == 0 {
440 return;
441 }
442
443 let text: ZleString = self.zleline[self.zlecs..self.zlecs + count].to_vec();
444
445 if append {
446 if let Some(front) = self.killring.front_mut() {
447 front.extend(text);
448 } else {
449 self.killring.push_front(text);
450 }
451 } else {
452 self.killring.push_front(text);
453 }
454
455 if self.killring.len() > self.killringmax {
456 self.killring.pop_back();
457 }
458
459 for _ in 0..count {
460 self.zleline.remove(self.zlecs);
461 }
462 self.zlell -= count;
463 self.resetneeded = true;
464 }
465
466 pub fn back_kill(&mut self, count: usize, append: bool) {
469 let count = count.min(self.zlecs);
470 if count == 0 {
471 return;
472 }
473
474 let text: ZleString = self.zleline[self.zlecs - count..self.zlecs].to_vec();
475
476 if append {
477 if let Some(front) = self.killring.front_mut() {
478 let mut new_text = text;
479 new_text.extend(front.iter());
480 *front = new_text;
481 } else {
482 self.killring.push_front(text);
483 }
484 } else {
485 self.killring.push_front(text);
486 }
487
488 if self.killring.len() > self.killringmax {
489 self.killring.pop_back();
490 }
491
492 self.zlecs -= count;
493 for _ in 0..count {
494 self.zleline.remove(self.zlecs);
495 }
496 self.zlell -= count;
497 self.resetneeded = true;
498 }
499
500 pub fn cut_text(&mut self, start: usize, end: usize, dir: CutDirection) {
503 if start >= end || end > self.zlell {
504 return;
505 }
506
507 let text: ZleString = self.zleline[start..end].to_vec();
508
509 match dir {
510 CutDirection::Front => {
511 self.killring.push_front(text);
512 }
513 CutDirection::Back => {
514 if let Some(front) = self.killring.front_mut() {
515 front.extend(text);
516 } else {
517 self.killring.push_front(text);
518 }
519 }
520 }
521
522 if self.killring.len() > self.killringmax {
523 self.killring.pop_back();
524 }
525 }
526
527 pub fn set_last_line(&mut self) {
530 }
532
533 pub fn show_msg(&self, msg: &str) {
536 eprintln!("{}", msg);
537 }
538
539 pub fn handle_feep(&self) {
542 print!("\x07"); }
544
545 pub fn add_to_line(&mut self, pos: usize, text: &str) {
548 for (i, c) in text.chars().enumerate() {
549 self.zleline.insert(pos + i, c);
550 }
551 self.zlell += text.chars().count();
552 if self.zlecs >= pos {
553 self.zlecs += text.chars().count();
554 }
555 self.resetneeded = true;
556 }
557
558 pub fn line_as_string(&self) -> String {
561 self.zleline.iter().collect()
562 }
563
564 pub fn string_as_line(&mut self, s: &str) {
567 self.zleline = s.chars().collect();
568 self.zlell = self.zleline.len();
569 if self.zlecs > self.zlell {
570 self.zlecs = self.zlell;
571 }
572 self.resetneeded = true;
573 }
574
575 pub fn get_zle_line(&self) -> &[ZleChar] {
578 &self.zleline
579 }
580
581 pub fn get_zle_query(&self) -> Option<String> {
584 None
586 }
587
588 pub fn handle_suffix(&mut self) {
591 }
593}
594
595#[derive(Debug, Clone)]
597pub struct SavedPositions {
598 pub zlecs: usize,
599 pub zlell: usize,
600 pub mark: usize,
601}
602
603impl Zle {
606 pub fn save_positions(&self) -> SavedPositions {
607 SavedPositions {
608 zlecs: self.zlecs,
609 zlell: self.zlell,
610 mark: self.mark,
611 }
612 }
613
614 pub fn restore_positions(&mut self, saved: &SavedPositions) {
615 self.zlecs = saved.zlecs.min(self.zlell);
616 self.mark = saved.mark.min(self.zlell);
617 }
618}
619
620bitflags::bitflags! {
621 #[derive(Debug, Clone, Copy, Default)]
623 pub struct CutFlags: u32 {
624 const KILL = 1 << 0; const COPY = 1 << 1; const APPEND = 1 << 2; }
628}
629
630#[derive(Debug, Clone, Copy)]
632pub enum CutDirection {
633 Front,
634 Back,
635}
636
637pub fn print_bind(seq: &[u8]) -> String {
640 let mut result = String::new();
641
642 for &b in seq {
643 match b {
644 0x1b => result.push_str("^["),
645 0..=31 => {
646 result.push('^');
647 result.push((b + 64) as char);
648 }
649 127 => result.push_str("^?"),
650 128..=159 => {
651 result.push_str("^[^");
652 result.push((b - 64) as char);
653 }
654 _ => result.push(b as char),
655 }
656 }
657
658 result
659}
660
661pub fn zle_call_hook(_name: &str, _args: &[&str]) -> i32 {
664 0
666}