1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
//! Snippet module contains structures used to generate the Snippet to be formatted.
//!
//! # Example:
//!
//! ```
//! use annotate_snippets::snippet::{Snippet, Slice, Annotation, TitleAnnotation, AnnotationType};
//!
//! let snippet = Snippet {
//!     slice: Slice {
//!         source: r#"
//!         ) -> Option<String> {
//!             for ann in annotations {
//!                 match (ann.range.0, ann.range.1) {
//!                     (None, None) => continue,
//!                     (Some(start), Some(end)) if start > end_index => continue,
//!                     (Some(start), Some(end)) if start >= start_index => {
//!                         let label = if let Some(ref label) = ann.label {
//!                             format!(" {}", label)
//!                         } else {
//!                             String::from("")
//!                         };
//!
//!                         return Some(format!(
//!                             "{}{}{}",
//!                             " ".repeat(start - start_index),
//!                             "^".repeat(end - start),
//!                             label
//!                         ));
//!                     }
//!                     _ => continue,
//!                 }
//!             }
//!         "#.to_string(),
//!         line_start: 51,
//!         origin: Some("src/format.rs".to_string())
//!     },
//!     title: Some(TitleAnnotation {
//!         label: Some("mismatched types".to_string()),
//!         id: Some("E0308".to_string()),
//!         annotation_type: AnnotationType::Error,
//!     }),
//!     main_annotation_pos: Some(0),
//!     fold: Some(true),
//!     annotations: vec![
//!         Annotation {
//!             label: Some("expected `Option<String>` because of return type".to_string()),
//!             annotation_type: AnnotationType::Warning,
//!             range: Some((6, 20))
//!         },
//!         Annotation {
//!             label: Some("expected enum `std::option::Option".to_string()),
//!             annotation_type: AnnotationType::Error,
//!             range: Some((23, 787))
//!         },
//!     ]
//! };
//! let output = format!("{}", snippet);
//! ```

use display_list::DisplayList;
use formatted_display_list::FormattedDisplayList;
use std::fmt;

/// Primary structure provided for formatting
#[derive(Debug, Clone)]
pub struct Snippet {
    pub slice: Slice,
    pub annotations: Vec<Annotation>,
    /// Index of an Annotation to be used
    /// as a main one in the snippet (for the header part).
    pub main_annotation_pos: Option<usize>,
    pub title: Option<TitleAnnotation>,
    /// If set explicitly to `true`, the snippet will fold
    /// parts of the slice that don't contain any annotations.
    pub fold: Option<bool>,
}

impl fmt::Display for Snippet {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let dl = DisplayList::from(self.clone());
        let fdl = FormattedDisplayList::from(dl);
        write!(f, "{}", fdl)
    }
}

/// Structure containing the slice of text to be annotated and
/// basic information about the location of the slice.
#[derive(Debug, Clone)]
pub struct Slice {
    pub source: String,
    pub line_start: usize,
    pub origin: Option<String>,
}

/// Types of annotations.
#[derive(Debug, Clone, Copy)]
pub enum AnnotationType {
    /// Error annotations are displayed using red color and "^" character.
    Error,
    /// Warning annotations are displayed using blue color and "-" character.
    Warning,
}

/// An Annotation is a pointer to a place in the Slice which is to be annotated.
#[derive(Debug, Clone)]
pub struct Annotation {
    pub range: Option<(usize, usize)>,
    pub label: Option<String>,
    pub annotation_type: AnnotationType,
}

/// An annotation used to describe the whole snippet.
#[derive(Debug, Clone)]
pub struct TitleAnnotation {
    /// Identifier of the annotation. Usually error code like "E0308".
    pub id: Option<String>,
    pub label: Option<String>,
    pub annotation_type: AnnotationType,
}