mirror of
https://github.com/zed-industries/zed.git
synced 2024-11-08 07:35:01 +03:00
Add docs to marked range functions
This commit is contained in:
parent
26fdaeb92b
commit
dc0a96c084
@ -1,5 +1,7 @@
|
||||
use std::{cmp::Ordering, collections::HashMap, ops::Range};
|
||||
|
||||
/// Construct a string and a list of offsets within that string using a single
|
||||
/// string containing embedded position markers.
|
||||
pub fn marked_text_offsets_by(
|
||||
marked_text: &str,
|
||||
markers: Vec<char>,
|
||||
@ -19,6 +21,12 @@ pub fn marked_text_offsets_by(
|
||||
(unmarked_text, extracted_markers)
|
||||
}
|
||||
|
||||
/// Construct a string and a list of ranges within that string using a single
|
||||
/// string containing embedded range markers, using arbitrary characters as
|
||||
/// range markers. By using multiple different range markers, you can construct
|
||||
/// ranges that overlap each other.
|
||||
///
|
||||
/// The returned ranges will be grouped by their range marking characters.
|
||||
pub fn marked_text_ranges_by(
|
||||
marked_text: &str,
|
||||
markers: Vec<TextRangeMarker>,
|
||||
@ -72,67 +80,94 @@ pub fn marked_text_ranges_by(
|
||||
(unmarked_text, range_lookup)
|
||||
}
|
||||
|
||||
pub fn marked_text_ranges(input_text: &str, indicate_cursors: bool) -> (String, Vec<Range<usize>>) {
|
||||
let mut output_text = String::with_capacity(input_text.len());
|
||||
/// Construct a string and a list of ranges within that string using a single
|
||||
/// string containing embedded range markers. The characters used to mark the
|
||||
/// ranges are as follows:
|
||||
///
|
||||
/// 1. To mark a range of text, surround it with the `«` and `»` angle brackets,
|
||||
/// which can be typed on a US keyboard with the `alt-|` and `alt-shift-|` keys.
|
||||
///
|
||||
/// ```
|
||||
/// foo «selected text» bar
|
||||
/// ```
|
||||
///
|
||||
/// 2. To mark a single position in the text, use the `ˇ` caron,
|
||||
/// which can be typed on a US keyboard with the `alt-shift-t` key.
|
||||
///
|
||||
/// ```
|
||||
/// the cursors are hereˇ and hereˇ.
|
||||
/// ```
|
||||
///
|
||||
/// 3. To mark a range whose direction is meaningful (like a selection),
|
||||
/// put a caron character beside one of its bounds, on the inside:
|
||||
///
|
||||
/// ```
|
||||
/// one «ˇreversed» selection and one «forwardˇ» selection
|
||||
/// ```
|
||||
pub fn marked_text_ranges(
|
||||
marked_text: &str,
|
||||
ranges_are_directed: bool,
|
||||
) -> (String, Vec<Range<usize>>) {
|
||||
let mut unmarked_text = String::with_capacity(marked_text.len());
|
||||
let mut ranges = Vec::new();
|
||||
let mut prev_input_ix = 0;
|
||||
let mut prev_marked_ix = 0;
|
||||
let mut current_range_start = None;
|
||||
let mut current_range_cursor = None;
|
||||
|
||||
for (input_ix, marker) in input_text.match_indices(&['«', '»', 'ˇ']) {
|
||||
output_text.push_str(&input_text[prev_input_ix..input_ix]);
|
||||
let output_len = output_text.len();
|
||||
for (marked_ix, marker) in marked_text.match_indices(&['«', '»', 'ˇ']) {
|
||||
unmarked_text.push_str(&marked_text[prev_marked_ix..marked_ix]);
|
||||
let unmarked_len = unmarked_text.len();
|
||||
let len = marker.len();
|
||||
prev_input_ix = input_ix + len;
|
||||
prev_marked_ix = marked_ix + len;
|
||||
|
||||
match marker {
|
||||
"ˇ" => {
|
||||
if current_range_start.is_some() {
|
||||
if current_range_cursor.is_some() {
|
||||
panic!("duplicate point marker 'ˇ' at index {input_ix}");
|
||||
panic!("duplicate point marker 'ˇ' at index {marked_ix}");
|
||||
} else {
|
||||
current_range_cursor = Some(output_len);
|
||||
current_range_cursor = Some(unmarked_len);
|
||||
}
|
||||
} else {
|
||||
ranges.push(output_len..output_len);
|
||||
ranges.push(unmarked_len..unmarked_len);
|
||||
}
|
||||
}
|
||||
"«" => {
|
||||
if current_range_start.is_some() {
|
||||
panic!("unexpected range start marker '«' at index {input_ix}");
|
||||
panic!("unexpected range start marker '«' at index {marked_ix}");
|
||||
}
|
||||
current_range_start = Some(output_len);
|
||||
current_range_start = Some(unmarked_len);
|
||||
}
|
||||
"»" => {
|
||||
let current_range_start = if let Some(start) = current_range_start.take() {
|
||||
start
|
||||
} else {
|
||||
panic!("unexpected range end marker '»' at index {input_ix}");
|
||||
panic!("unexpected range end marker '»' at index {marked_ix}");
|
||||
};
|
||||
|
||||
let mut reversed = false;
|
||||
if let Some(current_range_cursor) = current_range_cursor.take() {
|
||||
if current_range_cursor == current_range_start {
|
||||
reversed = true;
|
||||
} else if current_range_cursor != output_len {
|
||||
} else if current_range_cursor != unmarked_len {
|
||||
panic!("unexpected 'ˇ' marker in the middle of a range");
|
||||
}
|
||||
} else if indicate_cursors {
|
||||
} else if ranges_are_directed {
|
||||
panic!("missing 'ˇ' marker to indicate range direction");
|
||||
}
|
||||
|
||||
ranges.push(if reversed {
|
||||
output_len..current_range_start
|
||||
unmarked_len..current_range_start
|
||||
} else {
|
||||
current_range_start..output_len
|
||||
current_range_start..unmarked_len
|
||||
});
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
output_text.push_str(&input_text[prev_input_ix..]);
|
||||
(output_text, ranges)
|
||||
unmarked_text.push_str(&marked_text[prev_marked_ix..]);
|
||||
(unmarked_text, ranges)
|
||||
}
|
||||
|
||||
pub fn marked_text_offsets(marked_text: &str) -> (String, Vec<usize>) {
|
||||
@ -150,11 +185,11 @@ pub fn marked_text_offsets(marked_text: &str) -> (String, Vec<usize>) {
|
||||
}
|
||||
|
||||
pub fn generate_marked_text(
|
||||
output_text: &str,
|
||||
unmarked_text: &str,
|
||||
ranges: &[Range<usize>],
|
||||
indicate_cursors: bool,
|
||||
) -> String {
|
||||
let mut marked_text = output_text.to_string();
|
||||
let mut marked_text = unmarked_text.to_string();
|
||||
for range in ranges.iter().rev() {
|
||||
if indicate_cursors {
|
||||
match range.start.cmp(&range.end) {
|
||||
|
Loading…
Reference in New Issue
Block a user