rspack_style/css/
select.rs

1use crate::css::fileinfo::FileWeakRef;
2use crate::css::node::NodeWeakRef;
3use crate::css::select_node::SelectorNode;
4use crate::extend::string::StringExtend;
5use crate::extend::vec_str::VecCharExtend;
6use crate::sourcemap::loc::{Loc, LocMap};
7use crate::style_core::scan::traversal;
8use crate::token::lib::Token;
9use crate::token::select::{TokenAllowChar, TokenCombinaChar, TokenKeyWordChar, TokenSelectChar};
10use crate::util::str_enum::{CharToEnum, EnumToChar};
11use serde::ser::SerializeStruct;
12use serde::{Deserialize, Serialize, Serializer};
13use serde_json::{Map, Value};
14use std::cmp::Ordering;
15use std::ops::Deref;
16
17#[derive(Debug, Clone, Serialize, Eq, PartialEq)]
18#[serde(tag = "type", content = "value")]
19enum SelectVarText {
20  Txt(String),
21  Var(String),
22}
23
24#[derive(Debug, Clone, Serialize, Eq, PartialEq, Deserialize)]
25#[serde(tag = "type", content = "value")]
26pub enum SelectParadigm {
27  SelectWrap(String),
28  CominaWrap(TokenCombinaChar),
29  VarWrap(char),
30  KeyWrap(String),
31}
32
33impl SelectParadigm {
34  ///
35  /// 反序列化
36  ///
37  pub fn deserializer(val: &Value) -> Self {
38    serde_json::from_str(&serde_json::to_string(val).unwrap()).unwrap()
39  }
40}
41
42pub trait Paradigm {
43  ///
44  /// 转成 样式词的 方法
45  /// 简化版 -> 用于测试
46  ///
47  fn tostr(&self) -> String;
48}
49
50impl Paradigm for Vec<SelectParadigm> {
51  fn tostr(&self) -> String {
52    let mut txt = "".to_string();
53    self.iter().for_each(|par| match par {
54      SelectParadigm::SelectWrap(cc) => txt += cc,
55      SelectParadigm::CominaWrap(cc) => {
56        txt.push(cc.to_str());
57      }
58      SelectParadigm::VarWrap(cc) => txt.push(*cc),
59      SelectParadigm::KeyWrap(cc) => {
60        txt = cc.clone();
61      }
62    });
63    txt
64  }
65}
66
67#[derive(Debug, Clone)]
68pub struct NewSelector {
69  // 字符串规则 根据逗号分割
70  pub paradigm_vec: Vec<Vec<SelectParadigm>>,
71
72  // 坐标位置
73  pub loc: Option<Loc>,
74
75  // 内部处理 地图
76  map: LocMap,
77
78  // 字符串 操作 序列
79  pub charlist: Vec<char>,
80
81  // 节点 父节点
82  // 延迟赋值
83  pub parent: NodeWeakRef,
84
85  // 文件节点
86  pub fileinfo: FileWeakRef,
87}
88
89impl Serialize for NewSelector {
90  fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
91  where
92    S: Serializer,
93  {
94    let mut state = serializer.serialize_struct("FileInfo", 3)?;
95    state.serialize_field("loc", &self.loc)?;
96    state.serialize_field("content", &self.charlist.poly())?;
97    state.serialize_field("paradigm_vec", &self.paradigm_vec)?;
98    state.end()
99  }
100}
101
102impl NewSelector {
103  ///
104  ///  初始化
105  ///
106  pub fn new(
107    charlist: Vec<char>,
108    loc: Option<Loc>,
109    map: Option<LocMap>,
110    parent: NodeWeakRef,
111    fileinfo: FileWeakRef,
112  ) -> Self {
113    NewSelector {
114      paradigm_vec: vec![],
115      loc,
116      map: map.unwrap_or_else(|| LocMap::new(&charlist)),
117      charlist,
118      parent,
119      fileinfo,
120    }
121  }
122
123  ///
124  /// 向上查找 最近 select 节点 非 media
125  ///
126  pub fn find_up_select_node(node: NodeWeakRef) -> NodeWeakRef {
127    if let Some(ref heap_node) = node {
128      let rule = heap_node.upgrade().unwrap();
129      if matches!(
130        *rule.deref().borrow().selector.as_ref().unwrap(),
131        SelectorNode::Select(..)
132      ) {
133        node.clone()
134      } else {
135        let parent = rule.deref().borrow().parent.clone();
136        Self::find_up_select_node(parent)
137      }
138    } else {
139      None
140    }
141  }
142
143  ///
144  /// 反序列化
145  ///
146  pub fn deserializer(
147    map: &Map<String, Value>,
148    parent: NodeWeakRef,
149    fileinfo: FileWeakRef,
150  ) -> Result<Self, String> {
151    let mut select = Self {
152      paradigm_vec: vec![],
153      loc: None,
154      map: LocMap::new(&[]),
155      charlist: vec![],
156      parent,
157      fileinfo,
158    };
159    if let Some(Value::String(content)) = map.get("content") {
160      select.charlist = content.to_char_vec();
161    } else {
162      return Err("deserializer NewSelector has error -> charlist is empty!".to_string());
163    }
164    if let Some(Value::Object(loc)) = map.get("loc") {
165      select.loc = Some(Loc::deserializer(loc));
166      select.map = LocMap::merge(select.loc.as_ref().unwrap(), &select.charlist).0;
167    } else {
168      select.map = LocMap::new(&select.charlist);
169    }
170    if let Some(Value::Array(charlist)) = map.get("paradigm_vec") {
171      for paradigm_vec in charlist {
172        let mut list = vec![];
173        if let Value::Array(paradigm) = paradigm_vec {
174          list = paradigm.iter().map(SelectParadigm::deserializer).collect();
175        }
176        if !list.is_empty() {
177          select.paradigm_vec.push(list);
178        }
179      }
180    } else {
181      return Err("deserializer NewSelector has error -> paradigm_vec is empty!".to_string());
182    }
183    Ok(select)
184  }
185
186  ///
187  /// 尽量减少调用次数
188  ///
189  pub fn value(&self) -> String {
190    self.charlist.poly()
191  }
192
193  ///
194  /// 生成当前 select 字符
195  ///
196  pub fn code_gen(&self) -> Result<Vec<Vec<SelectParadigm>>, String> {
197    let mut split_select_txt: Vec<Vec<SelectParadigm>> = vec![];
198
199    for list in self.paradigm_vec.iter() {
200      // 计算父 表达式
201      let self_rule = self.parent.as_ref().unwrap().upgrade().unwrap();
202      let node = self_rule.deref().borrow().parent.clone();
203      let select_rule_node = Self::find_up_select_node(node);
204      let mut parent_select_txt = vec![];
205      if let Some(any_parent_rule) = select_rule_node {
206        let heap_any_parent_rule = any_parent_rule.upgrade().unwrap();
207        if let Some(SelectorNode::Select(ps)) =
208          heap_any_parent_rule.deref().borrow().selector.as_ref()
209        {
210          parent_select_txt = ps.code_gen()?;
211        };
212      }
213
214      // 清洗后 拼接自我结果
215      let mut self_list = vec![];
216      let mut has_var = false;
217
218      // 计算自己
219      let mut var_index = -1;
220      for (np, p) in list.iter().enumerate() {
221        if matches!(p, SelectParadigm::VarWrap(..)) {
222          var_index = np as i32;
223        } else if matches!(p, SelectParadigm::KeyWrap(..)) {
224          has_var = true;
225        }
226      }
227
228      if var_index > -1 {
229        has_var = true;
230
231        for expr in parent_select_txt.iter() {
232          let mut cplist = list.clone();
233          cplist.remove(var_index as usize);
234          for item in expr.iter().rev() {
235            cplist.insert(var_index as usize, item.clone())
236          }
237          self_list.push(cplist);
238        }
239      } else {
240        self_list.push(list.clone());
241      }
242
243      if has_var || parent_select_txt.is_empty() {
244        if !self_list.is_empty() {
245          split_select_txt.append(&mut self_list);
246        }
247      } else {
248        for expr in parent_select_txt.iter() {
249          for m in self_list.iter() {
250            let mut cp_expr = expr.clone();
251            if cp_expr.last() != Some(&SelectParadigm::CominaWrap(TokenCombinaChar::Space)) {
252              cp_expr.push(SelectParadigm::CominaWrap(TokenCombinaChar::Space));
253            }
254            cp_expr.append(&mut m.clone());
255            split_select_txt.push(cp_expr);
256          }
257        }
258      }
259    }
260
261    // 最终结果
262    Ok(split_select_txt)
263  }
264
265  ///
266  /// 打印错误信息
267  ///
268  pub fn errormsg(&self, index: &usize) -> Result<(), String> {
269    let mut safe_index = *index;
270    if *index > self.charlist.len() - 1 {
271      safe_index = self.charlist.len() - 1;
272    }
273    let char = *self.charlist.get(safe_index).unwrap();
274    let error_loc = self.map.get(safe_index).unwrap();
275    Err(format!(
276      "select text {}, char {} is not allow, line is {} col is {}",
277      self.charlist.poly(),
278      char,
279      error_loc.line,
280      error_loc.col
281    ))
282  }
283
284  ///
285  /// 在二维数组 的最后 追加 词
286  /// 需要在 连接词 前后适当 保持 1个 空格!
287  /// 加入 & 前 如果有 唯一 连接符 则需要清除!
288  /// > & .a {
289  ///
290  pub fn add_paradigm(&mut self, obj: SelectParadigm) {
291    if self.paradigm_vec.is_empty() {
292      if !matches!(obj, SelectParadigm::CominaWrap(..)) {
293        self.paradigm_vec.push(vec![obj]);
294      } else {
295        self.paradigm_vec.push(vec![
296          obj,
297          SelectParadigm::CominaWrap(TokenCombinaChar::Space),
298        ]);
299      }
300    } else {
301      let list = self.paradigm_vec.last_mut().unwrap();
302      if !matches!(obj, SelectParadigm::CominaWrap(..))
303        || matches!(obj, SelectParadigm::CominaWrap(TokenCombinaChar::Space))
304      {
305        if matches!(obj, SelectParadigm::VarWrap(..))
306          && matches!(list.get(0), Some(&SelectParadigm::CominaWrap(..)))
307        {
308          list.remove(0);
309        }
310        if list.is_empty() && !matches!(obj, SelectParadigm::CominaWrap(TokenCombinaChar::Space))
311          || !list.is_empty()
312        {
313          list.push(obj);
314        }
315      } else {
316        let last_paradigm = list.last();
317        if last_paradigm.is_some()
318          && !matches!(
319            last_paradigm,
320            Some(SelectParadigm::CominaWrap(TokenCombinaChar::Space))
321          )
322        {
323          list.push(SelectParadigm::CominaWrap(TokenCombinaChar::Space));
324        }
325        list.push(obj);
326        list.push(SelectParadigm::CominaWrap(TokenCombinaChar::Space));
327      }
328    }
329  }
330
331  ///
332  /// 最后一组词 的 最后一位 非空
333  /// 逗号情况 调用
334  /// example ->  .a > {}  remove '>'
335  ///
336  pub fn clear_paraigm(&mut self, index: &usize) -> Result<(), String> {
337    if let Some(list) = self.paradigm_vec.last_mut() {
338      let mut rm_index_list: Vec<usize> = vec![];
339      let mut num = 0;
340      for (index, word) in list.iter().rev().enumerate() {
341        match word {
342          SelectParadigm::CominaWrap(_) => {
343            rm_index_list.push(list.len() - 1 - index);
344          }
345          _ => {
346            break;
347          }
348        }
349      }
350      for (_, val) in rm_index_list.into_iter().enumerate() {
351        list.remove(val - num);
352        num += 1;
353      }
354      if list.is_empty() {
355        return Err(self.errormsg(index).err().unwrap());
356      }
357      Ok(())
358    } else {
359      Err(self.errormsg(index).err().unwrap())
360    }
361  }
362
363  ///
364  /// 在二维数组中 开辟 一组 新词 序列
365  ///
366  pub fn add_paradigm_vec(&mut self) {
367    self.paradigm_vec.push(vec![]);
368  }
369
370  ///
371  /// 获取 最后 词
372  ///
373  pub fn last_paradigm(&self) -> Option<&SelectParadigm> {
374    if self.paradigm_vec.last().is_some() {
375      return self.paradigm_vec.last().unwrap().last();
376    }
377    None
378  }
379
380  ///
381  /// 获取 最后 非空格 词
382  ///
383  pub fn last_paradigm_without_space(&self) -> Option<&SelectParadigm> {
384    if let Some(list) = self.paradigm_vec.last() {
385      for p in list.iter().rev() {
386        if *p != SelectParadigm::CominaWrap(TokenCombinaChar::Space) {
387          return Some(p);
388        } else {
389          continue;
390        }
391      }
392      None
393    } else {
394      None
395    }
396  }
397
398  ///
399  /// 是否 停词 的判断
400  ///
401  pub fn is_end(char: Option<&char>, extend_char: Option<Vec<char>>) -> bool {
402    if let Some(cc) = char {
403      let mut charlist: Vec<char> = vec![];
404      if let Some(mut extend_list) = extend_char {
405        charlist.append(&mut extend_list);
406      }
407      charlist.append(
408        &mut TokenSelectChar::iterator()
409          .map(|x| x.to_str())
410          .collect::<Vec<char>>(),
411      );
412      charlist.append(
413        &mut TokenCombinaChar::iterator()
414          .map(|x| x.to_str())
415          .collect::<Vec<char>>(),
416      );
417      charlist.append(
418        &mut TokenKeyWordChar::iterator()
419          .map(|x| x.to_str())
420          .collect::<Vec<char>>(),
421      );
422      charlist.contains(cc)
423    } else {
424      false
425    }
426  }
427
428  ///
429  /// parse select txt
430  /// https://www.w3schools.com/cssref/css_selectors.asp
431  ///
432  pub fn parse(&mut self) -> Result<(), String> {
433    let index: usize = 0;
434    // 先判断 可以减少工作量调用
435    if self.charlist.contains(&'@') {
436      self.pure_select_txt()?;
437    }
438    let charlist = &self.charlist.clone();
439
440    let (_, end) = traversal(
441      Some(index),
442      charlist,
443      &mut (|arg, charword| {
444        let (index, _, _) = arg;
445        let (_, char, _) = charword;
446
447        if Token::is_token(Some(char)) {
448          if TokenSelectChar::is(char) {
449            // example a, li , h2
450            let (select_word, end) = self.parse_selector_word(index)?;
451            self.add_paradigm(SelectParadigm::SelectWrap(select_word));
452            *index = end;
453          } else if TokenCombinaChar::is(char) {
454            let (_, end) = self.parse_combina_word(index)?;
455            *index = end;
456          } else if TokenKeyWordChar::is(char) {
457            if *char == '&' {
458              self.add_paradigm(SelectParadigm::VarWrap(*char));
459            } else {
460              // @ -> @keyframes @{abc}
461              let (key_word, end) = self.parse_at_keyword(index)?;
462              self.add_paradigm(SelectParadigm::KeyWrap(key_word));
463              *index = end;
464            }
465          } else if TokenAllowChar::is(char) {
466            // example a, li , h2
467            let (select_word, end) = self.parse_selector_word(index)?;
468            self.add_paradigm(SelectParadigm::SelectWrap(select_word));
469            *index = end;
470          } else {
471            return Err(self.errormsg(index).err().unwrap());
472          }
473        } else {
474          // example a, li , h2
475          let (select_word, end) = self.parse_selector_word(index)?;
476          self.add_paradigm(SelectParadigm::SelectWrap(select_word));
477          *index = end;
478        }
479        Ok(())
480      }),
481    )?;
482    self.clear_paraigm(&end)?;
483    Ok(())
484  }
485
486  ///
487  /// parse @
488  /// example -> @keyframes identifierb || @font-face
489  ///
490  fn parse_at_keyword(&mut self, index: &usize) -> Result<(String, usize), String> {
491    traversal(
492      Some(*index),
493      &self.charlist,
494      &mut (|arg, charword| {
495        let (index, temp, end) = arg;
496        let (_, char, next) = charword;
497        if Token::is_token(Some(char)) {
498          if *char == '@' {
499            if temp.is_empty() {
500              temp.push(*char);
501            } else {
502              return Err(self.errormsg(index).err().unwrap());
503            }
504          } else if TokenAllowChar::is(char) || Token::is_space_token(Some(char)) {
505            temp.push(*char);
506          } else {
507            return Err(self.errormsg(index).err().unwrap());
508          }
509        } else {
510          temp.push(*char);
511        }
512        if next.is_none() {
513          *end = true;
514        }
515        Ok(())
516      }),
517    )
518  }
519
520  ///
521  /// 连接词的处理
522  ///
523  fn parse_combina_word(&mut self, index: &usize) -> Result<(String, usize), String> {
524    let char = *self.charlist.get(*index).unwrap();
525    if Token::is_space_token(Some(&char)) {
526      let last_pardigm = self.last_paradigm();
527      if let Some(SelectParadigm::CominaWrap(token)) = last_pardigm {
528        if *token != TokenCombinaChar::Space {
529          self.add_paradigm(SelectParadigm::CominaWrap(TokenCombinaChar::Space));
530        }
531      } else {
532        self.add_paradigm(SelectParadigm::CominaWrap(TokenCombinaChar::Space));
533      }
534    } else if char == TokenCombinaChar::AddChar.to_str()
535      || char == TokenCombinaChar::ExtendChar.to_str()
536      || char == TokenCombinaChar::BrotherMatchChar.to_str()
537      || char == TokenCombinaChar::ColumnChar.to_str()
538    {
539      let last_pardigm = self.last_paradigm_without_space();
540      // 只要最后一个非空字符是 非链接符 即可
541      if !matches!(last_pardigm, Some(SelectParadigm::CominaWrap(..))) {
542        let combin_token = char.to_enum::<TokenCombinaChar>().unwrap();
543        self.add_paradigm(SelectParadigm::CominaWrap(combin_token));
544      } else {
545        return Err(self.errormsg(index).err().unwrap());
546      }
547    } else if char == TokenCombinaChar::Comma.to_str() {
548      self.clear_paraigm(index)?;
549      self.add_paradigm_vec();
550    }
551    Ok((char.to_string(), *index))
552  }
553
554  ///
555  /// parse select word
556  ///
557  fn parse_selector_word(&mut self, start: &usize) -> Result<(String, usize), String> {
558    let res: (String, usize);
559    let charlist = &self.charlist;
560    let char = charlist.get(*start).unwrap();
561    if *char == '.' || *char == '#' {
562      res = self.parse_selector_class_or_id_word(start)?;
563    } else if *char == ':' {
564      res = self.parse_selector_pseudo_class_word(start)?;
565    } else if *char == '*' {
566      res = ('*'.to_string(), *start);
567    } else if *char == '[' {
568      res = self.parse_selector_attr(start)?;
569    } else if *char == '(' {
570      res = self.parse_selector_brackets(start)?;
571    } else if !Token::is_token(Some(char)) || TokenAllowChar::is(char) {
572      res = self.parse_selector_ele(start)?;
573    } else {
574      return Err(self.errormsg(start).err().unwrap());
575    }
576    Ok(res)
577  }
578
579  ///
580  /// parse example h2 span div
581  ///
582  fn parse_selector_ele(&mut self, start: &usize) -> Result<(String, usize), String> {
583    traversal(
584      Some(*start),
585      &self.charlist,
586      &mut (|arg, charword| {
587        let (index, temp, end) = arg;
588        let (_, char, next) = charword;
589        if Token::is_token(Some(char)) {
590          if TokenAllowChar::is(char) {
591            temp.push(*char);
592          } else {
593            return Err(self.errormsg(index).err().unwrap());
594          }
595        } else {
596          temp.push(*char);
597        }
598        if next.is_none() || Self::is_end(next, None) {
599          *end = true;
600        }
601        Ok(())
602      }),
603    )
604  }
605
606  ///
607  /// parse example #h2 .abc
608  ///
609  fn parse_selector_class_or_id_word(&mut self, start: &usize) -> Result<(String, usize), String> {
610    let charlist = &self.charlist;
611    let mut record = false;
612    traversal(
613      Some(*start),
614      charlist,
615      &mut (|arg, charword| {
616        let (index, temp, end) = arg;
617        let (_, char, next) = charword;
618        if Token::is_token(Some(char)) {
619          if TokenAllowChar::is(char) {
620            temp.push(*char);
621          } else if TokenSelectChar::is(char) && !record {
622            record = true;
623            temp.push(*char);
624          } else {
625            return Err(self.errormsg(index).err().unwrap());
626          }
627        } else {
628          temp.push(*char);
629        }
630        // 执行结束检查
631        if (next.is_none() || Self::is_end(next, None)) && record {
632          if temp.len() < 2 {
633            // . , # single word is error
634            return Err(self.errormsg(index).err().unwrap());
635          }
636          *end = true;
637        }
638        Ok(())
639      }),
640    )
641  }
642
643  ///
644  /// parse example ::hide :next
645  ///
646  fn parse_selector_pseudo_class_word(&mut self, start: &usize) -> Result<(String, usize), String> {
647    let charlist = &self.charlist;
648    let mut record = false;
649    traversal(
650      Some(*start),
651      charlist,
652      &mut (|arg, charword| {
653        let (index, temp, end) = arg;
654        let (_, char, next) = charword;
655        let mut next_fix = next;
656        if Token::is_token(Some(char)) {
657          if !record && *char == ':' {
658            if next == Some(&':') {
659              temp.push(*char);
660              *index += 1;
661              next_fix = {
662                if *index + 1 < charlist.len() {
663                  charlist.get(*index + 1)
664                } else {
665                  None
666                }
667              };
668            }
669            temp.push(*char);
670            record = true;
671          } else if TokenAllowChar::is(char) {
672            temp.push(*char);
673          } else {
674            return Err(self.errormsg(index).err().unwrap());
675          }
676        } else {
677          temp.push(*char);
678        }
679        // 执行结束检查
680        if (next.is_none() || Self::is_end(next_fix, None)) && record {
681          if (temp.len() < 2 && *temp == vec![':']) || (temp.len() < 3 && *temp == vec![':', ':']) {
682            // . , # single word is error
683            return Err(self.errormsg(index).err().unwrap());
684          }
685          *end = true;
686        }
687        Ok(())
688      }),
689    )
690  }
691
692  ///
693  /// parse example (language)
694  ///
695  fn parse_selector_brackets(&mut self, start: &usize) -> Result<(String, usize), String> {
696    let mut level = 0;
697    let res = traversal(
698      Some(*start),
699      &self.charlist,
700      &mut (|arg, charword| {
701        let (index, temp, end) = arg;
702        let (_, char, next) = charword;
703        if Token::is_token(Some(char)) {
704          if TokenAllowChar::is(char) {
705            temp.push(*char);
706            return Ok(());
707          }
708          if *char == ')' {
709            level -= 1;
710            match level.cmp(&0) {
711              Ordering::Less => {
712                return Err(self.errormsg(index).err().unwrap());
713              }
714              Ordering::Equal => {
715                *end = true;
716                temp.push(*char);
717                return Ok(());
718              }
719              Ordering::Greater => {
720                temp.push(*char);
721              }
722            }
723          } else if *char == '@' && next != Some(&'{') {
724            return Err(self.errormsg(index).err().unwrap());
725          } else if *char == '(' {
726            level += 1;
727            temp.push(*char);
728          } else {
729            temp.push(*char);
730          }
731        } else {
732          temp.push(*char);
733        }
734        Ok(())
735      }),
736    )?;
737    if level > 0 {
738      return Err(self.errormsg(&res.1).err().unwrap());
739    }
740    Ok(res)
741  }
742
743  ///
744  /// parse example '[arco-theme='dark']'
745  ///
746  fn parse_selector_attr(&mut self, start: &usize) -> Result<(String, usize), String> {
747    // example ~= *= ^=
748    let equal_chars = vec!['~', '|', '^', '$', '*'];
749    let mut hasequal = false;
750    let mut has_brackest = false;
751    let mut queto: Option<char> = None;
752
753    let res = traversal(
754      Some(*start),
755      &self.charlist,
756      &mut (|arg, charword| {
757        let (index, temp, end) = arg;
758        let (prev, char, next) = charword;
759        let get_prev_char_without_space = || -> Option<char> {
760          let mut res: Option<char> = None;
761          for tc in temp.iter().rev() {
762            if *tc == ' ' {
763              continue;
764            } else {
765              res = Some(*tc);
766              break;
767            }
768          }
769          res
770        };
771
772        if let Some(token_queto) = queto {
773          if has_brackest {
774            if *char == token_queto && prev != Some(&'\\') {
775              queto = None;
776            }
777            temp.push(*char);
778          } else {
779            return Err(self.errormsg(index).err().unwrap());
780          }
781        } else if Token::is_token(Some(char)) {
782          if has_brackest {
783            if *char == '[' {
784              return Err(self.errormsg(index).err().unwrap());
785            } else if *char == ']' {
786              let prev_char_without_space = get_prev_char_without_space();
787              if prev_char_without_space == Some('=') {
788                return Err(self.errormsg(index).err().unwrap());
789              }
790              // is attr end record
791              temp.push(*char);
792              has_brackest = false;
793              *end = true;
794            } else if TokenAllowChar::is(char) {
795              temp.push(*char);
796            } else if equal_chars.contains(char) {
797              if next == Some(&'=') && !hasequal {
798                temp.push(*char);
799                temp.push('=');
800                hasequal = true;
801                *index += 1;
802              } else {
803                return Err(self.errormsg(index).err().unwrap());
804              }
805            } else if *char == '=' {
806              let prev_char_without_space = get_prev_char_without_space();
807              if prev_char_without_space == Some('[') {
808                return Err(self.errormsg(index).err().unwrap());
809              }
810              if !hasequal {
811                temp.push('=');
812                hasequal = true;
813              } else {
814                return Err(self.errormsg(index).err().unwrap());
815              }
816            } else if *char == '"' || *char == '\'' {
817              queto = Some(*char);
818              temp.push(*char);
819            } else {
820              return Err(self.errormsg(index).err().unwrap());
821            }
822          } else {
823            // start record attr
824            if *char == '[' {
825              temp.push(*char);
826              has_brackest = true;
827            } else {
828              return Err(self.errormsg(index).err().unwrap());
829            }
830          }
831        } else if has_brackest {
832          temp.push(*char);
833        } else {
834          return Err(self.errormsg(index).err().unwrap());
835        }
836        Ok(())
837      }),
838    )?;
839    if has_brackest {
840      return Err(self.errormsg(&res.1).err().unwrap());
841    }
842    Ok(res)
843  }
844
845  ///
846  /// support var in select_txt
847  /// like @{abc} .a{  .... }
848  ///
849  fn pure_select_txt(&mut self) -> Result<(), String> {
850    let mut record = false;
851    let mut list: Vec<SelectVarText> = vec![];
852    traversal(
853      None,
854      &self.charlist,
855      &mut (|arg, charword| {
856        let (index, temp, _end) = arg;
857        let (_prev, char, next) = charword;
858        if *char == '@' && next == Some(&'{') {
859          if !temp.is_empty() {
860            list.push(SelectVarText::Txt(temp.poly()));
861          }
862          temp.clear();
863          temp.push('@');
864          temp.push('{');
865          *index += 1;
866          record = true
867        } else if *char == '}' && record {
868          temp.push(*char);
869          if !temp.is_empty() {
870            list.push(SelectVarText::Var(temp.poly()));
871          } else {
872            return Err(format!(
873              "select txt {} index is {} -> @ var is not closure",
874              self.charlist.poly(),
875              *index
876            ));
877          }
878          temp.clear();
879          record = false;
880        } else {
881          temp.push(*char);
882        }
883        Ok(())
884      }),
885    )?;
886
887    let mut new_content = "".to_string();
888    if !list.is_empty() {
889      for tt in list {
890        if let SelectVarText::Txt(t) = tt {
891          new_content += &t;
892        }
893      }
894      self.charlist = new_content.to_char_vec();
895    }
896
897    Ok(())
898  }
899}