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", "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]] [[package]]
name = "either" name = "either"
version = "1.9.0" version = "1.9.0"
@ -11071,6 +11125,7 @@ dependencies = [
"copilot2", "copilot2",
"ctor", "ctor",
"db2", "db2",
"editor2",
"env_logger 0.9.3", "env_logger 0.9.3",
"feature_flags2", "feature_flags2",
"fs2", "fs2",

View file

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

View file

@ -61,7 +61,7 @@ impl BlinkManager {
} }
fn blink_cursors(&mut self, epoch: usize, cx: &mut ModelContext<Self>) { 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 { if epoch == self.blink_epoch && self.enabled && !self.blinking_paused {
self.visible = !self.visible; self.visible = !self.visible;
cx.notify(); cx.notify();
@ -107,7 +107,3 @@ impl BlinkManager {
self.visible 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 collections::{BTreeMap, HashMap, HashSet};
use fold_map::FoldMap; use fold_map::FoldMap;
use gpui::{ use gpui::{
color::Color,
fonts::{FontId, HighlightStyle, Underline}, fonts::{FontId, HighlightStyle, Underline},
text_layout::{Line, RunStyle}, text_layout::{Line, RunStyle},
Entity, ModelContext, ModelHandle, Entity, Hsla, Model, ModelContext,
}; };
use inlay_map::InlayMap; use inlay_map::InlayMap;
use language::{ use language::{
@ -49,12 +48,12 @@ type TextHighlights = TreeMap<Option<TypeId>, Arc<(HighlightStyle, Vec<Range<Anc
type InlayHighlights = BTreeMap<TypeId, HashMap<InlayId, (HighlightStyle, InlayHighlight)>>; type InlayHighlights = BTreeMap<TypeId, HashMap<InlayId, (HighlightStyle, InlayHighlight)>>;
pub struct DisplayMap { pub struct DisplayMap {
buffer: ModelHandle<MultiBuffer>, buffer: Model<MultiBuffer>,
buffer_subscription: BufferSubscription, buffer_subscription: BufferSubscription,
fold_map: FoldMap, fold_map: FoldMap,
inlay_map: InlayMap, inlay_map: InlayMap,
tab_map: TabMap, tab_map: TabMap,
wrap_map: ModelHandle<WrapMap>, wrap_map: Model<WrapMap>,
block_map: BlockMap, block_map: BlockMap,
text_highlights: TextHighlights, text_highlights: TextHighlights,
inlay_highlights: InlayHighlights, inlay_highlights: InlayHighlights,
@ -67,7 +66,7 @@ impl Entity for DisplayMap {
impl DisplayMap { impl DisplayMap {
pub fn new( pub fn new(
buffer: ModelHandle<MultiBuffer>, buffer: Model<MultiBuffer>,
font_id: FontId, font_id: FontId,
font_size: f32, font_size: f32,
wrap_width: Option<f32>, wrap_width: Option<f32>,
@ -1015,7 +1014,7 @@ pub mod tests {
movement, movement,
test::{editor_test_context::EditorTestContext, marked_display_snapshot}, 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::{ use language::{
language_settings::{AllLanguageSettings, AllLanguageSettingsContent}, language_settings::{AllLanguageSettings, AllLanguageSettingsContent},
Buffer, Language, LanguageConfig, SelectionGoal, Buffer, Language, LanguageConfig, SelectionGoal,

File diff suppressed because it is too large Load diff

View file

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

View file

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

View file

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

File diff suppressed because it is too large Load diff

View file

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

View file

@ -11,7 +11,7 @@ use crate::{
use anyhow::Context; use anyhow::Context;
use clock::Global; use clock::Global;
use futures::future; use futures::future;
use gpui::{ModelContext, ModelHandle, Task, ViewContext}; use gpui::{Model, ModelContext, Task, ViewContext};
use language::{language_settings::InlayHintKind, Buffer, BufferSnapshot}; use language::{language_settings::InlayHintKind, Buffer, BufferSnapshot};
use parking_lot::RwLock; use parking_lot::RwLock;
use project::{InlayHint, ResolveState}; 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.update(|cx| {
cx.set_global(SettingsStore::test(cx)); cx.set_global(SettingsStore::test(cx));
theme::init((), cx); theme::init(cx);
client::init_settings(cx); client::init_settings(cx);
language::init(cx); language::init(cx);
Project::init_settings(cx); Project::init_settings(cx);

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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