mirror of
https://github.com/zed-industries/zed.git
synced 2024-11-10 14:06:11 +03:00
Merge pull request #250 from zed-industries/go-to-line
Implement go-to-line interface
This commit is contained in:
commit
c47855424f
12
Cargo.lock
generated
12
Cargo.lock
generated
@ -2084,6 +2084,17 @@ dependencies = [
|
|||||||
"web-sys",
|
"web-sys",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "go_to_line"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"buffer",
|
||||||
|
"editor",
|
||||||
|
"gpui",
|
||||||
|
"postage",
|
||||||
|
"workspace",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "gpui"
|
name = "gpui"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
@ -5671,6 +5682,7 @@ dependencies = [
|
|||||||
"fsevent",
|
"fsevent",
|
||||||
"futures",
|
"futures",
|
||||||
"fuzzy",
|
"fuzzy",
|
||||||
|
"go_to_line",
|
||||||
"gpui",
|
"gpui",
|
||||||
"http-auth-basic",
|
"http-auth-basic",
|
||||||
"ignore",
|
"ignore",
|
||||||
|
@ -263,6 +263,20 @@ impl EditorElement {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let Some(highlighted_row) = layout.highlighted_row {
|
||||||
|
let origin = vec2f(
|
||||||
|
bounds.origin_x(),
|
||||||
|
bounds.origin_y() + (layout.line_height * highlighted_row as f32) - scroll_top,
|
||||||
|
);
|
||||||
|
let size = vec2f(bounds.width(), layout.line_height);
|
||||||
|
cx.scene.push_quad(Quad {
|
||||||
|
bounds: RectF::new(origin, size),
|
||||||
|
background: Some(style.highlighted_line_background),
|
||||||
|
border: Border::default(),
|
||||||
|
corner_radius: 0.,
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw block backgrounds
|
// Draw block backgrounds
|
||||||
@ -729,7 +743,9 @@ impl Element for EditorElement {
|
|||||||
|
|
||||||
let mut selections = HashMap::new();
|
let mut selections = HashMap::new();
|
||||||
let mut active_rows = BTreeMap::new();
|
let mut active_rows = BTreeMap::new();
|
||||||
|
let mut highlighted_row = None;
|
||||||
self.update_view(cx.app, |view, cx| {
|
self.update_view(cx.app, |view, cx| {
|
||||||
|
highlighted_row = view.highlighted_row();
|
||||||
for selection_set_id in view.active_selection_sets(cx).collect::<Vec<_>>() {
|
for selection_set_id in view.active_selection_sets(cx).collect::<Vec<_>>() {
|
||||||
let mut set = Vec::new();
|
let mut set = Vec::new();
|
||||||
for selection in view.selections_in_range(
|
for selection in view.selections_in_range(
|
||||||
@ -786,6 +802,7 @@ impl Element for EditorElement {
|
|||||||
snapshot,
|
snapshot,
|
||||||
style: self.settings.style.clone(),
|
style: self.settings.style.clone(),
|
||||||
active_rows,
|
active_rows,
|
||||||
|
highlighted_row,
|
||||||
line_layouts,
|
line_layouts,
|
||||||
line_number_layouts,
|
line_number_layouts,
|
||||||
block_layouts,
|
block_layouts,
|
||||||
@ -915,6 +932,7 @@ pub struct LayoutState {
|
|||||||
style: EditorStyle,
|
style: EditorStyle,
|
||||||
snapshot: Snapshot,
|
snapshot: Snapshot,
|
||||||
active_rows: BTreeMap<u32, bool>,
|
active_rows: BTreeMap<u32, bool>,
|
||||||
|
highlighted_row: Option<u32>,
|
||||||
line_layouts: Vec<text_layout::Line>,
|
line_layouts: Vec<text_layout::Line>,
|
||||||
line_number_layouts: Vec<Option<text_layout::Line>>,
|
line_number_layouts: Vec<Option<text_layout::Line>>,
|
||||||
block_layouts: Vec<(Range<u32>, BlockStyle)>,
|
block_layouts: Vec<(Range<u32>, BlockStyle)>,
|
||||||
|
@ -311,6 +311,11 @@ enum SelectMode {
|
|||||||
All,
|
All,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub enum Autoscroll {
|
||||||
|
Closest,
|
||||||
|
Center,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, PartialEq, Eq)]
|
#[derive(Copy, Clone, PartialEq, Eq)]
|
||||||
pub enum EditorMode {
|
pub enum EditorMode {
|
||||||
SingleLine,
|
SingleLine,
|
||||||
@ -338,7 +343,7 @@ pub struct Editor {
|
|||||||
active_diagnostics: Option<ActiveDiagnosticGroup>,
|
active_diagnostics: Option<ActiveDiagnosticGroup>,
|
||||||
scroll_position: Vector2F,
|
scroll_position: Vector2F,
|
||||||
scroll_top_anchor: Anchor,
|
scroll_top_anchor: Anchor,
|
||||||
autoscroll_requested: bool,
|
autoscroll_request: Option<Autoscroll>,
|
||||||
build_settings: Rc<RefCell<dyn Fn(&AppContext) -> EditorSettings>>,
|
build_settings: Rc<RefCell<dyn Fn(&AppContext) -> EditorSettings>>,
|
||||||
focused: bool,
|
focused: bool,
|
||||||
show_local_cursors: bool,
|
show_local_cursors: bool,
|
||||||
@ -346,6 +351,7 @@ pub struct Editor {
|
|||||||
blinking_paused: bool,
|
blinking_paused: bool,
|
||||||
mode: EditorMode,
|
mode: EditorMode,
|
||||||
placeholder_text: Option<Arc<str>>,
|
placeholder_text: Option<Arc<str>>,
|
||||||
|
highlighted_row: Option<u32>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Snapshot {
|
pub struct Snapshot {
|
||||||
@ -473,13 +479,14 @@ impl Editor {
|
|||||||
build_settings,
|
build_settings,
|
||||||
scroll_position: Vector2F::zero(),
|
scroll_position: Vector2F::zero(),
|
||||||
scroll_top_anchor: Anchor::min(),
|
scroll_top_anchor: Anchor::min(),
|
||||||
autoscroll_requested: false,
|
autoscroll_request: None,
|
||||||
focused: false,
|
focused: false,
|
||||||
show_local_cursors: false,
|
show_local_cursors: false,
|
||||||
blink_epoch: 0,
|
blink_epoch: 0,
|
||||||
blinking_paused: false,
|
blinking_paused: false,
|
||||||
mode: EditorMode::Full,
|
mode: EditorMode::Full,
|
||||||
placeholder_text: None,
|
placeholder_text: None,
|
||||||
|
highlighted_row: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -527,7 +534,7 @@ impl Editor {
|
|||||||
cx.notify();
|
cx.notify();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_scroll_position(&mut self, scroll_position: Vector2F, cx: &mut ViewContext<Self>) {
|
pub fn set_scroll_position(&mut self, scroll_position: Vector2F, cx: &mut ViewContext<Self>) {
|
||||||
let map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
|
let map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
|
||||||
let scroll_top_buffer_offset =
|
let scroll_top_buffer_offset =
|
||||||
DisplayPoint::new(scroll_position.y() as u32, 0).to_offset(&map, Bias::Right);
|
DisplayPoint::new(scroll_position.y() as u32, 0).to_offset(&map, Bias::Right);
|
||||||
@ -548,6 +555,11 @@ impl Editor {
|
|||||||
cx.notify();
|
cx.notify();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn scroll_position(&self, cx: &mut ViewContext<Self>) -> Vector2F {
|
||||||
|
let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
|
||||||
|
compute_scroll_position(&display_map, self.scroll_position, &self.scroll_top_anchor)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn clamp_scroll_left(&mut self, max: f32) -> bool {
|
pub fn clamp_scroll_left(&mut self, max: f32) -> bool {
|
||||||
if max < self.scroll_position.x() {
|
if max < self.scroll_position.x() {
|
||||||
self.scroll_position.set_x(max);
|
self.scroll_position.set_x(max);
|
||||||
@ -577,11 +589,11 @@ impl Editor {
|
|||||||
self.set_scroll_position(scroll_position, cx);
|
self.set_scroll_position(scroll_position, cx);
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.autoscroll_requested {
|
let autoscroll = if let Some(autoscroll) = self.autoscroll_request.take() {
|
||||||
self.autoscroll_requested = false;
|
autoscroll
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
}
|
};
|
||||||
|
|
||||||
let mut selections = self.selections::<Point>(cx).peekable();
|
let mut selections = self.selections::<Point>(cx).peekable();
|
||||||
let first_cursor_top = selections
|
let first_cursor_top = selections
|
||||||
@ -597,29 +609,35 @@ impl Editor {
|
|||||||
.to_display_point(&display_map)
|
.to_display_point(&display_map)
|
||||||
.row() as f32
|
.row() as f32
|
||||||
+ 1.0;
|
+ 1.0;
|
||||||
|
|
||||||
let margin = if matches!(self.mode, EditorMode::AutoHeight { .. }) {
|
let margin = if matches!(self.mode, EditorMode::AutoHeight { .. }) {
|
||||||
0.
|
0.
|
||||||
} else {
|
} else {
|
||||||
((visible_lines - (last_cursor_bottom - first_cursor_top)) / 2.0)
|
((visible_lines - (last_cursor_bottom - first_cursor_top)) / 2.0).floor()
|
||||||
.floor()
|
|
||||||
.min(3.0)
|
|
||||||
};
|
};
|
||||||
if margin < 0.0 {
|
if margin < 0.0 {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
let target_top = (first_cursor_top - margin).max(0.0);
|
match autoscroll {
|
||||||
let target_bottom = last_cursor_bottom + margin;
|
Autoscroll::Closest => {
|
||||||
let start_row = scroll_position.y();
|
let margin = margin.min(3.0);
|
||||||
let end_row = start_row + visible_lines;
|
let target_top = (first_cursor_top - margin).max(0.0);
|
||||||
|
let target_bottom = last_cursor_bottom + margin;
|
||||||
|
let start_row = scroll_position.y();
|
||||||
|
let end_row = start_row + visible_lines;
|
||||||
|
|
||||||
if target_top < start_row {
|
if target_top < start_row {
|
||||||
scroll_position.set_y(target_top);
|
scroll_position.set_y(target_top);
|
||||||
self.set_scroll_position(scroll_position, cx);
|
self.set_scroll_position(scroll_position, cx);
|
||||||
} else if target_bottom >= end_row {
|
} else if target_bottom >= end_row {
|
||||||
scroll_position.set_y(target_bottom - visible_lines);
|
scroll_position.set_y(target_bottom - visible_lines);
|
||||||
self.set_scroll_position(scroll_position, cx);
|
self.set_scroll_position(scroll_position, cx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Autoscroll::Center => {
|
||||||
|
scroll_position.set_y((first_cursor_top - margin).max(0.0));
|
||||||
|
self.set_scroll_position(scroll_position, cx);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
true
|
true
|
||||||
@ -782,7 +800,7 @@ impl Editor {
|
|||||||
};
|
};
|
||||||
|
|
||||||
if !add {
|
if !add {
|
||||||
self.update_selections::<usize>(Vec::new(), false, cx);
|
self.update_selections::<usize>(Vec::new(), None, cx);
|
||||||
} else if click_count > 1 {
|
} else if click_count > 1 {
|
||||||
// Remove the newest selection since it was only added as part of this multi-click.
|
// Remove the newest selection since it was only added as part of this multi-click.
|
||||||
let newest_selection = self.newest_selection::<usize>(cx);
|
let newest_selection = self.newest_selection::<usize>(cx);
|
||||||
@ -790,7 +808,7 @@ impl Editor {
|
|||||||
self.selections(cx)
|
self.selections(cx)
|
||||||
.filter(|selection| selection.id != newest_selection.id)
|
.filter(|selection| selection.id != newest_selection.id)
|
||||||
.collect(),
|
.collect(),
|
||||||
false,
|
None,
|
||||||
cx,
|
cx,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -921,7 +939,7 @@ impl Editor {
|
|||||||
self.columnar_selection_tail.take();
|
self.columnar_selection_tail.take();
|
||||||
if self.pending_selection.is_some() {
|
if self.pending_selection.is_some() {
|
||||||
let selections = self.selections::<usize>(cx).collect::<Vec<_>>();
|
let selections = self.selections::<usize>(cx).collect::<Vec<_>>();
|
||||||
self.update_selections(selections, false, cx);
|
self.update_selections(selections, None, cx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -961,7 +979,7 @@ impl Editor {
|
|||||||
})
|
})
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
self.update_selections(selections, false, cx);
|
self.update_selections(selections, None, cx);
|
||||||
cx.notify();
|
cx.notify();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -982,7 +1000,7 @@ impl Editor {
|
|||||||
goal: selection.goal,
|
goal: selection.goal,
|
||||||
};
|
};
|
||||||
if self.selections::<Point>(cx).next().is_none() {
|
if self.selections::<Point>(cx).next().is_none() {
|
||||||
self.update_selections(vec![selection], true, cx);
|
self.update_selections(vec![selection], Some(Autoscroll::Closest), cx);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let mut oldest_selection = self.oldest_selection::<usize>(cx);
|
let mut oldest_selection = self.oldest_selection::<usize>(cx);
|
||||||
@ -990,12 +1008,16 @@ impl Editor {
|
|||||||
oldest_selection.start = oldest_selection.head().clone();
|
oldest_selection.start = oldest_selection.head().clone();
|
||||||
oldest_selection.end = oldest_selection.head().clone();
|
oldest_selection.end = oldest_selection.head().clone();
|
||||||
}
|
}
|
||||||
self.update_selections(vec![oldest_selection], true, cx);
|
self.update_selections(vec![oldest_selection], Some(Autoscroll::Closest), cx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn select_ranges<I, T>(&mut self, ranges: I, autoscroll: bool, cx: &mut ViewContext<Self>)
|
pub fn select_ranges<I, T>(
|
||||||
where
|
&mut self,
|
||||||
|
ranges: I,
|
||||||
|
autoscroll: Option<Autoscroll>,
|
||||||
|
cx: &mut ViewContext<Self>,
|
||||||
|
) where
|
||||||
I: IntoIterator<Item = Range<T>>,
|
I: IntoIterator<Item = Range<T>>,
|
||||||
T: ToOffset,
|
T: ToOffset,
|
||||||
{
|
{
|
||||||
@ -1013,8 +1035,8 @@ impl Editor {
|
|||||||
};
|
};
|
||||||
Selection {
|
Selection {
|
||||||
id: post_inc(&mut self.next_selection_id),
|
id: post_inc(&mut self.next_selection_id),
|
||||||
start: start,
|
start,
|
||||||
end: end,
|
end,
|
||||||
reversed,
|
reversed,
|
||||||
goal: SelectionGoal::None,
|
goal: SelectionGoal::None,
|
||||||
}
|
}
|
||||||
@ -1053,7 +1075,7 @@ impl Editor {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
self.update_selections(selections, false, cx);
|
self.update_selections(selections, None, cx);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1179,7 +1201,7 @@ impl Editor {
|
|||||||
))
|
))
|
||||||
});
|
});
|
||||||
|
|
||||||
self.update_selections(new_selections, true, cx);
|
self.update_selections(new_selections, Some(Autoscroll::Closest), cx);
|
||||||
self.end_transaction(cx);
|
self.end_transaction(cx);
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
@ -1219,7 +1241,7 @@ impl Editor {
|
|||||||
.collect();
|
.collect();
|
||||||
});
|
});
|
||||||
|
|
||||||
self.update_selections(new_selections, true, cx);
|
self.update_selections(new_selections, Some(Autoscroll::Closest), cx);
|
||||||
self.end_transaction(cx);
|
self.end_transaction(cx);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1319,7 +1341,7 @@ impl Editor {
|
|||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
self.autoclose_stack.pop();
|
self.autoclose_stack.pop();
|
||||||
self.update_selections(new_selections, true, cx);
|
self.update_selections(new_selections, Some(Autoscroll::Closest), cx);
|
||||||
true
|
true
|
||||||
} else {
|
} else {
|
||||||
false
|
false
|
||||||
@ -1347,7 +1369,7 @@ impl Editor {
|
|||||||
selection.goal = SelectionGoal::None;
|
selection.goal = SelectionGoal::None;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.update_selections(selections, true, cx);
|
self.update_selections(selections, Some(Autoscroll::Closest), cx);
|
||||||
self.insert("", cx);
|
self.insert("", cx);
|
||||||
self.end_transaction(cx);
|
self.end_transaction(cx);
|
||||||
}
|
}
|
||||||
@ -1366,7 +1388,7 @@ impl Editor {
|
|||||||
selection.goal = SelectionGoal::None;
|
selection.goal = SelectionGoal::None;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.update_selections(selections, true, cx);
|
self.update_selections(selections, Some(Autoscroll::Closest), cx);
|
||||||
self.insert(&"", cx);
|
self.insert(&"", cx);
|
||||||
self.end_transaction(cx);
|
self.end_transaction(cx);
|
||||||
}
|
}
|
||||||
@ -1437,7 +1459,7 @@ impl Editor {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
self.update_selections(selections, true, cx);
|
self.update_selections(selections, Some(Autoscroll::Closest), cx);
|
||||||
self.end_transaction(cx);
|
self.end_transaction(cx);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1481,7 +1503,11 @@ impl Editor {
|
|||||||
buffer.edit(deletion_ranges, "", cx);
|
buffer.edit(deletion_ranges, "", cx);
|
||||||
});
|
});
|
||||||
|
|
||||||
self.update_selections(self.selections::<usize>(cx).collect(), true, cx);
|
self.update_selections(
|
||||||
|
self.selections::<usize>(cx).collect(),
|
||||||
|
Some(Autoscroll::Closest),
|
||||||
|
cx,
|
||||||
|
);
|
||||||
self.end_transaction(cx);
|
self.end_transaction(cx);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1550,7 +1576,7 @@ impl Editor {
|
|||||||
.collect();
|
.collect();
|
||||||
self.buffer
|
self.buffer
|
||||||
.update(cx, |buffer, cx| buffer.edit(edit_ranges, "", cx));
|
.update(cx, |buffer, cx| buffer.edit(edit_ranges, "", cx));
|
||||||
self.update_selections(new_selections, true, cx);
|
self.update_selections(new_selections, Some(Autoscroll::Closest), cx);
|
||||||
self.end_transaction(cx);
|
self.end_transaction(cx);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1608,7 +1634,7 @@ impl Editor {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
self.update_selections(selections, true, cx);
|
self.update_selections(selections, Some(Autoscroll::Closest), cx);
|
||||||
self.end_transaction(cx);
|
self.end_transaction(cx);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1697,7 +1723,7 @@ impl Editor {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
self.fold_ranges(new_folds, cx);
|
self.fold_ranges(new_folds, cx);
|
||||||
self.select_ranges(new_selection_ranges, true, cx);
|
self.select_ranges(new_selection_ranges, Some(Autoscroll::Closest), cx);
|
||||||
|
|
||||||
self.end_transaction(cx);
|
self.end_transaction(cx);
|
||||||
}
|
}
|
||||||
@ -1784,7 +1810,7 @@ impl Editor {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
self.fold_ranges(new_folds, cx);
|
self.fold_ranges(new_folds, cx);
|
||||||
self.select_ranges(new_selection_ranges, true, cx);
|
self.select_ranges(new_selection_ranges, Some(Autoscroll::Closest), cx);
|
||||||
|
|
||||||
self.end_transaction(cx);
|
self.end_transaction(cx);
|
||||||
}
|
}
|
||||||
@ -1814,7 +1840,7 @@ impl Editor {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.update_selections(selections, true, cx);
|
self.update_selections(selections, Some(Autoscroll::Closest), cx);
|
||||||
self.insert("", cx);
|
self.insert("", cx);
|
||||||
self.end_transaction(cx);
|
self.end_transaction(cx);
|
||||||
|
|
||||||
@ -1899,7 +1925,7 @@ impl Editor {
|
|||||||
selection.end = selection.start;
|
selection.end = selection.start;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
self.update_selections(selections, true, cx);
|
self.update_selections(selections, Some(Autoscroll::Closest), cx);
|
||||||
} else {
|
} else {
|
||||||
self.insert(clipboard_text, cx);
|
self.insert(clipboard_text, cx);
|
||||||
}
|
}
|
||||||
@ -1908,12 +1934,12 @@ impl Editor {
|
|||||||
|
|
||||||
pub fn undo(&mut self, _: &Undo, cx: &mut ViewContext<Self>) {
|
pub fn undo(&mut self, _: &Undo, cx: &mut ViewContext<Self>) {
|
||||||
self.buffer.update(cx, |buffer, cx| buffer.undo(cx));
|
self.buffer.update(cx, |buffer, cx| buffer.undo(cx));
|
||||||
self.request_autoscroll(cx);
|
self.request_autoscroll(Autoscroll::Closest, cx);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn redo(&mut self, _: &Redo, cx: &mut ViewContext<Self>) {
|
pub fn redo(&mut self, _: &Redo, cx: &mut ViewContext<Self>) {
|
||||||
self.buffer.update(cx, |buffer, cx| buffer.redo(cx));
|
self.buffer.update(cx, |buffer, cx| buffer.redo(cx));
|
||||||
self.request_autoscroll(cx);
|
self.request_autoscroll(Autoscroll::Closest, cx);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn move_left(&mut self, _: &MoveLeft, cx: &mut ViewContext<Self>) {
|
pub fn move_left(&mut self, _: &MoveLeft, cx: &mut ViewContext<Self>) {
|
||||||
@ -1935,7 +1961,7 @@ impl Editor {
|
|||||||
selection.reversed = false;
|
selection.reversed = false;
|
||||||
selection.goal = SelectionGoal::None;
|
selection.goal = SelectionGoal::None;
|
||||||
}
|
}
|
||||||
self.update_selections(selections, true, cx);
|
self.update_selections(selections, Some(Autoscroll::Closest), cx);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn select_left(&mut self, _: &SelectLeft, cx: &mut ViewContext<Self>) {
|
pub fn select_left(&mut self, _: &SelectLeft, cx: &mut ViewContext<Self>) {
|
||||||
@ -1949,7 +1975,7 @@ impl Editor {
|
|||||||
selection.set_head(cursor);
|
selection.set_head(cursor);
|
||||||
selection.goal = SelectionGoal::None;
|
selection.goal = SelectionGoal::None;
|
||||||
}
|
}
|
||||||
self.update_selections(selections, true, cx);
|
self.update_selections(selections, Some(Autoscroll::Closest), cx);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn move_right(&mut self, _: &MoveRight, cx: &mut ViewContext<Self>) {
|
pub fn move_right(&mut self, _: &MoveRight, cx: &mut ViewContext<Self>) {
|
||||||
@ -1971,7 +1997,7 @@ impl Editor {
|
|||||||
selection.reversed = false;
|
selection.reversed = false;
|
||||||
selection.goal = SelectionGoal::None;
|
selection.goal = SelectionGoal::None;
|
||||||
}
|
}
|
||||||
self.update_selections(selections, true, cx);
|
self.update_selections(selections, Some(Autoscroll::Closest), cx);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn select_right(&mut self, _: &SelectRight, cx: &mut ViewContext<Self>) {
|
pub fn select_right(&mut self, _: &SelectRight, cx: &mut ViewContext<Self>) {
|
||||||
@ -1985,7 +2011,7 @@ impl Editor {
|
|||||||
selection.set_head(cursor);
|
selection.set_head(cursor);
|
||||||
selection.goal = SelectionGoal::None;
|
selection.goal = SelectionGoal::None;
|
||||||
}
|
}
|
||||||
self.update_selections(selections, true, cx);
|
self.update_selections(selections, Some(Autoscroll::Closest), cx);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn move_up(&mut self, _: &MoveUp, cx: &mut ViewContext<Self>) {
|
pub fn move_up(&mut self, _: &MoveUp, cx: &mut ViewContext<Self>) {
|
||||||
@ -2010,7 +2036,7 @@ impl Editor {
|
|||||||
selection.goal = goal;
|
selection.goal = goal;
|
||||||
selection.reversed = false;
|
selection.reversed = false;
|
||||||
}
|
}
|
||||||
self.update_selections(selections, true, cx);
|
self.update_selections(selections, Some(Autoscroll::Closest), cx);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn select_up(&mut self, _: &SelectUp, cx: &mut ViewContext<Self>) {
|
pub fn select_up(&mut self, _: &SelectUp, cx: &mut ViewContext<Self>) {
|
||||||
@ -2023,7 +2049,7 @@ impl Editor {
|
|||||||
selection.set_head(cursor);
|
selection.set_head(cursor);
|
||||||
selection.goal = goal;
|
selection.goal = goal;
|
||||||
}
|
}
|
||||||
self.update_selections(selections, true, cx);
|
self.update_selections(selections, Some(Autoscroll::Closest), cx);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn move_down(&mut self, _: &MoveDown, cx: &mut ViewContext<Self>) {
|
pub fn move_down(&mut self, _: &MoveDown, cx: &mut ViewContext<Self>) {
|
||||||
@ -2048,7 +2074,7 @@ impl Editor {
|
|||||||
selection.goal = goal;
|
selection.goal = goal;
|
||||||
selection.reversed = false;
|
selection.reversed = false;
|
||||||
}
|
}
|
||||||
self.update_selections(selections, true, cx);
|
self.update_selections(selections, Some(Autoscroll::Closest), cx);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn select_down(&mut self, _: &SelectDown, cx: &mut ViewContext<Self>) {
|
pub fn select_down(&mut self, _: &SelectDown, cx: &mut ViewContext<Self>) {
|
||||||
@ -2061,7 +2087,7 @@ impl Editor {
|
|||||||
selection.set_head(cursor);
|
selection.set_head(cursor);
|
||||||
selection.goal = goal;
|
selection.goal = goal;
|
||||||
}
|
}
|
||||||
self.update_selections(selections, true, cx);
|
self.update_selections(selections, Some(Autoscroll::Closest), cx);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn move_to_previous_word_boundary(
|
pub fn move_to_previous_word_boundary(
|
||||||
@ -2079,7 +2105,7 @@ impl Editor {
|
|||||||
selection.reversed = false;
|
selection.reversed = false;
|
||||||
selection.goal = SelectionGoal::None;
|
selection.goal = SelectionGoal::None;
|
||||||
}
|
}
|
||||||
self.update_selections(selections, true, cx);
|
self.update_selections(selections, Some(Autoscroll::Closest), cx);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn select_to_previous_word_boundary(
|
pub fn select_to_previous_word_boundary(
|
||||||
@ -2095,7 +2121,7 @@ impl Editor {
|
|||||||
selection.set_head(cursor);
|
selection.set_head(cursor);
|
||||||
selection.goal = SelectionGoal::None;
|
selection.goal = SelectionGoal::None;
|
||||||
}
|
}
|
||||||
self.update_selections(selections, true, cx);
|
self.update_selections(selections, Some(Autoscroll::Closest), cx);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn delete_to_previous_word_boundary(
|
pub fn delete_to_previous_word_boundary(
|
||||||
@ -2115,7 +2141,7 @@ impl Editor {
|
|||||||
selection.goal = SelectionGoal::None;
|
selection.goal = SelectionGoal::None;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.update_selections(selections, true, cx);
|
self.update_selections(selections, Some(Autoscroll::Closest), cx);
|
||||||
self.insert("", cx);
|
self.insert("", cx);
|
||||||
self.end_transaction(cx);
|
self.end_transaction(cx);
|
||||||
}
|
}
|
||||||
@ -2135,7 +2161,7 @@ impl Editor {
|
|||||||
selection.reversed = false;
|
selection.reversed = false;
|
||||||
selection.goal = SelectionGoal::None;
|
selection.goal = SelectionGoal::None;
|
||||||
}
|
}
|
||||||
self.update_selections(selections, true, cx);
|
self.update_selections(selections, Some(Autoscroll::Closest), cx);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn select_to_next_word_boundary(
|
pub fn select_to_next_word_boundary(
|
||||||
@ -2151,7 +2177,7 @@ impl Editor {
|
|||||||
selection.set_head(cursor);
|
selection.set_head(cursor);
|
||||||
selection.goal = SelectionGoal::None;
|
selection.goal = SelectionGoal::None;
|
||||||
}
|
}
|
||||||
self.update_selections(selections, true, cx);
|
self.update_selections(selections, Some(Autoscroll::Closest), cx);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn delete_to_next_word_boundary(
|
pub fn delete_to_next_word_boundary(
|
||||||
@ -2171,7 +2197,7 @@ impl Editor {
|
|||||||
selection.goal = SelectionGoal::None;
|
selection.goal = SelectionGoal::None;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.update_selections(selections, true, cx);
|
self.update_selections(selections, Some(Autoscroll::Closest), cx);
|
||||||
self.insert("", cx);
|
self.insert("", cx);
|
||||||
self.end_transaction(cx);
|
self.end_transaction(cx);
|
||||||
}
|
}
|
||||||
@ -2192,7 +2218,7 @@ impl Editor {
|
|||||||
selection.reversed = false;
|
selection.reversed = false;
|
||||||
selection.goal = SelectionGoal::None;
|
selection.goal = SelectionGoal::None;
|
||||||
}
|
}
|
||||||
self.update_selections(selections, true, cx);
|
self.update_selections(selections, Some(Autoscroll::Closest), cx);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn select_to_beginning_of_line(
|
pub fn select_to_beginning_of_line(
|
||||||
@ -2208,7 +2234,7 @@ impl Editor {
|
|||||||
selection.set_head(new_head.to_point(&display_map));
|
selection.set_head(new_head.to_point(&display_map));
|
||||||
selection.goal = SelectionGoal::None;
|
selection.goal = SelectionGoal::None;
|
||||||
}
|
}
|
||||||
self.update_selections(selections, true, cx);
|
self.update_selections(selections, Some(Autoscroll::Closest), cx);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn delete_to_beginning_of_line(
|
pub fn delete_to_beginning_of_line(
|
||||||
@ -2236,7 +2262,7 @@ impl Editor {
|
|||||||
selection.goal = SelectionGoal::None;
|
selection.goal = SelectionGoal::None;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.update_selections(selections, true, cx);
|
self.update_selections(selections, Some(Autoscroll::Closest), cx);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn select_to_end_of_line(&mut self, _: &SelectToEndOfLine, cx: &mut ViewContext<Self>) {
|
pub fn select_to_end_of_line(&mut self, _: &SelectToEndOfLine, cx: &mut ViewContext<Self>) {
|
||||||
@ -2248,7 +2274,7 @@ impl Editor {
|
|||||||
selection.set_head(new_head.to_point(&display_map));
|
selection.set_head(new_head.to_point(&display_map));
|
||||||
selection.goal = SelectionGoal::None;
|
selection.goal = SelectionGoal::None;
|
||||||
}
|
}
|
||||||
self.update_selections(selections, true, cx);
|
self.update_selections(selections, Some(Autoscroll::Closest), cx);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn delete_to_end_of_line(&mut self, _: &DeleteToEndOfLine, cx: &mut ViewContext<Self>) {
|
pub fn delete_to_end_of_line(&mut self, _: &DeleteToEndOfLine, cx: &mut ViewContext<Self>) {
|
||||||
@ -2273,13 +2299,13 @@ impl Editor {
|
|||||||
reversed: false,
|
reversed: false,
|
||||||
goal: SelectionGoal::None,
|
goal: SelectionGoal::None,
|
||||||
};
|
};
|
||||||
self.update_selections(vec![selection], true, cx);
|
self.update_selections(vec![selection], Some(Autoscroll::Closest), cx);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn select_to_beginning(&mut self, _: &SelectToBeginning, cx: &mut ViewContext<Self>) {
|
pub fn select_to_beginning(&mut self, _: &SelectToBeginning, cx: &mut ViewContext<Self>) {
|
||||||
let mut selection = self.selections::<Point>(cx).last().unwrap().clone();
|
let mut selection = self.selections::<Point>(cx).last().unwrap().clone();
|
||||||
selection.set_head(Point::zero());
|
selection.set_head(Point::zero());
|
||||||
self.update_selections(vec![selection], true, cx);
|
self.update_selections(vec![selection], Some(Autoscroll::Closest), cx);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn move_to_end(&mut self, _: &MoveToEnd, cx: &mut ViewContext<Self>) {
|
pub fn move_to_end(&mut self, _: &MoveToEnd, cx: &mut ViewContext<Self>) {
|
||||||
@ -2292,13 +2318,13 @@ impl Editor {
|
|||||||
reversed: false,
|
reversed: false,
|
||||||
goal: SelectionGoal::None,
|
goal: SelectionGoal::None,
|
||||||
};
|
};
|
||||||
self.update_selections(vec![selection], true, cx);
|
self.update_selections(vec![selection], Some(Autoscroll::Closest), cx);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn select_to_end(&mut self, _: &SelectToEnd, cx: &mut ViewContext<Self>) {
|
pub fn select_to_end(&mut self, _: &SelectToEnd, cx: &mut ViewContext<Self>) {
|
||||||
let mut selection = self.selections::<usize>(cx).last().unwrap().clone();
|
let mut selection = self.selections::<usize>(cx).last().unwrap().clone();
|
||||||
selection.set_head(self.buffer.read(cx).len());
|
selection.set_head(self.buffer.read(cx).len());
|
||||||
self.update_selections(vec![selection], true, cx);
|
self.update_selections(vec![selection], Some(Autoscroll::Closest), cx);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn select_all(&mut self, _: &SelectAll, cx: &mut ViewContext<Self>) {
|
pub fn select_all(&mut self, _: &SelectAll, cx: &mut ViewContext<Self>) {
|
||||||
@ -2309,7 +2335,7 @@ impl Editor {
|
|||||||
reversed: false,
|
reversed: false,
|
||||||
goal: SelectionGoal::None,
|
goal: SelectionGoal::None,
|
||||||
};
|
};
|
||||||
self.update_selections(vec![selection], false, cx);
|
self.update_selections(vec![selection], None, cx);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn select_line(&mut self, _: &SelectLine, cx: &mut ViewContext<Self>) {
|
pub fn select_line(&mut self, _: &SelectLine, cx: &mut ViewContext<Self>) {
|
||||||
@ -2323,7 +2349,7 @@ impl Editor {
|
|||||||
selection.end = cmp::min(max_point, Point::new(rows.end, 0));
|
selection.end = cmp::min(max_point, Point::new(rows.end, 0));
|
||||||
selection.reversed = false;
|
selection.reversed = false;
|
||||||
}
|
}
|
||||||
self.update_selections(selections, true, cx);
|
self.update_selections(selections, Some(Autoscroll::Closest), cx);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn split_selection_into_lines(
|
pub fn split_selection_into_lines(
|
||||||
@ -2357,7 +2383,7 @@ impl Editor {
|
|||||||
to_unfold.push(selection.start..selection.end);
|
to_unfold.push(selection.start..selection.end);
|
||||||
}
|
}
|
||||||
self.unfold_ranges(to_unfold, cx);
|
self.unfold_ranges(to_unfold, cx);
|
||||||
self.update_selections(new_selections, true, cx);
|
self.update_selections(new_selections, Some(Autoscroll::Closest), cx);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_selection_above(&mut self, _: &AddSelectionAbove, cx: &mut ViewContext<Self>) {
|
pub fn add_selection_above(&mut self, _: &AddSelectionAbove, cx: &mut ViewContext<Self>) {
|
||||||
@ -2455,7 +2481,7 @@ impl Editor {
|
|||||||
state.stack.pop();
|
state.stack.pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
self.update_selections(new_selections, true, cx);
|
self.update_selections(new_selections, Some(Autoscroll::Closest), cx);
|
||||||
if state.stack.len() > 1 {
|
if state.stack.len() > 1 {
|
||||||
self.add_selections_state = Some(state);
|
self.add_selections_state = Some(state);
|
||||||
}
|
}
|
||||||
@ -2547,7 +2573,11 @@ impl Editor {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
self.update_selections(self.selections::<usize>(cx).collect(), true, cx);
|
self.update_selections(
|
||||||
|
self.selections::<usize>(cx).collect(),
|
||||||
|
Some(Autoscroll::Closest),
|
||||||
|
cx,
|
||||||
|
);
|
||||||
self.end_transaction(cx);
|
self.end_transaction(cx);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2592,7 +2622,7 @@ impl Editor {
|
|||||||
if selected_larger_node {
|
if selected_larger_node {
|
||||||
stack.push(old_selections);
|
stack.push(old_selections);
|
||||||
new_selections.sort_unstable_by_key(|selection| selection.start);
|
new_selections.sort_unstable_by_key(|selection| selection.start);
|
||||||
self.update_selections(new_selections, true, cx);
|
self.update_selections(new_selections, Some(Autoscroll::Closest), cx);
|
||||||
}
|
}
|
||||||
self.select_larger_syntax_node_stack = stack;
|
self.select_larger_syntax_node_stack = stack;
|
||||||
}
|
}
|
||||||
@ -2604,7 +2634,7 @@ impl Editor {
|
|||||||
) {
|
) {
|
||||||
let mut stack = mem::take(&mut self.select_larger_syntax_node_stack);
|
let mut stack = mem::take(&mut self.select_larger_syntax_node_stack);
|
||||||
if let Some(selections) = stack.pop() {
|
if let Some(selections) = stack.pop() {
|
||||||
self.update_selections(selections.to_vec(), true, cx);
|
self.update_selections(selections.to_vec(), Some(Autoscroll::Closest), cx);
|
||||||
}
|
}
|
||||||
self.select_larger_syntax_node_stack = stack;
|
self.select_larger_syntax_node_stack = stack;
|
||||||
}
|
}
|
||||||
@ -2633,7 +2663,7 @@ impl Editor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
self.update_selections(selections, true, cx);
|
self.update_selections(selections, Some(Autoscroll::Closest), cx);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn show_next_diagnostic(&mut self, _: &ShowNextDiagnostic, cx: &mut ViewContext<Self>) {
|
pub fn show_next_diagnostic(&mut self, _: &ShowNextDiagnostic, cx: &mut ViewContext<Self>) {
|
||||||
@ -2679,7 +2709,7 @@ impl Editor {
|
|||||||
reversed: false,
|
reversed: false,
|
||||||
goal: SelectionGoal::None,
|
goal: SelectionGoal::None,
|
||||||
}],
|
}],
|
||||||
true,
|
Some(Autoscroll::Center),
|
||||||
cx,
|
cx,
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
@ -3004,10 +3034,10 @@ impl Editor {
|
|||||||
.unwrap()
|
.unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update_selections<T>(
|
pub fn update_selections<T>(
|
||||||
&mut self,
|
&mut self,
|
||||||
mut selections: Vec<Selection<T>>,
|
mut selections: Vec<Selection<T>>,
|
||||||
autoscroll: bool,
|
autoscroll: Option<Autoscroll>,
|
||||||
cx: &mut ViewContext<Self>,
|
cx: &mut ViewContext<Self>,
|
||||||
) where
|
) where
|
||||||
T: ToOffset + ToPoint + Ord + std::marker::Copy + std::fmt::Debug,
|
T: ToOffset + ToPoint + Ord + std::marker::Copy + std::fmt::Debug,
|
||||||
@ -3053,8 +3083,8 @@ impl Editor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if autoscroll {
|
if let Some(autoscroll) = autoscroll {
|
||||||
self.request_autoscroll(cx);
|
self.request_autoscroll(autoscroll, cx);
|
||||||
}
|
}
|
||||||
self.pause_cursor_blinking(cx);
|
self.pause_cursor_blinking(cx);
|
||||||
|
|
||||||
@ -3065,8 +3095,8 @@ impl Editor {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn request_autoscroll(&mut self, cx: &mut ViewContext<Self>) {
|
fn request_autoscroll(&mut self, autoscroll: Autoscroll, cx: &mut ViewContext<Self>) {
|
||||||
self.autoscroll_requested = true;
|
self.autoscroll_request = Some(autoscroll);
|
||||||
cx.notify();
|
cx.notify();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3189,7 +3219,7 @@ impl Editor {
|
|||||||
fn fold_ranges<T: ToOffset>(&mut self, ranges: Vec<Range<T>>, cx: &mut ViewContext<Self>) {
|
fn fold_ranges<T: ToOffset>(&mut self, ranges: Vec<Range<T>>, cx: &mut ViewContext<Self>) {
|
||||||
if !ranges.is_empty() {
|
if !ranges.is_empty() {
|
||||||
self.display_map.update(cx, |map, cx| map.fold(ranges, cx));
|
self.display_map.update(cx, |map, cx| map.fold(ranges, cx));
|
||||||
self.autoscroll_requested = true;
|
self.request_autoscroll(Autoscroll::Closest, cx);
|
||||||
cx.notify();
|
cx.notify();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3198,7 +3228,7 @@ impl Editor {
|
|||||||
if !ranges.is_empty() {
|
if !ranges.is_empty() {
|
||||||
self.display_map
|
self.display_map
|
||||||
.update(cx, |map, cx| map.unfold(ranges, cx));
|
.update(cx, |map, cx| map.unfold(ranges, cx));
|
||||||
self.autoscroll_requested = true;
|
self.request_autoscroll(Autoscroll::Closest, cx);
|
||||||
cx.notify();
|
cx.notify();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3225,15 +3255,19 @@ impl Editor {
|
|||||||
.text()
|
.text()
|
||||||
}
|
}
|
||||||
|
|
||||||
// pub fn font_size(&self) -> f32 {
|
|
||||||
// self.settings.font_size
|
|
||||||
// }
|
|
||||||
|
|
||||||
pub fn set_wrap_width(&self, width: f32, cx: &mut MutableAppContext) -> bool {
|
pub fn set_wrap_width(&self, width: f32, cx: &mut MutableAppContext) -> bool {
|
||||||
self.display_map
|
self.display_map
|
||||||
.update(cx, |map, cx| map.set_wrap_width(Some(width), cx))
|
.update(cx, |map, cx| map.set_wrap_width(Some(width), cx))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn set_highlighted_row(&mut self, row: Option<u32>) {
|
||||||
|
self.highlighted_row = row;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn highlighted_row(&mut self) -> Option<u32> {
|
||||||
|
self.highlighted_row
|
||||||
|
}
|
||||||
|
|
||||||
fn next_blink_epoch(&mut self) -> usize {
|
fn next_blink_epoch(&mut self) -> usize {
|
||||||
self.blink_epoch += 1;
|
self.blink_epoch += 1;
|
||||||
self.blink_epoch
|
self.blink_epoch
|
||||||
@ -3403,6 +3437,7 @@ impl EditorSettings {
|
|||||||
background: Default::default(),
|
background: Default::default(),
|
||||||
gutter_background: Default::default(),
|
gutter_background: Default::default(),
|
||||||
active_line_background: Default::default(),
|
active_line_background: Default::default(),
|
||||||
|
highlighted_line_background: Default::default(),
|
||||||
line_number: Default::default(),
|
line_number: Default::default(),
|
||||||
line_number_active: Default::default(),
|
line_number_active: Default::default(),
|
||||||
selection: Default::default(),
|
selection: Default::default(),
|
||||||
@ -4698,14 +4733,14 @@ mod tests {
|
|||||||
|
|
||||||
// Cut with three selections. Clipboard text is divided into three slices.
|
// Cut with three selections. Clipboard text is divided into three slices.
|
||||||
view.update(cx, |view, cx| {
|
view.update(cx, |view, cx| {
|
||||||
view.select_ranges(vec![0..7, 11..17, 22..27], false, cx);
|
view.select_ranges(vec![0..7, 11..17, 22..27], None, cx);
|
||||||
view.cut(&Cut, cx);
|
view.cut(&Cut, cx);
|
||||||
assert_eq!(view.display_text(cx), "two four six ");
|
assert_eq!(view.display_text(cx), "two four six ");
|
||||||
});
|
});
|
||||||
|
|
||||||
// Paste with three cursors. Each cursor pastes one slice of the clipboard text.
|
// Paste with three cursors. Each cursor pastes one slice of the clipboard text.
|
||||||
view.update(cx, |view, cx| {
|
view.update(cx, |view, cx| {
|
||||||
view.select_ranges(vec![4..4, 9..9, 13..13], false, cx);
|
view.select_ranges(vec![4..4, 9..9, 13..13], None, cx);
|
||||||
view.paste(&Paste, cx);
|
view.paste(&Paste, cx);
|
||||||
assert_eq!(view.display_text(cx), "two one✅ four three six five ");
|
assert_eq!(view.display_text(cx), "two one✅ four three six five ");
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
@ -4722,7 +4757,7 @@ mod tests {
|
|||||||
// match the number of slices in the clipboard, the entire clipboard text
|
// match the number of slices in the clipboard, the entire clipboard text
|
||||||
// is pasted at each cursor.
|
// is pasted at each cursor.
|
||||||
view.update(cx, |view, cx| {
|
view.update(cx, |view, cx| {
|
||||||
view.select_ranges(vec![0..0, 31..31], false, cx);
|
view.select_ranges(vec![0..0, 31..31], None, cx);
|
||||||
view.handle_input(&Input("( ".into()), cx);
|
view.handle_input(&Input("( ".into()), cx);
|
||||||
view.paste(&Paste, cx);
|
view.paste(&Paste, cx);
|
||||||
view.handle_input(&Input(") ".into()), cx);
|
view.handle_input(&Input(") ".into()), cx);
|
||||||
@ -4733,7 +4768,7 @@ mod tests {
|
|||||||
});
|
});
|
||||||
|
|
||||||
view.update(cx, |view, cx| {
|
view.update(cx, |view, cx| {
|
||||||
view.select_ranges(vec![0..0], false, cx);
|
view.select_ranges(vec![0..0], None, cx);
|
||||||
view.handle_input(&Input("123\n4567\n89\n".into()), cx);
|
view.handle_input(&Input("123\n4567\n89\n".into()), cx);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
view.display_text(cx),
|
view.display_text(cx),
|
||||||
|
11
crates/go_to_line/Cargo.toml
Normal file
11
crates/go_to_line/Cargo.toml
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
[package]
|
||||||
|
name = "go_to_line"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2018"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
buffer = { path = "../buffer" }
|
||||||
|
editor = { path = "../editor" }
|
||||||
|
gpui = { path = "../gpui" }
|
||||||
|
workspace = { path = "../workspace" }
|
||||||
|
postage = { version = "0.4", features = ["futures-traits"] }
|
212
crates/go_to_line/src/lib.rs
Normal file
212
crates/go_to_line/src/lib.rs
Normal file
@ -0,0 +1,212 @@
|
|||||||
|
use buffer::{Bias, Point, Selection};
|
||||||
|
use editor::{Autoscroll, Editor, EditorSettings};
|
||||||
|
use gpui::{
|
||||||
|
action, elements::*, geometry::vector::Vector2F, keymap::Binding, Axis, Entity,
|
||||||
|
MutableAppContext, RenderContext, View, ViewContext, ViewHandle,
|
||||||
|
};
|
||||||
|
use postage::watch;
|
||||||
|
use workspace::{Settings, Workspace};
|
||||||
|
|
||||||
|
action!(Toggle);
|
||||||
|
action!(Confirm);
|
||||||
|
|
||||||
|
pub fn init(cx: &mut MutableAppContext) {
|
||||||
|
cx.add_bindings([
|
||||||
|
Binding::new("ctrl-g", Toggle, Some("Editor")),
|
||||||
|
Binding::new("escape", Toggle, Some("GoToLine")),
|
||||||
|
Binding::new("enter", Confirm, Some("GoToLine")),
|
||||||
|
]);
|
||||||
|
cx.add_action(GoToLine::toggle);
|
||||||
|
cx.add_action(GoToLine::confirm);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct GoToLine {
|
||||||
|
settings: watch::Receiver<Settings>,
|
||||||
|
line_editor: ViewHandle<Editor>,
|
||||||
|
active_editor: ViewHandle<Editor>,
|
||||||
|
restore_state: Option<RestoreState>,
|
||||||
|
cursor_point: Point,
|
||||||
|
max_point: Point,
|
||||||
|
}
|
||||||
|
|
||||||
|
struct RestoreState {
|
||||||
|
scroll_position: Vector2F,
|
||||||
|
selections: Vec<Selection<usize>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum Event {
|
||||||
|
Dismissed,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl GoToLine {
|
||||||
|
pub fn new(
|
||||||
|
active_editor: ViewHandle<Editor>,
|
||||||
|
settings: watch::Receiver<Settings>,
|
||||||
|
cx: &mut ViewContext<Self>,
|
||||||
|
) -> Self {
|
||||||
|
let line_editor = cx.add_view(|cx| {
|
||||||
|
Editor::single_line(
|
||||||
|
{
|
||||||
|
let settings = settings.clone();
|
||||||
|
move |_| {
|
||||||
|
let settings = settings.borrow();
|
||||||
|
EditorSettings {
|
||||||
|
tab_size: settings.tab_size,
|
||||||
|
style: settings.theme.selector.input_editor.as_editor(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
cx,
|
||||||
|
)
|
||||||
|
});
|
||||||
|
cx.subscribe(&line_editor, Self::on_line_editor_event)
|
||||||
|
.detach();
|
||||||
|
|
||||||
|
let (restore_state, cursor_point, max_point) = active_editor.update(cx, |editor, cx| {
|
||||||
|
let restore_state = Some(RestoreState {
|
||||||
|
scroll_position: editor.scroll_position(cx),
|
||||||
|
selections: editor.selections::<usize>(cx).collect(),
|
||||||
|
});
|
||||||
|
|
||||||
|
(
|
||||||
|
restore_state,
|
||||||
|
editor.newest_selection(cx).head(),
|
||||||
|
editor.buffer().read(cx).max_point(),
|
||||||
|
)
|
||||||
|
});
|
||||||
|
|
||||||
|
Self {
|
||||||
|
settings: settings.clone(),
|
||||||
|
line_editor,
|
||||||
|
active_editor,
|
||||||
|
restore_state,
|
||||||
|
cursor_point,
|
||||||
|
max_point,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn toggle(workspace: &mut Workspace, _: &Toggle, cx: &mut ViewContext<Workspace>) {
|
||||||
|
workspace.toggle_modal(cx, |cx, workspace| {
|
||||||
|
let editor = workspace
|
||||||
|
.active_item(cx)
|
||||||
|
.unwrap()
|
||||||
|
.to_any()
|
||||||
|
.downcast::<Editor>()
|
||||||
|
.unwrap();
|
||||||
|
let view = cx.add_view(|cx| GoToLine::new(editor, workspace.settings.clone(), cx));
|
||||||
|
cx.subscribe(&view, Self::on_event).detach();
|
||||||
|
view
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
fn confirm(&mut self, _: &Confirm, cx: &mut ViewContext<Self>) {
|
||||||
|
self.restore_state.take();
|
||||||
|
cx.emit(Event::Dismissed);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn on_event(
|
||||||
|
workspace: &mut Workspace,
|
||||||
|
_: ViewHandle<Self>,
|
||||||
|
event: &Event,
|
||||||
|
cx: &mut ViewContext<Workspace>,
|
||||||
|
) {
|
||||||
|
match event {
|
||||||
|
Event::Dismissed => workspace.dismiss_modal(cx),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn on_line_editor_event(
|
||||||
|
&mut self,
|
||||||
|
_: ViewHandle<Editor>,
|
||||||
|
event: &editor::Event,
|
||||||
|
cx: &mut ViewContext<Self>,
|
||||||
|
) {
|
||||||
|
match event {
|
||||||
|
editor::Event::Blurred => cx.emit(Event::Dismissed),
|
||||||
|
editor::Event::Edited => {
|
||||||
|
let line_editor = self.line_editor.read(cx).buffer().read(cx).text();
|
||||||
|
let mut components = line_editor.trim().split(&[',', ':'][..]);
|
||||||
|
let row = components.next().and_then(|row| row.parse::<u32>().ok());
|
||||||
|
let column = components.next().and_then(|row| row.parse::<u32>().ok());
|
||||||
|
if let Some(point) = row.map(|row| {
|
||||||
|
Point::new(
|
||||||
|
row.saturating_sub(1),
|
||||||
|
column.map(|column| column.saturating_sub(1)).unwrap_or(0),
|
||||||
|
)
|
||||||
|
}) {
|
||||||
|
self.active_editor.update(cx, |active_editor, cx| {
|
||||||
|
let buffer = active_editor.buffer().read(cx);
|
||||||
|
let point = buffer.clip_point(point, Bias::Left);
|
||||||
|
active_editor.select_ranges([point..point], Some(Autoscroll::Center), cx);
|
||||||
|
active_editor.set_highlighted_row(Some(point.row));
|
||||||
|
});
|
||||||
|
cx.notify();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Entity for GoToLine {
|
||||||
|
type Event = Event;
|
||||||
|
|
||||||
|
fn release(&mut self, cx: &mut MutableAppContext) {
|
||||||
|
let restore_state = self.restore_state.take();
|
||||||
|
self.active_editor.update(cx, |editor, cx| {
|
||||||
|
editor.set_highlighted_row(None);
|
||||||
|
if let Some(restore_state) = restore_state {
|
||||||
|
editor.set_scroll_position(restore_state.scroll_position, cx);
|
||||||
|
editor.update_selections(restore_state.selections, None, cx);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl View for GoToLine {
|
||||||
|
fn ui_name() -> &'static str {
|
||||||
|
"GoToLine"
|
||||||
|
}
|
||||||
|
|
||||||
|
fn render(&mut self, _: &mut RenderContext<Self>) -> ElementBox {
|
||||||
|
let theme = &self.settings.borrow().theme.selector;
|
||||||
|
|
||||||
|
let label = format!(
|
||||||
|
"{},{} of {} lines",
|
||||||
|
self.cursor_point.row + 1,
|
||||||
|
self.cursor_point.column + 1,
|
||||||
|
self.max_point.row + 1
|
||||||
|
);
|
||||||
|
|
||||||
|
Align::new(
|
||||||
|
ConstrainedBox::new(
|
||||||
|
Container::new(
|
||||||
|
Flex::new(Axis::Vertical)
|
||||||
|
.with_child(
|
||||||
|
Container::new(ChildView::new(self.line_editor.id()).boxed())
|
||||||
|
.with_style(theme.input_editor.container)
|
||||||
|
.boxed(),
|
||||||
|
)
|
||||||
|
.with_child(
|
||||||
|
Container::new(Label::new(label, theme.empty.label.clone()).boxed())
|
||||||
|
.with_style(theme.empty.container)
|
||||||
|
.boxed(),
|
||||||
|
)
|
||||||
|
.boxed(),
|
||||||
|
)
|
||||||
|
.with_style(theme.container)
|
||||||
|
.boxed(),
|
||||||
|
)
|
||||||
|
.with_max_width(500.0)
|
||||||
|
.boxed(),
|
||||||
|
)
|
||||||
|
.top()
|
||||||
|
.named("go to line")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn on_focus(&mut self, cx: &mut ViewContext<Self>) {
|
||||||
|
cx.focus(&self.line_editor);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn on_blur(&mut self, _: &mut ViewContext<Self>) {}
|
||||||
|
}
|
@ -223,6 +223,7 @@ pub struct EditorStyle {
|
|||||||
pub selection: SelectionStyle,
|
pub selection: SelectionStyle,
|
||||||
pub gutter_background: Color,
|
pub gutter_background: Color,
|
||||||
pub active_line_background: Color,
|
pub active_line_background: Color,
|
||||||
|
pub highlighted_line_background: Color,
|
||||||
pub line_number: Color,
|
pub line_number: Color,
|
||||||
pub line_number_active: Color,
|
pub line_number_active: Color,
|
||||||
pub guest_selections: Vec<SelectionStyle>,
|
pub guest_selections: Vec<SelectionStyle>,
|
||||||
@ -286,6 +287,7 @@ impl InputEditorStyle {
|
|||||||
selection: self.selection,
|
selection: self.selection,
|
||||||
gutter_background: Default::default(),
|
gutter_background: Default::default(),
|
||||||
active_line_background: Default::default(),
|
active_line_background: Default::default(),
|
||||||
|
highlighted_line_background: Default::default(),
|
||||||
line_number: Default::default(),
|
line_number: Default::default(),
|
||||||
line_number_active: Default::default(),
|
line_number_active: Default::default(),
|
||||||
guest_selections: Default::default(),
|
guest_selections: Default::default(),
|
||||||
|
@ -36,6 +36,7 @@ fsevent = { path = "../fsevent" }
|
|||||||
fuzzy = { path = "../fuzzy" }
|
fuzzy = { path = "../fuzzy" }
|
||||||
editor = { path = "../editor" }
|
editor = { path = "../editor" }
|
||||||
file_finder = { path = "../file_finder" }
|
file_finder = { path = "../file_finder" }
|
||||||
|
go_to_line = { path = "../go_to_line" }
|
||||||
gpui = { path = "../gpui" }
|
gpui = { path = "../gpui" }
|
||||||
language = { path = "../language" }
|
language = { path = "../language" }
|
||||||
lsp = { path = "../lsp" }
|
lsp = { path = "../lsp" }
|
||||||
|
@ -231,6 +231,7 @@ text = "$text.1"
|
|||||||
background = "$surface.1"
|
background = "$surface.1"
|
||||||
gutter_background = "$surface.1"
|
gutter_background = "$surface.1"
|
||||||
active_line_background = "$state.active_line"
|
active_line_background = "$state.active_line"
|
||||||
|
highlighted_line_background = "$state.highlighted_line"
|
||||||
line_number = "$text.2.color"
|
line_number = "$text.2.color"
|
||||||
line_number_active = "$text.0.color"
|
line_number_active = "$text.0.color"
|
||||||
selection = "$selection.host"
|
selection = "$selection.host"
|
||||||
|
@ -37,6 +37,7 @@ bad = "#b7372e"
|
|||||||
|
|
||||||
[state]
|
[state]
|
||||||
active_line = "#00000033"
|
active_line = "#00000033"
|
||||||
|
highlighted_line = "#faca5033"
|
||||||
hover = "#00000033"
|
hover = "#00000033"
|
||||||
|
|
||||||
[editor.syntax]
|
[editor.syntax]
|
||||||
|
@ -37,6 +37,7 @@ bad = "#b7372e"
|
|||||||
|
|
||||||
[state]
|
[state]
|
||||||
active_line = "#00000022"
|
active_line = "#00000022"
|
||||||
|
highlighted_line = "#faca5033"
|
||||||
hover = "#00000033"
|
hover = "#00000033"
|
||||||
|
|
||||||
[editor.syntax]
|
[editor.syntax]
|
||||||
|
@ -37,6 +37,7 @@ bad = "#b7372e"
|
|||||||
|
|
||||||
[state]
|
[state]
|
||||||
active_line = "#00000008"
|
active_line = "#00000008"
|
||||||
|
highlighted_line = "#faca5033"
|
||||||
hover = "#0000000D"
|
hover = "#0000000D"
|
||||||
|
|
||||||
[editor.syntax]
|
[editor.syntax]
|
||||||
|
@ -38,6 +38,7 @@ fn main() {
|
|||||||
client::init(client.clone(), cx);
|
client::init(client.clone(), cx);
|
||||||
workspace::init(cx);
|
workspace::init(cx);
|
||||||
editor::init(cx, &mut entry_openers);
|
editor::init(cx, &mut entry_openers);
|
||||||
|
go_to_line::init(cx);
|
||||||
file_finder::init(cx);
|
file_finder::init(cx);
|
||||||
people_panel::init(cx);
|
people_panel::init(cx);
|
||||||
chat_panel::init(cx);
|
chat_panel::init(cx);
|
||||||
|
Loading…
Reference in New Issue
Block a user