1pub mod agent;
19pub mod diagnostic;
20pub mod error;
21mod escape;
22mod hex;
23mod lower;
24pub mod model;
25pub mod musicxml;
26pub mod options;
27pub mod parse;
28pub mod source;
29pub mod syntax;
30mod text;
31pub mod to_abc;
32
33pub use agent::{AgentTopic, agent_topics, find_agent_topic};
34pub use diagnostic::{Diagnostic, RecoveryNote, Severity, Span, SpecReference};
35pub use error::{CromaError, Result};
36pub use model::{
37 Accidental, AccidentalMark, AccidentalPolicy, AccidentalScope, BarlineKind, ChordEvent,
38 ChordMemberEvent, Event, EventAttachments, Fraction, KeySignatureModel, Measure, MeasureId,
39 MeterModel, NoteEvent, Part, Pitch, Rational, RestEvent, RestVisibility, Score, ScoreMetadata,
40 Staff, StaffId, TimedEvent, TimedEventKind, Tune, TupletAttachment, TupletRole, Voice,
41};
42pub use options::{
43 AbcSpecVersion, DiagnosticOptions, ExportOptions, LowerOptions, MusicXmlWriteOptions,
44 ParseMode, ParseOptions, TupletDisplay,
45};
46pub use parse::field::{
47 DecorationDelimiter, FieldState, LineBreakMode, ParsedAbcFields, ParsedField,
48};
49pub use parse::{AbcDocument, ParseReport};
50pub use source::{LineColumn, LineColumnSpan, LineEnding, SourceLine, SourceText};
51pub use syntax::{
52 BarlineSyntax, LengthSyntax, MusicItem, MusicLine, MusicToken, MusicTokenKind,
53 ParsedMusicDocument, ParsedTuneMusic,
54};
55pub use to_abc::{AbcWriteOptions, write_abc};
56
57#[cfg(feature = "musicxml-reader")]
64pub use musicxml::read::read_musicxml;
65
66#[cfg(feature = "musicxml-reader")]
72pub use musicxml::read::complete_score_for_abc;
73
74#[cfg(test)]
75pub(crate) mod test_support;
76
77#[derive(Debug, Clone, PartialEq, Eq)]
78pub struct MusicXmlExport {
79 pub musicxml: String,
80 pub diagnostics: Vec<Diagnostic>,
81}
82
83pub fn abc_to_musicxml(source: &str) -> Result<String> {
84 export_musicxml(source).map(|export| export.musicxml)
85}
86
87pub fn export_musicxml(source: &str) -> Result<MusicXmlExport> {
88 export_musicxml_with_options(source, ExportOptions::default())
89}
90
91pub fn parse_document(source: &str, options: ParseOptions) -> ParseReport<AbcDocument> {
92 parse::parse_document(source, options)
93}
94
95pub fn lower_score(document: &AbcDocument, _options: LowerOptions) -> ParseReport<Option<Score>> {
96 let report = parse::parse_tune_report_from_document(document);
97 ParseReport {
98 value: report.value.map(|tune| tune.score),
99 diagnostics: report.diagnostics,
100 }
101}
102
103pub fn write_musicxml(score: &Score) -> MusicXmlExport {
104 write_musicxml_with_options(score, MusicXmlWriteOptions::default())
105}
106
107pub fn write_musicxml_with_options(score: &Score, options: MusicXmlWriteOptions) -> MusicXmlExport {
110 let report = musicxml::write_score_partwise_with_options(score, options);
111 MusicXmlExport {
112 musicxml: report.value,
113 diagnostics: report.diagnostics,
114 }
115}
116
117pub fn export_musicxml_with_options(
118 source: &str,
119 options: ExportOptions,
120) -> Result<MusicXmlExport> {
121 let parse_report = parse_document(source, options.parse_options());
122 if parse_report.has_errors() {
123 return Err(CromaError::from_diagnostics(parse_report.diagnostics));
124 }
125
126 let ParseReport {
127 value: document,
128 mut diagnostics,
129 } = parse_report;
130 let tune_report = parse::parse_tune_report_from_document(&document);
131 diagnostics.extend(tune_report.diagnostics);
132
133 let Some(tune) = tune_report.value else {
134 return Err(CromaError::from_diagnostics(diagnostics));
135 };
136
137 let write_report = musicxml::write_score_partwise_with_options(&tune.score, options.write);
138 diagnostics.extend(write_report.diagnostics);
139
140 Ok(MusicXmlExport {
141 musicxml: write_report.value,
142 diagnostics,
143 })
144}
145
146#[cfg(test)]
147#[path = "totality_tests.rs"]
148mod totality_tests;
149
150#[cfg(test)]
151#[path = "lib_tests.rs"]
152mod tests;