///|
/// Unicode Line Break classes (UAX #14)
pub enum LineBreakClass {
BK // Mandatory Break
CR // Carriage Return
LF // Line Feed
SP // Space
OP // Opening Punctuation
CL // Closing Punctuation
QU // Quotation
GL // Non-breaking
NS // Nonstarter
EX // Exclamation/Interrogation
SY // Symbols allowing break after
IS // Infix Numeric Separator
NU // Numeric
AL // Alphabetic
ID // Ideographic
IN // Inseparable characters
HY // Hyphen
BA // Break After
BB // Break Before
B2 // Break Opportunity Before and After
ZW // Zero Width Space
CM // Combining Mark
WJ // Word Joiner
H2 // Hangul L Jamo
H3 // Hangul LV Syllable
JL // Hangul LVT Syllable
JT // Hangul V Jamo
JV // Hangul T Jamo
CP // Close Parenthesis
RI // Regional Indicator
EB // EBase
EModifier // EModifier
ZWJ // Zero Width Joiner
AI // Ambiguous
Unknown
} derive(Eq, Debug)
///|
pub extend LineBreakClass with Debug::{to_repr}
///|
pub extend LineBreakClass with Eq::{not_equal, equal}
///|
pub extend LineBreakClass with Show::{output}
///|
pub impl Show for LineBreakClass with fn output(self, logger) {
logger.write_string(self.to_string())
}
///|
pub fn LineBreakClass::to_string(self : LineBreakClass) -> String {
match self {
BK => "BK"
CR => "CR"
LF => "LF"
SP => "SP"
OP => "OP"
CL => "CL"
QU => "QU"
GL => "GL"
NS => "NS"
EX => "EX"
SY => "SY"
IS => "IS"
NU => "NU"
AL => "AL"
ID => "ID"
IN => "IN"
HY => "HY"
BA => "BA"
BB => "BB"
B2 => "B2"
ZW => "ZW"
CM => "CM"
WJ => "WJ"
H2 => "H2"
H3 => "H3"
JL => "JL"
JT => "JT"
JV => "JV"
CP => "CP"
RI => "RI"
EB => "EB"
EModifier => "EModifier"
ZWJ => "ZWJ"
AI => "AI"
Unknown => "Unknown"
}
}
///|
/// Get line break class for a character
pub fn get_line_break_class(ch : Int) -> LineBreakClass {
// Basic implementation - can be extended with full Unicode data
match ch {
_ if ch < 0 || ch > 0x10FFFF => Unknown
// Line break mandatory
0x000A => LF // Line Feed
0x000D => CR // Carriage Return
0x000B => BK // Vertical Tab
0x000C => BK // Form Feed
0x0085 => BK // Next Line
0x2028 => BK // Line Separator
0x2029 => BK // Paragraph Separator
// Space
0x0020 => SP // Space
0x00A0 => GL // No-Break Space
0x2000 => BA // En Quad
0x2001 => BA // Em Quad
0x2002 => BA // En Space
0x2003 => BA // Em Space
0x2004 => BA // Three-Per-Em Space
0x2005 => BA // Four-Per-Em Space
0x2006 => BA // Six-Per-Em Space
0x2007 => GL // Figure Space
0x2008 => BA // Punctuation Space
0x2009 => BA // Thin Space
0x200A => BA // Hair Space
0x200B => ZW // Zero Width Space
0x0300..=0x036F => CM // Combining Diacritical Marks
0x1F1E6..=0x1F1FF => RI // Regional Indicator Symbols
0x1F3FB..=0x1F3FF => EModifier // Emoji modifiers
0x2060 => WJ // Word Joiner
0xFEFF => WJ // Zero Width No-Break Space
// Opening Punctuation
0x0028 => OP // Left Parenthesis
0x005B => OP // Left Square Bracket
0x007B => OP // Left Curly Bracket
0x00AB => QU // Left-Pointing Double Angle Quotation Mark
0x2018 => QU // Left Single Quotation Mark
0x201C => QU // Left Double Quotation Mark
0x201D => QU // Right Double Quotation Mark
0x2039 => QU // Single Left-Pointing Angle Quotation Mark
0x3008 => OP // Left Angle Bracket
0x300A => OP // Left Double Angle Bracket
0x300C => OP // Left Corner Bracket
0x300E => OP // Left White Corner Bracket
0x3010 => OP // Left Black Lenticular Bracket
0x3014 => OP // Left Tortoise Shell Bracket
0x3016 => OP // Left White Lenticular Bracket
0x3018 => OP // Left White Tortoise Shell Bracket
0x301A => OP // Left White Square Bracket
0xFF08 => OP // Fullwidth Left Parenthesis
0xFF3B => OP // Fullwidth Left Square Bracket
0xFF5B => OP // Fullwidth Left Curly Bracket
// Closing Punctuation
0x0029 => CP // Right Parenthesis
0x005D => CL // Right Square Bracket
0x007D => CL // Right Curly Bracket
0x00BB => QU // Right-Pointing Double Angle Quotation Mark
0x2019 => QU // Right Single Quotation Mark
0x3009 => CL // Right Angle Bracket
0x300B => CL // Right Double Angle Bracket
0x300D => CL // Right Corner Bracket
0x300F => CL // Right White Corner Bracket
0x3011 => CL // Right Black Lenticular Bracket
0x3015 => CL // Right Tortoise Shell Bracket
0x3017 => CL // Right White Lenticular Bracket
0x3019 => CL // Right White Tortoise Shell Bracket
0x301B => CL // Right White Square Bracket
0xFF09 => CP // Fullwidth Right Parenthesis
0xFF3D => CL // Fullwidth Right Square Bracket
0xFF5D => CL // Fullwidth Right Curly Bracket
// Hyphen
0x002D => HY // Hyphen-Minus
0x00AD => BA // Soft Hyphen
0x2010 => BA // Hyphen
0x2012 => BA // Figure Dash
0x2013 => BA // En Dash
0x2014 => BA // Em Dash
0x2015 => AI // Horizontal Bar (ambiguous)
0x2024 => IN // One Dot Leader
0x2025 => IN // Two Dot Leader
0x2026 => IN // Horizontal Ellipsis
// Exclamation/Interrogation
0x0021 => EX // Exclamation Mark
0x003F => EX // Question Mark
0xFF01 => EX // Fullwidth Exclamation Mark
0xFF1F => EX // Fullwidth Question Mark
// Symbols allowing break after
0x002F => SY // Solidus
0x002C => IS // Comma
0x002E => IS // Full Stop
0x0030..=0x0039 => NU // ASCII digits
0x003A => IS // Colon
0x003B => IS // Semicolon
0x0600..=0x0605 => NS // Arabic number signs
0x0E40..=0x0E44 => NS // Thai leading vowels
0x0EC0..=0x0EC4 => NS // Lao leading vowels
0x1100..=0x115F => JL // Hangul choseong
0x1160..=0x11A7 => JV // Hangul jungseong
0x11A8..=0x11FF => JT // Hangul jongseong
0x200D => ZWJ // Zero Width Joiner
0x21D4 => B2 // Left Right Double Arrow
0x2329 => OP // Left-Pointing Angle Bracket
0x232A => CL // Right-Pointing Angle Bracket
0x261D => EB // White Up Pointing Index
0x270B => EB // Raised Hand
0x275B => QU // Heavy Single Turned Comma Quotation Mark Ornament
0x275C => QU // Heavy Single Comma Quotation Mark Ornament
0x2E3A => BB // Two-Em Dash
0x2E3B => BB // Three-Em Dash
0x301C => NS // Wave Dash
0x30A0 => NS // Katakana-Hiragana Double Hyphen
0x30FB => NS // Katakana Middle Dot
0xFE17 => B2 // Presentation Form for Vertical Left White Lenticular Bracket
0xFE31 => B2 // Presentation Form for Vertical Em Dash
0xFE32 => B2 // Presentation Form for Vertical En Dash
0xFF10..=0xFF19 => NU // Fullwidth digits
// Ideographic (CJK)
_ if ch >= 0x3000 && ch <= 0x303F => ID // CJK Symbols
_ if ch >= 0x3040 && ch <= 0x309F => ID // Hiragana
_ if ch >= 0x30A0 && ch <= 0x30FF => ID // Katakana
_ if ch >= 0x3100 && ch <= 0x312F => ID // Bopomofo
_ if ch >= 0x3130 && ch <= 0x318F => ID // Hangul Compatibility Jamo
_ if ch >= 0x3190 && ch <= 0x319F => ID // Kanbun
_ if ch >= 0x31A0 && ch <= 0x31BF => ID // Bopomofo Extended
_ if ch >= 0x31C0 && ch <= 0x31EF => ID // CJK Strokes
_ if ch >= 0x31F0 && ch <= 0x31FF => ID // Katakana Phonetic Extensions
_ if ch >= 0x3200 && ch <= 0x32FF => ID // Enclosed CJK Letters and Months
_ if ch >= 0x3300 && ch <= 0x33FF => ID // CJK Compatibility
_ if ch >= 0x3400 && ch <= 0x4DBF => ID // CJK Unified Ideographs Extension A
_ if ch >= 0x4E00 && ch <= 0x9FFF => ID // CJK Unified Ideographs
_ if ch >= 0xA000 && ch <= 0xA4CF => ID // Yi Syllables
_ if ch >= 0xAC00 && ch <= 0xD7A3 => hangul_syllable_class(ch)
_ if ch >= 0xF900 && ch <= 0xFAFF => ID // CJK Compatibility Ideographs
_ if ch >= 0xFE30 && ch <= 0xFE4F => ID // CJK Compatibility Forms
_ if ch >= 0xFF65 && ch <= 0xFFDC => ID // Halfwidth Katakana
_ if ch >= 0x20000 && ch <= 0x2A6DF => ID // CJK Unified Ideographs Extension B
_ if ch >= 0x2A700 && ch <= 0x2B73F => ID // CJK Unified Ideographs Extension C
_ if ch >= 0x2B740 && ch <= 0x2B81F => ID // CJK Unified Ideographs Extension D
_ if ch >= 0x2F800 && ch <= 0x2FA1F => ID // CJK Compatibility Ideographs Supplement
// Default to AL (Alphabetic)
_ => AL
}
}
///|
fn hangul_syllable_class(ch : Int) -> LineBreakClass {
let syllable = ch - 0xAC00
if syllable % 28 == 0 {
H2
} else {
H3
}
}
///|
/// Check if a line break is allowed between two line break classes
pub fn is_line_break_allowed(
prev_class : LineBreakClass,
curr_class : LineBreakClass,
) -> Bool {
// Simplified UAX #14 rules
match (prev_class, curr_class) {
// Always break after mandatory breaks
(BK, _) => true
(CR, LF) => false
(CR, _) => true
(LF, _) => true
// Keep glue, word joiner, combining marks, and ZWJ sequences intact.
(_, GL) => false
(GL, _) => false
(_, WJ) => false
(WJ, _) => false
(_, CM) => false
(_, ZWJ) => false
(ZWJ, _) => false
// Break after spaces
(SP, _) => true
// Don't break before closing punctuation
(_, CL) => false
(_, CP) => false
// Don't break after opening punctuation
(OP, _) => false
// Break between ideographic characters
(ID, ID) => true
(ID, _) => true
(_, ID) => true
// Keep Hangul jamo/syllable clusters together.
(JL, JL) => false
(JL, JV) => false
(JL, H2) => false
(JL, H3) => false
(JV, JV) => false
(JV, JT) => false
(H2, JV) => false
(H2, JT) => false
(JT, JT) => false
(H3, JT) => false
// Break before classes that explicitly prefer a preceding break.
(_, BB) => true
// Don't break within numbers
(NU, NU) => false
(NU, IS) => false
(IS, NU) => false
// Don't break between alphabetic characters
(AL, AL) => false
(AL, NU) => false
(NU, AL) => false
// Break after hyphens
(HY, _) => true
(BA, _) => true
// Default: allow break
_ => true
}
}