diff --git a/.github/workflows/release_actions.yml b/.github/workflows/release_actions.yml index f767324e4f..c1df24a8e5 100644 --- a/.github/workflows/release_actions.yml +++ b/.github/workflows/release_actions.yml @@ -6,8 +6,8 @@ jobs: discord_release: runs-on: ubuntu-latest steps: - - name: Get appropriate URL - id: get-appropriate-url + - name: Get release URL + id: get-release-url run: | if [ "${{ github.event.release.prerelease }}" == "true" ]; then URL="https://zed.dev/releases/preview/latest" @@ -15,14 +15,19 @@ jobs: URL="https://zed.dev/releases/stable/latest" fi echo "::set-output name=URL::$URL" + - name: Get content + uses: 2428392/gh-truncate-string-action@v1.2.0 + id: get-content + with: + stringToTruncate: | + 📣 Zed ${{ github.event.release.tag_name }} was just released! + Restart your Zed or head to ${{ steps.get-release-url.outputs.URL }} to grab it. + + ${{ github.event.release.body }} + maxLength: 2000 - name: Discord Webhook Action uses: tsickert/discord-webhook@v5.3.0 with: webhook-url: ${{ secrets.DISCORD_WEBHOOK_URL }} - content: | - 📣 Zed ${{ github.event.release.tag_name }} was just released! - - Restart your Zed or head to ${{ steps.get-appropriate-url.outputs.URL }} to grab it. - - ${{ github.event.release.body }} + content: ${{ steps.get-content.outputs.string }} diff --git a/Cargo.lock b/Cargo.lock index 3342bf39b8..e2ce29496e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2210,6 +2210,9 @@ dependencies = [ "lsp", "postage", "project", + "schemars", + "serde", + "serde_derive", "serde_json", "settings", "smallvec", @@ -9831,7 +9834,7 @@ dependencies = [ [[package]] name = "zed" -version = "0.106.0" +version = "0.106.2" dependencies = [ "activity_indicator", "anyhow", diff --git a/assets/settings/default.json b/assets/settings/default.json index 1f8068d109..7785f5dd44 100644 --- a/assets/settings/default.json +++ b/assets/settings/default.json @@ -227,6 +227,11 @@ }, // Automatically update Zed "auto_update": true, + // Diagnostics configuration. + "diagnostics": { + // Whether to show warnings or not by default. + "include_warnings": true + }, // Git gutter behavior configuration. "git": { // Control whether the git gutter is shown. May take 2 values: @@ -370,28 +375,28 @@ }, // Difference settings for semantic_index "semantic_index": { - "enabled": false + "enabled": true }, // Settings specific to our elixir integration "elixir": { - // Set Zed to use the experimental Next LS LSP server. + // Change the LSP zed uses for elixir. // Note that changing this setting requires a restart of Zed // to take effect. // // May take 3 values: - // 1. Use the standard elixir-ls LSP server - // "next": "off" - // 2. Use a bundled version of the next Next LS LSP server - // "next": "on", - // 3. Use a local build of the next Next LS LSP server: - // "next": { + // 1. Use the standard ElixirLS, this is the default + // "lsp": "elixir_ls" + // 2. Use the experimental NextLs + // "lsp": "next_ls", + // 3. Use a language server installed locally on your machine: + // "lsp": { // "local": { // "path": "~/next-ls/bin/start", // "arguments": ["--stdio"] // } // }, // - "next": "off" + "lsp": "elixir_ls" }, // Different settings for specific languages. "languages": { diff --git a/crates/diagnostics/Cargo.toml b/crates/diagnostics/Cargo.toml index 4e898cca0a..b0b2450f05 100644 --- a/crates/diagnostics/Cargo.toml +++ b/crates/diagnostics/Cargo.toml @@ -21,6 +21,9 @@ util = { path = "../util" } workspace = { path = "../workspace" } anyhow.workspace = true +schemars.workspace = true +serde.workspace = true +serde_derive.workspace = true smallvec.workspace = true postage.workspace = true diff --git a/crates/diagnostics/src/diagnostics.rs b/crates/diagnostics/src/diagnostics.rs index ac45bcbb79..0b1c6f8470 100644 --- a/crates/diagnostics/src/diagnostics.rs +++ b/crates/diagnostics/src/diagnostics.rs @@ -1,4 +1,6 @@ pub mod items; +mod project_diagnostics_settings; +mod toolbar_controls; use anyhow::Result; use collections::{BTreeSet, HashSet}; @@ -19,6 +21,7 @@ use language::{ }; use lsp::LanguageServerId; use project::{DiagnosticSummary, Project, ProjectPath}; +use project_diagnostics_settings::ProjectDiagnosticsSettings; use serde_json::json; use smallvec::SmallVec; use std::{ @@ -30,18 +33,21 @@ use std::{ sync::Arc, }; use theme::ThemeSettings; +pub use toolbar_controls::ToolbarControls; use util::TryFutureExt; use workspace::{ item::{BreadcrumbText, Item, ItemEvent, ItemHandle}, ItemNavHistory, Pane, PaneBackdrop, ToolbarItemLocation, Workspace, }; -actions!(diagnostics, [Deploy]); +actions!(diagnostics, [Deploy, ToggleWarnings]); const CONTEXT_LINE_COUNT: u32 = 1; pub fn init(cx: &mut AppContext) { + settings::register::(cx); cx.add_action(ProjectDiagnosticsEditor::deploy); + cx.add_action(ProjectDiagnosticsEditor::toggle_warnings); items::init(cx); } @@ -55,6 +61,7 @@ struct ProjectDiagnosticsEditor { excerpts: ModelHandle, path_states: Vec, paths_to_update: BTreeSet<(ProjectPath, LanguageServerId)>, + include_warnings: bool, } struct PathState { @@ -187,6 +194,7 @@ impl ProjectDiagnosticsEditor { editor, path_states: Default::default(), paths_to_update, + include_warnings: settings::get::(cx).include_warnings, }; this.update_excerpts(None, cx); this @@ -204,6 +212,18 @@ impl ProjectDiagnosticsEditor { } } + fn toggle_warnings(&mut self, _: &ToggleWarnings, cx: &mut ViewContext) { + self.include_warnings = !self.include_warnings; + self.paths_to_update = self + .project + .read(cx) + .diagnostic_summaries(cx) + .map(|(path, server_id, _)| (path, server_id)) + .collect(); + self.update_excerpts(None, cx); + cx.notify(); + } + fn update_excerpts( &mut self, language_server_id: Option, @@ -277,14 +297,18 @@ impl ProjectDiagnosticsEditor { let mut blocks_to_add = Vec::new(); let mut blocks_to_remove = HashSet::default(); let mut first_excerpt_id = None; + let max_severity = if self.include_warnings { + DiagnosticSeverity::WARNING + } else { + DiagnosticSeverity::ERROR + }; let excerpts_snapshot = self.excerpts.update(cx, |excerpts, excerpts_cx| { let mut old_groups = path_state.diagnostic_groups.iter().enumerate().peekable(); let mut new_groups = snapshot .diagnostic_groups(language_server_id) .into_iter() .filter(|(_, group)| { - group.entries[group.primary_ix].diagnostic.severity - <= DiagnosticSeverity::WARNING + group.entries[group.primary_ix].diagnostic.severity <= max_severity }) .peekable(); loop { @@ -1501,6 +1525,7 @@ mod tests { client::init_settings(cx); workspace::init_settings(cx); Project::init_settings(cx); + crate::init(cx); }); } diff --git a/crates/diagnostics/src/project_diagnostics_settings.rs b/crates/diagnostics/src/project_diagnostics_settings.rs new file mode 100644 index 0000000000..1592d3c7f0 --- /dev/null +++ b/crates/diagnostics/src/project_diagnostics_settings.rs @@ -0,0 +1,28 @@ +use schemars::JsonSchema; +use serde::{Deserialize, Serialize}; + +#[derive(Deserialize, Debug)] +pub struct ProjectDiagnosticsSettings { + pub include_warnings: bool, +} + +#[derive(Clone, Default, Serialize, Deserialize, JsonSchema, Debug)] +pub struct ProjectDiagnosticsSettingsContent { + include_warnings: Option, +} + +impl settings::Setting for ProjectDiagnosticsSettings { + const KEY: Option<&'static str> = Some("diagnostics"); + type FileContent = ProjectDiagnosticsSettingsContent; + + fn load( + default_value: &Self::FileContent, + user_values: &[&Self::FileContent], + _cx: &gpui::AppContext, + ) -> anyhow::Result + where + Self: Sized, + { + Self::load_via_json_merge(default_value, user_values) + } +} diff --git a/crates/diagnostics/src/toolbar_controls.rs b/crates/diagnostics/src/toolbar_controls.rs new file mode 100644 index 0000000000..421571eede --- /dev/null +++ b/crates/diagnostics/src/toolbar_controls.rs @@ -0,0 +1,115 @@ +use crate::{ProjectDiagnosticsEditor, ToggleWarnings}; +use gpui::{ + elements::*, + platform::{CursorStyle, MouseButton}, + Action, Entity, EventContext, View, ViewContext, WeakViewHandle, +}; +use workspace::{item::ItemHandle, ToolbarItemLocation, ToolbarItemView}; + +pub struct ToolbarControls { + editor: Option>, +} + +impl Entity for ToolbarControls { + type Event = (); +} + +impl View for ToolbarControls { + fn ui_name() -> &'static str { + "ToolbarControls" + } + + fn render(&mut self, cx: &mut ViewContext) -> AnyElement { + let include_warnings = self + .editor + .as_ref() + .and_then(|editor| editor.upgrade(cx)) + .map(|editor| editor.read(cx).include_warnings) + .unwrap_or(false); + let tooltip = if include_warnings { + "Exclude Warnings".into() + } else { + "Include Warnings".into() + }; + Flex::row() + .with_child(render_toggle_button( + 0, + "icons/warning.svg", + include_warnings, + (tooltip, Some(Box::new(ToggleWarnings))), + cx, + move |this, cx| { + if let Some(editor) = this.editor.and_then(|editor| editor.upgrade(cx)) { + editor.update(cx, |editor, cx| { + editor.toggle_warnings(&Default::default(), cx) + }); + } + }, + )) + .into_any() + } +} + +impl ToolbarItemView for ToolbarControls { + fn set_active_pane_item( + &mut self, + active_pane_item: Option<&dyn ItemHandle>, + _: &mut ViewContext, + ) -> ToolbarItemLocation { + if let Some(pane_item) = active_pane_item.as_ref() { + if let Some(editor) = pane_item.downcast::() { + self.editor = Some(editor.downgrade()); + ToolbarItemLocation::PrimaryRight { flex: None } + } else { + ToolbarItemLocation::Hidden + } + } else { + ToolbarItemLocation::Hidden + } + } +} + +impl ToolbarControls { + pub fn new() -> Self { + ToolbarControls { editor: None } + } +} + +fn render_toggle_button< + F: 'static + Fn(&mut ToolbarControls, &mut EventContext), +>( + index: usize, + icon: &'static str, + toggled: bool, + tooltip: (String, Option>), + cx: &mut ViewContext, + on_click: F, +) -> AnyElement { + enum Button {} + + let theme = theme::current(cx); + let (tooltip_text, action) = tooltip; + + MouseEventHandler::new::(index, cx, |mouse_state, _| { + let style = theme + .workspace + .toolbar + .toggleable_tool + .in_state(toggled) + .style_for(mouse_state); + Svg::new(icon) + .with_color(style.color) + .constrained() + .with_width(style.icon_width) + .aligned() + .constrained() + .with_width(style.button_width) + .with_height(style.button_width) + .contained() + .with_style(style.container) + }) + .with_cursor_style(CursorStyle::PointingHand) + .on_click(MouseButton::Left, move |_, view, cx| on_click(view, cx)) + .with_tooltip::