This commit is contained in:
Conrad Irwin 2023-11-02 15:27:49 -06:00
parent 09efa017d4
commit 583c36e24b
21 changed files with 11815 additions and 11788 deletions

55
Cargo.lock generated
View File

@ -2622,6 +2622,60 @@ dependencies = [
"workspace",
]
[[package]]
name = "editor2"
version = "0.1.0"
dependencies = [
"aho-corasick",
"anyhow",
"client2",
"clock",
"collections",
"context_menu",
"convert_case 0.6.0",
"copilot2",
"ctor",
"db2",
"drag_and_drop",
"env_logger 0.9.3",
"futures 0.3.28",
"fuzzy2",
"git",
"gpui2",
"indoc",
"itertools 0.10.5",
"language2",
"lazy_static",
"log",
"lsp2",
"multi_buffer",
"ordered-float 2.10.0",
"parking_lot 0.11.2",
"postage",
"project2",
"rand 0.8.5",
"rich_text",
"rpc2",
"schemars",
"serde",
"serde_derive",
"settings2",
"smallvec",
"smol",
"snippet",
"sqlez",
"sum_tree",
"text2",
"theme2",
"tree-sitter",
"tree-sitter-html",
"tree-sitter-rust",
"tree-sitter-typescript",
"unindent",
"util",
"workspace2",
]
[[package]]
name = "either"
version = "1.9.0"
@ -11071,6 +11125,7 @@ dependencies = [
"copilot2",
"ctor",
"db2",
"editor2",
"env_logger 0.9.3",
"feature_flags2",
"fs2",

View File

@ -1,5 +1,5 @@
[package]
name = "editor"
name = "editor2"
version = "0.1.0"
edition = "2021"
publish = false
@ -23,30 +23,30 @@ test-support = [
]
[dependencies]
client = { path = "../client" }
client = { package = "client2", path = "../client2" }
clock = { path = "../clock" }
copilot = { path = "../copilot" }
db = { path = "../db" }
copilot = { package="copilot2", path = "../copilot2" }
db = { package="db2", path = "../db2" }
drag_and_drop = { path = "../drag_and_drop" }
collections = { path = "../collections" }
context_menu = { path = "../context_menu" }
fuzzy = { path = "../fuzzy" }
fuzzy = { package = "fuzzy2", path = "../fuzzy2" }
git = { path = "../git" }
gpui = { path = "../gpui" }
language = { path = "../language" }
lsp = { path = "../lsp" }
gpui = { package = "gpui2", path = "../gpui2" }
language = { package = "language2", path = "../language2" }
lsp = { package = "lsp2", path = "../lsp2" }
multi_buffer = { path = "../multi_buffer" }
project = { path = "../project" }
rpc = { path = "../rpc" }
project = { package = "project2", path = "../project2" }
rpc = { package = "rpc2", path = "../rpc2" }
rich_text = { path = "../rich_text" }
settings = { path = "../settings" }
settings = { package="settings2", path = "../settings2" }
snippet = { path = "../snippet" }
sum_tree = { path = "../sum_tree" }
text = { path = "../text" }
theme = { path = "../theme" }
text = { package="text2", path = "../text2" }
theme = { package="theme2", path = "../theme2" }
util = { path = "../util" }
sqlez = { path = "../sqlez" }
workspace = { path = "../workspace" }
workspace = { package="workspace2", path = "../workspace2" }
aho-corasick = "1.1"
anyhow.workspace = true
@ -71,15 +71,15 @@ tree-sitter-html = { workspace = true, optional = true }
tree-sitter-typescript = { workspace = true, optional = true }
[dev-dependencies]
copilot = { path = "../copilot", features = ["test-support"] }
text = { path = "../text", features = ["test-support"] }
language = { path = "../language", features = ["test-support"] }
lsp = { path = "../lsp", features = ["test-support"] }
gpui = { path = "../gpui", features = ["test-support"] }
copilot = { package="copilot2", path = "../copilot2", features = ["test-support"] }
text = { package="text2", path = "../text2", features = ["test-support"] }
language = { package="language2", path = "../language2", features = ["test-support"] }
lsp = { package = "lsp2", path = "../lsp2", features = ["test-support"] }
gpui = { package = "gpui2", path = "../gpui2", features = ["test-support"] }
util = { path = "../util", features = ["test-support"] }
project = { path = "../project", features = ["test-support"] }
settings = { path = "../settings", features = ["test-support"] }
workspace = { path = "../workspace", features = ["test-support"] }
project = { package = "project2", path = "../project2", features = ["test-support"] }
settings = { package = "settings2", path = "../settings2", features = ["test-support"] }
workspace = { package = "workspace2", path = "../workspace2", features = ["test-support"] }
multi_buffer = { path = "../multi_buffer", features = ["test-support"] }
ctor.workspace = true

View File

@ -61,7 +61,7 @@ impl BlinkManager {
}
fn blink_cursors(&mut self, epoch: usize, cx: &mut ModelContext<Self>) {
if settings::get::<EditorSettings>(cx).cursor_blink {
if EditorSettings::get_global(cx).cursor_blink {
if epoch == self.blink_epoch && self.enabled && !self.blinking_paused {
self.visible = !self.visible;
cx.notify();
@ -107,7 +107,3 @@ impl BlinkManager {
self.visible
}
}
impl Entity for BlinkManager {
type Event = ();
}

View File

@ -12,10 +12,9 @@ pub use block_map::{BlockMap, BlockPoint};
use collections::{BTreeMap, HashMap, HashSet};
use fold_map::FoldMap;
use gpui::{
color::Color,
fonts::{FontId, HighlightStyle, Underline},
text_layout::{Line, RunStyle},
Entity, ModelContext, ModelHandle,
Entity, Hsla, Model, ModelContext,
};
use inlay_map::InlayMap;
use language::{
@ -49,12 +48,12 @@ type TextHighlights = TreeMap<Option<TypeId>, Arc<(HighlightStyle, Vec<Range<Anc
type InlayHighlights = BTreeMap<TypeId, HashMap<InlayId, (HighlightStyle, InlayHighlight)>>;
pub struct DisplayMap {
buffer: ModelHandle<MultiBuffer>,
buffer: Model<MultiBuffer>,
buffer_subscription: BufferSubscription,
fold_map: FoldMap,
inlay_map: InlayMap,
tab_map: TabMap,
wrap_map: ModelHandle<WrapMap>,
wrap_map: Model<WrapMap>,
block_map: BlockMap,
text_highlights: TextHighlights,
inlay_highlights: InlayHighlights,
@ -67,7 +66,7 @@ impl Entity for DisplayMap {
impl DisplayMap {
pub fn new(
buffer: ModelHandle<MultiBuffer>,
buffer: Model<MultiBuffer>,
font_id: FontId,
font_size: f32,
wrap_width: Option<f32>,
@ -1015,7 +1014,7 @@ pub mod tests {
movement,
test::{editor_test_context::EditorTestContext, marked_display_snapshot},
};
use gpui::{color::Color, elements::*, test::observe, AppContext};
use gpui::{elements::*, test::observe, AppContext, Hsla};
use language::{
language_settings::{AllLanguageSettings, AllLanguageSettingsContent},
Buffer, Language, LanguageConfig, SelectionGoal,

File diff suppressed because it is too large Load Diff

View File

@ -3,7 +3,7 @@ use super::{
Highlights,
};
use crate::{Anchor, AnchorRangeExt, MultiBufferSnapshot, ToOffset};
use gpui::{color::Color, fonts::HighlightStyle};
use gpui::{fonts::HighlightStyle, Hsla};
use language::{Chunk, Edit, Point, TextSummary};
use std::{
any::TypeId,
@ -174,7 +174,7 @@ impl<'a> FoldMapWriter<'a> {
pub struct FoldMap {
snapshot: FoldSnapshot,
ellipses_color: Option<Color>,
ellipses_color: Option<Hsla>,
}
impl FoldMap {

View File

@ -1890,6 +1890,6 @@ mod tests {
fn init_test(cx: &mut AppContext) {
cx.set_global(SettingsStore::test(cx));
theme::init((), cx);
theme::init(cx);
}
}

View File

@ -4,9 +4,7 @@ use super::{
Highlights,
};
use crate::MultiBufferSnapshot;
use gpui::{
fonts::FontId, text_layout::LineWrapper, AppContext, Entity, ModelContext, ModelHandle, Task,
};
use gpui::{AppContext, Entity, Model, ModelContext, Task};
use language::{Chunk, Point};
use lazy_static::lazy_static;
use smol::future::yield_now;
@ -27,10 +25,6 @@ pub struct WrapMap {
font: (FontId, f32),
}
impl Entity for WrapMap {
type Event = ();
}
#[derive(Clone)]
pub struct WrapSnapshot {
tab_snapshot: TabSnapshot,
@ -78,7 +72,7 @@ impl WrapMap {
font_size: f32,
wrap_width: Option<f32>,
cx: &mut AppContext,
) -> (ModelHandle<Self>, WrapSnapshot) {
) -> (Model<Self>, WrapSnapshot) {
let handle = cx.add_model(|cx| {
let mut this = Self {
font: (font_id, font_size),
@ -1019,337 +1013,337 @@ fn consolidate_wrap_edits(edits: &mut Vec<WrapEdit>) {
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::{
display_map::{fold_map::FoldMap, inlay_map::InlayMap, tab_map::TabMap},
MultiBuffer,
};
use gpui::test::observe;
use rand::prelude::*;
use settings::SettingsStore;
use smol::stream::StreamExt;
use std::{cmp, env, num::NonZeroU32};
use text::Rope;
// #[cfg(test)]
// mod tests {
// use super::*;
// use crate::{
// display_map::{fold_map::FoldMap, inlay_map::InlayMap, tab_map::TabMap},
// MultiBuffer,
// };
// use gpui::test::observe;
// use rand::prelude::*;
// use settings::SettingsStore;
// use smol::stream::StreamExt;
// use std::{cmp, env, num::NonZeroU32};
// use text::Rope;
#[gpui::test(iterations = 100)]
async fn test_random_wraps(cx: &mut gpui::TestAppContext, mut rng: StdRng) {
init_test(cx);
// #[gpui::test(iterations = 100)]
// async fn test_random_wraps(cx: &mut gpui::TestAppContext, mut rng: StdRng) {
// init_test(cx);
cx.foreground().set_block_on_ticks(0..=50);
let operations = env::var("OPERATIONS")
.map(|i| i.parse().expect("invalid `OPERATIONS` variable"))
.unwrap_or(10);
// cx.foreground().set_block_on_ticks(0..=50);
// let operations = env::var("OPERATIONS")
// .map(|i| i.parse().expect("invalid `OPERATIONS` variable"))
// .unwrap_or(10);
let font_cache = cx.font_cache().clone();
let font_system = cx.platform().fonts();
let mut wrap_width = if rng.gen_bool(0.1) {
None
} else {
Some(rng.gen_range(0.0..=1000.0))
};
let tab_size = NonZeroU32::new(rng.gen_range(1..=4)).unwrap();
let family_id = font_cache
.load_family(&["Helvetica"], &Default::default())
.unwrap();
let font_id = font_cache
.select_font(family_id, &Default::default())
.unwrap();
let font_size = 14.0;
// let font_cache = cx.font_cache().clone();
// let font_system = cx.platform().fonts();
// let mut wrap_width = if rng.gen_bool(0.1) {
// None
// } else {
// Some(rng.gen_range(0.0..=1000.0))
// };
// let tab_size = NonZeroU32::new(rng.gen_range(1..=4)).unwrap();
// let family_id = font_cache
// .load_family(&["Helvetica"], &Default::default())
// .unwrap();
// let font_id = font_cache
// .select_font(family_id, &Default::default())
// .unwrap();
// let font_size = 14.0;
log::info!("Tab size: {}", tab_size);
log::info!("Wrap width: {:?}", wrap_width);
// log::info!("Tab size: {}", tab_size);
// log::info!("Wrap width: {:?}", wrap_width);
let buffer = cx.update(|cx| {
if rng.gen() {
MultiBuffer::build_random(&mut rng, cx)
} else {
let len = rng.gen_range(0..10);
let text = util::RandomCharIter::new(&mut rng)
.take(len)
.collect::<String>();
MultiBuffer::build_simple(&text, cx)
}
});
let mut buffer_snapshot = buffer.read_with(cx, |buffer, cx| buffer.snapshot(cx));
log::info!("Buffer text: {:?}", buffer_snapshot.text());
let (mut inlay_map, inlay_snapshot) = InlayMap::new(buffer_snapshot.clone());
log::info!("InlayMap text: {:?}", inlay_snapshot.text());
let (mut fold_map, fold_snapshot) = FoldMap::new(inlay_snapshot.clone());
log::info!("FoldMap text: {:?}", fold_snapshot.text());
let (mut tab_map, _) = TabMap::new(fold_snapshot.clone(), tab_size);
let tabs_snapshot = tab_map.set_max_expansion_column(32);
log::info!("TabMap text: {:?}", tabs_snapshot.text());
// let buffer = cx.update(|cx| {
// if rng.gen() {
// MultiBuffer::build_random(&mut rng, cx)
// } else {
// let len = rng.gen_range(0..10);
// let text = util::RandomCharIter::new(&mut rng)
// .take(len)
// .collect::<String>();
// MultiBuffer::build_simple(&text, cx)
// }
// });
// let mut buffer_snapshot = buffer.read_with(cx, |buffer, cx| buffer.snapshot(cx));
// log::info!("Buffer text: {:?}", buffer_snapshot.text());
// let (mut inlay_map, inlay_snapshot) = InlayMap::new(buffer_snapshot.clone());
// log::info!("InlayMap text: {:?}", inlay_snapshot.text());
// let (mut fold_map, fold_snapshot) = FoldMap::new(inlay_snapshot.clone());
// log::info!("FoldMap text: {:?}", fold_snapshot.text());
// let (mut tab_map, _) = TabMap::new(fold_snapshot.clone(), tab_size);
// let tabs_snapshot = tab_map.set_max_expansion_column(32);
// log::info!("TabMap text: {:?}", tabs_snapshot.text());
let mut line_wrapper = LineWrapper::new(font_id, font_size, font_system);
let unwrapped_text = tabs_snapshot.text();
let expected_text = wrap_text(&unwrapped_text, wrap_width, &mut line_wrapper);
// let mut line_wrapper = LineWrapper::new(font_id, font_size, font_system);
// let unwrapped_text = tabs_snapshot.text();
// let expected_text = wrap_text(&unwrapped_text, wrap_width, &mut line_wrapper);
let (wrap_map, _) =
cx.update(|cx| WrapMap::new(tabs_snapshot.clone(), font_id, font_size, wrap_width, cx));
let mut notifications = observe(&wrap_map, cx);
// let (wrap_map, _) =
// cx.update(|cx| WrapMap::new(tabs_snapshot.clone(), font_id, font_size, wrap_width, cx));
// let mut notifications = observe(&wrap_map, cx);
if wrap_map.read_with(cx, |map, _| map.is_rewrapping()) {
notifications.next().await.unwrap();
}
// if wrap_map.read_with(cx, |map, _| map.is_rewrapping()) {
// notifications.next().await.unwrap();
// }
let (initial_snapshot, _) = wrap_map.update(cx, |map, cx| {
assert!(!map.is_rewrapping());
map.sync(tabs_snapshot.clone(), Vec::new(), cx)
});
// let (initial_snapshot, _) = wrap_map.update(cx, |map, cx| {
// assert!(!map.is_rewrapping());
// map.sync(tabs_snapshot.clone(), Vec::new(), cx)
// });
let actual_text = initial_snapshot.text();
assert_eq!(
actual_text, expected_text,
"unwrapped text is: {:?}",
unwrapped_text
);
log::info!("Wrapped text: {:?}", actual_text);
// let actual_text = initial_snapshot.text();
// assert_eq!(
// actual_text, expected_text,
// "unwrapped text is: {:?}",
// unwrapped_text
// );
// log::info!("Wrapped text: {:?}", actual_text);
let mut next_inlay_id = 0;
let mut edits = Vec::new();
for _i in 0..operations {
log::info!("{} ==============================================", _i);
// let mut next_inlay_id = 0;
// let mut edits = Vec::new();
// for _i in 0..operations {
// log::info!("{} ==============================================", _i);
let mut buffer_edits = Vec::new();
match rng.gen_range(0..=100) {
0..=19 => {
wrap_width = if rng.gen_bool(0.2) {
None
} else {
Some(rng.gen_range(0.0..=1000.0))
};
log::info!("Setting wrap width to {:?}", wrap_width);
wrap_map.update(cx, |map, cx| map.set_wrap_width(wrap_width, cx));
}
20..=39 => {
for (fold_snapshot, fold_edits) in fold_map.randomly_mutate(&mut rng) {
let (tabs_snapshot, tab_edits) =
tab_map.sync(fold_snapshot, fold_edits, tab_size);
let (mut snapshot, wrap_edits) =
wrap_map.update(cx, |map, cx| map.sync(tabs_snapshot, tab_edits, cx));
snapshot.check_invariants();
snapshot.verify_chunks(&mut rng);
edits.push((snapshot, wrap_edits));
}
}
40..=59 => {
let (inlay_snapshot, inlay_edits) =
inlay_map.randomly_mutate(&mut next_inlay_id, &mut rng);
let (fold_snapshot, fold_edits) = fold_map.read(inlay_snapshot, inlay_edits);
let (tabs_snapshot, tab_edits) =
tab_map.sync(fold_snapshot, fold_edits, tab_size);
let (mut snapshot, wrap_edits) =
wrap_map.update(cx, |map, cx| map.sync(tabs_snapshot, tab_edits, cx));
snapshot.check_invariants();
snapshot.verify_chunks(&mut rng);
edits.push((snapshot, wrap_edits));
}
_ => {
buffer.update(cx, |buffer, cx| {
let subscription = buffer.subscribe();
let edit_count = rng.gen_range(1..=5);
buffer.randomly_mutate(&mut rng, edit_count, cx);
buffer_snapshot = buffer.snapshot(cx);
buffer_edits.extend(subscription.consume());
});
}
}
// let mut buffer_edits = Vec::new();
// match rng.gen_range(0..=100) {
// 0..=19 => {
// wrap_width = if rng.gen_bool(0.2) {
// None
// } else {
// Some(rng.gen_range(0.0..=1000.0))
// };
// log::info!("Setting wrap width to {:?}", wrap_width);
// wrap_map.update(cx, |map, cx| map.set_wrap_width(wrap_width, cx));
// }
// 20..=39 => {
// for (fold_snapshot, fold_edits) in fold_map.randomly_mutate(&mut rng) {
// let (tabs_snapshot, tab_edits) =
// tab_map.sync(fold_snapshot, fold_edits, tab_size);
// let (mut snapshot, wrap_edits) =
// wrap_map.update(cx, |map, cx| map.sync(tabs_snapshot, tab_edits, cx));
// snapshot.check_invariants();
// snapshot.verify_chunks(&mut rng);
// edits.push((snapshot, wrap_edits));
// }
// }
// 40..=59 => {
// let (inlay_snapshot, inlay_edits) =
// inlay_map.randomly_mutate(&mut next_inlay_id, &mut rng);
// let (fold_snapshot, fold_edits) = fold_map.read(inlay_snapshot, inlay_edits);
// let (tabs_snapshot, tab_edits) =
// tab_map.sync(fold_snapshot, fold_edits, tab_size);
// let (mut snapshot, wrap_edits) =
// wrap_map.update(cx, |map, cx| map.sync(tabs_snapshot, tab_edits, cx));
// snapshot.check_invariants();
// snapshot.verify_chunks(&mut rng);
// edits.push((snapshot, wrap_edits));
// }
// _ => {
// buffer.update(cx, |buffer, cx| {
// let subscription = buffer.subscribe();
// let edit_count = rng.gen_range(1..=5);
// buffer.randomly_mutate(&mut rng, edit_count, cx);
// buffer_snapshot = buffer.snapshot(cx);
// buffer_edits.extend(subscription.consume());
// });
// }
// }
log::info!("Buffer text: {:?}", buffer_snapshot.text());
let (inlay_snapshot, inlay_edits) =
inlay_map.sync(buffer_snapshot.clone(), buffer_edits);
log::info!("InlayMap text: {:?}", inlay_snapshot.text());
let (fold_snapshot, fold_edits) = fold_map.read(inlay_snapshot, inlay_edits);
log::info!("FoldMap text: {:?}", fold_snapshot.text());
let (tabs_snapshot, tab_edits) = tab_map.sync(fold_snapshot, fold_edits, tab_size);
log::info!("TabMap text: {:?}", tabs_snapshot.text());
// log::info!("Buffer text: {:?}", buffer_snapshot.text());
// let (inlay_snapshot, inlay_edits) =
// inlay_map.sync(buffer_snapshot.clone(), buffer_edits);
// log::info!("InlayMap text: {:?}", inlay_snapshot.text());
// let (fold_snapshot, fold_edits) = fold_map.read(inlay_snapshot, inlay_edits);
// log::info!("FoldMap text: {:?}", fold_snapshot.text());
// let (tabs_snapshot, tab_edits) = tab_map.sync(fold_snapshot, fold_edits, tab_size);
// log::info!("TabMap text: {:?}", tabs_snapshot.text());
let unwrapped_text = tabs_snapshot.text();
let expected_text = wrap_text(&unwrapped_text, wrap_width, &mut line_wrapper);
let (mut snapshot, wrap_edits) =
wrap_map.update(cx, |map, cx| map.sync(tabs_snapshot.clone(), tab_edits, cx));
snapshot.check_invariants();
snapshot.verify_chunks(&mut rng);
edits.push((snapshot, wrap_edits));
// let unwrapped_text = tabs_snapshot.text();
// let expected_text = wrap_text(&unwrapped_text, wrap_width, &mut line_wrapper);
// let (mut snapshot, wrap_edits) =
// wrap_map.update(cx, |map, cx| map.sync(tabs_snapshot.clone(), tab_edits, cx));
// snapshot.check_invariants();
// snapshot.verify_chunks(&mut rng);
// edits.push((snapshot, wrap_edits));
if wrap_map.read_with(cx, |map, _| map.is_rewrapping()) && rng.gen_bool(0.4) {
log::info!("Waiting for wrapping to finish");
while wrap_map.read_with(cx, |map, _| map.is_rewrapping()) {
notifications.next().await.unwrap();
}
wrap_map.read_with(cx, |map, _| assert!(map.pending_edits.is_empty()));
}
// if wrap_map.read_with(cx, |map, _| map.is_rewrapping()) && rng.gen_bool(0.4) {
// log::info!("Waiting for wrapping to finish");
// while wrap_map.read_with(cx, |map, _| map.is_rewrapping()) {
// notifications.next().await.unwrap();
// }
// wrap_map.read_with(cx, |map, _| assert!(map.pending_edits.is_empty()));
// }
if !wrap_map.read_with(cx, |map, _| map.is_rewrapping()) {
let (mut wrapped_snapshot, wrap_edits) =
wrap_map.update(cx, |map, cx| map.sync(tabs_snapshot, Vec::new(), cx));
let actual_text = wrapped_snapshot.text();
let actual_longest_row = wrapped_snapshot.longest_row();
log::info!("Wrapping finished: {:?}", actual_text);
wrapped_snapshot.check_invariants();
wrapped_snapshot.verify_chunks(&mut rng);
edits.push((wrapped_snapshot.clone(), wrap_edits));
assert_eq!(
actual_text, expected_text,
"unwrapped text is: {:?}",
unwrapped_text
);
// if !wrap_map.read_with(cx, |map, _| map.is_rewrapping()) {
// let (mut wrapped_snapshot, wrap_edits) =
// wrap_map.update(cx, |map, cx| map.sync(tabs_snapshot, Vec::new(), cx));
// let actual_text = wrapped_snapshot.text();
// let actual_longest_row = wrapped_snapshot.longest_row();
// log::info!("Wrapping finished: {:?}", actual_text);
// wrapped_snapshot.check_invariants();
// wrapped_snapshot.verify_chunks(&mut rng);
// edits.push((wrapped_snapshot.clone(), wrap_edits));
// assert_eq!(
// actual_text, expected_text,
// "unwrapped text is: {:?}",
// unwrapped_text
// );
let mut summary = TextSummary::default();
for (ix, item) in wrapped_snapshot
.transforms
.items(&())
.into_iter()
.enumerate()
{
summary += &item.summary.output;
log::info!("{} summary: {:?}", ix, item.summary.output,);
}
// let mut summary = TextSummary::default();
// for (ix, item) in wrapped_snapshot
// .transforms
// .items(&())
// .into_iter()
// .enumerate()
// {
// summary += &item.summary.output;
// log::info!("{} summary: {:?}", ix, item.summary.output,);
// }
if tab_size.get() == 1
|| !wrapped_snapshot
.tab_snapshot
.fold_snapshot
.text()
.contains('\t')
{
let mut expected_longest_rows = Vec::new();
let mut longest_line_len = -1;
for (row, line) in expected_text.split('\n').enumerate() {
let line_char_count = line.chars().count() as isize;
if line_char_count > longest_line_len {
expected_longest_rows.clear();
longest_line_len = line_char_count;
}
if line_char_count >= longest_line_len {
expected_longest_rows.push(row as u32);
}
}
// if tab_size.get() == 1
// || !wrapped_snapshot
// .tab_snapshot
// .fold_snapshot
// .text()
// .contains('\t')
// {
// let mut expected_longest_rows = Vec::new();
// let mut longest_line_len = -1;
// for (row, line) in expected_text.split('\n').enumerate() {
// let line_char_count = line.chars().count() as isize;
// if line_char_count > longest_line_len {
// expected_longest_rows.clear();
// longest_line_len = line_char_count;
// }
// if line_char_count >= longest_line_len {
// expected_longest_rows.push(row as u32);
// }
// }
assert!(
expected_longest_rows.contains(&actual_longest_row),
"incorrect longest row {}. expected {:?} with length {}",
actual_longest_row,
expected_longest_rows,
longest_line_len,
)
}
}
}
// assert!(
// expected_longest_rows.contains(&actual_longest_row),
// "incorrect longest row {}. expected {:?} with length {}",
// actual_longest_row,
// expected_longest_rows,
// longest_line_len,
// )
// }
// }
// }
let mut initial_text = Rope::from(initial_snapshot.text().as_str());
for (snapshot, patch) in edits {
let snapshot_text = Rope::from(snapshot.text().as_str());
for edit in &patch {
let old_start = initial_text.point_to_offset(Point::new(edit.new.start, 0));
let old_end = initial_text.point_to_offset(cmp::min(
Point::new(edit.new.start + edit.old.len() as u32, 0),
initial_text.max_point(),
));
let new_start = snapshot_text.point_to_offset(Point::new(edit.new.start, 0));
let new_end = snapshot_text.point_to_offset(cmp::min(
Point::new(edit.new.end, 0),
snapshot_text.max_point(),
));
let new_text = snapshot_text
.chunks_in_range(new_start..new_end)
.collect::<String>();
// let mut initial_text = Rope::from(initial_snapshot.text().as_str());
// for (snapshot, patch) in edits {
// let snapshot_text = Rope::from(snapshot.text().as_str());
// for edit in &patch {
// let old_start = initial_text.point_to_offset(Point::new(edit.new.start, 0));
// let old_end = initial_text.point_to_offset(cmp::min(
// Point::new(edit.new.start + edit.old.len() as u32, 0),
// initial_text.max_point(),
// ));
// let new_start = snapshot_text.point_to_offset(Point::new(edit.new.start, 0));
// let new_end = snapshot_text.point_to_offset(cmp::min(
// Point::new(edit.new.end, 0),
// snapshot_text.max_point(),
// ));
// let new_text = snapshot_text
// .chunks_in_range(new_start..new_end)
// .collect::<String>();
initial_text.replace(old_start..old_end, &new_text);
}
assert_eq!(initial_text.to_string(), snapshot_text.to_string());
}
// initial_text.replace(old_start..old_end, &new_text);
// }
// assert_eq!(initial_text.to_string(), snapshot_text.to_string());
// }
if wrap_map.read_with(cx, |map, _| map.is_rewrapping()) {
log::info!("Waiting for wrapping to finish");
while wrap_map.read_with(cx, |map, _| map.is_rewrapping()) {
notifications.next().await.unwrap();
}
}
wrap_map.read_with(cx, |map, _| assert!(map.pending_edits.is_empty()));
}
// if wrap_map.read_with(cx, |map, _| map.is_rewrapping()) {
// log::info!("Waiting for wrapping to finish");
// while wrap_map.read_with(cx, |map, _| map.is_rewrapping()) {
// notifications.next().await.unwrap();
// }
// }
// wrap_map.read_with(cx, |map, _| assert!(map.pending_edits.is_empty()));
// }
fn init_test(cx: &mut gpui::TestAppContext) {
cx.foreground().forbid_parking();
cx.update(|cx| {
cx.set_global(SettingsStore::test(cx));
theme::init((), cx);
});
}
// fn init_test(cx: &mut gpui::TestAppContext) {
// cx.foreground().forbid_parking();
// cx.update(|cx| {
// cx.set_global(SettingsStore::test(cx));
// theme::init((), cx);
// });
// }
fn wrap_text(
unwrapped_text: &str,
wrap_width: Option<f32>,
line_wrapper: &mut LineWrapper,
) -> String {
if let Some(wrap_width) = wrap_width {
let mut wrapped_text = String::new();
for (row, line) in unwrapped_text.split('\n').enumerate() {
if row > 0 {
wrapped_text.push('\n')
}
// fn wrap_text(
// unwrapped_text: &str,
// wrap_width: Option<f32>,
// line_wrapper: &mut LineWrapper,
// ) -> String {
// if let Some(wrap_width) = wrap_width {
// let mut wrapped_text = String::new();
// for (row, line) in unwrapped_text.split('\n').enumerate() {
// if row > 0 {
// wrapped_text.push('\n')
// }
let mut prev_ix = 0;
for boundary in line_wrapper.wrap_line(line, wrap_width) {
wrapped_text.push_str(&line[prev_ix..boundary.ix]);
wrapped_text.push('\n');
wrapped_text.push_str(&" ".repeat(boundary.next_indent as usize));
prev_ix = boundary.ix;
}
wrapped_text.push_str(&line[prev_ix..]);
}
wrapped_text
} else {
unwrapped_text.to_string()
}
}
// let mut prev_ix = 0;
// for boundary in line_wrapper.wrap_line(line, wrap_width) {
// wrapped_text.push_str(&line[prev_ix..boundary.ix]);
// wrapped_text.push('\n');
// wrapped_text.push_str(&" ".repeat(boundary.next_indent as usize));
// prev_ix = boundary.ix;
// }
// wrapped_text.push_str(&line[prev_ix..]);
// }
// wrapped_text
// } else {
// unwrapped_text.to_string()
// }
// }
impl WrapSnapshot {
pub fn text(&self) -> String {
self.text_chunks(0).collect()
}
// impl WrapSnapshot {
// pub fn text(&self) -> String {
// self.text_chunks(0).collect()
// }
pub fn text_chunks(&self, wrap_row: u32) -> impl Iterator<Item = &str> {
self.chunks(
wrap_row..self.max_point().row() + 1,
false,
Highlights::default(),
)
.map(|h| h.text)
}
// pub fn text_chunks(&self, wrap_row: u32) -> impl Iterator<Item = &str> {
// self.chunks(
// wrap_row..self.max_point().row() + 1,
// false,
// Highlights::default(),
// )
// .map(|h| h.text)
// }
fn verify_chunks(&mut self, rng: &mut impl Rng) {
for _ in 0..5 {
let mut end_row = rng.gen_range(0..=self.max_point().row());
let start_row = rng.gen_range(0..=end_row);
end_row += 1;
// fn verify_chunks(&mut self, rng: &mut impl Rng) {
// for _ in 0..5 {
// let mut end_row = rng.gen_range(0..=self.max_point().row());
// let start_row = rng.gen_range(0..=end_row);
// end_row += 1;
let mut expected_text = self.text_chunks(start_row).collect::<String>();
if expected_text.ends_with('\n') {
expected_text.push('\n');
}
let mut expected_text = expected_text
.lines()
.take((end_row - start_row) as usize)
.collect::<Vec<_>>()
.join("\n");
if end_row <= self.max_point().row() {
expected_text.push('\n');
}
// let mut expected_text = self.text_chunks(start_row).collect::<String>();
// if expected_text.ends_with('\n') {
// expected_text.push('\n');
// }
// let mut expected_text = expected_text
// .lines()
// .take((end_row - start_row) as usize)
// .collect::<Vec<_>>()
// .join("\n");
// if end_row <= self.max_point().row() {
// expected_text.push('\n');
// }
let actual_text = self
.chunks(start_row..end_row, true, Highlights::default())
.map(|c| c.text)
.collect::<String>();
assert_eq!(
expected_text,
actual_text,
"chunks != highlighted_chunks for rows {:?}",
start_row..end_row
);
}
}
}
}
// let actual_text = self
// .chunks(start_row..end_row, true, Highlights::default())
// .map(|c| c.text)
// .collect::<String>();
// assert_eq!(
// expected_text,
// actual_text,
// "chunks != highlighted_chunks for rows {:?}",
// start_row..end_row
// );
// }
// }
// }
// }

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
use gpui::Settings;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use settings::Setting;
#[derive(Deserialize)]
pub struct EditorSettings {
@ -47,7 +47,7 @@ pub struct ScrollbarContent {
pub selections: Option<bool>,
}
impl Setting for EditorSettings {
impl Settings for EditorSettings {
const KEY: Option<&'static str> = None;
type FileContent = EditorSettingsContent;

File diff suppressed because it is too large Load Diff

View File

@ -9,7 +9,7 @@ use gpui::{
actions,
elements::{Flex, MouseEventHandler, Padding, ParentElement, Text},
platform::{CursorStyle, MouseButton},
AnyElement, AppContext, Element, ModelHandle, Task, ViewContext, WeakViewHandle,
AnyElement, AppContext, Element, Model, Task, ViewContext, WeakViewHandle,
};
use language::{
markdown, Bias, DiagnosticEntry, DiagnosticSeverity, Language, LanguageRegistry, ParsedMarkdown,

View File

@ -11,7 +11,7 @@ use crate::{
use anyhow::Context;
use clock::Global;
use futures::future;
use gpui::{ModelContext, ModelHandle, Task, ViewContext};
use gpui::{Model, ModelContext, Task, ViewContext};
use language::{language_settings::InlayHintKind, Buffer, BufferSnapshot};
use parking_lot::RwLock;
use project::{InlayHint, ResolveState};
@ -3244,7 +3244,7 @@ all hints should be invalidated and requeried for all of its visible excerpts"
cx.update(|cx| {
cx.set_global(SettingsStore::test(cx));
theme::init((), cx);
theme::init(cx);
client::init_settings(cx);
language::init(cx);
Project::init_settings(cx);

View File

@ -7,10 +7,8 @@ use anyhow::{Context, Result};
use collections::HashSet;
use futures::future::try_join_all;
use gpui::{
elements::*,
geometry::vector::{vec2f, Vector2F},
AppContext, AsyncAppContext, Entity, ModelHandle, Subscription, Task, View, ViewContext,
ViewHandle, WeakViewHandle,
point, AnyElement, AppContext, AsyncAppContext, Entity, Model, Pixels, Subscription, Task,
View, ViewContext, WeakView,
};
use language::{
proto::serialize_anchor as serialize_text_anchor, Bias, Buffer, OffsetRangeExt, Point,
@ -49,12 +47,12 @@ impl FollowableItem for Editor {
}
fn from_state_proto(
pane: ViewHandle<workspace::Pane>,
workspace: ViewHandle<Workspace>,
pane: View<workspace::Pane>,
workspace: View<Workspace>,
remote_id: ViewId,
state: &mut Option<proto::view::Variant>,
cx: &mut AppContext,
) -> Option<Task<Result<ViewHandle<Self>>>> {
) -> Option<Task<Result<View<Self>>>> {
let project = workspace.read(cx).project().to_owned();
let Some(proto::view::Variant::Editor(_)) = state else {
return None;
@ -286,7 +284,7 @@ impl FollowableItem for Editor {
fn apply_update_proto(
&mut self,
project: &ModelHandle<Project>,
project: &Model<Project>,
message: update_view::Variant,
cx: &mut ViewContext<Self>,
) -> Task<Result<()>> {
@ -312,8 +310,8 @@ impl FollowableItem for Editor {
}
async fn update_editor_from_message(
this: WeakViewHandle<Editor>,
project: ModelHandle<Project>,
this: WeakView<Editor>,
project: Model<Project>,
message: proto::update_view::Editor,
cx: &mut AsyncAppContext,
) -> Result<()> {
@ -353,7 +351,7 @@ async fn update_editor_from_message(
continue;
};
let buffer_id = excerpt.buffer_id;
let Some(buffer) = project.read(cx).buffer_for_id(buffer_id, cx) else {
let Some(buffer) = project.read(cx).buffer_for_id(buffer_id) else {
continue;
};
@ -430,7 +428,7 @@ async fn update_editor_from_message(
editor.set_scroll_anchor_remote(
ScrollAnchor {
anchor: scroll_top_anchor,
offset: vec2f(message.scroll_x, message.scroll_y),
offset: point(message.scroll_x, message.scroll_y),
},
cx,
);
@ -573,29 +571,26 @@ impl Item for Editor {
}
}
fn tab_content<T: 'static>(
&self,
detail: Option<usize>,
style: &theme::Tab,
cx: &AppContext,
) -> AnyElement<T> {
Flex::row()
.with_child(Label::new(self.title(cx).to_string(), style.label.clone()).into_any())
.with_children(detail.and_then(|detail| {
let path = path_for_buffer(&self.buffer, detail, false, cx)?;
let description = path.to_string_lossy();
Some(
Label::new(
util::truncate_and_trailoff(&description, MAX_TAB_TITLE_LEN),
style.description.text.clone(),
)
.contained()
.with_style(style.description.container)
.aligned(),
)
}))
.align_children_center()
.into_any()
fn tab_content<T: 'static>(&self, detail: Option<usize>, cx: &AppContext) -> AnyElement<T> {
todo!();
// Flex::row()
// .with_child(Label::new(self.title(cx).to_string(), style.label.clone()).into_any())
// .with_children(detail.and_then(|detail| {
// let path = path_for_buffer(&self.buffer, detail, false, cx)?;
// let description = path.to_string_lossy();
// Some(
// Label::new(
// util::truncate_and_trailoff(&description, MAX_TAB_TITLE_LEN),
// style.description.text.clone(),
// )
// .contained()
// .with_style(style.description.container)
// .aligned(),
// )
// }))
// .align_children_center()
// .into_any()
}
fn for_each_project_item(&self, cx: &AppContext, f: &mut dyn FnMut(usize, &dyn project::Item)) {
@ -646,11 +641,7 @@ impl Item for Editor {
}
}
fn save(
&mut self,
project: ModelHandle<Project>,
cx: &mut ViewContext<Self>,
) -> Task<Result<()>> {
fn save(&mut self, project: Model<Project>, cx: &mut ViewContext<Self>) -> Task<Result<()>> {
self.report_editor_event("save", None, cx);
let format = self.perform_format(project.clone(), FormatTrigger::Save, cx);
let buffers = self.buffer().clone().read(cx).all_buffers();
@ -690,7 +681,7 @@ impl Item for Editor {
fn save_as(
&mut self,
project: ModelHandle<Project>,
project: Model<Project>,
abs_path: PathBuf,
cx: &mut ViewContext<Self>,
) -> Task<Result<()>> {
@ -710,11 +701,7 @@ impl Item for Editor {
})
}
fn reload(
&mut self,
project: ModelHandle<Project>,
cx: &mut ViewContext<Self>,
) -> Task<Result<()>> {
fn reload(&mut self, project: Model<Project>, cx: &mut ViewContext<Self>) -> Task<Result<()>> {
let buffer = self.buffer().clone();
let buffers = self.buffer.read(cx).all_buffers();
let reload_buffers =
@ -761,11 +748,11 @@ impl Item for Editor {
result
}
fn as_searchable(&self, handle: &ViewHandle<Self>) -> Option<Box<dyn SearchableItemHandle>> {
fn as_searchable(&self, handle: &View<Self>) -> Option<Box<dyn SearchableItemHandle>> {
Some(Box::new(handle.clone()))
}
fn pixel_position_of_cursor(&self, _: &AppContext) -> Option<Vector2F> {
fn pixel_position_of_cursor(&self, _: &AppContext) -> Option<gpui::Point<Pixels>> {
self.pixel_position_of_newest_cursor
}
@ -773,35 +760,36 @@ impl Item for Editor {
ToolbarItemLocation::PrimaryLeft { flex: None }
}
fn breadcrumbs(&self, theme: &theme::Theme, cx: &AppContext) -> Option<Vec<BreadcrumbText>> {
let cursor = self.selections.newest_anchor().head();
let multibuffer = &self.buffer().read(cx);
let (buffer_id, symbols) =
multibuffer.symbols_containing(cursor, Some(&theme.editor.syntax), cx)?;
let buffer = multibuffer.buffer(buffer_id)?;
fn breadcrumbs(&self, cx: &AppContext) -> Option<Vec<BreadcrumbText>> {
todo!();
// let cursor = self.selections.newest_anchor().head();
// let multibuffer = &self.buffer().read(cx);
// let (buffer_id, symbols) =
// multibuffer.symbols_containing(cursor, Some(&theme.editor.syntax), cx)?;
// let buffer = multibuffer.buffer(buffer_id)?;
let buffer = buffer.read(cx);
let filename = buffer
.snapshot()
.resolve_file_path(
cx,
self.project
.as_ref()
.map(|project| project.read(cx).visible_worktrees(cx).count() > 1)
.unwrap_or_default(),
)
.map(|path| path.to_string_lossy().to_string())
.unwrap_or_else(|| "untitled".to_string());
// let buffer = buffer.read(cx);
// let filename = buffer
// .snapshot()
// .resolve_file_path(
// cx,
// self.project
// .as_ref()
// .map(|project| project.read(cx).visible_worktrees(cx).count() > 1)
// .unwrap_or_default(),
// )
// .map(|path| path.to_string_lossy().to_string())
// .unwrap_or_else(|| "untitled".to_string());
let mut breadcrumbs = vec![BreadcrumbText {
text: filename,
highlights: None,
}];
breadcrumbs.extend(symbols.into_iter().map(|symbol| BreadcrumbText {
text: symbol.text,
highlights: Some(symbol.highlight_ranges),
}));
Some(breadcrumbs)
// let mut breadcrumbs = vec![BreadcrumbText {
// text: filename,
// highlights: None,
// }];
// breadcrumbs.extend(symbols.into_iter().map(|symbol| BreadcrumbText {
// text: symbol.text,
// highlights: Some(symbol.highlight_ranges),
// }));
// Some(breadcrumbs)
}
fn added_to_workspace(&mut self, workspace: &mut Workspace, cx: &mut ViewContext<Self>) {
@ -810,7 +798,7 @@ impl Item for Editor {
self.workspace = Some((workspace.weak_handle(), workspace.database_id()));
fn serialize(
buffer: ModelHandle<Buffer>,
buffer: Model<Buffer>,
workspace_id: WorkspaceId,
item_id: ItemId,
cx: &mut AppContext,
@ -847,12 +835,12 @@ impl Item for Editor {
}
fn deserialize(
project: ModelHandle<Project>,
_workspace: WeakViewHandle<Workspace>,
project: Model<Project>,
_workspace: WeakView<Workspace>,
workspace_id: workspace::WorkspaceId,
item_id: ItemId,
cx: &mut ViewContext<Pane>,
) -> Task<Result<ViewHandle<Self>>> {
) -> Task<Result<View<Self>>> {
let project_item: Result<_> = project.update(cx, |project, cx| {
// Look up the path with this key associated, create a self with that path
let path = DB
@ -894,8 +882,8 @@ impl ProjectItem for Editor {
type Item = Buffer;
fn for_project_item(
project: ModelHandle<Project>,
buffer: ModelHandle<Buffer>,
project: Model<Project>,
buffer: Model<Buffer>,
cx: &mut ViewContext<Self>,
) -> Self {
Self::for_buffer(buffer, Some(project), cx)
@ -1134,89 +1122,89 @@ pub struct CursorPosition {
_observe_active_editor: Option<Subscription>,
}
impl Default for CursorPosition {
fn default() -> Self {
Self::new()
}
}
// impl Default for CursorPosition {
// fn default() -> Self {
// Self::new()
// }
// }
impl CursorPosition {
pub fn new() -> Self {
Self {
position: None,
selected_count: 0,
_observe_active_editor: None,
}
}
// impl CursorPosition {
// pub fn new() -> Self {
// Self {
// position: None,
// selected_count: 0,
// _observe_active_editor: None,
// }
// }
fn update_position(&mut self, editor: ViewHandle<Editor>, cx: &mut ViewContext<Self>) {
let editor = editor.read(cx);
let buffer = editor.buffer().read(cx).snapshot(cx);
// fn update_position(&mut self, editor: View<Editor>, cx: &mut ViewContext<Self>) {
// let editor = editor.read(cx);
// let buffer = editor.buffer().read(cx).snapshot(cx);
self.selected_count = 0;
let mut last_selection: Option<Selection<usize>> = None;
for selection in editor.selections.all::<usize>(cx) {
self.selected_count += selection.end - selection.start;
if last_selection
.as_ref()
.map_or(true, |last_selection| selection.id > last_selection.id)
{
last_selection = Some(selection);
}
}
self.position = last_selection.map(|s| s.head().to_point(&buffer));
// self.selected_count = 0;
// let mut last_selection: Option<Selection<usize>> = None;
// for selection in editor.selections.all::<usize>(cx) {
// self.selected_count += selection.end - selection.start;
// if last_selection
// .as_ref()
// .map_or(true, |last_selection| selection.id > last_selection.id)
// {
// last_selection = Some(selection);
// }
// }
// self.position = last_selection.map(|s| s.head().to_point(&buffer));
cx.notify();
}
}
// cx.notify();
// }
// }
impl Entity for CursorPosition {
type Event = ();
}
// impl Entity for CursorPosition {
// type Event = ();
// }
impl View for CursorPosition {
fn ui_name() -> &'static str {
"CursorPosition"
}
// impl View for CursorPosition {
// fn ui_name() -> &'static str {
// "CursorPosition"
// }
fn render(&mut self, cx: &mut ViewContext<Self>) -> AnyElement<Self> {
if let Some(position) = self.position {
let theme = &theme::current(cx).workspace.status_bar;
let mut text = format!(
"{}{FILE_ROW_COLUMN_DELIMITER}{}",
position.row + 1,
position.column + 1
);
if self.selected_count > 0 {
write!(text, " ({} selected)", self.selected_count).unwrap();
}
Label::new(text, theme.cursor_position.clone()).into_any()
} else {
Empty::new().into_any()
}
}
}
// fn render(&mut self, cx: &mut ViewContext<Self>) -> AnyElement<Self> {
// if let Some(position) = self.position {
// let theme = &theme::current(cx).workspace.status_bar;
// let mut text = format!(
// "{}{FILE_ROW_COLUMN_DELIMITER}{}",
// position.row + 1,
// position.column + 1
// );
// if self.selected_count > 0 {
// write!(text, " ({} selected)", self.selected_count).unwrap();
// }
// Label::new(text, theme.cursor_position.clone()).into_any()
// } else {
// Empty::new().into_any()
// }
// }
// }
impl StatusItemView for CursorPosition {
fn set_active_pane_item(
&mut self,
active_pane_item: Option<&dyn ItemHandle>,
cx: &mut ViewContext<Self>,
) {
if let Some(editor) = active_pane_item.and_then(|item| item.act_as::<Editor>(cx)) {
self._observe_active_editor = Some(cx.observe(&editor, Self::update_position));
self.update_position(editor, cx);
} else {
self.position = None;
self._observe_active_editor = None;
}
// impl StatusItemView for CursorPosition {
// fn set_active_pane_item(
// &mut self,
// active_pane_item: Option<&dyn ItemHandle>,
// cx: &mut ViewContext<Self>,
// ) {
// if let Some(editor) = active_pane_item.and_then(|item| item.act_as::<Editor>(cx)) {
// self._observe_active_editor = Some(cx.observe(&editor, Self::update_position));
// self.update_position(editor, cx);
// } else {
// self.position = None;
// self._observe_active_editor = None;
// }
cx.notify();
}
}
// cx.notify();
// }
// }
fn path_for_buffer<'a>(
buffer: &ModelHandle<MultiBuffer>,
buffer: &Model<MultiBuffer>,
height: usize,
include_filename: bool,
cx: &'a AppContext,

View File

@ -919,7 +919,7 @@ mod tests {
fn init_test(cx: &mut gpui::AppContext) {
cx.set_global(SettingsStore::test(cx));
theme::init((), cx);
theme::init(cx);
language::init(cx);
crate::init(cx);
Project::init_settings(cx);

View File

@ -1,152 +1,148 @@
use gpui::{actions, geometry::vector::Vector2F, AppContext, Axis, ViewContext};
use language::Bias;
use gpui::AppContext;
use crate::{Editor, EditorMode};
use super::{autoscroll::Autoscroll, scroll_amount::ScrollAmount, ScrollAnchor};
actions!(
editor,
[
LineDown,
LineUp,
HalfPageDown,
HalfPageUp,
PageDown,
PageUp,
NextScreen,
ScrollCursorTop,
ScrollCursorCenter,
ScrollCursorBottom,
]
);
// actions!(
// editor,
// [
// LineDown,
// LineUp,
// HalfPageDown,
// HalfPageUp,
// PageDown,
// PageUp,
// NextScreen,
// ScrollCursorTop,
// ScrollCursorCenter,
// ScrollCursorBottom,
// ]
// );
pub fn init(cx: &mut AppContext) {
cx.add_action(Editor::next_screen);
cx.add_action(Editor::scroll_cursor_top);
cx.add_action(Editor::scroll_cursor_center);
cx.add_action(Editor::scroll_cursor_bottom);
cx.add_action(|this: &mut Editor, _: &LineDown, cx| {
this.scroll_screen(&ScrollAmount::Line(1.), cx)
});
cx.add_action(|this: &mut Editor, _: &LineUp, cx| {
this.scroll_screen(&ScrollAmount::Line(-1.), cx)
});
cx.add_action(|this: &mut Editor, _: &HalfPageDown, cx| {
this.scroll_screen(&ScrollAmount::Page(0.5), cx)
});
cx.add_action(|this: &mut Editor, _: &HalfPageUp, cx| {
this.scroll_screen(&ScrollAmount::Page(-0.5), cx)
});
cx.add_action(|this: &mut Editor, _: &PageDown, cx| {
this.scroll_screen(&ScrollAmount::Page(1.), cx)
});
cx.add_action(|this: &mut Editor, _: &PageUp, cx| {
this.scroll_screen(&ScrollAmount::Page(-1.), cx)
});
/// todo!()
// cx.add_action(Editor::next_screen);
// cx.add_action(Editor::scroll_cursor_top);
// cx.add_action(Editor::scroll_cursor_center);
// cx.add_action(Editor::scroll_cursor_bottom);
// cx.add_action(|this: &mut Editor, _: &LineDown, cx| {
// this.scroll_screen(&ScrollAmount::Line(1.), cx)
// });
// cx.add_action(|this: &mut Editor, _: &LineUp, cx| {
// this.scroll_screen(&ScrollAmount::Line(-1.), cx)
// });
// cx.add_action(|this: &mut Editor, _: &HalfPageDown, cx| {
// this.scroll_screen(&ScrollAmount::Page(0.5), cx)
// });
// cx.add_action(|this: &mut Editor, _: &HalfPageUp, cx| {
// this.scroll_screen(&ScrollAmount::Page(-0.5), cx)
// });
// cx.add_action(|this: &mut Editor, _: &PageDown, cx| {
// this.scroll_screen(&ScrollAmount::Page(1.), cx)
// });
// cx.add_action(|this: &mut Editor, _: &PageUp, cx| {
// this.scroll_screen(&ScrollAmount::Page(-1.), cx)
// });
}
impl Editor {
pub fn next_screen(&mut self, _: &NextScreen, cx: &mut ViewContext<Editor>) -> Option<()> {
if self.take_rename(true, cx).is_some() {
return None;
}
// impl Editor {
// pub fn next_screen(&mut self, _: &NextScreen, cx: &mut ViewContext<Editor>) -> Option<()> {
// if self.take_rename(true, cx).is_some() {
// return None;
// }
if self.mouse_context_menu.read(cx).visible() {
return None;
}
// if self.mouse_context_menu.read(cx).visible() {
// return None;
// }
if matches!(self.mode, EditorMode::SingleLine) {
cx.propagate_action();
return None;
}
self.request_autoscroll(Autoscroll::Next, cx);
Some(())
}
// if matches!(self.mode, EditorMode::SingleLine) {
// cx.propagate_action();
// return None;
// }
// self.request_autoscroll(Autoscroll::Next, cx);
// Some(())
// }
pub fn scroll(
&mut self,
scroll_position: Vector2F,
axis: Option<Axis>,
cx: &mut ViewContext<Self>,
) {
self.scroll_manager.update_ongoing_scroll(axis);
self.set_scroll_position(scroll_position, cx);
}
// pub fn scroll(
// &mut self,
// scroll_position: Vector2F,
// axis: Option<Axis>,
// cx: &mut ViewContext<Self>,
// ) {
// self.scroll_manager.update_ongoing_scroll(axis);
// self.set_scroll_position(scroll_position, cx);
// }
fn scroll_cursor_top(editor: &mut Editor, _: &ScrollCursorTop, cx: &mut ViewContext<Editor>) {
let snapshot = editor.snapshot(cx).display_snapshot;
let scroll_margin_rows = editor.vertical_scroll_margin() as u32;
// fn scroll_cursor_top(editor: &mut Editor, _: &ScrollCursorTop, cx: &mut ViewContext<Editor>) {
// let snapshot = editor.snapshot(cx).display_snapshot;
// let scroll_margin_rows = editor.vertical_scroll_margin() as u32;
let mut new_screen_top = editor.selections.newest_display(cx).head();
*new_screen_top.row_mut() = new_screen_top.row().saturating_sub(scroll_margin_rows);
*new_screen_top.column_mut() = 0;
let new_screen_top = new_screen_top.to_offset(&snapshot, Bias::Left);
let new_anchor = snapshot.buffer_snapshot.anchor_before(new_screen_top);
// let mut new_screen_top = editor.selections.newest_display(cx).head();
// *new_screen_top.row_mut() = new_screen_top.row().saturating_sub(scroll_margin_rows);
// *new_screen_top.column_mut() = 0;
// let new_screen_top = new_screen_top.to_offset(&snapshot, Bias::Left);
// let new_anchor = snapshot.buffer_snapshot.anchor_before(new_screen_top);
editor.set_scroll_anchor(
ScrollAnchor {
anchor: new_anchor,
offset: Default::default(),
},
cx,
)
}
// editor.set_scroll_anchor(
// ScrollAnchor {
// anchor: new_anchor,
// offset: Default::default(),
// },
// cx,
// )
// }
fn scroll_cursor_center(
editor: &mut Editor,
_: &ScrollCursorCenter,
cx: &mut ViewContext<Editor>,
) {
let snapshot = editor.snapshot(cx).display_snapshot;
let visible_rows = if let Some(visible_rows) = editor.visible_line_count() {
visible_rows as u32
} else {
return;
};
// fn scroll_cursor_center(
// editor: &mut Editor,
// _: &ScrollCursorCenter,
// cx: &mut ViewContext<Editor>,
// ) {
// let snapshot = editor.snapshot(cx).display_snapshot;
// let visible_rows = if let Some(visible_rows) = editor.visible_line_count() {
// visible_rows as u32
// } else {
// return;
// };
let mut new_screen_top = editor.selections.newest_display(cx).head();
*new_screen_top.row_mut() = new_screen_top.row().saturating_sub(visible_rows / 2);
*new_screen_top.column_mut() = 0;
let new_screen_top = new_screen_top.to_offset(&snapshot, Bias::Left);
let new_anchor = snapshot.buffer_snapshot.anchor_before(new_screen_top);
// let mut new_screen_top = editor.selections.newest_display(cx).head();
// *new_screen_top.row_mut() = new_screen_top.row().saturating_sub(visible_rows / 2);
// *new_screen_top.column_mut() = 0;
// let new_screen_top = new_screen_top.to_offset(&snapshot, Bias::Left);
// let new_anchor = snapshot.buffer_snapshot.anchor_before(new_screen_top);
editor.set_scroll_anchor(
ScrollAnchor {
anchor: new_anchor,
offset: Default::default(),
},
cx,
)
}
// editor.set_scroll_anchor(
// ScrollAnchor {
// anchor: new_anchor,
// offset: Default::default(),
// },
// cx,
// )
// }
fn scroll_cursor_bottom(
editor: &mut Editor,
_: &ScrollCursorBottom,
cx: &mut ViewContext<Editor>,
) {
let snapshot = editor.snapshot(cx).display_snapshot;
let scroll_margin_rows = editor.vertical_scroll_margin() as u32;
let visible_rows = if let Some(visible_rows) = editor.visible_line_count() {
visible_rows as u32
} else {
return;
};
// fn scroll_cursor_bottom(
// editor: &mut Editor,
// _: &ScrollCursorBottom,
// cx: &mut ViewContext<Editor>,
// ) {
// let snapshot = editor.snapshot(cx).display_snapshot;
// let scroll_margin_rows = editor.vertical_scroll_margin() as u32;
// let visible_rows = if let Some(visible_rows) = editor.visible_line_count() {
// visible_rows as u32
// } else {
// return;
// };
let mut new_screen_top = editor.selections.newest_display(cx).head();
*new_screen_top.row_mut() = new_screen_top
.row()
.saturating_sub(visible_rows.saturating_sub(scroll_margin_rows));
*new_screen_top.column_mut() = 0;
let new_screen_top = new_screen_top.to_offset(&snapshot, Bias::Left);
let new_anchor = snapshot.buffer_snapshot.anchor_before(new_screen_top);
// let mut new_screen_top = editor.selections.newest_display(cx).head();
// *new_screen_top.row_mut() = new_screen_top
// .row()
// .saturating_sub(visible_rows.saturating_sub(scroll_margin_rows));
// *new_screen_top.column_mut() = 0;
// let new_screen_top = new_screen_top.to_offset(&snapshot, Bias::Left);
// let new_anchor = snapshot.buffer_snapshot.anchor_before(new_screen_top);
editor.set_scroll_anchor(
ScrollAnchor {
anchor: new_anchor,
offset: Default::default(),
},
cx,
)
}
}
// editor.set_scroll_anchor(
// ScrollAnchor {
// anchor: new_anchor,
// offset: Default::default(),
// },
// cx,
// )
// }
// }

View File

@ -6,7 +6,7 @@ use std::{
};
use collections::HashMap;
use gpui::{AppContext, ModelHandle};
use gpui::{AppContext, Model};
use itertools::Itertools;
use language::{Bias, Point, Selection, SelectionGoal, TextDimension, ToPoint};
use util::post_inc;

View File

@ -6,7 +6,7 @@ use crate::{
DisplayPoint, Editor, EditorMode, MultiBuffer,
};
use gpui::{ModelHandle, ViewContext};
use gpui::{Model, ViewContext};
use project::Project;
use util::test::{marked_text_offsets, marked_text_ranges};

View File

@ -1,6 +1,7 @@
pub use crate::{
diagnostic_set::DiagnosticSet,
highlight_map::{HighlightId, HighlightMap},
markdown::ParsedMarkdown,
proto, BracketPair, Grammar, Language, LanguageConfig, LanguageRegistry, PLAIN_TEXT,
};
use crate::{

View File

@ -13,9 +13,12 @@ mod status_bar;
mod toolbar;
mod workspace_settings;
use crate::persistence::model::{
DockData, DockStructure, SerializedItem, SerializedPane, SerializedPaneGroup,
SerializedWorkspace,
pub use crate::persistence::{
model::{
DockData, DockStructure, ItemId, SerializedItem, SerializedPane, SerializedPaneGroup,
SerializedWorkspace,
},
WorkspaceDb,
};
use anyhow::{anyhow, Context as _, Result};
use call2::ActiveCall;
@ -44,15 +47,13 @@ use node_runtime::NodeRuntime;
use notifications::{simple_message_notification::MessageNotification, NotificationHandle};
pub use pane::*;
pub use pane_group::*;
use persistence::{
model::{ItemId, WorkspaceLocation},
DB,
};
use persistence::{model::WorkspaceLocation, DB};
use postage::stream::Stream;
use project2::{Project, ProjectEntryId, ProjectPath, Worktree};
use serde::Deserialize;
use settings2::Settings;
use status_bar::StatusBar;
pub use status_bar::StatusItemView;
use std::{
any::TypeId,
borrow::Cow,

View File

@ -34,7 +34,7 @@ copilot = { package = "copilot2", path = "../copilot2" }
# copilot_button = { path = "../copilot_button" }
# diagnostics = { path = "../diagnostics" }
db = { package = "db2", path = "../db2" }
# editor = { path = "../editor" }
editor = { package="editor2", path = "../editor2" }
# feedback = { path = "../feedback" }
# file_finder = { path = "../file_finder" }
# search = { path = "../search" }