auto_exit_block.rs 1.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354
  1. use crate::{client_document::InsertExt, util::is_newline};
  2. use lib_ot::core::{is_empty_line_at_index, OperationBuilder, OperationIterator};
  3. use lib_ot::text_delta::{attributes_except_header, BuildInTextAttributeKey, TextOperations};
  4. pub struct AutoExitBlock {}
  5. impl InsertExt for AutoExitBlock {
  6. fn ext_name(&self) -> &str {
  7. "AutoExitBlock"
  8. }
  9. fn apply(&self, delta: &TextOperations, replace_len: usize, text: &str, index: usize) -> Option<TextOperations> {
  10. // Auto exit block will be triggered by enter two new lines
  11. if !is_newline(text) {
  12. return None;
  13. }
  14. if !is_empty_line_at_index(delta, index) {
  15. return None;
  16. }
  17. let mut iter = OperationIterator::from_offset(delta, index);
  18. let next = iter.next_op()?;
  19. let mut attributes = next.get_attributes();
  20. let block_attributes = attributes_except_header(&next);
  21. if block_attributes.is_empty() {
  22. return None;
  23. }
  24. if next.len() > 1 {
  25. return None;
  26. }
  27. match iter.next_op_with_newline() {
  28. None => {}
  29. Some((newline_op, _)) => {
  30. let newline_attributes = attributes_except_header(&newline_op);
  31. if block_attributes == newline_attributes {
  32. return None;
  33. }
  34. }
  35. }
  36. attributes.retain_values(&[BuildInTextAttributeKey::Header.as_ref()]);
  37. Some(
  38. OperationBuilder::new()
  39. .retain(index + replace_len)
  40. .retain_with_attributes(1, attributes)
  41. .build(),
  42. )
  43. }
  44. }