Compare commits

...

12 Commits

Author SHA1 Message Date
Mikayla Maki
023a617b30 zed 0.97.4 2023-07-27 16:36:49 -07:00
Mikayla Maki
286d302273 Make mode indicator follow vim enabled state (#2802)
There was a minor visual bug introduced in
https://github.com/zed-industries/zed/pull/2801, this PR corrects it.

Release Notes:

- N/A
2023-07-27 16:32:28 -07:00
Julia
4091a2004e Avoid panic by accessing view handle by global in wrong window
View handles are window specific but this global will be doing things
in all windows, that would cause a panic when it attempted to update
a status bar mode indicator in a background window

Co-Authored-By: Mikayla Maki <mikayla@zed.dev>
2023-07-27 16:32:20 -07:00
Joseph T. Lyons
9d4a2bfb58 Publish preview releases to discord (#2800)
Release Notes:

- N/A
2023-07-27 15:26:36 -04:00
Joseph T. Lyons
33e58d47ac zed 0.97.3 2023-07-27 14:30:24 -04:00
Mikayla Maki
056282f59b Downgrade our dependency on treesitter-cpp (#2799)
Our dependency on `tree-sitter-cpp` got upgraded to an incompatible
version despite semver 'guarantees'. This pins the dependency onto the
commit of version 0.20.0

Release Notes:

- Restored language detection for C++ (preview-only)
2023-07-27 14:21:16 -04:00
Antonio Scandurra
553b9601d1 zed 0.97.2 2023-07-27 14:47:09 +02:00
Antonio Scandurra
a166f0b56a Maintain cursor stack's position correctly when ascending the tree (#2795)
This fixes a bug that could cause the cursor to incorrectly report its
start when using `slice` or `seek_forward`, and then calling `prev`. We
didn't notice this because we were not testing those three methods
together.

I suppose this could explain some of the panics we've observed because
we do use `slice`/`seek_forward` followed by `prev` calls in production.
2023-07-27 14:45:38 +02:00
Joseph T. Lyons
badc2ec0e9 zed 0.97.1 2023-07-26 18:57:44 -04:00
Mikayla Maki
9c3c719ce0 Downgrade tree sitter elm to 5.6.4 (#2794)
The tree sitter elm parser contains a c symbol which collides with other
linked symbols. This PR downgrades the tree sitter elm parser to a
version which doesn't have this problem.

Release Notes:
- Fixed crash when parsing elm files
2023-07-26 18:55:24 -04:00
Mikayla Maki
3594b5e2a8 Block extra drag events in original drag handlers (#2793)
In https://github.com/zed-industries/zed/pull/2790 I added an extra drag
event on mouse_up which signaled the end of a drag event, as mouse_up
event themselves wouldn't reliably fire if users moved their mouse too
quickly. This broke the assumptions of the terminal element. This PR
adds filters to all current on_drag handlers which removes this new
event.

Release Notes:

- Fixed a bug causing terminal links to never open (preview only)
- Fixed a bug in terminal link detection causing it to miss files with a
`-` in it
2023-07-26 18:20:50 -04:00
Joseph T. Lyons
99d0ed4a76 v0.97.x preview 2023-07-26 13:27:34 -04:00
17 changed files with 142 additions and 87 deletions

View File

@@ -8,7 +8,6 @@ jobs:
steps:
- name: Discord Webhook Action
uses: tsickert/discord-webhook@v5.3.0
if: ${{ ! github.event.release.prerelease }}
with:
webhook-url: ${{ secrets.DISCORD_WEBHOOK_URL }}
content: |

24
Cargo.lock generated
View File

@@ -6513,7 +6513,7 @@ dependencies = [
"theme",
"tiktoken-rs 0.5.0",
"tree-sitter",
"tree-sitter-cpp",
"tree-sitter-cpp 0.20.2",
"tree-sitter-elixir 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"tree-sitter-json 0.19.0",
"tree-sitter-rust",
@@ -8032,9 +8032,18 @@ dependencies = [
[[package]]
name = "tree-sitter-cpp"
version = "0.20.1"
version = "0.20.0"
source = "git+https://github.com/tree-sitter/tree-sitter-cpp?rev=f44509141e7e483323d2ec178f2d2e6c0fc041c1#f44509141e7e483323d2ec178f2d2e6c0fc041c1"
dependencies = [
"cc",
"tree-sitter",
]
[[package]]
name = "tree-sitter-cpp"
version = "0.20.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0dbedbf4066bfab725b3f9e2a21530507419a7d2f98621d3c13213502b734ec0"
checksum = "1c88fd925d0333e63ac64e521f5bd79c53019e569ffbbccfeef346a326f459e9"
dependencies = [
"cc",
"tree-sitter",
@@ -8070,9 +8079,8 @@ dependencies = [
[[package]]
name = "tree-sitter-elm"
version = "5.6.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "95236155fa1cd5fcf92123e7e6aa7b6e8c6756b54b5d39afd792a23bd6c9eb7b"
version = "5.6.4"
source = "git+https://github.com/elm-tooling/tree-sitter-elm?rev=692c50c0b961364c40299e73c1306aecb5d20f40#692c50c0b961364c40299e73c1306aecb5d20f40"
dependencies = [
"cc",
"tree-sitter",
@@ -9536,7 +9544,7 @@ dependencies = [
[[package]]
name = "zed"
version = "0.97.0"
version = "0.97.4"
dependencies = [
"activity_indicator",
"ai",
@@ -9623,7 +9631,7 @@ dependencies = [
"tree-sitter",
"tree-sitter-bash",
"tree-sitter-c",
"tree-sitter-cpp",
"tree-sitter-cpp 0.20.0",
"tree-sitter-css",
"tree-sitter-elixir 0.1.0 (git+https://github.com/elixir-lang/tree-sitter-elixir?rev=4ba9dab6e2602960d95b2b625f3386c27e08084e)",
"tree-sitter-elm",

View File

@@ -109,10 +109,10 @@ pretty_assertions = "1.3.0"
tree-sitter-bash = { git = "https://github.com/tree-sitter/tree-sitter-bash", rev = "1b0321ee85701d5036c334a6f04761cdc672e64c" }
tree-sitter-c = "0.20.1"
tree-sitter-cpp = "0.20.0"
tree-sitter-cpp = { git = "https://github.com/tree-sitter/tree-sitter-cpp", rev="f44509141e7e483323d2ec178f2d2e6c0fc041c1" }
tree-sitter-css = { git = "https://github.com/tree-sitter/tree-sitter-css", rev = "769203d0f9abe1a9a691ac2b9fe4bb4397a73c51" }
tree-sitter-elixir = { git = "https://github.com/elixir-lang/tree-sitter-elixir", rev = "4ba9dab6e2602960d95b2b625f3386c27e08084e" }
tree-sitter-elm = "5.6.4"
tree-sitter-elm = { git = "https://github.com/elm-tooling/tree-sitter-elm", rev = "692c50c0b961364c40299e73c1306aecb5d20f40"}
tree-sitter-embedded-template = "0.20.0"
tree-sitter-glsl = { git = "https://github.com/theHamsta/tree-sitter-glsl", rev = "2a56fb7bc8bb03a1892b4741279dd0a8758b7fb3" }
tree-sitter-go = { git = "https://github.com/tree-sitter/tree-sitter-go", rev = "aeb2f33b366fd78d5789ff104956ce23508b85db" }

View File

@@ -172,6 +172,10 @@ impl EditorElement {
.on_drag(MouseButton::Left, {
let position_map = position_map.clone();
move |event, editor, cx| {
if event.end {
return;
}
if !Self::mouse_dragged(
editor,
event.platform_event,
@@ -1235,6 +1239,10 @@ impl EditorElement {
})
.on_drag(MouseButton::Left, {
move |event, editor: &mut Editor, cx| {
if event.end {
return;
}
let y = event.prev_mouse_position.y();
let new_y = event.position.y();
if thumb_top < y && y < thumb_bottom {

View File

@@ -147,6 +147,9 @@ impl<V: View> Element<V> for Resizable<V> {
let max_size = side.relevant_component(constraint.max);
let on_resize = self.on_resize.clone();
move |event, view: &mut V, cx| {
if event.end {
return;
}
let new_size = min_size
.max(prev_size + side.compute_delta(event))
.min(max_size)

View File

@@ -844,8 +844,8 @@ impl LanguageRegistry {
}
}
}
Err(err) => {
log::error!("failed to load language {name} - {err}");
Err(e) => {
log::error!("failed to load language {name}:\n{:?}", e);
let mut state = this.state.write();
state.mark_language_loaded(id);
if let Some(mut txs) = state.loading_languages.remove(&id) {
@@ -853,7 +853,7 @@ impl LanguageRegistry {
let _ = tx.send(Err(anyhow!(
"failed to load language {}: {}",
name,
err
e
)));
}
}
@@ -1188,25 +1188,39 @@ impl Language {
pub fn with_queries(mut self, queries: LanguageQueries) -> Result<Self> {
if let Some(query) = queries.highlights {
self = self.with_highlights_query(query.as_ref())?;
self = self
.with_highlights_query(query.as_ref())
.context("Error loading highlights query")?;
}
if let Some(query) = queries.brackets {
self = self.with_brackets_query(query.as_ref())?;
self = self
.with_brackets_query(query.as_ref())
.context("Error loading brackets query")?;
}
if let Some(query) = queries.indents {
self = self.with_indents_query(query.as_ref())?;
self = self
.with_indents_query(query.as_ref())
.context("Error loading indents query")?;
}
if let Some(query) = queries.outline {
self = self.with_outline_query(query.as_ref())?;
self = self
.with_outline_query(query.as_ref())
.context("Error loading outline query")?;
}
if let Some(query) = queries.embedding {
self = self.with_embedding_query(query.as_ref())?;
self = self
.with_embedding_query(query.as_ref())
.context("Error loading embedding query")?;
}
if let Some(query) = queries.injections {
self = self.with_injection_query(query.as_ref())?;
self = self
.with_injection_query(query.as_ref())
.context("Error loading injection query")?;
}
if let Some(query) = queries.overrides {
self = self.with_override_query(query.as_ref())?;
self = self
.with_override_query(query.as_ref())
.context("Error loading override query")?;
}
Ok(self)
}

View File

@@ -438,6 +438,7 @@ where
} => {
if ascending {
entry.index += 1;
entry.position = self.position.clone();
}
for (child_tree, child_summary) in child_trees[entry.index..]

View File

@@ -738,7 +738,7 @@ mod tests {
for _ in 0..num_operations {
let splice_end = rng.gen_range(0..tree.extent::<Count>(&()).0 + 1);
let splice_start = rng.gen_range(0..splice_end + 1);
let count = rng.gen_range(0..3);
let count = rng.gen_range(0..10);
let tree_end = tree.extent::<Count>(&());
let new_items = rng
.sample_iter(distributions::Standard)
@@ -805,10 +805,12 @@ mod tests {
}
assert_eq!(filter_cursor.item(), None);
let mut pos = rng.gen_range(0..tree.extent::<Count>(&()).0 + 1);
let mut before_start = false;
let mut cursor = tree.cursor::<Count>();
cursor.seek(&Count(pos), Bias::Right, &());
let start_pos = rng.gen_range(0..=reference_items.len());
cursor.seek(&Count(start_pos), Bias::Right, &());
let mut pos = rng.gen_range(start_pos..=reference_items.len());
cursor.seek_forward(&Count(pos), Bias::Right, &());
for i in 0..10 {
assert_eq!(cursor.start().0, pos);

View File

@@ -78,7 +78,7 @@ lazy_static! {
// * use more strict regex for `file://` protocol matching: original regex has `file:` inside, but we want to avoid matching `some::file::module` strings.
static ref URL_REGEX: RegexSearch = RegexSearch::new(r#"(ipfs:|ipns:|magnet:|mailto:|gemini://|gopher://|https://|http://|news:|file://|git://|ssh:|ftp://)[^\u{0000}-\u{001F}\u{007F}-\u{009F}<>"\s{-}\^⟨⟩`]+"#).unwrap();
static ref WORD_REGEX: RegexSearch = RegexSearch::new("[\\w.:/@-~]+").unwrap();
static ref WORD_REGEX: RegexSearch = RegexSearch::new(r#"[\w.:/@\-~]+"#).unwrap();
}
///Upward flowing events, for changing the title and such

View File

@@ -411,6 +411,10 @@ impl TerminalElement {
})
// Update drag selections
.on_drag(MouseButton::Left, move |event, _: &mut TerminalView, cx| {
if event.end {
return;
}
if cx.is_self_focused() {
if let Some(conn_handle) = connection.upgrade(cx) {
conn_handle.update(cx, |terminal, cx| {

View File

@@ -1,20 +1,64 @@
use gpui::{elements::Label, AnyElement, Element, Entity, View, ViewContext};
use gpui::{
elements::{Empty, Label},
AnyElement, Element, Entity, Subscription, View, ViewContext,
};
use settings::SettingsStore;
use workspace::{item::ItemHandle, StatusItemView};
use crate::state::Mode;
use crate::{state::Mode, Vim, VimEvent, VimModeSetting};
pub struct ModeIndicator {
pub mode: Mode,
pub mode: Option<Mode>,
_subscription: Subscription,
}
impl ModeIndicator {
pub fn new(mode: Mode) -> Self {
Self { mode }
pub fn new(cx: &mut ViewContext<Self>) -> Self {
let handle = cx.handle().downgrade();
let _subscription = cx.subscribe_global::<VimEvent, _>(move |&event, cx| {
if let Some(mode_indicator) = handle.upgrade(cx) {
match event {
VimEvent::ModeChanged { mode } => {
cx.update_window(mode_indicator.window_id(), |cx| {
mode_indicator.update(cx, move |mode_indicator, cx| {
mode_indicator.set_mode(mode, cx);
})
});
}
}
}
});
cx.observe_global::<SettingsStore, _>(move |mode_indicator, cx| {
if settings::get::<VimModeSetting>(cx).0 {
mode_indicator.mode = cx
.has_global::<Vim>()
.then(|| cx.global::<Vim>().state.mode);
} else {
mode_indicator.mode.take();
}
})
.detach();
// Vim doesn't exist in some tests
let mode = cx
.has_global::<Vim>()
.then(|| {
let vim = cx.global::<Vim>();
vim.enabled.then(|| vim.state.mode)
})
.flatten();
Self {
mode,
_subscription,
}
}
pub fn set_mode(&mut self, mode: Mode, cx: &mut ViewContext<Self>) {
if mode != self.mode {
self.mode = mode;
if self.mode != Some(mode) {
self.mode = Some(mode);
cx.notify();
}
}
@@ -30,11 +74,16 @@ impl View for ModeIndicator {
}
fn render(&mut self, cx: &mut ViewContext<Self>) -> AnyElement<Self> {
let Some(mode) = self.mode.as_ref() else {
return Empty::new().into_any();
};
let theme = &theme::current(cx).workspace.status_bar;
// we always choose text to be 12 monospace characters
// so that as the mode indicator changes, the rest of the
// UI stays still.
let text = match self.mode {
let text = match mode {
Mode::Normal => "-- NORMAL --",
Mode::Insert => "-- INSERT --",
Mode::Visual { line: false } => "-- VISUAL --",

View File

@@ -215,7 +215,7 @@ async fn test_status_indicator(
assert_eq!(
cx.workspace(|_, cx| mode_indicator.read(cx).mode),
Mode::Normal
Some(Mode::Normal)
);
// shows the correct mode
@@ -223,7 +223,7 @@ async fn test_status_indicator(
deterministic.run_until_parked();
assert_eq!(
cx.workspace(|_, cx| mode_indicator.read(cx).mode),
Mode::Insert
Some(Mode::Insert)
);
// shows even in search
@@ -231,7 +231,7 @@ async fn test_status_indicator(
deterministic.run_until_parked();
assert_eq!(
cx.workspace(|_, cx| mode_indicator.read(cx).mode),
Mode::Visual { line: false }
Some(Mode::Visual { line: false })
);
// hides if vim mode is disabled
@@ -239,15 +239,15 @@ async fn test_status_indicator(
deterministic.run_until_parked();
cx.workspace(|workspace, cx| {
let status_bar = workspace.status_bar().read(cx);
let mode_indicator = status_bar.item_of_type::<ModeIndicator>();
assert!(mode_indicator.is_none());
let mode_indicator = status_bar.item_of_type::<ModeIndicator>().unwrap();
assert!(mode_indicator.read(cx).mode.is_none());
});
cx.enable_vim();
deterministic.run_until_parked();
cx.workspace(|workspace, cx| {
let status_bar = workspace.status_bar().read(cx);
let mode_indicator = status_bar.item_of_type::<ModeIndicator>();
assert!(mode_indicator.is_some());
let mode_indicator = status_bar.item_of_type::<ModeIndicator>().unwrap();
assert!(mode_indicator.read(cx).mode.is_some());
});
}

View File

@@ -43,6 +43,10 @@ impl<'a> VimTestContext<'a> {
toolbar.add_item(project_search_bar, cx);
})
});
workspace.status_bar().update(cx, |status_bar, cx| {
let vim_mode_indicator = cx.add_view(ModeIndicator::new);
status_bar.add_right_item(vim_mode_indicator, cx);
});
});
Self { cx }

View File

@@ -43,6 +43,11 @@ struct Number(u8);
actions!(vim, [Tab, Enter]);
impl_actions!(vim, [Number, SwitchMode, PushOperator]);
#[derive(Copy, Clone, Debug)]
enum VimEvent {
ModeChanged { mode: Mode },
}
pub fn init(cx: &mut AppContext) {
settings::register::<VimModeSetting>(cx);
@@ -121,8 +126,6 @@ pub fn observe_keystrokes(cx: &mut WindowContext) {
pub struct Vim {
active_editor: Option<WeakViewHandle<Editor>>,
editor_subscription: Option<Subscription>,
mode_indicator: Option<ViewHandle<ModeIndicator>>,
enabled: bool,
state: VimState,
}
@@ -181,9 +184,7 @@ impl Vim {
self.state.mode = mode;
self.state.operator_stack.clear();
if let Some(mode_indicator) = &self.mode_indicator {
mode_indicator.update(cx, |mode_indicator, cx| mode_indicator.set_mode(mode, cx))
}
cx.emit_global(VimEvent::ModeChanged { mode });
// Sync editor settings like clip mode
self.sync_vim_settings(cx);
@@ -271,44 +272,6 @@ impl Vim {
}
}
fn sync_mode_indicator(cx: &mut WindowContext) {
let Some(workspace) = cx.root_view()
.downcast_ref::<Workspace>()
.map(|workspace| workspace.downgrade()) else {
return;
};
cx.spawn(|mut cx| async move {
workspace.update(&mut cx, |workspace, cx| {
Vim::update(cx, |vim, cx| {
workspace.status_bar().update(cx, |status_bar, cx| {
let current_position = status_bar.position_of_item::<ModeIndicator>();
if vim.enabled && current_position.is_none() {
if vim.mode_indicator.is_none() {
vim.mode_indicator =
Some(cx.add_view(|_| ModeIndicator::new(vim.state.mode)));
};
let mode_indicator = vim.mode_indicator.as_ref().unwrap();
let position = status_bar
.position_of_item::<language_selector::ActiveBufferLanguage>();
if let Some(position) = position {
status_bar.insert_item_after(position, mode_indicator.clone(), cx)
} else {
status_bar.add_left_item(mode_indicator.clone(), cx)
}
} else if !vim.enabled {
if let Some(position) = current_position {
status_bar.remove_item_at(position, cx)
}
}
})
})
})
})
.detach_and_log_err(cx);
}
fn set_enabled(&mut self, enabled: bool, cx: &mut AppContext) {
if self.enabled != enabled {
self.enabled = enabled;
@@ -359,8 +322,6 @@ impl Vim {
self.unhook_vim_settings(editor, cx);
}
});
Vim::sync_mode_indicator(cx);
}
fn unhook_vim_settings(&self, editor: &mut Editor, cx: &mut ViewContext<Editor>) {

View File

@@ -3,7 +3,7 @@ authors = ["Nathan Sobo <nathansobo@gmail.com>"]
description = "The fast, collaborative code editor."
edition = "2021"
name = "zed"
version = "0.97.0"
version = "0.97.4"
publish = false
[lib]

View File

@@ -1 +1 @@
dev
preview

View File

@@ -308,6 +308,7 @@ pub fn initialize_workspace(
);
let active_buffer_language =
cx.add_view(|_| language_selector::ActiveBufferLanguage::new(workspace));
let vim_mode_indicator = cx.add_view(|cx| vim::ModeIndicator::new(cx));
let feedback_button = cx.add_view(|_| {
feedback::deploy_feedback_button::DeployFeedbackButton::new(workspace)
});
@@ -319,6 +320,7 @@ pub fn initialize_workspace(
status_bar.add_right_item(feedback_button, cx);
status_bar.add_right_item(copilot, cx);
status_bar.add_right_item(active_buffer_language, cx);
status_bar.add_right_item(vim_mode_indicator, cx);
status_bar.add_right_item(cursor_position, cx);
});