text-reader === [![Build Status](https://drone.0u0.me/api/badges/fewensa/text-reader/status.svg)](https://drone.0u0.me/fewensa/text-reader) Rust string character reader. # Usage ```toml [dependencies] text-reader = "0.2" ``` # Examples ## TextReader ```rust use text_reader::TextReader; #[test] fn test_while() { let mut reader = TextReader::new("華文\ndef"); while reader.has_next() { let position = reader.position(); match reader.next() { Some(ch) => match position { 0 => assert_eq!('華', ch), 1 => assert_eq!('文', ch), 2 => assert_eq!('\n', ch), 3 => assert_eq!('d', ch), 4 => assert_eq!('e', ch), 5 => assert_eq!('f', ch), _ => {} }, None => panic!("None") } } } ``` ## TextReader and Detector ```rust #[test] fn test_detector() { let text = r#" {"type": "typeA", "name": "Earth", "continent": ["Asia", "Europe"]} "#; let mut reader = TextReader::new(text); let mut rets = Vec::new(); while reader.has_next() { match reader.next() { Some('"') => { let mut detector = reader.detector(); rets.push('"'); if detector.next_text("type").yes() { detector.rollback(); rets.push('t'); } continue; }, Some(ch) => { rets.push(ch); continue; } None => {} } } let ret = rets.iter().collect::(); println!("{}", ret); } ``` ## more [more](./tests) # Analysis ```rust use text_reader::TextReader; #[test] fn test_stat() { let mut reader = TextReader::new("abc\ndef"); println!("{:?}", reader); reader.next(); println!("{:?}", reader); reader.back(); println!("{:?}", reader); let line_text = reader.this_line(); println!("{:?}", line_text); let position = reader.position(); println!("{:?}", position); println!("{:?}", reader); reader.next(); reader.next(); reader.next(); let line = reader.line(); // 1 assert_eq!(1, line); println!("{:?}", reader); reader.next(); let line = reader.line(); // 2 assert_eq!(2, line); println!("{:?}", reader); } ``` When create a TextReader `TextReader::new("abc\ndef")`, TextReader status is: `TextReader { len: 7, text: ['a', 'b', 'c', '\n', 'd', 'e', 'f'], position: 0, line: 1, cursor: 0 }` ## next And then, read next character `let ch = reader.next()`, `ch` will return `Some('a')`; TextReader status: `TextReader { len: 7, text: ['a', 'b', 'c', '\n', 'd', 'e', 'f'], position: 1, line: 1, cursor: 1 }` ## peek peek function not change status, only get current character `let ch = reader.peek()` `TextReader { len: 7, text: ['a', 'b', 'c', '\n', 'd', 'e', 'f'], position: 1, line: 1, cursor: 1 }` ## back Back will change TextReader to previous status. return TextReader reference. `reader.back()`. `TextReader { len: 7, text: ['a', 'b', 'c', '\n', 'd', 'e', 'f'], position: 0, line: 1, cursor: 0 }` ## this_line this line return current line text, not change TextReader status. `let line_text = reader.this_line()`. `TextReader { len: 7, text: ['a', 'b', 'c', '\n', 'd', 'e', 'f'], position: 0, line: 1, cursor: 0 }` line_text is `Some("abc")` ## position position function return TextReader position value. the num of character position. `let position = reader.position()` position is `0` `TextReader { len: 7, text: ['a', 'b', 'c', '\n', 'd', 'e', 'f'], position: 0, line: 1, cursor: 0 }` ## line return current line number, split of `\n`. ```rust reader.next(); reader.next(); reader.next(); let line = reader.line(); // 1 // TextReader { len: 7, text: ['a', 'b', 'c', '\n', 'd', 'e', 'f'], position: 3, line: 1, cursor: 3 } reader.next(); let line = reader.line(); // 2 // TextReader { len: 7, text: ['a', 'b', 'c', '\n', 'd', 'e', 'f'], position: 4, line: 2, cursor: 0 } ``` ## cursor position of line. starting from 0. and change to 0 when it encounters `\n` ## has_next has next character. can be used with while. or determine if the last character