A graphical client for plain-text protocols written in Rust with GTK. It currently supports the Gemini, Gopher and Finger protocols.
您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

parser.rs 2.3KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667
  1. use crate::colors::*;
  2. use std::str::FromStr;
  3. #[derive(Debug)]
  4. pub enum TextElement {
  5. Binary(String),
  6. ExternalLinkItem(String),
  7. LinkItem(String),
  8. Image(String),
  9. Text(String),
  10. }
  11. #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
  12. pub struct ParseError;
  13. impl FromStr for TextElement {
  14. type Err = ParseError;
  15. // Parses a &str into an instance of 'TextElement'
  16. fn from_str(line: &str) -> Result<TextElement, ParseError> {
  17. let els = line.split('\t');
  18. if els.count() >= 2 {
  19. // Gophermap line
  20. if line.starts_with('0') || line.starts_with('1') {
  21. Ok(TextElement::LinkItem(colors::cleanup(line)))
  22. } else if line.starts_with('i') {
  23. let mut els = line.split('\t');
  24. let text = els.next().expect("");
  25. let mut text = String::from(text);
  26. text.remove(0);
  27. Ok(TextElement::Text(colors::colorize(&text)))
  28. } else if line.starts_with('h') {
  29. Ok(TextElement::ExternalLinkItem(colors::cleanup(line)))
  30. } else if line.starts_with('I') || line.starts_with('g') {
  31. Ok(TextElement::Image(colors::cleanup(line)))
  32. } else if line.starts_with('9') {
  33. Ok(TextElement::Binary(String::from(line)))
  34. } else {
  35. Ok(TextElement::Text(colors::colorize(line)))
  36. }
  37. } else {
  38. // Text line
  39. if line.contains("gopher://") {
  40. Ok(TextElement::LinkItem(String::from(line)))
  41. } else if line.contains("http://") || line.contains("https://") {
  42. Ok(TextElement::ExternalLinkItem(String::from(line)))
  43. } else if line.contains("gemini://") {
  44. Ok(TextElement::ExternalLinkItem(String::from(line)))
  45. } else if line.contains("ftp://") {
  46. Ok(TextElement::ExternalLinkItem(String::from(line)))
  47. } else if line.contains("finger://") {
  48. Ok(TextElement::ExternalLinkItem(String::from(line)))
  49. } else {
  50. Ok(TextElement::Text(colors::colorize(line)))
  51. }
  52. }
  53. }
  54. }
  55. pub fn parse(content: String) -> Vec<Result<TextElement, ParseError>> {
  56. let mut parsed = Vec::new();
  57. for line in content.lines() {
  58. parsed.push(TextElement::from_str(line));
  59. }
  60. parsed
  61. }