ass_editor/lib.rs
1//! High-performance, ergonomic editor layer for ASS subtitles
2//!
3//! `ass-editor` provides an interactive editing interface built on top of `ass-core`,
4//! featuring zero-copy efficiency, incremental updates, and multi-document support.
5//! Designed for building subtitle editors, conversion tools, and automation scripts.
6//!
7//! # Key Features
8//!
9//! ## ๐ Interactive Editing
10//! - **Undo/redo**: Full history management with configurable depth
11//! - **Multi-document sessions**: Manage multiple files with shared resources
12//! - **Incremental parsing**: <1ms edits, <5ms re-parses via ass-core's streaming parser
13//! - **Fluent APIs**: Ergonomic builders and method chaining for all operations
14//!
15//! ## โก High Performance
16//! - **Zero-copy editing**: Direct manipulation of ass-core's zero-copy spans
17//! - **Memory efficient**: ~1.2x input size including undo history with arena pooling
18//! - **SIMD acceleration**: Optional SIMD features for parsing performance
19//! - **Thread-safe**: Optional multi-threading support with Arc/Mutex
20//!
21//! ## ๐ Advanced Features
22//! - **Search indexing**: FST-based trie indexing for fast regex queries across large scripts
23//! - **Plugin system**: Extensible architecture with syntax highlighting and auto-completion
24//! - **Format support**: Import/export SRT, WebVTT with configurable conversion options
25//! - **Karaoke support**: Generate, split, adjust, and apply karaoke timing with syllable detection
26//!
27//! # Quick Start
28//!
29//! ```
30//! use ass_editor::{EditorDocument, Position, Range};
31//!
32//! // Create a new document with ASS content
33//! let mut doc = EditorDocument::from_content(r#"
34//! [Script Info]
35//! Title: My Subtitle
36//!
37//! [V4+ Styles]
38//! Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding
39//! Style: Default,Arial,20,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,0,0,0,0,100,100,0,0,1,2,0,2,10,10,10,1
40//!
41//! [Events]
42//! Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text
43//! Dialogue: 0,0:00:00.00,0:00:05.00,Default,,0,0,0,,Hello World
44//! "#).unwrap();
45//!
46//! // Basic text editing with position-based operations
47//! let pos = Position::new(doc.text().len() - 11); // Before "Hello World"
48//! doc.insert(pos, "Welcome! ").unwrap();
49//!
50//! // Range-based operations
51//! let range = Range::new(Position::new(pos.offset), Position::new(pos.offset + 8));
52//! doc.replace(range, "Hi").unwrap();
53//!
54//! // Undo/redo support
55//! assert!(doc.can_undo());
56//! doc.undo().unwrap();
57//! assert!(doc.can_redo());
58//! doc.redo().unwrap();
59//!
60//! println!("Final text contains: {}", doc.text().contains("Hi World"));
61//! ```
62//!
63//! # Advanced Usage Examples
64//!
65//! ## Style Management
66//!
67//! ```
68//! # use ass_editor::{EditorDocument, StyleBuilder};
69//! let mut doc = EditorDocument::new();
70//!
71//! // Create styles with builder pattern
72//! let style = StyleBuilder::new()
73//! .font("Arial")
74//! .size(24)
75//! .color("&H00FFFFFF")
76//! .bold(true);
77//!
78//! // Apply styles to document
79//! doc.styles().create("Title", style).unwrap();
80//! ```
81//!
82//! ## Karaoke Timing
83//!
84//! ```
85//! # use ass_editor::{EditorDocument, Position, Range, commands::karaoke_commands::*};
86//! let mut doc = EditorDocument::from_content("Karaoke text here").unwrap();
87//! let range = Range::new(Position::new(0), Position::new(17));
88//!
89//! // Generate karaoke with automatic syllable detection
90//! doc.karaoke()
91//! .in_range(range)
92//! .generate(50) // 50 centiseconds per syllable
93//! .karaoke_type(KaraokeType::Fill)
94//! .execute()
95//! .unwrap();
96//!
97//! // Adjust timing
98//! doc.karaoke()
99//! .in_range(range)
100//! .adjust()
101//! .scale(1.5) // Make 50% longer
102//! .unwrap();
103//! ```
104//!
105//! ## Multi-Document Sessions
106//!
107//! ```
108//! # #[cfg(feature = "std")]
109//! # {
110//! # use ass_editor::{EditorSessionManager, SessionConfig};
111//! let mut manager = EditorSessionManager::new();
112//!
113//! manager.create_session("subtitle1.ass".to_string()).unwrap();
114//! manager.create_session("subtitle2.ass".to_string()).unwrap();
115//!
116//! // Switch between sessions with <100ยตs overhead
117//! manager.switch_session("subtitle1.ass").unwrap();
118//! // Edit session1...
119//!
120//! manager.switch_session("subtitle2.ass").unwrap();
121//! // Edit session2 with shared plugins and memory pools...
122//! # }
123//! ```
124//!
125//! # Feature Flags
126//!
127//! ass-editor uses a two-tier feature system for maximum flexibility:
128//!
129//! ## Main Flavors
130//! - **`default`**: Enables `full` for complete desktop functionality
131//! - **`minimal`**: Core editing features - no_std compatible with alloc
132//! - **`full`**: All features including std, analysis, plugins, formats, search, concurrency
133//!
134//! ## Optional Features
135//! - **`simd`**: SIMD acceleration for parsing performance
136//! - **`nostd`**: No-standard library support for embedded/WASM
137//! - **`dev-benches`**: Development benchmarking
138//!
139//! See the README for `Cargo.toml` dependency snippets for each flavor.
140
141#![cfg_attr(not(feature = "std"), no_std)]
142#![cfg_attr(docsrs, feature(doc_cfg))]
143
144#[cfg(not(feature = "std"))]
145extern crate alloc;
146
147pub mod commands;
148pub mod core;
149pub mod events;
150pub mod extensions;
151pub mod utils;
152
153#[cfg(feature = "std")]
154pub mod sessions;
155
156#[cfg(feature = "std")]
157pub mod formats;
158
159// Re-export ass-core types as first-class citizens
160pub use ass_core::parser::ast::{Event, EventType, ScriptInfo, Section, SectionType, Span, Style};
161pub use ass_core::parser::Script;
162
163// Public API exports
164pub use commands::{
165 BatchCommand, CommandResult, DeleteTextCommand, DocumentCommandExt, EditorCommand,
166 InsertTextCommand, ReplaceTextCommand, TextCommand,
167};
168pub use core::{
169 DocumentPosition, EditorDocument, EditorError, EventAccessor, EventBuilder, EventInfo,
170 EventQuery, EventSortCriteria, EventSortOptions, HistoryEntry, HistoryStats, OwnedEvent,
171 Position, PositionBuilder, Range, Result, Selection, StyleBuilder, UndoManager, UndoStack,
172 UndoStackConfig,
173};
174// Re-export the fluent EventFilter directly
175pub use core::fluent::EventFilter;
176// Re-export the events EventFilter with a specific name to avoid conflict
177pub use events::{
178 DocumentEvent, EventChannel, EventChannelConfig, EventFilter as DocumentEventFilter,
179 EventHandler, EventStats,
180};
181pub use extensions::{
182 EditorContext, EditorExtension, ExtensionCapability, ExtensionCommand, ExtensionContext,
183 ExtensionInfo, ExtensionManager, ExtensionResult, ExtensionState, MessageLevel,
184};
185
186pub use utils::{
187 LazyValidator, ValidationIssue, ValidationResult, ValidationSeverity, ValidatorConfig,
188};
189
190#[cfg(feature = "std")]
191pub use sessions::{EditorSession, EditorSessionManager, SessionConfig, SessionStats};
192
193#[cfg(feature = "std")]
194pub use formats::{
195 Format, FormatExporter, FormatImporter, FormatInfo, FormatOptions, FormatRegistry, FormatResult,
196};