Merge branch 'main' into collab-titlebar-fixes
This commit is contained in:
commit
afbbb1c41f
19 changed files with 187 additions and 117 deletions
|
@ -1157,6 +1157,7 @@ impl Render for AssistantPanel {
|
||||||
});
|
});
|
||||||
|
|
||||||
v_stack()
|
v_stack()
|
||||||
|
.key_context("AssistantPanel")
|
||||||
.size_full()
|
.size_full()
|
||||||
.on_action(cx.listener(|this, _: &workspace::NewFile, cx| {
|
.on_action(cx.listener(|this, _: &workspace::NewFile, cx| {
|
||||||
this.new_conversation(cx);
|
this.new_conversation(cx);
|
||||||
|
|
|
@ -270,7 +270,7 @@ impl AutoUpdater {
|
||||||
ReleaseChannel::Nightly => cx
|
ReleaseChannel::Nightly => cx
|
||||||
.try_read_global::<AppCommitSha, _>(|sha, _| release.version != sha.0)
|
.try_read_global::<AppCommitSha, _>(|sha, _| release.version != sha.0)
|
||||||
.unwrap_or(true),
|
.unwrap_or(true),
|
||||||
_ => release.version.parse::<SemanticVersion>()? <= current_version,
|
_ => release.version.parse::<SemanticVersion>()? > current_version,
|
||||||
};
|
};
|
||||||
|
|
||||||
if !should_download {
|
if !should_download {
|
||||||
|
|
|
@ -370,6 +370,7 @@ mod tests {
|
||||||
use gpui::TestAppContext;
|
use gpui::TestAppContext;
|
||||||
use language::Point;
|
use language::Point;
|
||||||
use project::Project;
|
use project::Project;
|
||||||
|
use settings::KeymapFile;
|
||||||
use workspace::{AppState, Workspace};
|
use workspace::{AppState, Workspace};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -503,7 +504,20 @@ mod tests {
|
||||||
workspace::init(app_state.clone(), cx);
|
workspace::init(app_state.clone(), cx);
|
||||||
init(cx);
|
init(cx);
|
||||||
Project::init_settings(cx);
|
Project::init_settings(cx);
|
||||||
settings::load_default_keymap(cx);
|
KeymapFile::parse(
|
||||||
|
r#"[
|
||||||
|
{
|
||||||
|
"bindings": {
|
||||||
|
"cmd-n": "workspace::NewFile",
|
||||||
|
"enter": "menu::Confirm",
|
||||||
|
"cmd-shift-p": "command_palette::Toggle"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]"#,
|
||||||
|
)
|
||||||
|
.unwrap()
|
||||||
|
.add_to_cx(cx)
|
||||||
|
.unwrap();
|
||||||
app_state
|
app_state
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -641,8 +641,13 @@ impl Item for ProjectDiagnosticsEditor {
|
||||||
|
|
||||||
fn tab_content(&self, _detail: Option<usize>, selected: bool, _: &WindowContext) -> AnyElement {
|
fn tab_content(&self, _detail: Option<usize>, selected: bool, _: &WindowContext) -> AnyElement {
|
||||||
if self.summary.error_count == 0 && self.summary.warning_count == 0 {
|
if self.summary.error_count == 0 && self.summary.warning_count == 0 {
|
||||||
let label = Label::new("No problems");
|
Label::new("No problems")
|
||||||
label.into_any_element()
|
.color(if selected {
|
||||||
|
Color::Default
|
||||||
|
} else {
|
||||||
|
Color::Muted
|
||||||
|
})
|
||||||
|
.into_any_element()
|
||||||
} else {
|
} else {
|
||||||
h_stack()
|
h_stack()
|
||||||
.gap_1()
|
.gap_1()
|
||||||
|
|
|
@ -9565,7 +9565,7 @@ impl InputHandler for Editor {
|
||||||
) -> Option<gpui::Bounds<Pixels>> {
|
) -> Option<gpui::Bounds<Pixels>> {
|
||||||
let text_layout_details = self.text_layout_details(cx);
|
let text_layout_details = self.text_layout_details(cx);
|
||||||
let style = &text_layout_details.editor_style;
|
let style = &text_layout_details.editor_style;
|
||||||
let font_id = cx.text_system().font_id(&style.text.font()).unwrap();
|
let font_id = cx.text_system().resolve_font(&style.text.font());
|
||||||
let font_size = style.text.font_size.to_pixels(cx.rem_size());
|
let font_size = style.text.font_size.to_pixels(cx.rem_size());
|
||||||
let line_height = style.text.line_height_in_pixels(cx.rem_size());
|
let line_height = style.text.line_height_in_pixels(cx.rem_size());
|
||||||
let em_width = cx
|
let em_width = cx
|
||||||
|
|
|
@ -1230,6 +1230,14 @@ impl EditorElement {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If a drag took place after we started dragging the scrollbar,
|
||||||
|
// cancel the scrollbar drag.
|
||||||
|
if cx.has_active_drag() {
|
||||||
|
self.editor.update(cx, |editor, cx| {
|
||||||
|
editor.scroll_manager.set_is_dragging_scrollbar(false, cx);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
let top = bounds.origin.y;
|
let top = bounds.origin.y;
|
||||||
let bottom = bounds.lower_left().y;
|
let bottom = bounds.lower_left().y;
|
||||||
let right = bounds.lower_right().x;
|
let right = bounds.lower_right().x;
|
||||||
|
@ -1767,7 +1775,7 @@ impl EditorElement {
|
||||||
let snapshot = editor.snapshot(cx);
|
let snapshot = editor.snapshot(cx);
|
||||||
let style = self.style.clone();
|
let style = self.style.clone();
|
||||||
|
|
||||||
let font_id = cx.text_system().font_id(&style.text.font()).unwrap();
|
let font_id = cx.text_system().resolve_font(&style.text.font());
|
||||||
let font_size = style.text.font_size.to_pixels(cx.rem_size());
|
let font_size = style.text.font_size.to_pixels(cx.rem_size());
|
||||||
let line_height = style.text.line_height_in_pixels(cx.rem_size());
|
let line_height = style.text.line_height_in_pixels(cx.rem_size());
|
||||||
let em_width = cx
|
let em_width = cx
|
||||||
|
@ -3774,7 +3782,7 @@ fn compute_auto_height_layout(
|
||||||
}
|
}
|
||||||
|
|
||||||
let style = editor.style.as_ref().unwrap();
|
let style = editor.style.as_ref().unwrap();
|
||||||
let font_id = cx.text_system().font_id(&style.text.font()).unwrap();
|
let font_id = cx.text_system().resolve_font(&style.text.font());
|
||||||
let font_size = style.text.font_size.to_pixels(cx.rem_size());
|
let font_size = style.text.font_size.to_pixels(cx.rem_size());
|
||||||
let line_height = style.text.line_height_in_pixels(cx.rem_size());
|
let line_height = style.text.line_height_in_pixels(cx.rem_size());
|
||||||
let em_width = cx
|
let em_width = cx
|
||||||
|
|
|
@ -327,6 +327,7 @@ impl AppContext {
|
||||||
pub fn refresh(&mut self) {
|
pub fn refresh(&mut self) {
|
||||||
self.pending_effects.push_back(Effect::Refresh);
|
self.pending_effects.push_back(Effect::Refresh);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn update<R>(&mut self, update: impl FnOnce(&mut Self) -> R) -> R {
|
pub(crate) fn update<R>(&mut self, update: impl FnOnce(&mut Self) -> R) -> R {
|
||||||
self.pending_updates += 1;
|
self.pending_updates += 1;
|
||||||
let result = update(self);
|
let result = update(self);
|
||||||
|
@ -840,10 +841,12 @@ impl AppContext {
|
||||||
/// Update the global of the given type with a closure. Unlike `global_mut`, this method provides
|
/// Update the global of the given type with a closure. Unlike `global_mut`, this method provides
|
||||||
/// your closure with mutable access to the `AppContext` and the global simultaneously.
|
/// your closure with mutable access to the `AppContext` and the global simultaneously.
|
||||||
pub fn update_global<G: 'static, R>(&mut self, f: impl FnOnce(&mut G, &mut Self) -> R) -> R {
|
pub fn update_global<G: 'static, R>(&mut self, f: impl FnOnce(&mut G, &mut Self) -> R) -> R {
|
||||||
let mut global = self.lease_global::<G>();
|
self.update(|cx| {
|
||||||
let result = f(&mut global, self);
|
let mut global = cx.lease_global::<G>();
|
||||||
self.end_global_lease(global);
|
let result = f(&mut global, cx);
|
||||||
result
|
cx.end_global_lease(global);
|
||||||
|
result
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Register a callback to be invoked when a global of the given type is updated.
|
/// Register a callback to be invoked when a global of the given type is updated.
|
||||||
|
@ -941,6 +944,11 @@ impl AppContext {
|
||||||
self.pending_effects.push_back(Effect::Refresh);
|
self.pending_effects.push_back(Effect::Refresh);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn clear_key_bindings(&mut self) {
|
||||||
|
self.keymap.lock().clear();
|
||||||
|
self.pending_effects.push_back(Effect::Refresh);
|
||||||
|
}
|
||||||
|
|
||||||
/// Register a global listener for actions invoked via the keyboard.
|
/// Register a global listener for actions invoked via the keyboard.
|
||||||
pub fn on_action<A: Action>(&mut self, listener: impl Fn(&A, &mut Self) + 'static) {
|
pub fn on_action<A: Action>(&mut self, listener: impl Fn(&A, &mut Self) + 'static) {
|
||||||
self.global_action_listeners
|
self.global_action_listeners
|
||||||
|
|
|
@ -16,6 +16,7 @@ float gaussian(float x, float sigma);
|
||||||
float2 erf(float2 x);
|
float2 erf(float2 x);
|
||||||
float blur_along_x(float x, float y, float sigma, float corner,
|
float blur_along_x(float x, float y, float sigma, float corner,
|
||||||
float2 half_size);
|
float2 half_size);
|
||||||
|
float4 over(float4 below, float4 above);
|
||||||
|
|
||||||
struct QuadVertexOutput {
|
struct QuadVertexOutput {
|
||||||
float4 position [[position]];
|
float4 position [[position]];
|
||||||
|
@ -108,21 +109,11 @@ fragment float4 quad_fragment(QuadFragmentInput input [[stage_in]],
|
||||||
color = input.background_color;
|
color = input.background_color;
|
||||||
} else {
|
} else {
|
||||||
float inset_distance = distance + border_width;
|
float inset_distance = distance + border_width;
|
||||||
|
// Blend the border on top of the background and then linearly interpolate
|
||||||
// Decrease border's opacity as we move inside the background.
|
// between the two as we slide inside the background.
|
||||||
input.border_color.a *= 1. - saturate(0.5 - inset_distance);
|
float4 blended_border = over(input.background_color, input.border_color);
|
||||||
|
color = mix(blended_border, input.background_color,
|
||||||
// Alpha-blend the border and the background.
|
saturate(0.5 - inset_distance));
|
||||||
float output_alpha = input.border_color.a +
|
|
||||||
input.background_color.a * (1. - input.border_color.a);
|
|
||||||
float3 premultiplied_border_rgb =
|
|
||||||
input.border_color.rgb * input.border_color.a;
|
|
||||||
float3 premultiplied_background_rgb =
|
|
||||||
input.background_color.rgb * input.background_color.a;
|
|
||||||
float3 premultiplied_output_rgb =
|
|
||||||
premultiplied_border_rgb +
|
|
||||||
premultiplied_background_rgb * (1. - input.border_color.a);
|
|
||||||
color = float4(premultiplied_output_rgb, output_alpha);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return color * float4(1., 1., 1., saturate(0.5 - distance));
|
return color * float4(1., 1., 1., saturate(0.5 - distance));
|
||||||
|
@ -653,3 +644,12 @@ float4 distance_from_clip_rect(float2 unit_vertex, Bounds_ScaledPixels bounds,
|
||||||
position.y - clip_bounds.origin.y,
|
position.y - clip_bounds.origin.y,
|
||||||
clip_bounds.origin.y + clip_bounds.size.height - position.y);
|
clip_bounds.origin.y + clip_bounds.size.height - position.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float4 over(float4 below, float4 above) {
|
||||||
|
float4 result;
|
||||||
|
float alpha = above.a + below.a * (1.0 - above.a);
|
||||||
|
result.rgb =
|
||||||
|
(above.rgb * above.a + below.rgb * below.a * (1.0 - above.a)) / alpha;
|
||||||
|
result.a = alpha;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
|
@ -15,8 +15,9 @@ use crate::{
|
||||||
use anyhow::anyhow;
|
use anyhow::anyhow;
|
||||||
use collections::FxHashMap;
|
use collections::FxHashMap;
|
||||||
use core::fmt;
|
use core::fmt;
|
||||||
|
use itertools::Itertools;
|
||||||
use parking_lot::{Mutex, RwLock, RwLockUpgradableReadGuard};
|
use parking_lot::{Mutex, RwLock, RwLockUpgradableReadGuard};
|
||||||
use smallvec::SmallVec;
|
use smallvec::{smallvec, SmallVec};
|
||||||
use std::{
|
use std::{
|
||||||
cmp,
|
cmp,
|
||||||
fmt::{Debug, Display, Formatter},
|
fmt::{Debug, Display, Formatter},
|
||||||
|
@ -42,6 +43,7 @@ pub struct TextSystem {
|
||||||
raster_bounds: RwLock<FxHashMap<RenderGlyphParams, Bounds<DevicePixels>>>,
|
raster_bounds: RwLock<FxHashMap<RenderGlyphParams, Bounds<DevicePixels>>>,
|
||||||
wrapper_pool: Mutex<FxHashMap<FontIdWithSize, Vec<LineWrapper>>>,
|
wrapper_pool: Mutex<FxHashMap<FontIdWithSize, Vec<LineWrapper>>>,
|
||||||
font_runs_pool: Mutex<Vec<Vec<FontRun>>>,
|
font_runs_pool: Mutex<Vec<Vec<FontRun>>>,
|
||||||
|
fallback_font_stack: SmallVec<[Font; 2]>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TextSystem {
|
impl TextSystem {
|
||||||
|
@ -54,6 +56,12 @@ impl TextSystem {
|
||||||
font_ids_by_font: RwLock::default(),
|
font_ids_by_font: RwLock::default(),
|
||||||
wrapper_pool: Mutex::default(),
|
wrapper_pool: Mutex::default(),
|
||||||
font_runs_pool: Mutex::default(),
|
font_runs_pool: Mutex::default(),
|
||||||
|
fallback_font_stack: smallvec![
|
||||||
|
// TODO: This is currently Zed-specific.
|
||||||
|
// We should allow GPUI users to provide their own fallback font stack.
|
||||||
|
font("Zed Mono"),
|
||||||
|
font("Helvetica")
|
||||||
|
],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -72,6 +80,33 @@ impl TextSystem {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Resolves the specified font, falling back to the default font stack if
|
||||||
|
/// the font fails to load.
|
||||||
|
///
|
||||||
|
/// # Panics
|
||||||
|
///
|
||||||
|
/// Panics if the font and none of the fallbacks can be resolved.
|
||||||
|
pub fn resolve_font(&self, font: &Font) -> FontId {
|
||||||
|
if let Ok(font_id) = self.font_id(font) {
|
||||||
|
return font_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
for fallback in &self.fallback_font_stack {
|
||||||
|
if let Ok(font_id) = self.font_id(fallback) {
|
||||||
|
return font_id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
panic!(
|
||||||
|
"failed to resolve font '{}' or any of the fallbacks: {}",
|
||||||
|
font.family,
|
||||||
|
self.fallback_font_stack
|
||||||
|
.iter()
|
||||||
|
.map(|fallback| &fallback.family)
|
||||||
|
.join(", ")
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
pub fn bounding_box(&self, font_id: FontId, font_size: Pixels) -> Bounds<Pixels> {
|
pub fn bounding_box(&self, font_id: FontId, font_size: Pixels) -> Bounds<Pixels> {
|
||||||
self.read_metrics(font_id, |metrics| metrics.bounding_box(font_size))
|
self.read_metrics(font_id, |metrics| metrics.bounding_box(font_size))
|
||||||
}
|
}
|
||||||
|
@ -159,7 +194,7 @@ impl TextSystem {
|
||||||
) -> Result<Arc<LineLayout>> {
|
) -> Result<Arc<LineLayout>> {
|
||||||
let mut font_runs = self.font_runs_pool.lock().pop().unwrap_or_default();
|
let mut font_runs = self.font_runs_pool.lock().pop().unwrap_or_default();
|
||||||
for run in runs.iter() {
|
for run in runs.iter() {
|
||||||
let font_id = self.font_id(&run.font)?;
|
let font_id = self.resolve_font(&run.font);
|
||||||
if let Some(last_run) = font_runs.last_mut() {
|
if let Some(last_run) = font_runs.last_mut() {
|
||||||
if last_run.font_id == font_id {
|
if last_run.font_id == font_id {
|
||||||
last_run.len += run.len;
|
last_run.len += run.len;
|
||||||
|
@ -253,7 +288,7 @@ impl TextSystem {
|
||||||
last_font = Some(run.font.clone());
|
last_font = Some(run.font.clone());
|
||||||
font_runs.push(FontRun {
|
font_runs.push(FontRun {
|
||||||
len: run_len_within_line,
|
len: run_len_within_line,
|
||||||
font_id: self.platform_text_system.font_id(&run.font)?,
|
font_id: self.resolve_font(&run.font),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -113,7 +113,6 @@ pub struct LanguageServerName(pub Arc<str>);
|
||||||
pub struct CachedLspAdapter {
|
pub struct CachedLspAdapter {
|
||||||
pub name: LanguageServerName,
|
pub name: LanguageServerName,
|
||||||
pub short_name: &'static str,
|
pub short_name: &'static str,
|
||||||
pub initialization_options: Option<Value>,
|
|
||||||
pub disk_based_diagnostic_sources: Vec<String>,
|
pub disk_based_diagnostic_sources: Vec<String>,
|
||||||
pub disk_based_diagnostics_progress_token: Option<String>,
|
pub disk_based_diagnostics_progress_token: Option<String>,
|
||||||
pub language_ids: HashMap<String, String>,
|
pub language_ids: HashMap<String, String>,
|
||||||
|
@ -125,7 +124,6 @@ impl CachedLspAdapter {
|
||||||
pub async fn new(adapter: Arc<dyn LspAdapter>) -> Arc<Self> {
|
pub async fn new(adapter: Arc<dyn LspAdapter>) -> Arc<Self> {
|
||||||
let name = adapter.name().await;
|
let name = adapter.name().await;
|
||||||
let short_name = adapter.short_name();
|
let short_name = adapter.short_name();
|
||||||
let initialization_options = adapter.initialization_options().await;
|
|
||||||
let disk_based_diagnostic_sources = adapter.disk_based_diagnostic_sources().await;
|
let disk_based_diagnostic_sources = adapter.disk_based_diagnostic_sources().await;
|
||||||
let disk_based_diagnostics_progress_token =
|
let disk_based_diagnostics_progress_token =
|
||||||
adapter.disk_based_diagnostics_progress_token().await;
|
adapter.disk_based_diagnostics_progress_token().await;
|
||||||
|
@ -134,7 +132,6 @@ impl CachedLspAdapter {
|
||||||
Arc::new(CachedLspAdapter {
|
Arc::new(CachedLspAdapter {
|
||||||
name,
|
name,
|
||||||
short_name,
|
short_name,
|
||||||
initialization_options,
|
|
||||||
disk_based_diagnostic_sources,
|
disk_based_diagnostic_sources,
|
||||||
disk_based_diagnostics_progress_token,
|
disk_based_diagnostics_progress_token,
|
||||||
language_ids,
|
language_ids,
|
||||||
|
|
|
@ -10,7 +10,7 @@ use language::{LanguageServerId, LanguageServerName};
|
||||||
use lsp::IoKind;
|
use lsp::IoKind;
|
||||||
use project::{search::SearchQuery, Project};
|
use project::{search::SearchQuery, Project};
|
||||||
use std::{borrow::Cow, sync::Arc};
|
use std::{borrow::Cow, sync::Arc};
|
||||||
use ui::{h_stack, popover_menu, Button, Checkbox, Clickable, ContextMenu, Label, Selection};
|
use ui::{popover_menu, prelude::*, Button, Checkbox, ContextMenu, Label, Selection};
|
||||||
use workspace::{
|
use workspace::{
|
||||||
item::{Item, ItemHandle},
|
item::{Item, ItemHandle},
|
||||||
searchable::{SearchEvent, SearchableItem, SearchableItemHandle},
|
searchable::{SearchEvent, SearchableItem, SearchableItemHandle},
|
||||||
|
@ -614,8 +614,14 @@ impl Item for LspLogView {
|
||||||
Editor::to_item_events(event, f)
|
Editor::to_item_events(event, f)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn tab_content(&self, _: Option<usize>, _: bool, _: &WindowContext<'_>) -> AnyElement {
|
fn tab_content(&self, _: Option<usize>, selected: bool, _: &WindowContext<'_>) -> AnyElement {
|
||||||
Label::new("LSP Logs").into_any_element()
|
Label::new("LSP Logs")
|
||||||
|
.color(if selected {
|
||||||
|
Color::Default
|
||||||
|
} else {
|
||||||
|
Color::Muted
|
||||||
|
})
|
||||||
|
.into_any_element()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn as_searchable(&self, handle: &View<Self>) -> Option<Box<dyn SearchableItemHandle>> {
|
fn as_searchable(&self, handle: &View<Self>) -> Option<Box<dyn SearchableItemHandle>> {
|
||||||
|
|
|
@ -405,8 +405,14 @@ impl Item for SyntaxTreeView {
|
||||||
|
|
||||||
fn to_item_events(_: &Self::Event, _: impl FnMut(workspace::item::ItemEvent)) {}
|
fn to_item_events(_: &Self::Event, _: impl FnMut(workspace::item::ItemEvent)) {}
|
||||||
|
|
||||||
fn tab_content(&self, _: Option<usize>, _: bool, _: &WindowContext<'_>) -> AnyElement {
|
fn tab_content(&self, _: Option<usize>, selected: bool, _: &WindowContext<'_>) -> AnyElement {
|
||||||
Label::new("Syntax Tree").into_any_element()
|
Label::new("Syntax Tree")
|
||||||
|
.color(if selected {
|
||||||
|
Color::Default
|
||||||
|
} else {
|
||||||
|
Color::Muted
|
||||||
|
})
|
||||||
|
.into_any_element()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn clone_on_split(
|
fn clone_on_split(
|
||||||
|
|
|
@ -2816,15 +2816,6 @@ impl Project {
|
||||||
let lsp = project_settings.lsp.get(&adapter.name.0);
|
let lsp = project_settings.lsp.get(&adapter.name.0);
|
||||||
let override_options = lsp.map(|s| s.initialization_options.clone()).flatten();
|
let override_options = lsp.map(|s| s.initialization_options.clone()).flatten();
|
||||||
|
|
||||||
let mut initialization_options = adapter.initialization_options.clone();
|
|
||||||
match (&mut initialization_options, override_options) {
|
|
||||||
(Some(initialization_options), Some(override_options)) => {
|
|
||||||
merge_json_value_into(override_options, initialization_options);
|
|
||||||
}
|
|
||||||
(None, override_options) => initialization_options = override_options,
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
|
|
||||||
let server_id = pending_server.server_id;
|
let server_id = pending_server.server_id;
|
||||||
let container_dir = pending_server.container_dir.clone();
|
let container_dir = pending_server.container_dir.clone();
|
||||||
let state = LanguageServerState::Starting({
|
let state = LanguageServerState::Starting({
|
||||||
|
@ -2837,7 +2828,7 @@ impl Project {
|
||||||
let result = Self::setup_and_insert_language_server(
|
let result = Self::setup_and_insert_language_server(
|
||||||
this.clone(),
|
this.clone(),
|
||||||
&worktree_path,
|
&worktree_path,
|
||||||
initialization_options,
|
override_options,
|
||||||
pending_server,
|
pending_server,
|
||||||
adapter.clone(),
|
adapter.clone(),
|
||||||
language.clone(),
|
language.clone(),
|
||||||
|
@ -2958,7 +2949,7 @@ impl Project {
|
||||||
async fn setup_and_insert_language_server(
|
async fn setup_and_insert_language_server(
|
||||||
this: WeakModel<Self>,
|
this: WeakModel<Self>,
|
||||||
worktree_path: &Path,
|
worktree_path: &Path,
|
||||||
initialization_options: Option<serde_json::Value>,
|
override_initialization_options: Option<serde_json::Value>,
|
||||||
pending_server: PendingLanguageServer,
|
pending_server: PendingLanguageServer,
|
||||||
adapter: Arc<CachedLspAdapter>,
|
adapter: Arc<CachedLspAdapter>,
|
||||||
language: Arc<Language>,
|
language: Arc<Language>,
|
||||||
|
@ -2968,7 +2959,7 @@ impl Project {
|
||||||
) -> Result<Option<Arc<LanguageServer>>> {
|
) -> Result<Option<Arc<LanguageServer>>> {
|
||||||
let language_server = Self::setup_pending_language_server(
|
let language_server = Self::setup_pending_language_server(
|
||||||
this.clone(),
|
this.clone(),
|
||||||
initialization_options,
|
override_initialization_options,
|
||||||
pending_server,
|
pending_server,
|
||||||
worktree_path,
|
worktree_path,
|
||||||
adapter.clone(),
|
adapter.clone(),
|
||||||
|
@ -2998,7 +2989,7 @@ impl Project {
|
||||||
|
|
||||||
async fn setup_pending_language_server(
|
async fn setup_pending_language_server(
|
||||||
this: WeakModel<Self>,
|
this: WeakModel<Self>,
|
||||||
initialization_options: Option<serde_json::Value>,
|
override_options: Option<serde_json::Value>,
|
||||||
pending_server: PendingLanguageServer,
|
pending_server: PendingLanguageServer,
|
||||||
worktree_path: &Path,
|
worktree_path: &Path,
|
||||||
adapter: Arc<CachedLspAdapter>,
|
adapter: Arc<CachedLspAdapter>,
|
||||||
|
@ -3164,7 +3155,14 @@ impl Project {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.detach();
|
.detach();
|
||||||
|
let mut initialization_options = adapter.adapter.initialization_options().await;
|
||||||
|
match (&mut initialization_options, override_options) {
|
||||||
|
(Some(initialization_options), Some(override_options)) => {
|
||||||
|
merge_json_value_into(override_options, initialization_options);
|
||||||
|
}
|
||||||
|
(None, override_options) => initialization_options = override_options,
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
let language_server = language_server.initialize(initialization_options).await?;
|
let language_server = language_server.initialize(initialization_options).await?;
|
||||||
|
|
||||||
language_server
|
language_server
|
||||||
|
|
|
@ -971,25 +971,16 @@ impl ProjectPanel {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn open_in_terminal(&mut self, _: &OpenInTerminal, _cx: &mut ViewContext<Self>) {
|
fn open_in_terminal(&mut self, _: &OpenInTerminal, cx: &mut ViewContext<Self>) {
|
||||||
todo!()
|
if let Some((worktree, entry)) = self.selected_entry(cx) {
|
||||||
// if let Some((worktree, entry)) = self.selected_entry(cx) {
|
let path = worktree.abs_path().join(&entry.path);
|
||||||
// let window = cx.window();
|
cx.dispatch_action(
|
||||||
// let view_id = cx.view_id();
|
workspace::OpenTerminal {
|
||||||
// let path = worktree.abs_path().join(&entry.path);
|
working_directory: path,
|
||||||
|
}
|
||||||
// cx.app_context()
|
.boxed_clone(),
|
||||||
// .spawn(|mut cx| async move {
|
)
|
||||||
// window.dispatch_action(
|
}
|
||||||
// view_id,
|
|
||||||
// &workspace::OpenTerminal {
|
|
||||||
// working_directory: path,
|
|
||||||
// },
|
|
||||||
// &mut cx,
|
|
||||||
// );
|
|
||||||
// })
|
|
||||||
// .detach();
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_search_in_directory(
|
pub fn new_search_in_directory(
|
||||||
|
@ -1404,7 +1395,7 @@ impl ProjectPanel {
|
||||||
.child(if let Some(icon) = &icon {
|
.child(if let Some(icon) = &icon {
|
||||||
div().child(IconElement::from_path(icon.to_string()).color(Color::Muted))
|
div().child(IconElement::from_path(icon.to_string()).color(Color::Muted))
|
||||||
} else {
|
} else {
|
||||||
div()
|
div().size(IconSize::default().rems()).invisible()
|
||||||
})
|
})
|
||||||
.child(
|
.child(
|
||||||
if let (Some(editor), true) = (Some(&self.filename_editor), show_editor) {
|
if let (Some(editor), true) = (Some(&self.filename_editor), show_editor) {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::{settings_store::SettingsStore, KeymapFile, Settings};
|
use crate::{settings_store::SettingsStore, Settings};
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use fs::Fs;
|
use fs::Fs;
|
||||||
use futures::{channel::mpsc, StreamExt};
|
use futures::{channel::mpsc, StreamExt};
|
||||||
|
@ -77,7 +77,6 @@ pub fn handle_settings_file_changes(
|
||||||
});
|
});
|
||||||
cx.spawn(move |mut cx| async move {
|
cx.spawn(move |mut cx| async move {
|
||||||
while let Some(user_settings_content) = user_settings_file_rx.next().await {
|
while let Some(user_settings_content) = user_settings_file_rx.next().await {
|
||||||
eprintln!("settings file changed");
|
|
||||||
let result = cx.update_global(|store: &mut SettingsStore, cx| {
|
let result = cx.update_global(|store: &mut SettingsStore, cx| {
|
||||||
store
|
store
|
||||||
.set_user_settings(&user_settings_content, cx)
|
.set_user_settings(&user_settings_content, cx)
|
||||||
|
@ -121,14 +120,3 @@ pub fn update_settings_file<T: Settings>(
|
||||||
})
|
})
|
||||||
.detach_and_log_err(cx);
|
.detach_and_log_err(cx);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn load_default_keymap(cx: &mut AppContext) {
|
|
||||||
for path in ["keymaps/default.json", "keymaps/vim.json"] {
|
|
||||||
KeymapFile::load_asset(path, cx).unwrap();
|
|
||||||
}
|
|
||||||
|
|
||||||
// todo!()
|
|
||||||
// if let Some(asset_path) = settings::get::<BaseKeymap>(cx).asset_path() {
|
|
||||||
// KeymapFile::load_asset(asset_path, cx).unwrap();
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
|
|
|
@ -421,7 +421,7 @@ impl TerminalElement {
|
||||||
let rem_size = cx.rem_size();
|
let rem_size = cx.rem_size();
|
||||||
let font_pixels = text_style.font_size.to_pixels(rem_size);
|
let font_pixels = text_style.font_size.to_pixels(rem_size);
|
||||||
let line_height = font_pixels * line_height.to_pixels(rem_size);
|
let line_height = font_pixels * line_height.to_pixels(rem_size);
|
||||||
let font_id = cx.text_system().font_id(&text_style.font()).unwrap();
|
let font_id = cx.text_system().resolve_font(&text_style.font());
|
||||||
|
|
||||||
// todo!(do we need to keep this unwrap?)
|
// todo!(do we need to keep this unwrap?)
|
||||||
let cell_width = text_system
|
let cell_width = text_system
|
||||||
|
|
|
@ -126,13 +126,14 @@ impl RenderOnce for Tab {
|
||||||
if self.selected {
|
if self.selected {
|
||||||
this.border_l().border_r().pb_px()
|
this.border_l().border_r().pb_px()
|
||||||
} else {
|
} else {
|
||||||
this.pr_px().pl_px().border_b()
|
this.pr_px().pl_px().border_b().border_r()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
TabPosition::Middle(Ordering::Equal) => this.border_l().border_r().pb_px(),
|
TabPosition::Middle(Ordering::Equal) => this.border_l().border_r().pb_px(),
|
||||||
TabPosition::Middle(Ordering::Less) => this.border_l().pr_px().border_b(),
|
TabPosition::Middle(Ordering::Less) => this.border_l().pr_px().border_b(),
|
||||||
TabPosition::Middle(Ordering::Greater) => this.border_r().pl_px().border_b(),
|
TabPosition::Middle(Ordering::Greater) => this.border_r().pl_px().border_b(),
|
||||||
})
|
})
|
||||||
|
.cursor_pointer()
|
||||||
.child(
|
.child(
|
||||||
h_stack()
|
h_stack()
|
||||||
.group("")
|
.group("")
|
||||||
|
|
|
@ -150,14 +150,6 @@ pub fn app_menus() -> Vec<Menu<'static>> {
|
||||||
MenuItem::action("View Dependency Licenses", crate::OpenLicenses),
|
MenuItem::action("View Dependency Licenses", crate::OpenLicenses),
|
||||||
MenuItem::action("Show Welcome", workspace::Welcome),
|
MenuItem::action("Show Welcome", workspace::Welcome),
|
||||||
MenuItem::separator(),
|
MenuItem::separator(),
|
||||||
// todo!(): Needs `feedback` crate.
|
|
||||||
// MenuItem::action("Give us feedback", feedback::feedback_editor::GiveFeedback),
|
|
||||||
// MenuItem::action(
|
|
||||||
// "Copy System Specs Into Clipboard",
|
|
||||||
// feedback::CopySystemSpecsIntoClipboard,
|
|
||||||
// ),
|
|
||||||
// MenuItem::action("File Bug Report", feedback::FileBugReport),
|
|
||||||
// MenuItem::action("Request Feature", feedback::RequestFeature),
|
|
||||||
MenuItem::separator(),
|
MenuItem::separator(),
|
||||||
MenuItem::action(
|
MenuItem::action(
|
||||||
"Documentation",
|
"Documentation",
|
||||||
|
|
|
@ -18,11 +18,11 @@ pub use only_instance::*;
|
||||||
pub use open_listener::*;
|
pub use open_listener::*;
|
||||||
|
|
||||||
use anyhow::{anyhow, Context as _};
|
use anyhow::{anyhow, Context as _};
|
||||||
use futures::{channel::mpsc, StreamExt};
|
use futures::{channel::mpsc, select_biased, StreamExt};
|
||||||
use project_panel::ProjectPanel;
|
use project_panel::ProjectPanel;
|
||||||
use quick_action_bar::QuickActionBar;
|
use quick_action_bar::QuickActionBar;
|
||||||
use search::project_search::ProjectSearchBar;
|
use search::project_search::ProjectSearchBar;
|
||||||
use settings::{initial_local_settings_content, load_default_keymap, KeymapFile, Settings};
|
use settings::{initial_local_settings_content, KeymapFile, Settings, SettingsStore};
|
||||||
use std::{borrow::Cow, ops::Deref, sync::Arc};
|
use std::{borrow::Cow, ops::Deref, sync::Arc};
|
||||||
use terminal_view::terminal_panel::TerminalPanel;
|
use terminal_view::terminal_panel::TerminalPanel;
|
||||||
use util::{
|
use util::{
|
||||||
|
@ -32,6 +32,7 @@ use util::{
|
||||||
ResultExt,
|
ResultExt,
|
||||||
};
|
};
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
use welcome::BaseKeymap;
|
||||||
use workspace::Pane;
|
use workspace::Pane;
|
||||||
use workspace::{
|
use workspace::{
|
||||||
create_and_open_local_file, notifications::simple_message_notification::MessageNotification,
|
create_and_open_local_file, notifications::simple_message_notification::MessageNotification,
|
||||||
|
@ -399,8 +400,7 @@ pub fn initialize_workspace(app_state: Arc<AppState>, cx: &mut AppContext) {
|
||||||
});
|
});
|
||||||
|
|
||||||
workspace.focus_handle(cx).focus(cx);
|
workspace.focus_handle(cx).focus(cx);
|
||||||
//todo!()
|
load_default_keymap(cx);
|
||||||
// load_default_keymap(cx);
|
|
||||||
})
|
})
|
||||||
.detach();
|
.detach();
|
||||||
}
|
}
|
||||||
|
@ -558,38 +558,58 @@ pub fn handle_keymap_file_changes(
|
||||||
mut user_keymap_file_rx: mpsc::UnboundedReceiver<String>,
|
mut user_keymap_file_rx: mpsc::UnboundedReceiver<String>,
|
||||||
cx: &mut AppContext,
|
cx: &mut AppContext,
|
||||||
) {
|
) {
|
||||||
cx.spawn(move |cx| async move {
|
BaseKeymap::register(cx);
|
||||||
// let mut settings_subscription = None;
|
|
||||||
while let Some(user_keymap_content) = user_keymap_file_rx.next().await {
|
|
||||||
if let Some(keymap_content) = KeymapFile::parse(&user_keymap_content).log_err() {
|
|
||||||
cx.update(|cx| reload_keymaps(cx, &keymap_content)).ok();
|
|
||||||
|
|
||||||
// todo!()
|
let (base_keymap_tx, mut base_keymap_rx) = mpsc::unbounded();
|
||||||
// let mut old_base_keymap = cx.read(|cx| *settings::get::<BaseKeymap>(cx));
|
let mut old_base_keymap = *BaseKeymap::get_global(cx);
|
||||||
// drop(settings_subscription);
|
cx.observe_global::<SettingsStore>(move |cx| {
|
||||||
// settings_subscription = Some(cx.update(|cx| {
|
let new_base_keymap = *BaseKeymap::get_global(cx);
|
||||||
// cx.observe_global::<SettingsStore, _>(move |cx| {
|
if new_base_keymap != old_base_keymap {
|
||||||
// let new_base_keymap = *settings::get::<BaseKeymap>(cx);
|
old_base_keymap = new_base_keymap.clone();
|
||||||
// if new_base_keymap != old_base_keymap {
|
base_keymap_tx.unbounded_send(()).unwrap();
|
||||||
// old_base_keymap = new_base_keymap.clone();
|
}
|
||||||
// reload_keymaps(cx, &keymap_content);
|
})
|
||||||
// }
|
.detach();
|
||||||
// })
|
|
||||||
// }));
|
cx.spawn(move |cx| async move {
|
||||||
|
let mut user_keymap = KeymapFile::default();
|
||||||
|
loop {
|
||||||
|
select_biased! {
|
||||||
|
_ = base_keymap_rx.next() => {}
|
||||||
|
user_keymap_content = user_keymap_file_rx.next() => {
|
||||||
|
if let Some(user_keymap_content) = user_keymap_content {
|
||||||
|
if let Some(keymap_content) = KeymapFile::parse(&user_keymap_content).log_err() {
|
||||||
|
user_keymap = keymap_content;
|
||||||
|
} else {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cx.update(|cx| reload_keymaps(cx, &user_keymap)).ok();
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.detach();
|
.detach();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn reload_keymaps(cx: &mut AppContext, keymap_content: &KeymapFile) {
|
fn reload_keymaps(cx: &mut AppContext, keymap_content: &KeymapFile) {
|
||||||
// todo!()
|
cx.clear_key_bindings();
|
||||||
// cx.clear_bindings();
|
|
||||||
load_default_keymap(cx);
|
load_default_keymap(cx);
|
||||||
keymap_content.clone().add_to_cx(cx).log_err();
|
keymap_content.clone().add_to_cx(cx).log_err();
|
||||||
cx.set_menus(app_menus());
|
cx.set_menus(app_menus());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn load_default_keymap(cx: &mut AppContext) {
|
||||||
|
for path in ["keymaps/default.json", "keymaps/vim.json"] {
|
||||||
|
KeymapFile::load_asset(path, cx).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(asset_path) = BaseKeymap::get_global(cx).asset_path() {
|
||||||
|
KeymapFile::load_asset(asset_path, cx).unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn open_local_settings_file(
|
fn open_local_settings_file(
|
||||||
workspace: &mut Workspace,
|
workspace: &mut Workspace,
|
||||||
_: &OpenLocalSettings,
|
_: &OpenLocalSettings,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue