1use makepad_render::*;
2
3use crate::textcursor::*;
4
5#[derive(Clone, Default)]
6pub struct TextBuffer {
7 pub lines: Vec<Vec<char>>,
13 pub undo_stack: Vec<TextUndo>,
14 pub redo_stack: Vec<TextUndo>,
15
16 pub is_loaded: bool,
18 pub signal: Signal,
19
20 pub mutation_id: u64,
21 pub is_crlf: bool,
22 pub messages: TextBufferMessages,
23 pub flat_text: Vec<char>,
24 pub token_chunks: Vec<TokenChunk>,
25 pub token_chunks_id: u64,
26 pub keyboard: TextBufferKeyboard,
27}
28
29impl TextBuffer{
30 pub fn status_loaded()->StatusId{uid!()}
31 pub fn status_message_update()->StatusId{uid!()}
32 pub fn status_jump_to_offset()->StatusId{uid!()}
33 pub fn status_data_update()->StatusId{uid!()}
34 pub fn status_keyboard_update()->StatusId{uid!()}
35}
36
37#[derive(Clone, Default)]
38pub struct TextBufferKeyboard {
39 pub modifiers: KeyModifiers,
40 pub key_down: Option<KeyCode>,
41 pub key_up: Option<KeyCode>
42}
43
44#[derive(Clone, Default)]
45pub struct TextBufferMessages {
46 pub mutation_id: u64,
49 pub cursors: Vec<TextCursor>,
51 pub bodies: Vec<TextBufferMessage>,
52 pub jump_to_offset: usize
53}
54
55#[derive(Clone, PartialEq)]
56pub enum TextBufferMessageLevel {
57 Error,
58 Warning,
59 Log
60}
61
62#[derive(Clone)]
63pub struct TextBufferMessage {
64 pub level: TextBufferMessageLevel,
65 pub body: String
66}
67
68#[derive(Clone, Copy)]
108pub struct TextPos {
109 pub row: usize,
110 pub col: usize
111}
112
113impl TextPos {
114 pub fn dist(&self, other: &TextPos) -> f64 {
115 let dr = (self.row as f64) - (other.row as f64);
116 let dc = (self.col as f64) - (other.col as f64);
117 (dr * dr + dc * dc).sqrt()
118 }
119
120 pub fn zero() -> TextPos {
121 TextPos {row: 0, col: 0}
122 }
123}
124
125#[derive(Clone, PartialEq)]
126pub enum TextUndoGrouping {
127 Space,
128 Newline,
129 Character(u64),
130 Backspace(u64),
131 Delete(usize),
132 Block,
133 Tab,
134 Cut,
135 Format,
136 Other
137}
138
139impl Default for TextUndoGrouping {
140 fn default() -> TextUndoGrouping {
141 TextUndoGrouping::Other
142 }
143}
144
145impl TextUndoGrouping {
146 fn wants_grouping(&self) -> bool {
147 match self {
148 TextUndoGrouping::Space => true,
149 TextUndoGrouping::Newline => false,
150 TextUndoGrouping::Character(_) => true,
151 TextUndoGrouping::Backspace(_) => true,
152 TextUndoGrouping::Delete(_) => true,
153 TextUndoGrouping::Block => false,
154 TextUndoGrouping::Tab => false,
155 TextUndoGrouping::Format => false,
156 TextUndoGrouping::Cut => false,
157 TextUndoGrouping::Other => false
158 }
159 }
160}
161
162#[derive(Clone)]
163pub struct TextUndo {
164 pub ops: Vec<TextOp>,
165 pub grouping: TextUndoGrouping,
166 pub cursors: TextCursorSet
167}
168
169#[derive(Clone)]
170pub struct TextOp {
171 pub start: usize,
172 pub len: usize,
173 pub lines: Vec<Vec<char>>,
174}
175
176fn calc_char_count(lines: &Vec<Vec<char>>) -> usize {
177 let mut char_count = 0;
178 for line in lines {
179 char_count += line.len()
180 }
181 char_count += lines.len() - 1;
182 char_count
184}
185
186impl TextBuffer {
187 pub fn with_signal(cx:&mut Cx)->Self{
188 let mut tb = TextBuffer::default();
189 tb.signal = cx.new_signal();
190 tb
191 }
192
193 pub fn from_utf8(data: &str) -> Self {
194 let mut tb = TextBuffer::default();
195 tb.load_from_utf8(data);
196 tb
197 }
198
199 pub fn needs_token_chunks(&mut self) -> bool {
200 if self.token_chunks_id != self.mutation_id && self.is_loaded {
201 self.token_chunks_id = self.mutation_id;
202 self.token_chunks.truncate(0);
203 self.flat_text.truncate(0);
204 return true
205 }
206 return false
207 }
208
209 pub fn offset_to_text_pos(&self, char_offset: usize) -> TextPos {
210 let mut char_count = 0;
211 for (row, line) in self.lines.iter().enumerate() {
212 let next_char_count = char_count + line.len() + 1;
213 if next_char_count > char_offset {
214 return TextPos {row: row, col: char_offset - char_count}
215 }
216 char_count = next_char_count;
217 }
218 TextPos {row: self.lines.len().max(1) - 1, col: 0}
219 }
220
221 pub fn offset_to_text_pos_next(&self, query_off: usize, old_pos: TextPos, old_off: usize) -> TextPos {
222 let mut row = old_pos.row;
223 let mut iter_off = old_off - old_pos.col;
224 while row < self.lines.len() {
225 let line = &self.lines[row];
226 let next_off = iter_off + line.len() + 1;
227 if next_off > query_off {
228 return TextPos {row: row, col: query_off - iter_off}
229 }
230 iter_off = next_off;
231 row += 1;
232 }
233 TextPos {row: self.lines.len().max(1) - 1, col: 0}
234 }
235
236 pub fn text_pos_to_offset(&self, pos: TextPos) -> usize {
237 let mut char_count = 0;
238 if pos.row >= self.lines.len() {
239 return self.calc_char_count()
240 }
241 for (ln_row, line) in self.lines.iter().enumerate() {
242 if ln_row == pos.row {
243 return char_count + (line.len()).min(pos.col);
244 }
245 char_count += line.len() + 1;
246 }
247 0
248 }
249
250 pub fn get_nearest_line_range(&self, offset: usize) -> (usize, usize) {
251 let pos = self.offset_to_text_pos(offset);
252 let line = &self.lines[pos.row];
253 return (offset - pos.col, line.len() + if pos.row < (line.len().max(1) - 1) {1}else {0})
254 }
255
256 pub fn calc_next_line_indent_depth(&self, offset: usize, tabsize: usize) -> (usize, usize) {
257 let pos = self.offset_to_text_pos(offset);
258 let line = &self.lines[pos.row];
259 let mut prev_index = pos.col;
260 if prev_index == 0 || prev_index > line.len() {
261 return (offset - pos.col, 0);
262 };
263
264 let mut instep = 0;
265 while prev_index > 0 {
266 let prev = line[prev_index - 1];
267 if prev == ')' || prev == '}' || prev == ']' {
268 break;
269 }
270 if prev == '{' || prev == '(' || prev == '[' {
271 instep = tabsize;
272 break;
273 }
274 prev_index -= 1;
275 }
276 for (i, ch) in line.iter().enumerate() {
277 if *ch != ' ' {
278 return (offset - pos.col, i + instep);
279 }
280 };
281 return (offset - pos.col, line.len());
282 }
283
284 pub fn calc_line_indent_depth(&self, row: usize) -> usize {
285 let line = &self.lines[row];
286 for (i, ch) in line.iter().enumerate() {
287 if *ch != ' ' {
288 return i
289 }
290 };
291 return line.len()
292 }
293
294 pub fn calc_backspace_line_indent_depth_and_pair(&self, offset: usize) -> (usize, usize) {
295 let pos = self.offset_to_text_pos(offset);
296 let line = &self.lines[pos.row];
297 for i in 0..line.len() {
298 let ch = line[i];
299 if ch != ' ' {
300 if i == pos.col {
301 return (offset - (i + 1), 1 + i);
302 }
303 if pos.col >= 1 && pos.col <line.len() {
305 let pch = line[pos.col - 1];
306 let nch = line[pos.col];
307 if pch == '{' && nch == '}'
308 || pch == '(' && nch == ')'
309 || pch == '[' && nch == ']' {
310 return (offset - 1, 2)
311 }
312 }
313 return (offset - 1, 1);
314 }
315 };
316 return ((offset - pos.col - 1), line.len() + 1);
317 }
318
319 pub fn calc_deletion_whitespace(&self, offset: usize) -> Option<(usize, usize, usize, usize)> {
320 let pos = self.offset_to_text_pos(offset);
321 if self.lines.len() < 1 || pos.row >= self.lines.len() - 1 {
322 return None
323 }
324 let line1 = &self.lines[pos.row];
325 let mut line1_ws = 0;
326 for ch in line1 {
327 if *ch != ' ' {
328 break;
329 }
330 line1_ws += 1;
331 };
332
333 let line2 = &self.lines[pos.row + 1];
334 let mut line2_ws = 0;
335 for ch in line2 {
336 if *ch != ' ' {
337 break;
338 }
339 line2_ws += 1;
340 };
341
342 return Some((offset - pos.col, line1_ws, line1.len(), line2_ws));
343 }
344
345
346 pub fn calc_deindent_whitespace(&self, offset: usize) -> Option<(usize, usize, usize)> {
347 let pos = self.offset_to_text_pos(offset);
348 if self.lines.len() < 1 || pos.row >= self.lines.len() {
349 return None
350 }
351 let line1 = &self.lines[pos.row];
352 let mut line1_ws = 0;
353 for ch in line1 {
354 if *ch != ' ' {
355 break;
356 }
357 line1_ws += 1;
358 };
359
360 return Some((offset - pos.col, line1_ws, line1.len()));
361 }
362
363 pub fn calc_char_count(&self) -> usize {
364 calc_char_count(&self.lines)
365 }
366
367 pub fn get_line_count(&self) -> usize {
368 self.lines.len()
369 }
370
371 pub fn is_empty(&self) -> bool {
372 self.lines.len() == 0 || self.lines.len() == 1 && self.lines[0].len() == 0
373 }
374
375 pub fn get_range_as_string(&self, start: usize, len: usize, ret: &mut String) {
376 let mut pos = self.offset_to_text_pos(start);
377 for _ in 0..len {
378 let line = &self.lines[pos.row];
379 if pos.col >= line.len() {
380 ret.push('\n');
381 pos.col = 0;
382 pos.row += 1;
383 if pos.row >= self.lines.len() {
384 return;
385 }
386 }
387 else {
388 ret.push(line[pos.col]);
389 pos.col += 1;
390 }
391 };
392 }
393
394
395 pub fn get_char(&self, start: usize) -> char {
396 let pos = self.offset_to_text_pos(start);
397 let line = &self.lines[pos.row];
398 if pos.row == self.lines.len() - 1 && pos.col >= line.len() {
399 return '\0'
400 }
401 if pos.col >= line.len() {
402 return '\n'
403 }
404 return line[pos.col]
405 }
406
407 pub fn get_as_string(&self) -> String {
408 let mut ret = String::new();
409 for i in 0..self.lines.len() {
410 let line = &self.lines[i];
411 for ch in line {
412 ret.push(*ch);
413 }
414 if i != self.lines.len() - 1 {
415 if self.is_crlf {
416 ret.push('\r');
417 ret.push('\n');
418 }
419 else {
420 ret.push('\n');
421 }
422 }
423 }
424 return ret
425 }
426
427 pub fn send_textbuffer_loaded_signal(&self, cx: &mut Cx) {
428 cx.send_signal(self.signal, TextBuffer::status_loaded());
429 }
430
431 pub fn load_from_utf8(&mut self, utf8: &str) {
432 self.is_loaded = true;
433 self.is_crlf = !utf8.find("\r\n").is_none();
434 self.lines = TextBuffer::split_string_to_lines(utf8);
435 self.mutation_id += 1;
436 }
437
438 pub fn replace_line(&mut self, row: usize, start_col: usize, len: usize, rep_line: Vec<char>) -> Vec<char> {
439 self.mutation_id += 1;
440 self.lines[row].splice(start_col..(start_col + len), rep_line).collect()
441 }
442
443 pub fn copy_line(&self, row: usize, start_col: usize, len: usize) -> Vec<char> {
444 let line = &self.lines[row];
445 if start_col >= line.len() {
446 return vec![]
447 }
448 if start_col + len > line.len() {
449 self.lines[row][start_col..line.len()].iter().cloned().collect()
450 }
451 else {
452 self.lines[row][start_col..(start_col + len)].iter().cloned().collect()
453 }
454 }
455
456 pub fn replace_range(&mut self, start: usize, len: usize, mut rep_lines: Vec<Vec<char>>) -> Vec<Vec<char>> {
457 self.mutation_id += 1;
458 let start_pos = self.offset_to_text_pos(start);
459 let end_pos = self.offset_to_text_pos_next(start + len, start_pos, start);
460
461 if start_pos.row == end_pos.row && rep_lines.len() == 1 { let rep_line_zero = rep_lines.drain(0..1).next().unwrap();
463
464 if start_pos.col>end_pos.col {
465 return vec![];
466 }
467 let line = self.lines[start_pos.row].splice(start_pos.col..end_pos.col, rep_line_zero).collect();
468 return vec![line];
469 }
470 else {
471 if rep_lines.len() == 1 { let rep_line_zero = rep_lines.drain(0..1).next().unwrap();
474
475 let first = self.lines[start_pos.row].splice(start_pos.col.., rep_line_zero).collect();
477
478 let mut middle: Vec<Vec<char>> = self.lines.drain((start_pos.row + 1)..(end_pos.row)).collect();
480
481 let last: Vec<char> = self.lines[start_pos.row + 1].drain(0..end_pos.col).collect();
483
484 let mut last_line = self.lines.drain((start_pos.row + 1)..(start_pos.row + 2)).next().unwrap();
486
487 self.lines[start_pos.row].append(&mut last_line);
489
490 middle.insert(0, first);
492 middle.push(last);
493
494 return middle
495 }
496 else if start_pos.row == end_pos.row { let mut last_bit: Vec<char> = self.lines[start_pos.row].drain(end_pos.col..).collect();
498 let rep_lines_len = rep_lines.len();
502 let rep_line_first: Vec<char> = rep_lines.drain(0..1).next().unwrap();
503 let line = self.lines[start_pos.row].splice(start_pos.col.., rep_line_first).collect();
504
505 let rep_line_mid = rep_lines.drain(0..(rep_lines.len()));
507 self.lines.splice((start_pos.row + 1)..(start_pos.row + 1), rep_line_mid);
508
509 self.lines[start_pos.row + rep_lines_len - 1].append(&mut last_bit);
511
512 return vec![line];
513 }
514 else { let rep_line_last = rep_lines.drain((rep_lines.len() - 1)..(rep_lines.len())).next().unwrap();
517 let last = self.lines[end_pos.row].splice(..end_pos.col, rep_line_last).collect();
518
519 let rep_line_mid = rep_lines.drain(1..(rep_lines.len()));
521 let mut middle: Vec<Vec<char>> = self.lines.splice((start_pos.row + 1)..end_pos.row, rep_line_mid).collect();
522
523 let rep_line_zero = rep_lines.drain(0..1).next().unwrap();
525 let first = self.lines[start_pos.row].splice(start_pos.col.., rep_line_zero).collect();
526
527 middle.insert(0, first);
529 middle.push(last);
530 return middle
531 }
532 }
533 }
534
535 pub fn replace_lines(&mut self, start_row: usize, end_row: usize, rep_lines: Vec<Vec<char>>) -> TextOp {
536 let start = self.text_pos_to_offset(TextPos {row: start_row, col: 0});
537 let end = self.text_pos_to_offset(TextPos {row: end_row, col: 0});
538 let end_mark = if end_row >= self.lines.len() {0}else {1};
539 let rep_lines_chars = calc_char_count(&rep_lines);
540 let lines = self.replace_range(start, end - start - end_mark, rep_lines);
541 TextOp {
542 start: start,
543 len: rep_lines_chars,
544 lines: lines
545 }
546 }
547
548 pub fn split_string_to_lines(string: &str) -> Vec<Vec<char>> {
549 if !string.find("\r\n").is_none() {
550 return string.split("\r\n").map( | s | s.chars().collect()).collect()
551 }
552 else {
553 return string.split("\n").map( | s | s.chars().collect()).collect()
554 }
555 }
556
557 pub fn replace_lines_with_string(&mut self, start: usize, len: usize, string: &str) -> TextOp {
558 let rep_lines = Self::split_string_to_lines(string);
559 let rep_lines_chars = calc_char_count(&rep_lines);
560 let lines = self.replace_range(start, len, rep_lines);
561 TextOp {
562 start: start,
563 len: rep_lines_chars,
564 lines: lines
565 }
566 }
567
568 pub fn replace_line_with_string(&mut self, start: usize, row: usize, col: usize, len: usize, string: &str) -> TextOp {
569 let rep_line: Vec<char> = string.chars().collect();
570 let rep_line_chars = rep_line.len();
571 let line = self.replace_line(row, col, len, rep_line);
572 TextOp {
573 start: start,
574 len: rep_line_chars,
575 lines: vec![line]
576 }
577 }
578
579 pub fn replace_with_textop(&mut self, text_op: TextOp) -> TextOp {
580 let rep_lines_chars = calc_char_count(&text_op.lines);
581 let lines = self.replace_range(text_op.start, text_op.len, text_op.lines);
582 TextOp {
583 start: text_op.start,
584 len: rep_lines_chars,
585 lines: lines
586 }
587 }
588
589 pub fn save_buffer(&mut self) {
590 }
592
593 pub fn undoredo(&mut self, mut text_undo: TextUndo, cursor_set: &mut TextCursorSet) -> TextUndo {
594 let mut ops = Vec::new();
595 while text_undo.ops.len() > 0 {
596 let op = text_undo.ops.pop().unwrap();
597 ops.push(self.replace_with_textop(op));
599 }
600 let text_undo_inverse = TextUndo {
601 ops: ops,
602 grouping: text_undo.grouping,
603 cursors: cursor_set.clone()
604 };
605 cursor_set.set = text_undo.cursors.set.clone();
606 cursor_set.last_cursor = text_undo.cursors.last_cursor;
607 text_undo_inverse
608 }
609
610 pub fn undo(&mut self, grouped: bool, cursor_set: &mut TextCursorSet) {
612
613 if self.undo_stack.len() == 0 {
614 return;
615 }
616 let mut last_grouping = TextUndoGrouping::Other;
617 let mut first = true;
618 while self.undo_stack.len() > 0 {
619 if !first && !grouped {
620 break
621 }
622 if self.undo_stack.last().unwrap().grouping != last_grouping && !first {
623 break
624 }
625 first = false;
626 let text_undo = self.undo_stack.pop().unwrap();
627 let wants_grouping = text_undo.grouping.wants_grouping();
628 last_grouping = text_undo.grouping.clone();
629 let text_redo = self.undoredo(text_undo, cursor_set);
630 self.redo_stack.push(text_redo);
631 if !wants_grouping {
632 break;
633 }
634 }
635 }
636
637 pub fn redo(&mut self, grouped: bool, cursor_set: &mut TextCursorSet) {
638 if self.redo_stack.len() == 0 {
639 return;
640 }
641 let mut last_grouping = TextUndoGrouping::Other;
642 let mut first = true;
643 while self.redo_stack.len() > 0 {
644 if !first {
645 if self.redo_stack.last().unwrap().grouping != last_grouping || !grouped {
646 break
647 }
648 }
649 first = false;
650 let text_redo = self.redo_stack.pop().unwrap();
651 let wants_grouping = text_redo.grouping.wants_grouping();
652 last_grouping = text_redo.grouping.clone();
653 let text_undo = self.undoredo(text_redo, cursor_set);
654 self.undo_stack.push(text_undo);
655 if !wants_grouping {
656 break;
657 }
658 }
659 }
660
661}
662
663pub struct LineTokenizer<'a> {
664 pub prev: char,
665 pub cur: char,
666 pub next: char,
667 iter: std::str::Chars<'a>
668}
669
670impl<'a> LineTokenizer<'a> {
671 pub fn new(st: &'a str) -> Self {
672 let mut ret = Self {
673 prev: '\0',
674 cur: '\0',
675 next: '\0',
676 iter: st.chars()
677 };
678 ret.advance();
679 ret
680 }
681
682 pub fn advance(&mut self) {
683 if let Some(next) = self.iter.next() {
684 self.next = next;
685 }
686 else {
687 self.next = '\0'
688 }
689 }
690
691 pub fn next_is_digit(&self) -> bool {
692 self.next >= '0' && self.next <= '9'
693 }
694
695 pub fn next_is_letter(&self) -> bool {
696 self.next >= 'a' && self.next <= 'z'
697 || self.next >= 'A' && self.next <= 'Z'
698 }
699
700 pub fn next_is_lowercase_letter(&self) -> bool {
701 self.next >= 'a' && self.next <= 'z'
702 }
703
704 pub fn next_is_uppercase_letter(&self) -> bool {
705 self.next >= 'A' && self.next <= 'Z'
706 }
707
708 pub fn next_is_hex(&self) -> bool {
709 self.next >= '0' && self.next <= '9'
710 || self.next >= 'a' && self.next <= 'f'
711 || self.next >= 'A' && self.next <= 'F'
712 }
713
714 pub fn advance_with_cur(&mut self) {
715 self.cur = self.next;
716 self.advance();
717 }
718
719 pub fn advance_with_prev(&mut self) {
720 self.prev = self.cur;
721 self.cur = self.next;
722 self.advance();
723 }
724
725 pub fn keyword(&mut self, chunk: &mut Vec<char>, word: &str) -> bool {
726 for m in word.chars() {
727 if m == self.next {
728 chunk.push(m);
729 self.advance();
730 }
731 else {
732 return false
733 }
734 }
735 return true
736 }
737}
738
739pub struct TokenizerState<'a> {
740 pub prev: char,
741 pub cur: char,
742 pub next: char,
743 pub lines: &'a Vec<Vec<char>>,
744 pub line_counter: usize,
745 pub offset: usize,
746 iter: std::slice::Iter<'a, char>
747}
748
749impl<'a> TokenizerState<'a> {
750 pub fn new(lines: &'a Vec<Vec<char>>) -> Self {
751 let mut ret = Self {
752 lines: lines,
753 line_counter: 0,
754 offset: 0,
755 prev: '\0',
756 cur: '\0',
757 next: '\0',
758 iter: lines[0].iter()
759 };
760 ret.advance_with_cur();
761 ret
762 }
763
764 pub fn advance(&mut self) {
765 if let Some(next) = self.iter.next() {
766 self.next = *next;
767 self.offset += 1;
768 }
769 else {
770 self.next_line();
771 }
772 }
773
774 pub fn next_line(&mut self) {
775 if self.line_counter < self.lines.len() - 1 {
776 self.line_counter += 1;
777 self.offset += 1;
778 self.iter = self.lines[self.line_counter].iter();
779 self.next = '\n'
780 }
781 else {
782 self.offset += 1;
783 self.next = '\0'
784 }
785 }
786
787 pub fn next_is_digit(&self) -> bool {
788 self.next >= '0' && self.next <= '9'
789 }
790
791 pub fn next_is_letter(&self) -> bool {
792 self.next >= 'a' && self.next <= 'z'
793 || self.next >= 'A' && self.next <= 'Z'
794 }
795
796 pub fn next_is_lowercase_letter(&self) -> bool {
797 self.next >= 'a' && self.next <= 'z'
798 }
799
800 pub fn next_is_uppercase_letter(&self) -> bool {
801 self.next >= 'A' && self.next <= 'Z'
802 }
803
804 pub fn next_is_hex(&self) -> bool {
805 self.next >= '0' && self.next <= '9'
806 || self.next >= 'a' && self.next <= 'f'
807 || self.next >= 'A' && self.next <= 'F'
808 }
809
810 pub fn advance_with_cur(&mut self) {
811 self.cur = self.next;
812 self.advance();
813 }
814
815 pub fn advance_with_prev(&mut self) {
816 self.prev = self.cur;
817 self.cur = self.next;
818 self.advance();
819 }
820
821 pub fn keyword(&mut self, chunk: &mut Vec<char>, word: &str) -> bool {
822 for m in word.chars() {
823 if m == self.next {
824 chunk.push(m);
825 self.advance();
826 }
827 else {
828 return false
829 }
830 }
831 return true
832 }
833}
834
835#[derive(Clone, PartialEq, Copy, Debug)]
836pub enum TokenType {
837 Whitespace,
838 Newline,
839 Keyword,
840 Flow,
841 Fn,
842 TypeDef,
843 Looping,
844 Identifier,
845 Call,
846 TypeName,
847 ThemeName,
848 BuiltinType,
849 Hash,
850
851 Regex,
852 String,
853 Number,
854 Bool,
855
856 StringMultiBegin,
857 StringChunk,
858 StringMultiEnd,
859
860 CommentLine,
861 CommentMultiBegin,
862 CommentChunk,
863 CommentMultiEnd,
864
865 ParenOpen,
866 ParenClose,
867 Operator,
868 Namespace,
869 Splat,
870 Delimiter,
871 Colon,
872
873 Warning,
874 Error,
875 Defocus,
876
877 Unexpected,
878 Eof
879}
880
881impl TokenType {
882 pub fn should_ignore(&self) -> bool {
883 match self {
884 TokenType::Whitespace => true,
885 TokenType::Newline => true,
886 TokenType::CommentLine => true,
887 TokenType::CommentMultiBegin => true,
888 TokenType::CommentChunk => true,
889 TokenType::CommentMultiEnd => true,
890 _ => false
891 }
892 }
893}
894
895#[derive(Clone)]
896pub struct TokenChunk {
897 pub token_type: TokenType,
898 pub offset: usize,
899 pub pair_token: usize,
900 pub len: usize,
901 pub next: char,
902 }
904
905impl TokenChunk {
906 pub fn scan_last_token(token_chunks: &Vec<TokenChunk>) -> TokenType {
907 let mut prev_tok_index = token_chunks.len();
908 while prev_tok_index > 0 {
909 let tt = &token_chunks[prev_tok_index - 1].token_type;
910 if !tt.should_ignore() {
911 return tt.clone();
912 }
913 prev_tok_index -= 1;
914 }
915 return TokenType::Unexpected
916 }
917
918 pub fn push_with_pairing(token_chunks: &mut Vec<TokenChunk>, pair_stack: &mut Vec<usize>, next: char, offset: usize, offset2: usize, token_type: TokenType) {
919 let pair_token = if token_type == TokenType::ParenOpen {
920 pair_stack.push(token_chunks.len());
921 token_chunks.len()
922 }
923 else if token_type == TokenType::ParenClose {
924 if pair_stack.len() > 0 {
925 let other = pair_stack.pop().unwrap();
926 token_chunks[other].pair_token = token_chunks.len();
927 other
928 }
929 else {
930 token_chunks.len()
931 }
932 }
933 else {
934 token_chunks.len()
935 };
936 token_chunks.push(TokenChunk {
937 offset: offset,
938 pair_token: pair_token,
939 len: offset2 - offset,
940 next: next,
941 token_type: token_type.clone()
942 })
943 }
944
945}
946
947pub struct TokenParserItem {
948 pub chunk: Vec<char>,
949 pub token_type: TokenType,
950}
951
952pub struct TokenParser<'a> {
953 pub tokens: &'a Vec<TokenChunk>,
954 pub flat_text: &'a Vec<char>,
955 pub index: usize,
956 pub next_index: usize
957}
958
959impl <'a>TokenParser<'a> {
960 pub fn new(flat_text: &'a Vec<char>, token_chunks: &'a Vec<TokenChunk>) -> TokenParser<'a> {
961 TokenParser {
962 tokens: token_chunks,
963 flat_text: flat_text,
964 index: 0,
965 next_index: 0
966 }
967 }
968
969 pub fn advance(&mut self) -> bool {
970 if self.next_index >= self.tokens.len() {
971 return false
972 }
973 self.index = self.next_index;
974 self.next_index += 1;
975 return true;
976 }
977
978 pub fn prev_type(&self) -> TokenType {
979 if self.index > 0 {
980 self.tokens[self.index - 1].token_type
981 }
982 else {
983 TokenType::Unexpected
984 }
985 }
986
987 pub fn cur_type(&self) -> TokenType {
988 self.tokens[self.index].token_type
989 }
990
991 pub fn next_type(&self) -> TokenType {
992 if self.index < self.tokens.len() - 1 {
993 self.tokens[self.index + 1].token_type
994 }
995 else {
996 TokenType::Unexpected
997 }
998 }
999
1000 pub fn prev_char(&self) -> char {
1001 if self.index > 0 {
1002 let len = self.tokens[self.index - 1].len;
1003 let ch = self.flat_text[self.tokens[self.index - 1].offset];
1004 if len == 1 || ch == ' ' {
1005 return ch
1006 }
1007 }
1008 '\0'
1009 }
1010
1011 pub fn cur_char(&self) -> char {
1012 let len = self.tokens[self.index].len;
1013 let ch = self.flat_text[self.tokens[self.index].offset];
1014 if len == 1 || ch == ' ' {
1015 return ch
1016 }
1017 '\0'
1018 }
1019
1020 pub fn cur_chunk(&self) -> &[char] {
1021 let offset = self.tokens[self.index].offset;
1022 let len = self.tokens[self.index].len;
1023 &self.flat_text[offset..(offset + len)]
1024 }
1025
1026 pub fn next_char(&self) -> char {
1027 if self.index < self.tokens.len() - 1 {
1028 let len = self.tokens[self.index + 1].len;
1029 let ch = self.flat_text[self.tokens[self.index + 1].offset];
1030 if len == 1 || ch == ' ' {
1031 return ch
1032 }
1033 }
1034 '\0'
1035 }
1036}
1037
1038pub struct FormatOutput {
1039 pub out_lines: Vec<Vec<char >>
1040}
1041
1042impl FormatOutput {
1043 pub fn new() -> FormatOutput {
1044 FormatOutput {
1045 out_lines: Vec::new()
1046 }
1047 }
1048
1049 pub fn indent(&mut self, indent_depth: usize) {
1050 let last_line = self.out_lines.last_mut().unwrap();
1051 for _ in 0..indent_depth {
1052 last_line.push(' ');
1053 }
1054 }
1055
1056 pub fn strip_space(&mut self) {
1057 let last_line = self.out_lines.last_mut().unwrap();
1058 if last_line.len()>0 && *last_line.last().unwrap() == ' ' {
1059 last_line.pop();
1060 }
1061 }
1062
1063 pub fn new_line(&mut self) {
1064 self.out_lines.push(Vec::new());
1065 }
1066
1067 pub fn extend(&mut self, chunk: &[char]) {
1068 let last_line = self.out_lines.last_mut().unwrap();
1069 last_line.extend_from_slice(chunk);
1070 }
1071
1072 pub fn add_space(&mut self) {
1073 let last_line = self.out_lines.last_mut().unwrap();
1074 if last_line.len()>0 {
1075 if *last_line.last().unwrap() != ' ' {
1076 last_line.push(' ');
1077 }
1078 }
1079 else {
1080 last_line.push(' ');
1081 }
1082 }
1083
1084}