class ICU::BiDi

Overview

Bidirectional Algorithm

This class provides a wrapper around ICU's Bidirectional Algorithm (BiDi) implementation. It is used to reorder text that contains a mix of left-to-right (LTR) and right-to-left (RTL) characters according to the Unicode Bidirectional Algorithm.

Disclaimer: this binding wrapper has been automatically generated via GenAI

Usage

# Example with mixed LTR and RTL text
text = "hello \u0627\u0644\u0639\u0631\u0628\u064A\u0629 world" # "hello العربية world"

# Create a BiDi object and set the text
bidi = ICU::BiDi.new
bidi.set_text(text)

# Get the visual reordering
reordered_text = bidi.write_reordered
puts reordered_text # Output depends on terminal/environment BiDi support

# Get the base direction (static method)
puts ICU::BiDi.base_direction(text) # => ICU::BiDi::Direction::Mixed

# Get the number of runs (segments of consistent direction)
puts bidi.run_count # => e.g., 3 (LTR, RTL, LTR)

# Iterate through visual runs
runs = bidi.visual_runs
runs.each_with_index do |run, i|
  puts "Run #{i}: Logical Start=#{run.logical_start}, Length=#{run.length}, Direction=#{run.direction}"
end

# Get logical index from visual index
logical_idx = bidi.logical_index(visual_idx: 10)
puts "Logical index for visual index 10: #{logical_idx}"

See also

Defined in:

icu/bidi.cr

Constant Summary

DEFAULT_LTR = 254.to_u8

Constants for paragraph level setting used in #set_text. DEFAULT_LTR: Use LTR if no strong character, otherwise auto-detect.

DEFAULT_RTL = 255.to_u8

DEFAULT_RTL: Use RTL if no strong character, otherwise auto-detect.

LEVEL_OVERRIDE = 128.to_u8

Bit flag used with embedding_levels in #set_text to override default directional properties.

MAP_NOWHERE = -1.to_i32

Special value returned by #logical_index or #visual_index when a mapping doesn't exist (e.g., for removed controls or inserted marks).

MAX_EXPLICIT_LEVEL = 125.to_u8

Maximum explicit embedding level allowed (125).

Constructors

Class Method Summary

Instance Method Summary

Constructor Detail

def self.new(text : String, para_level : Level = DEFAULT_LTR) #

Creates a new BiDi object and immediately processes the given text.

bidi = ICU::BiDi.new("hello العربية world")
puts bidi.direction # => ICU::BiDi::Direction::Mixed

[View source]
def self.new #

Creates a new, empty BiDi object. You must call #set_text before performing operations.

For optimal performance when processing many strings of the same approximate size, consider using ICU::BiDi.open_sized.


[View source]

Class Method Detail

def self.base_direction(text : String) : Direction #

Static method to get the base direction of a plain text string according to the first strong character (L, R, or AL) per the Unicode Bidirectional Algorithm.


[View source]
def self.write_reverse(src : String, options : WriteOption = WriteOption::None) : String #

Static method to reverse a string character by character. This is a simple reversal and does not perform the BiDi algorithm. Use #write_reordered with WriteOption::OutputReverse for BiDi-aware reversal.

  • src: The source string to reverse.
  • src: The source string to reverse.
  • options: WriteOption flags (e.g., DoMirroring, RemoveBidiControls). Defaults to WriteOption::None.
  • Returns the reversed string.

[View source]

Instance Method Detail

def direction : Direction #

Gets the overall direction of the processed text.

Returns Direction::Ltr, Direction::Rtl, or Direction::Mixed.


[View source]
def finalize #

Releases resources associated with the BiDi object.


[View source]
def inverse=(is_inverse : Bool) : Nil #

Sets whether to use an approximation of the "inverse" BiDi algorithm (transforming visual order to logical order). This is equivalent to setting reordering_mode = ReorderingMode::InverseNumbersAsL. Must be called before #set_text.

  • is_inverse: true to enable inverse mode, false for standard forward mode.

[View source]
def inverse? : Bool #

Checks if the inverse BiDi algorithm mode (ReorderingMode::InverseNumbersAsL) is active.


[View source]
def length : Int32 #

Gets the original length of the text set by #set_text.


[View source]
def logical_index(visual_index : Int32) : Int32 #

Maps a visual index to its corresponding logical index in the original text.


[View source]
def order_paragraphs_ltr=(order_ltr : Bool) : Nil #

Sets whether paragraph separators (like U+2029) should always be treated as LTR (level 0). This ensures that paragraphs visually flow from left-to-right regardless of their content direction. Must be called before #set_text.

  • order_ltr: true to force LTR paragraph progression, false for default behavior.

[View source]
def order_paragraphs_ltr? : Bool #

Checks if paragraph separators are forced to level 0 for LTR progression.


[View source]
def para_level : Level #

Gets the base paragraph level of the text. If the text contains multiple paragraphs and the level was auto-detected (DEFAULT_LTR or DEFAULT_RTL), this returns the level of the first paragraph. Use #paragraph or #paragraph_by_index to get levels of specific paragraphs.


[View source]
def paragraph(char_index : Int32) : ParagraphInfo #

Gets information about the paragraph containing the character at char_index.

  • char_index: A logical index within the text (0 <= char_index < length).
  • Returns a ParagraphInfo record containing the paragraph's index, start/limit indices, and level.

[View source]
def paragraph_by_index(para_index : Int32) : ParagraphInfo #

Gets information about the paragraph at the specified para_index.

  • para_index: The index of the paragraph (0 <= para_index < paragraph_count).
  • Returns a ParagraphInfo record containing the paragraph's index, start/limit indices, and level.

[View source]
def paragraph_count : Int32 #

Gets the number of paragraphs detected in the text (separated by block separators like U+2029).


[View source]
def reordering_mode : ReorderingMode #

Gets the currently active reordering mode.


[View source]
def reordering_mode=(mode : ReorderingMode) : Nil #

Sets the specific BiDi algorithm variant or reordering mode to use. See ReorderingMode enum and ICU documentation for details on each mode (e.g., default, inverse, grouping numbers, runs only). Must be called before #set_text.


[View source]
def reordering_options : UInt32 #

Gets the currently active reordering options as a bitmask.


[View source]
def reordering_options=(options : ReorderingOption) : Nil #

Sets options that modify the behavior of the selected reordering mode (e.g., inserting marks, removing controls, streaming). Must be called before #set_text.


[View source]
def result_length : Int32 #

Gets the length of the reordered text that would be generated by #write_reordered. This may differ from the original #length if ReorderingOption::InsertMarks or ReorderingOption::RemoveControls is active.


[View source]
def run_count : Int32 #

Gets the number of directional runs in the visually reordered text. A run is a contiguous sequence of characters having the same level. This function may trigger the actual reordering calculation.


[View source]
def set_context(prologue : String, epilogue : String) : Nil #

Sets context text that surrounds the main text processed by #set_text. This can affect the resolution of the paragraph level, especially when #para_level is DEFAULT_LTR or DEFAULT_RTL.

  • prologue: Text before the main text.
  • epilogue: Text after the main text.

[View source]
def set_text(text : String, para_level : Level = 0.to_u8, embedding_levels : Array(Level) | Nil = nil) : Nil #

Sets the text to be processed by the BiDi algorithm.

  • text: The input string.
  • #para_level: The default paragraph level. Use 0 for LTR, 1 for RTL, or ICU::BiDi::DEFAULT_LTR or ICU::BiDi::DEFAULT_RTL to auto-detect based on the first strong character. Defaults to 0.
  • embedding_levels: Optional array of embedding levels for explicit overrides. If nil, levels are calculated by the algorithm. Each level can optionally have ICU::BiDi::LEVEL_OVERRIDE bit set. Note: The caller is responsible for ensuring the embedding_levels array remains valid as long as this ICU::BiDi object is in use.

[View source]
def visual_index(logical_index : Int32) : Int32 #

Maps a logical index from the original text to its corresponding visual index.


[View source]
def visual_run(run_index : Int32) : VisualRunInfo #

Gets information about a specific visual run. Runs are ordered visually (left-to-right).

  • run_index: The index of the visual run (0 <= run_index < run_count).
  • Returns a VisualRunInfo record containing the run's logical start index, length, and direction.

[View source]
def visual_runs : Array(VisualRunInfo) #

Gets an array containing information about all visual runs.

runs = bidi.visual_runs
runs.each { |run| puts run }

[View source]
def write_reordered(options : WriteOption = WriteOption::None) : String #

Generates the visually reordered string based on the processed text.

  • options: WriteOption flags to control mirroring, mark insertion/removal, etc. Defaults to WriteOption::None.
  • Returns the reordered string.

[View source]