auto_exit_block.rs 1.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970
  1. use crate::{
  2. client::{extensions::InsertExt, util::is_newline},
  3. core::{
  4. AttributeKey,
  5. AttributeValue,
  6. Attributes,
  7. CharMetric,
  8. Delta,
  9. DeltaBuilder,
  10. DeltaIter,
  11. Operation,
  12. },
  13. };
  14. use crate::core::is_empty_line_at_index;
  15. pub struct AutoExitBlockExt {}
  16. impl InsertExt for AutoExitBlockExt {
  17. fn ext_name(&self) -> &str { "AutoExitBlockExt" }
  18. fn apply(&self, delta: &Delta, replace_len: usize, text: &str, index: usize) -> Option<Delta> {
  19. // Auto exit block will be triggered by enter two new lines
  20. if !is_newline(text) {
  21. return None;
  22. }
  23. if !is_empty_line_at_index(delta, index) {
  24. return None;
  25. }
  26. let mut iter = DeltaIter::from_offset(delta, index);
  27. let next = iter.next_op()?;
  28. let mut attributes = next.get_attributes();
  29. let block_attributes = attributes_except_header(&next);
  30. if block_attributes.is_empty() {
  31. return None;
  32. }
  33. if next.len() > 1 {
  34. return None;
  35. }
  36. match iter.first_op_contains_newline() {
  37. None => {},
  38. Some((newline_op, _)) => {
  39. let newline_attributes = attributes_except_header(&newline_op);
  40. if block_attributes == newline_attributes {
  41. return None;
  42. }
  43. },
  44. }
  45. attributes.mark_as_removed_except(&AttributeKey::Header);
  46. Some(
  47. DeltaBuilder::new()
  48. .retain(index + replace_len)
  49. .retain_with_attributes(1, attributes)
  50. .build(),
  51. )
  52. }
  53. }
  54. fn attributes_except_header(op: &Operation) -> Attributes {
  55. let mut attributes = op.get_attributes();
  56. attributes.remove(AttributeKey::Header);
  57. attributes
  58. }