auto_format.rs 2.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. use crate::{client_document::InsertExt, util::is_whitespace};
  2. use lib_ot::core::Attributes;
  3. use lib_ot::{
  4. core::{count_utf16_code_units, OperationBuilder, OperationIterator},
  5. text_delta::{empty_attributes, BuildInTextAttribute, TextDelta},
  6. };
  7. use std::cmp::min;
  8. use url::Url;
  9. pub struct AutoFormatExt {}
  10. impl InsertExt for AutoFormatExt {
  11. fn ext_name(&self) -> &str {
  12. "AutoFormatExt"
  13. }
  14. fn apply(&self, delta: &TextDelta, replace_len: usize, text: &str, index: usize) -> Option<TextDelta> {
  15. // enter whitespace to trigger auto format
  16. if !is_whitespace(text) {
  17. return None;
  18. }
  19. let mut iter = OperationIterator::new(delta);
  20. if let Some(prev) = iter.next_op_with_len(index) {
  21. match AutoFormat::parse(prev.get_data()) {
  22. None => {}
  23. Some(formatter) => {
  24. let mut new_attributes = prev.get_attributes();
  25. // format_len should not greater than index. The url crate will add "/" to the
  26. // end of input string that causes the format_len greater than the input string
  27. let format_len = min(index, formatter.format_len());
  28. let format_attributes = formatter.to_attributes();
  29. format_attributes.iter().for_each(|(k, v)| {
  30. if !new_attributes.contains_key(k) {
  31. new_attributes.insert(k.clone(), v.clone());
  32. }
  33. });
  34. let next_attributes = match iter.next_op() {
  35. None => empty_attributes(),
  36. Some(op) => op.get_attributes(),
  37. };
  38. return Some(
  39. OperationBuilder::new()
  40. .retain(index + replace_len - min(index, format_len))
  41. .retain_with_attributes(format_len, format_attributes)
  42. .insert_with_attributes(text, next_attributes)
  43. .build(),
  44. );
  45. }
  46. }
  47. }
  48. None
  49. }
  50. }
  51. pub enum AutoFormatter {
  52. Url(Url),
  53. }
  54. impl AutoFormatter {
  55. pub fn to_attributes(&self) -> Attributes {
  56. match self {
  57. AutoFormatter::Url(url) => BuildInTextAttribute::Link(url.as_str()).into(),
  58. }
  59. }
  60. pub fn format_len(&self) -> usize {
  61. let s = match self {
  62. AutoFormatter::Url(url) => url.to_string(),
  63. };
  64. count_utf16_code_units(&s)
  65. }
  66. }
  67. pub struct AutoFormat {}
  68. impl AutoFormat {
  69. fn parse(s: &str) -> Option<AutoFormatter> {
  70. if let Ok(url) = Url::parse(s) {
  71. return Some(AutoFormatter::Url(url));
  72. }
  73. None
  74. }
  75. }