///|
fn markdown_editor_complete_code_fence_on_enter(
chars : Array[Char],
range : MarkdownSourceRange,
line : String,
caret : Int,
) -> RichTextInputTransform? {
if caret != range.end {
return None
}
let fence = match markdown_editor_opening_code_fence_marker(line) {
Some(fence) => fence.marker
None => return None
}
let indent = markdown_editor_line_indent_prefix(line)
let insert = "\n" + indent + "\n" + indent + fence
let text = String::from_array(chars[:caret]) +
insert +
String::from_array(chars[caret:])
Some(
markdown_editor_transform_result(
text~,
caret=caret + 1 + markdown_editor_text_length(indent),
),
)
}
///|
fn markdown_editor_complete_quoted_code_fence_on_enter(
chars : Array[Char],
range : MarkdownSourceRange,
line : String,
caret : Int,
) -> RichTextInputTransform? {
if caret != range.end {
return None
}
let nested = match markdown_editor_quoted_code_nested_text(line) {
Some(nested) => nested
None => return None
}
let fence = match markdown_editor_opening_code_fence_marker(nested) {
Some(fence) => fence.marker
None => return None
}
let content_prefix = match markdown_editor_quoted_code_content_prefix(line) {
Some(prefix) => prefix
None => return None
}
let insert = "\n" + content_prefix + "\n" + content_prefix + fence
let text = String::from_array(chars[:caret]) +
insert +
String::from_array(chars[caret:])
Some(
markdown_editor_transform_result(
text~,
caret=caret + 1 + markdown_editor_text_length(content_prefix),
),
)
}
///|
fn markdown_editor_exit_empty_code_block_on_enter(
source : String,
block : MarkdownEditorBlock,
caret : Int,
) -> RichTextInputTransform? {
let chars = source.to_array()
let caret = markdown_editor_clamp_int(caret, 0, chars.length())
let current_line = markdown_editor_current_line_range(source, {
caret,
selection: None,
})
let line = String::from_array(chars[current_line.start:current_line.end])
if line.trim().to_owned() != "" {
return None
}
if current_line.start < block.content_range.start ||
current_line.end > block.content_range.end {
return None
}
let opening_line_end = markdown_editor_next_line_end(
chars,
block.source_range.start,
)
let opening_line = String::from_array(
chars[block.source_range.start:opening_line_end],
)
let fence = match markdown_editor_opening_code_fence_marker(opening_line) {
Some(fence) => fence.marker
None => return None
}
let closing_start = current_line.end + 1
if closing_start >= chars.length() || closing_start > block.source_range.end {
return None
}
let closing_end = markdown_editor_next_line_end(chars, closing_start)
let closing_line = String::from_array(chars[closing_start:closing_end])
if !markdown_editor_closing_code_fence(closing_line, fence) {
return None
}
let exit_indent = markdown_editor_line_indent_prefix(closing_line)
if closing_end >= chars.length() {
let insert = "\n" + exit_indent
Some(
markdown_editor_transform_result(
text=source + insert,
caret=closing_end + markdown_editor_text_length(insert),
),
)
} else {
let after_close = closing_end + 1
if after_close >= chars.length() {
if exit_indent == "" {
Some(markdown_editor_transform_result(text=source, caret=after_close))
} else {
Some(
markdown_editor_transform_result(
text=source + exit_indent,
caret=after_close + markdown_editor_text_length(exit_indent),
),
)
}
} else {
let insert = exit_indent + "\n"
Some(
markdown_editor_transform_result(
text=String::from_array(chars[:after_close]) +
insert +
String::from_array(chars[after_close:]),
caret=after_close + markdown_editor_text_length(exit_indent),
),
)
}
}
}
///|
fn markdown_editor_quoted_code_block_at_content_offset(
source : String,
caret : Int,
selection : @core.TextRange?,
) -> MarkdownEditorQuotedCodeBlock? {
if markdown_editor_active_selection(selection) is Some(_) {
return None
}
let caret = markdown_editor_clamp_int(
caret,
0,
markdown_editor_text_length(source),
)
match
markdown_editor_containing_quoted_code_block(
source,
({ caret, selection } : MarkdownEditorSelection),
) {
Some(block) =>
if caret >= block.content_range.start && caret <= block.content_range.end {
Some(block)
} else {
None
}
None => None
}
}
///|
fn markdown_editor_any_code_block_at_content_offset(
source : String,
caret : Int,
selection : @core.TextRange?,
) -> Bool {
markdown_editor_code_block_at_content_offset(source, caret, selection)
is Some(_) ||
markdown_editor_quoted_code_block_at_content_offset(source, caret, selection)
is Some(_)
}
///|
fn markdown_editor_exit_empty_quoted_code_block_on_enter(
source : String,
block : MarkdownEditorQuotedCodeBlock,
caret : Int,
) -> RichTextInputTransform? {
let chars = source.to_array()
let caret = markdown_editor_clamp_int(caret, 0, chars.length())
let current_line = markdown_editor_current_line_range(source, {
caret,
selection: None,
})
let line = String::from_array(chars[current_line.start:current_line.end])
let nested = match markdown_editor_quoted_code_nested_text(line) {
Some(nested) => nested
None => return None
}
if nested.trim().to_owned() != "" {
return None
}
if current_line.start < block.content_range.start ||
current_line.end > block.content_range.end {
return None
}
let opening_line_end = markdown_editor_next_line_end(
chars,
block.source_range.start,
)
let opening_line = String::from_array(
chars[block.source_range.start:opening_line_end],
)
let opening = match markdown_editor_quoted_code_fence_opening(opening_line) {
Some(opening) => opening
None => return None
}
let closing_start = current_line.end + 1
if closing_start >= chars.length() || closing_start > block.source_range.end {
return None
}
let closing_end = markdown_editor_next_line_end(chars, closing_start)
let closing_line = String::from_array(chars[closing_start:closing_end])
if !markdown_editor_quoted_code_fence_closing(closing_line, opening) {
return None
}
let exit_indent = match
markdown_editor_quoted_code_content_prefix(closing_line) {
Some(prefix) => prefix
None => opening.quote_prefix
}
if closing_end >= chars.length() {
let insert = "\n" + exit_indent
Some(
markdown_editor_transform_result(
text=source + insert,
caret=closing_end + markdown_editor_text_length(insert),
),
)
} else {
let after_close = closing_end + 1
if after_close >= chars.length() {
Some(
markdown_editor_transform_result(
text=source + exit_indent,
caret=after_close + markdown_editor_text_length(exit_indent),
),
)
} else {
let insert = exit_indent + "\n"
Some(
markdown_editor_transform_result(
text=String::from_array(chars[:after_close]) +
insert +
String::from_array(chars[after_close:]),
caret=after_close + markdown_editor_text_length(exit_indent),
),
)
}
}
}
///|
fn markdown_editor_quoted_code_block_enter(
source : String,
block : MarkdownEditorQuotedCodeBlock,
caret : Int,
) -> RichTextInputTransform {
let chars = source.to_array()
let caret = markdown_editor_clamp_int(caret, 0, chars.length())
let current_line = markdown_editor_current_line_range(source, {
caret,
selection: None,
})
let line = String::from_array(chars[current_line.start:current_line.end])
let prefix = match markdown_editor_quoted_code_content_prefix(line) {
Some(prefix) => prefix
None =>
markdown_editor_quoted_code_block_opening_content_prefix(source, block)
}
let insert = "\n" + prefix
markdown_editor_transform_result(
text=String::from_array(chars[:caret]) +
insert +
String::from_array(chars[caret:]),
caret=caret + markdown_editor_text_length(insert),
)
}
///|
fn markdown_editor_quoted_code_block_opening_content_prefix(
source : String,
block : MarkdownEditorQuotedCodeBlock,
) -> String {
let chars = source.to_array()
let opening_line_end = markdown_editor_next_line_end(
chars,
block.source_range.start,
)
let opening_line = String::from_array(
chars[block.source_range.start:opening_line_end],
)
match markdown_editor_quoted_code_content_prefix(opening_line) {
Some(prefix) => prefix
None => ""
}
}
///|
fn markdown_editor_quoted_code_nested_text(line : String) -> String? {
let quote_prefix = markdown_editor_quote_context_prefix(line)
if quote_prefix == "" {
return None
}
Some(
markdown_editor_substring(
line,
markdown_editor_text_length(quote_prefix),
markdown_editor_text_length(line),
),
)
}
///|
fn markdown_editor_quoted_code_content_prefix(line : String) -> String? {
let quote_prefix = markdown_editor_quote_context_prefix(line)
if quote_prefix == "" {
return None
}
let nested = markdown_editor_substring(
line,
markdown_editor_text_length(quote_prefix),
markdown_editor_text_length(line),
)
Some(quote_prefix + markdown_editor_line_indent_prefix(nested))
}
///|
fn markdown_editor_opening_code_fence_marker(
line : String,
) -> MarkdownCodeFenceInfo? {
let chars = line.to_array()
let indent = markdown_editor_leading_indent_length(chars)
if !markdown_editor_code_fence_indent_allowed(chars, indent) ||
chars.length() < indent + 3 {
return None
}
let fence_char = chars[indent]
if (fence_char != '`' && fence_char != '~') ||
chars[indent + 1] != fence_char ||
chars[indent + 2] != fence_char {
return None
}
let mut fence_end = indent + 3
while fence_end < chars.length() && chars[fence_end] == fence_char {
fence_end = fence_end + 1
}
for index in fence_end.. Bool {
if indent > 3 {
return false
}
for index in 0.. MarkdownBlock {
{
kind: MarkdownBlockKind::CodeBlock,
text,
inlines: [],
table_alignments: [],
code_language,
}
}
///|
fn markdown_editor_line_indent_prefix(line : String) -> String {
let chars = line.to_array()
let indent = markdown_editor_leading_indent_length(chars)
String::from_array(chars[:indent])
}