///|
fn matrix_column_count(body : Array[Array[ParseNode]]) -> Int {
let mut count = 0
for row in body {
if row.length() > count {
count = row.length()
}
}
count
}
///|
fn matrix_columns(count : Int, alignment : String) -> Array[ArrayColumn] {
Array::make(count, AlignColumn(alignment~, pre_gap=0.0, post_gap=0.0))
}
///|
fn array_with_columns(
node : ParseNode,
columns : Array[ArrayColumn],
) -> ParseNode raise ParseFailure {
match node {
Array(
mode~,
body~,
add_jot~,
array_stretch~,
row_gaps~,
hskip_before_and_after~,
hlines_before_row~,
column_separation_type~,
tags~,
auto_tags~,
leqno~,
..
) =>
Array(
mode~,
body~,
add_jot~,
array_stretch~,
columns=Some(columns),
row_gaps~,
hskip_before_and_after~,
hlines_before_row~,
column_separation_type~,
tags~,
auto_tags~,
leqno~,
)
_ => raise InternalInvariant(message="Expected matrix array")
}
}
///|
fn matrix_delimiters(name : String) -> (String, String)? {
match name {
"matrix" => None
"pmatrix" => Some(("(", ")"))
"bmatrix" => Some(("[", "]"))
"Bmatrix" => Some(("\\{", "\\}"))
"vmatrix" => Some(("|", "|"))
"Vmatrix" => Some(("\\Vert", "\\Vert"))
_ => None
}
}
///|
fn matrix_environment_handler(
context : EnvironmentContext,
_ : Array[ParseNode],
_ : Array[ParseNode?],
) -> ParseNode raise ParseFailure {
let starred = context.env_name.length() > 0 &&
context.env_name[context.env_name.length() - 1] == '*'
let base_name = if starred {
context.env_name.unsafe_substring(
start=0,
end=context.env_name.length() - 1,
)
} else {
context.env_name
}
let requested_alignment = if starred {
(context.parse_matrix_alignment)()
} else {
None
}
let alignment = requested_alignment.unwrap_or("c")
let array = (context.parse_array)({
columns: None,
array_stretch: 1.0,
hskip_before_and_after: false,
cell_style: TextStyle,
max_columns: None,
single_row: false,
auto_tag: None,
leqno: false,
add_jot: false,
column_separation_type: None,
})
let array = match array {
Array(body~, ..) =>
array_with_columns(
array,
matrix_columns(matrix_column_count(body), alignment),
)
_ => raise InternalInvariant(message="Expected matrix array")
}
matrix_delimiters(base_name).map_or(array, value => {
let (left, right) = value
LeftRight(mode=context.mode, body=[array], left~, right~, right_color=None)
})
}
///|
fn smallmatrix_environment_handler(
context : EnvironmentContext,
_ : Array[ParseNode],
_ : Array[ParseNode?],
) -> ParseNode raise ParseFailure {
let array = (context.parse_array)({
columns: None,
array_stretch: 0.5,
hskip_before_and_after: false,
cell_style: ScriptStyle,
max_columns: None,
single_row: false,
auto_tag: None,
leqno: false,
add_jot: false,
column_separation_type: Some(SmallSeparation),
})
match array {
Array(body~, ..) =>
array_with_columns(array, matrix_columns(matrix_column_count(body), "c"))
_ => raise InternalInvariant(message="Expected smallmatrix array")
}
}