text-reader 0.2.1

Text reader.
Documentation
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::<String>();
  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