Detailed changes
@@ -15,7 +15,7 @@ use gpui::{
color::Color,
fonts::{FontId, HighlightStyle, Underline},
text_layout::{Line, RunStyle},
- AppContext, Entity, FontCache, ModelContext, ModelHandle, TextLayoutCache,
+ Entity, ModelContext, ModelHandle,
};
use inlay_map::InlayMap;
use language::{
@@ -576,7 +576,6 @@ impl DisplaySnapshot {
let range = display_row..display_row + 1;
for chunk in self.highlighted_chunks(range, editor_style) {
- dbg!(chunk.chunk);
line.push_str(chunk.chunk);
let text_style = if let Some(style) = chunk.style {
@@ -600,7 +599,6 @@ impl DisplaySnapshot {
));
}
- dbg!(&line, &editor_style.text.font_size, &styles);
text_layout_cache.layout_str(&line, editor_style.text.font_size, &styles)
}
@@ -623,49 +621,6 @@ impl DisplaySnapshot {
layout_line.closest_index_for_x(x_coordinate) as u32
}
- // column_for_x(row, x)
-
- fn point(
- &self,
- display_point: DisplayPoint,
- text_layout_cache: &TextLayoutCache,
- editor_style: &EditorStyle,
- cx: &AppContext,
- ) -> f32 {
- let mut styles = Vec::new();
- let mut line = String::new();
-
- let range = display_point.row()..display_point.row() + 1;
- for chunk in self.highlighted_chunks(range, editor_style) {
- dbg!(chunk.chunk);
- line.push_str(chunk.chunk);
-
- let text_style = if let Some(style) = chunk.style {
- editor_style
- .text
- .clone()
- .highlight(style, cx.font_cache())
- .map(Cow::Owned)
- .unwrap_or_else(|_| Cow::Borrowed(&editor_style.text))
- } else {
- Cow::Borrowed(&editor_style.text)
- };
-
- styles.push((
- chunk.chunk.len(),
- RunStyle {
- font_id: text_style.font_id,
- color: text_style.color,
- underline: text_style.underline,
- },
- ));
- }
-
- dbg!(&line, &editor_style.text.font_size, &styles);
- let layout_line = text_layout_cache.layout_str(&line, editor_style.text.font_size, &styles);
- layout_line.x_for_index(display_point.column() as usize)
- }
-
pub fn chars_at(
&self,
mut point: DisplayPoint,
@@ -1374,7 +1329,6 @@ pub mod tests {
);
let x = snapshot.x_for_point(DisplayPoint::new(1, 10), &text_layout_details);
- dbg!(x);
assert_eq!(
movement::up(
&snapshot,
@@ -1401,7 +1355,6 @@ pub mod tests {
SelectionGoal::HorizontalPosition(x)
)
);
- dbg!("starting down...");
assert_eq!(
movement::down(
&snapshot,
@@ -48,9 +48,9 @@ use gpui::{
impl_actions,
keymap_matcher::KeymapContext,
platform::{CursorStyle, MouseButton},
- serde_json, text_layout, AnyElement, AnyViewHandle, AppContext, AsyncAppContext, ClipboardItem,
- Element, Entity, ModelHandle, Subscription, Task, View, ViewContext, ViewHandle,
- WeakViewHandle, WindowContext,
+ serde_json, AnyElement, AnyViewHandle, AppContext, AsyncAppContext, ClipboardItem, Element,
+ Entity, ModelHandle, Subscription, Task, View, ViewContext, ViewHandle, WeakViewHandle,
+ WindowContext,
};
use highlight_matching_bracket::refresh_matching_bracket_highlights;
use hover_popover::{hide_hover, HoverState};
@@ -5953,11 +5953,14 @@ impl Editor {
fn add_selection(&mut self, above: bool, cx: &mut ViewContext<Self>) {
let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
let mut selections = self.selections.all::<Point>(cx);
+ let text_layout_details = TextLayoutDetails::new(self, cx);
let mut state = self.add_selections_state.take().unwrap_or_else(|| {
let oldest_selection = selections.iter().min_by_key(|s| s.id).unwrap().clone();
let range = oldest_selection.display_range(&display_map).sorted();
- let columns = cmp::min(range.start.column(), range.end.column())
- ..cmp::max(range.start.column(), range.end.column());
+
+ let start_x = display_map.x_for_point(range.start, &text_layout_details);
+ let end_x = display_map.x_for_point(range.end, &text_layout_details);
+ let positions = start_x.min(end_x)..start_x.max(end_x);
selections.clear();
let mut stack = Vec::new();
@@ -5965,8 +5968,9 @@ impl Editor {
if let Some(selection) = self.selections.build_columnar_selection(
&display_map,
row,
- &columns,
+ &positions,
oldest_selection.reversed,
+ &text_layout_details,
) {
stack.push(selection.id);
selections.push(selection);
@@ -5994,12 +5998,15 @@ impl Editor {
let range = selection.display_range(&display_map).sorted();
debug_assert_eq!(range.start.row(), range.end.row());
let mut row = range.start.row();
- let columns = if let SelectionGoal::ColumnRange { start, end } = selection.goal
+ let positions = if let SelectionGoal::HorizontalRange { start, end } =
+ selection.goal
{
start..end
} else {
- cmp::min(range.start.column(), range.end.column())
- ..cmp::max(range.start.column(), range.end.column())
+ let start_x = display_map.x_for_point(range.start, &text_layout_details);
+ let end_x = display_map.x_for_point(range.end, &text_layout_details);
+
+ start_x.min(end_x)..start_x.max(end_x)
};
while row != end_row {
@@ -6012,8 +6019,9 @@ impl Editor {
if let Some(new_selection) = self.selections.build_columnar_selection(
&display_map,
row,
- &columns,
+ &positions,
selection.reversed,
+ &text_layout_details,
) {
state.stack.push(new_selection.id);
if above {
@@ -22,7 +22,7 @@ use git::diff::DiffHunkStatus;
use gpui::{
color::Color,
elements::*,
- fonts::{HighlightStyle, TextStyle, Underline},
+ fonts::TextStyle,
geometry::{
rect::RectF,
vector::{vec2f, Vector2F},
@@ -37,8 +37,7 @@ use gpui::{
use itertools::Itertools;
use json::json;
use language::{
- language_settings::ShowWhitespaceSetting, Bias, CursorShape, DiagnosticSeverity, OffsetUtf16,
- Selection,
+ language_settings::ShowWhitespaceSetting, Bias, CursorShape, OffsetUtf16, Selection,
};
use project::{
project_settings::{GitGutterSetting, ProjectSettings},
@@ -1,6 +1,6 @@
use super::{Bias, DisplayPoint, DisplaySnapshot, SelectionGoal, ToDisplayPoint};
use crate::{char_kind, CharKind, Editor, EditorStyle, ToOffset, ToPoint};
-use gpui::{text_layout, FontCache, TextLayoutCache, WindowContext};
+use gpui::{FontCache, TextLayoutCache, WindowContext};
use language::Point;
use std::{ops::Range, sync::Arc};
@@ -105,7 +105,9 @@ pub fn up_by_rows(
) -> (DisplayPoint, SelectionGoal) {
let mut goal_x = match goal {
SelectionGoal::HorizontalPosition(x) => x,
+ SelectionGoal::WrappedHorizontalPosition((_, x)) => x,
SelectionGoal::HorizontalRange { end, .. } => end,
+ SelectionGoal::WrappedHorizontalRange { end: (_, end), .. } => end,
_ => map.x_for_point(start, text_layout_details),
};
@@ -140,7 +142,9 @@ pub fn down_by_rows(
) -> (DisplayPoint, SelectionGoal) {
let mut goal_x = match goal {
SelectionGoal::HorizontalPosition(x) => x,
+ SelectionGoal::WrappedHorizontalPosition((_, x)) => x,
SelectionGoal::HorizontalRange { end, .. } => end,
+ SelectionGoal::WrappedHorizontalRange { end: (_, end), .. } => end,
_ => map.x_for_point(start, text_layout_details),
};
@@ -1,6 +1,6 @@
use std::{
cell::Ref,
- cmp, iter, mem,
+ iter, mem,
ops::{Deref, DerefMut, Range, Sub},
sync::Arc,
};
@@ -13,6 +13,7 @@ use util::post_inc;
use crate::{
display_map::{DisplayMap, DisplaySnapshot, ToDisplayPoint},
+ movement::TextLayoutDetails,
Anchor, DisplayPoint, ExcerptId, MultiBuffer, MultiBufferSnapshot, SelectMode, ToOffset,
};
@@ -305,23 +306,27 @@ impl SelectionsCollection {
&mut self,
display_map: &DisplaySnapshot,
row: u32,
- columns: &Range<u32>,
+ positions: &Range<f32>,
reversed: bool,
+ text_layout_details: &TextLayoutDetails,
) -> Option<Selection<Point>> {
- let is_empty = columns.start == columns.end;
+ let is_empty = positions.start == positions.end;
let line_len = display_map.line_len(row);
- if columns.start < line_len || (is_empty && columns.start == line_len) {
- let start = DisplayPoint::new(row, columns.start);
- let end = DisplayPoint::new(row, cmp::min(columns.end, line_len));
+
+ let start_col = display_map.column_for_x(row, positions.start, text_layout_details);
+ if start_col < line_len || (is_empty && start_col == line_len) {
+ let start = DisplayPoint::new(row, start_col);
+ let end_col = display_map.column_for_x(row, positions.end, text_layout_details);
+ let end = DisplayPoint::new(row, end_col);
Some(Selection {
id: post_inc(&mut self.next_selection_id),
start: start.to_point(display_map),
end: end.to_point(display_map),
reversed,
- goal: SelectionGoal::ColumnRange {
- start: columns.start,
- end: columns.end,
+ goal: SelectionGoal::HorizontalRange {
+ start: positions.start,
+ end: positions.end,
},
})
} else {
@@ -7,8 +7,8 @@ pub enum SelectionGoal {
None,
HorizontalPosition(f32),
HorizontalRange { start: f32, end: f32 },
- Column(u32),
- ColumnRange { start: u32, end: u32 },
+ WrappedHorizontalPosition((u32, f32)),
+ WrappedHorizontalRange { start: (u32, f32), end: (u32, f32) },
}
#[derive(Clone, Debug, PartialEq)]
@@ -1,5 +1,3 @@
-use std::cmp;
-
use editor::{
char_kind,
display_map::{DisplaySnapshot, FoldPoint, ToDisplayPoint},
@@ -371,13 +369,13 @@ impl Motion {
Backspace => (backspace(map, point, times), SelectionGoal::None),
Down {
display_lines: false,
- } => down(map, point, goal, times),
+ } => up_down_buffer_rows(map, point, goal, times as isize, &text_layout_details),
Down {
display_lines: true,
} => down_display(map, point, goal, times, &text_layout_details),
Up {
display_lines: false,
- } => up(map, point, goal, times),
+ } => up_down_buffer_rows(map, point, goal, 0 - times as isize, &text_layout_details),
Up {
display_lines: true,
} => up_display(map, point, goal, times, &text_layout_details),
@@ -536,35 +534,86 @@ fn backspace(map: &DisplaySnapshot, mut point: DisplayPoint, times: usize) -> Di
point
}
-fn down(
+pub(crate) fn start_of_relative_buffer_row(
+ map: &DisplaySnapshot,
+ point: DisplayPoint,
+ times: isize,
+) -> DisplayPoint {
+ let start = map.display_point_to_fold_point(point, Bias::Left);
+ let target = start.row() as isize + times;
+ let new_row = (target.max(0) as u32).min(map.fold_snapshot.max_point().row());
+
+ map.clip_point(
+ map.fold_point_to_display_point(
+ map.fold_snapshot
+ .clip_point(FoldPoint::new(new_row, 0), Bias::Right),
+ ),
+ Bias::Right,
+ )
+}
+
+fn up_down_buffer_rows(
map: &DisplaySnapshot,
point: DisplayPoint,
mut goal: SelectionGoal,
- times: usize,
+ times: isize,
+ text_layout_details: &TextLayoutDetails,
) -> (DisplayPoint, SelectionGoal) {
let start = map.display_point_to_fold_point(point, Bias::Left);
+ let begin_folded_line = map.fold_point_to_display_point(
+ map.fold_snapshot
+ .clip_point(FoldPoint::new(start.row(), 0), Bias::Left),
+ );
+ let select_nth_wrapped_row = point.row() - begin_folded_line.row();
- let goal_column = match goal {
- SelectionGoal::Column(column) => column,
- SelectionGoal::ColumnRange { end, .. } => end,
+ let (goal_wrap, goal_x) = match goal {
+ SelectionGoal::WrappedHorizontalPosition((row, x)) => (row, x),
+ SelectionGoal::WrappedHorizontalRange { end: (row, x), .. } => (row, x),
+ SelectionGoal::HorizontalRange { end, .. } => (select_nth_wrapped_row, end),
+ SelectionGoal::HorizontalPosition(x) => (select_nth_wrapped_row, x),
_ => {
- goal = SelectionGoal::Column(start.column());
- start.column()
+ let x = map.x_for_point(point, text_layout_details);
+ goal = SelectionGoal::WrappedHorizontalPosition((select_nth_wrapped_row, x));
+ (select_nth_wrapped_row, x)
}
};
- let new_row = cmp::min(
- start.row() + times as u32,
- map.fold_snapshot.max_point().row(),
- );
- let new_col = cmp::min(goal_column, map.fold_snapshot.line_len(new_row));
- let point = map.fold_point_to_display_point(
+ let target = start.row() as isize + times;
+ let new_row = (target.max(0) as u32).min(map.fold_snapshot.max_point().row());
+
+ let mut begin_folded_line = map.fold_point_to_display_point(
map.fold_snapshot
- .clip_point(FoldPoint::new(new_row, new_col), Bias::Left),
+ .clip_point(FoldPoint::new(new_row, 0), Bias::Left),
);
- // clip twice to "clip at end of line"
- (map.clip_point(point, Bias::Left), goal)
+ let mut i = 0;
+ while i < goal_wrap && begin_folded_line.row() < map.max_point().row() {
+ let next_folded_line = DisplayPoint::new(begin_folded_line.row() + 1, 0);
+ if map
+ .display_point_to_fold_point(next_folded_line, Bias::Right)
+ .row()
+ == new_row
+ {
+ i += 1;
+ begin_folded_line = next_folded_line;
+ } else {
+ break;
+ }
+ }
+
+ let new_col = if i == goal_wrap {
+ map.column_for_x(begin_folded_line.row(), goal_x, text_layout_details)
+ } else {
+ map.line_len(begin_folded_line.row())
+ };
+
+ (
+ map.clip_point(
+ DisplayPoint::new(begin_folded_line.row(), new_col),
+ Bias::Left,
+ ),
+ goal,
+ )
}
fn down_display(
@@ -581,33 +630,6 @@ fn down_display(
(point, goal)
}
-pub(crate) fn up(
- map: &DisplaySnapshot,
- point: DisplayPoint,
- mut goal: SelectionGoal,
- times: usize,
-) -> (DisplayPoint, SelectionGoal) {
- let start = map.display_point_to_fold_point(point, Bias::Left);
-
- let goal_column = match goal {
- SelectionGoal::Column(column) => column,
- SelectionGoal::ColumnRange { end, .. } => end,
- _ => {
- goal = SelectionGoal::Column(start.column());
- start.column()
- }
- };
-
- let new_row = start.row().saturating_sub(times as u32);
- let new_col = cmp::min(goal_column, map.fold_snapshot.line_len(new_row));
- let point = map.fold_point_to_display_point(
- map.fold_snapshot
- .clip_point(FoldPoint::new(new_row, new_col), Bias::Left),
- );
-
- (map.clip_point(point, Bias::Left), goal)
-}
-
fn up_display(
map: &DisplaySnapshot,
mut point: DisplayPoint,
@@ -894,7 +916,7 @@ fn find_backward(
}
fn next_line_start(map: &DisplaySnapshot, point: DisplayPoint, times: usize) -> DisplayPoint {
- let correct_line = down(map, point, SelectionGoal::None, times).0;
+ let correct_line = start_of_relative_buffer_row(map, point, times as isize);
first_non_whitespace(map, false, correct_line)
}
@@ -904,7 +926,7 @@ pub(crate) fn next_line_end(
times: usize,
) -> DisplayPoint {
if times > 1 {
- point = down(map, point, SelectionGoal::None, times - 1).0;
+ point = start_of_relative_buffer_row(map, point, times as isize - 1);
}
end_of_line(map, false, point)
}
@@ -194,9 +194,7 @@ fn insert_after(_: &mut Workspace, _: &InsertAfter, cx: &mut ViewContext<Workspa
vim.switch_mode(Mode::Insert, false, cx);
vim.update_active_editor(cx, |editor, cx| {
editor.change_selections(Some(Autoscroll::fit()), cx, |s| {
- s.move_cursors_with(|map, cursor, goal| {
- (right(map, cursor, 1), SelectionGoal::None)
- });
+ s.move_cursors_with(|map, cursor, _| (right(map, cursor, 1), SelectionGoal::None));
});
});
});
@@ -219,7 +217,7 @@ fn insert_first_non_whitespace(
vim.switch_mode(Mode::Insert, false, cx);
vim.update_active_editor(cx, |editor, cx| {
editor.change_selections(Some(Autoscroll::fit()), cx, |s| {
- s.move_cursors_with(|map, cursor, goal| {
+ s.move_cursors_with(|map, cursor, _| {
(
first_non_whitespace(map, false, cursor),
SelectionGoal::None,
@@ -236,7 +234,7 @@ fn insert_end_of_line(_: &mut Workspace, _: &InsertEndOfLine, cx: &mut ViewConte
vim.switch_mode(Mode::Insert, false, cx);
vim.update_active_editor(cx, |editor, cx| {
editor.change_selections(Some(Autoscroll::fit()), cx, |s| {
- s.move_cursors_with(|map, cursor, goal| {
+ s.move_cursors_with(|map, cursor, _| {
(next_line_end(map, cursor, 1), SelectionGoal::None)
});
});
@@ -267,7 +265,7 @@ fn insert_line_above(_: &mut Workspace, _: &InsertLineAbove, cx: &mut ViewContex
editor.edit_with_autoindent(edits, cx);
editor.change_selections(Some(Autoscroll::fit()), cx, |s| {
s.move_cursors_with(|map, cursor, _| {
- let previous_line = motion::up(map, cursor, SelectionGoal::None, 1).0;
+ let previous_line = motion::start_of_relative_buffer_row(map, cursor, -1);
let insert_point = motion::end_of_line(map, false, previous_line);
(insert_point, SelectionGoal::None)
});
@@ -398,12 +396,26 @@ mod test {
#[gpui::test]
async fn test_j(cx: &mut gpui::TestAppContext) {
- let mut cx = NeovimBackedTestContext::new(cx).await.binding(["j"]);
- cx.assert_all(indoc! {"
- ΛThe qΛuick broΛwn
- Λfox jumps"
+ let mut cx = NeovimBackedTestContext::new(cx).await;
+
+ cx.set_shared_state(indoc! {"
+ aaΛaa
+ ππ"
+ })
+ .await;
+ cx.simulate_shared_keystrokes(["j"]).await;
+ cx.assert_shared_state(indoc! {"
+ aaaa
+ πΛπ"
})
.await;
+
+ for marked_position in cx.each_marked_position(indoc! {"
+ ΛThe qΛuick broΛwn
+ Λfox jumps"
+ }) {
+ cx.assert_neovim_compatible(&marked_position, ["j"]).await;
+ }
}
#[gpui::test]
@@ -3,11 +3,7 @@ use gpui::{actions, AppContext, WindowContext};
use language::Point;
use workspace::Workspace;
-use crate::{
- motion::{right, Motion},
- utils::copy_selections_content,
- Mode, Vim,
-};
+use crate::{motion::Motion, utils::copy_selections_content, Mode, Vim};
actions!(vim, [Substitute, SubstituteLine]);
@@ -652,3 +652,59 @@ async fn test_selection_goal(cx: &mut gpui::TestAppContext) {
Lorem Ipsum"})
.await;
}
+
+async fn test_wrapped_motions(cx: &mut gpui::TestAppContext) {
+ let mut cx = NeovimBackedTestContext::new(cx).await;
+
+ cx.set_shared_wrap(12).await;
+
+ cx.set_shared_state(indoc! {"
+ aaΛaa
+ ππ"
+ })
+ .await;
+ cx.simulate_shared_keystrokes(["j"]).await;
+ cx.assert_shared_state(indoc! {"
+ aaaa
+ πΛπ"
+ })
+ .await;
+
+ cx.set_shared_state(indoc! {"
+ 123456789012aaΛaa
+ 123456789012ππ"
+ })
+ .await;
+ cx.simulate_shared_keystrokes(["j"]).await;
+ cx.assert_shared_state(indoc! {"
+ 123456789012aaaa
+ 123456789012πΛπ"
+ })
+ .await;
+
+ cx.set_shared_state(indoc! {"
+ 123456789012aaΛaa
+ 123456789012ππ"
+ })
+ .await;
+ cx.simulate_shared_keystrokes(["j"]).await;
+ cx.assert_shared_state(indoc! {"
+ 123456789012aaaa
+ 123456789012πΛπ"
+ })
+ .await;
+
+ cx.set_shared_state(indoc! {"
+ 123456789012aaaaΛaaaaaaaa123456789012
+ wow
+ 123456789012ππππππ123456789012"
+ })
+ .await;
+ cx.simulate_shared_keystrokes(["j", "j"]).await;
+ cx.assert_shared_state(indoc! {"
+ 123456789012aaaaaaaaaaaa123456789012
+ wow
+ 123456789012ππΛππππ123456789012"
+ })
+ .await;
+}
@@ -581,7 +581,7 @@ impl Setting for VimModeSetting {
fn local_selections_changed(newest: Selection<usize>, cx: &mut WindowContext) {
Vim::update(cx, |vim, cx| {
if vim.enabled && vim.state().mode == Mode::Normal && !newest.is_empty() {
- if matches!(newest.goal, SelectionGoal::ColumnRange { .. }) {
+ if matches!(newest.goal, SelectionGoal::HorizontalRange { .. }) {
vim.switch_mode(Mode::VisualBlock, false, cx);
} else {
vim.switch_mode(Mode::Visual, false, cx)
@@ -140,17 +140,21 @@ pub fn visual_block_motion(
SelectionGoal,
) -> Option<(DisplayPoint, SelectionGoal)>,
) {
+ let text_layout_details = TextLayoutDetails::new(editor, cx);
editor.change_selections(Some(Autoscroll::fit()), cx, |s| {
let map = &s.display_map();
let mut head = s.newest_anchor().head().to_display_point(map);
let mut tail = s.oldest_anchor().tail().to_display_point(map);
let (start, end) = match s.newest_anchor().goal {
- SelectionGoal::ColumnRange { start, end } if preserve_goal => (start, end),
- SelectionGoal::Column(start) if preserve_goal => (start, start + 1),
- _ => (tail.column(), head.column()),
+ SelectionGoal::HorizontalRange { start, end } if preserve_goal => (start, end),
+ SelectionGoal::HorizontalPosition(start) if preserve_goal => (start, start + 10.0),
+ _ => (
+ map.x_for_point(tail, &text_layout_details),
+ map.x_for_point(head, &text_layout_details),
+ ),
};
- let goal = SelectionGoal::ColumnRange { start, end };
+ let goal = SelectionGoal::HorizontalRange { start, end };
let was_reversed = tail.column() > head.column();
if !was_reversed && !preserve_goal {
@@ -172,21 +176,39 @@ pub fn visual_block_motion(
head = movement::saturating_right(map, head)
}
- let columns = if is_reversed {
- head.column()..tail.column()
+ let positions = if is_reversed {
+ map.x_for_point(head, &text_layout_details)..map.x_for_point(tail, &text_layout_details)
} else if head.column() == tail.column() {
- head.column()..(head.column() + 1)
+ map.x_for_point(head, &text_layout_details)
+ ..map.x_for_point(head, &text_layout_details) + 10.0
} else {
- tail.column()..head.column()
+ map.x_for_point(tail, &text_layout_details)..map.x_for_point(head, &text_layout_details)
};
let mut selections = Vec::new();
let mut row = tail.row();
loop {
- let start = map.clip_point(DisplayPoint::new(row, columns.start), Bias::Left);
- let end = map.clip_point(DisplayPoint::new(row, columns.end), Bias::Left);
- if columns.start <= map.line_len(row) {
+ let start = map.clip_point(
+ DisplayPoint::new(
+ row,
+ map.column_for_x(row, positions.start, &text_layout_details),
+ ),
+ Bias::Left,
+ );
+ let end = map.clip_point(
+ DisplayPoint::new(
+ row,
+ map.column_for_x(row, positions.end, &text_layout_details),
+ ),
+ Bias::Left,
+ );
+ if positions.start
+ <= map.x_for_point(
+ DisplayPoint::new(row, map.line_len(row)),
+ &text_layout_details,
+ )
+ {
let selection = Selection {
id: s.new_selection_id(),
start: start.to_point(map),
@@ -1,3 +1,6 @@
+{"Put":{"state":"aaΛaa\nππ"}}
+{"Key":"j"}
+{"Get":{"state":"aaaa\nπΛπ","mode":"Normal"}}
{"Put":{"state":"ΛThe quick brown\nfox jumps"}}
{"Key":"j"}
{"Get":{"state":"The quick brown\nΛfox jumps","mode":"Normal"}}