You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

138 lines
3.4KB

  1. use melib::Graphemes;
  2. #[derive(Debug, Clone, Default, PartialEq)]
  3. pub struct UText {
  4. content: String,
  5. cursor_pos: usize,
  6. grapheme_cursor_pos: usize,
  7. }
  8. impl UText {
  9. pub fn new(content: String) -> Self {
  10. UText {
  11. content,
  12. cursor_pos: 0,
  13. grapheme_cursor_pos: 0,
  14. }
  15. }
  16. pub fn set_cursor(&mut self, cursor_pos: usize) {
  17. if cursor_pos > self.content.len() {
  18. return;
  19. }
  20. let (first, _) = self.content.split_at(cursor_pos);
  21. self.grapheme_cursor_pos = first.split_graphemes().len();
  22. self.cursor_pos = cursor_pos;
  23. }
  24. pub fn as_str(&self) -> &str {
  25. self.content.as_str()
  26. }
  27. pub fn clear(&mut self) {
  28. self.content.clear();
  29. self.cursor_pos = 0;
  30. self.grapheme_cursor_pos = 0;
  31. }
  32. pub fn into_string(self) -> String {
  33. self.content
  34. }
  35. pub fn grapheme_len(&self) -> usize {
  36. self.content.split_graphemes().len()
  37. }
  38. pub fn cursor_inc(&mut self) {
  39. if self.cursor_pos >= self.content.len() {
  40. return;
  41. }
  42. let (_, right) = self.content.split_at(self.cursor_pos);
  43. if let Some((_, graph)) = right.next_grapheme() {
  44. self.cursor_pos += graph.len();
  45. self.grapheme_cursor_pos += 1;
  46. }
  47. }
  48. pub fn cursor_dec(&mut self) {
  49. if self.cursor_pos == 0 {
  50. return;
  51. }
  52. let (left, _) = self.content.split_at(self.cursor_pos);
  53. if let Some((_, graph)) = left.last_grapheme() {
  54. self.cursor_pos -= graph.len();
  55. self.grapheme_cursor_pos -= 1;
  56. }
  57. }
  58. pub fn cursor_pos(&self) -> usize {
  59. self.cursor_pos
  60. }
  61. pub fn grapheme_pos(&self) -> usize {
  62. self.grapheme_cursor_pos
  63. }
  64. /*
  65. * Insert code point `k` in position `self.cursor_pos`:
  66. *
  67. * before:
  68. *
  69. * self.content = xxxxxx....xxxxxxx;
  70. * ^
  71. * self.cursor_pos
  72. *
  73. * after:
  74. *
  75. * self.content = xxxxxx....xxxxkxxx;
  76. * ^
  77. * self.cursor_pos
  78. */
  79. pub fn insert_char(&mut self, k: char) {
  80. self.content.insert(self.cursor_pos, k);
  81. self.cursor_pos += k.len_utf8();
  82. self.grapheme_cursor_pos += 1;
  83. }
  84. /*
  85. * remove grapheme cluster that ends on `self.cursor_pos`:
  86. *
  87. * before:
  88. *
  89. * self.content = xxxxxx....xxggxxx;
  90. * ^
  91. * self.cursor_pos
  92. *
  93. * after:
  94. *
  95. * self.content = xxxxxx....xxxxxx;
  96. * ^
  97. * self.cursor_pos
  98. */
  99. pub fn backspace(&mut self) {
  100. if self.content.is_empty() {
  101. return;
  102. }
  103. let (offset, graph_len) = {
  104. /*
  105. * Split string at cursor_pos:
  106. */
  107. let (left, _) = self.content.split_at(self.cursor_pos);
  108. /*
  109. * left = xxxxxx....xxgg;
  110. * right = xxx;
  111. */
  112. if let Some((offset, graph)) = left.last_grapheme() {
  113. (offset, graph.len())
  114. } else {
  115. return;
  116. }
  117. };
  118. self.cursor_dec();
  119. self.content
  120. .drain(std::dbg!(offset..offset + graph_len))
  121. .count();
  122. }
  123. }