1use super::main::{Zle, ZleChar};
6
7#[derive(Debug, Clone, Copy, PartialEq, Eq)]
9pub enum WordStyle {
10 Emacs,
12 Vi,
14 Shell,
16 BlankDelimited,
18}
19
20impl Zle {
21 pub fn find_word_start(&self, style: WordStyle) -> usize {
23 let mut pos = self.zlecs;
24
25 match style {
26 WordStyle::Emacs => {
27 while pos > 0 && !is_emacs_word_char(self.zleline[pos - 1]) {
29 pos -= 1;
30 }
31 while pos > 0 && is_emacs_word_char(self.zleline[pos - 1]) {
33 pos -= 1;
34 }
35 }
36 WordStyle::Vi => {
37 while pos > 0 && self.zleline[pos - 1].is_whitespace() {
39 pos -= 1;
40 }
41 if pos > 0 {
42 let is_word = is_vi_word_char(self.zleline[pos - 1]);
43 while pos > 0 {
45 let c = self.zleline[pos - 1];
46 if c.is_whitespace() || (is_vi_word_char(c) != is_word) {
47 break;
48 }
49 pos -= 1;
50 }
51 }
52 }
53 WordStyle::Shell => {
54 while pos > 0 && !self.zleline[pos - 1].is_whitespace() {
56 pos -= 1;
57 }
58 }
59 WordStyle::BlankDelimited => {
60 while pos > 0 && self.zleline[pos - 1].is_whitespace() {
62 pos -= 1;
63 }
64 while pos > 0 && !self.zleline[pos - 1].is_whitespace() {
66 pos -= 1;
67 }
68 }
69 }
70
71 pos
72 }
73
74 pub fn find_word_end(&self, style: WordStyle) -> usize {
76 let mut pos = self.zlecs;
77
78 match style {
79 WordStyle::Emacs => {
80 while pos < self.zlell && !is_emacs_word_char(self.zleline[pos]) {
82 pos += 1;
83 }
84 while pos < self.zlell && is_emacs_word_char(self.zleline[pos]) {
86 pos += 1;
87 }
88 }
89 WordStyle::Vi => {
90 if pos < self.zlell {
91 let is_word = is_vi_word_char(self.zleline[pos]);
92 while pos < self.zlell {
94 let c = self.zleline[pos];
95 if c.is_whitespace() || (is_vi_word_char(c) != is_word) {
96 break;
97 }
98 pos += 1;
99 }
100 while pos < self.zlell && self.zleline[pos].is_whitespace() {
102 pos += 1;
103 }
104 }
105 }
106 WordStyle::Shell => {
107 while pos < self.zlell && !self.zleline[pos].is_whitespace() {
109 pos += 1;
110 }
111 while pos < self.zlell && self.zleline[pos].is_whitespace() {
112 pos += 1;
113 }
114 }
115 WordStyle::BlankDelimited => {
116 while pos < self.zlell && !self.zleline[pos].is_whitespace() {
118 pos += 1;
119 }
120 while pos < self.zlell && self.zleline[pos].is_whitespace() {
122 pos += 1;
123 }
124 }
125 }
126
127 pos
128 }
129
130 pub fn get_current_word(&self, style: WordStyle) -> &[ZleChar] {
132 let start = self.find_word_start(style);
133 let end = self.find_word_end(style);
134 &self.zleline[start..end]
135 }
136}
137
138fn is_emacs_word_char(c: ZleChar) -> bool {
140 c.is_alphanumeric() || c == '_'
141}
142
143fn is_vi_word_char(c: ZleChar) -> bool {
145 c.is_alphanumeric() || c == '_'
146}