Compare commits
12 Commits
docs_highl
...
v0.131.4-p
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bc6e7dbd1b | ||
|
|
18f0bc4c84 | ||
|
|
4ef4748681 | ||
|
|
30824089b2 | ||
|
|
5df5a400e9 | ||
|
|
ca62f6e231 | ||
|
|
b01c07b17d | ||
|
|
c35c957e7a | ||
|
|
0137e7e1e0 | ||
|
|
25b8e46b98 | ||
|
|
04e6d5d553 | ||
|
|
547d02227d |
3
Cargo.lock
generated
3
Cargo.lock
generated
@@ -3588,6 +3588,7 @@ dependencies = [
|
||||
"fs",
|
||||
"futures 0.3.28",
|
||||
"gpui",
|
||||
"isahc",
|
||||
"language",
|
||||
"log",
|
||||
"lsp",
|
||||
@@ -12514,7 +12515,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "zed"
|
||||
version = "0.131.0"
|
||||
version = "0.131.4"
|
||||
dependencies = [
|
||||
"activity_indicator",
|
||||
"anyhow",
|
||||
|
||||
@@ -52,12 +52,19 @@ impl Render for Breadcrumbs {
|
||||
Some(BreadcrumbText {
|
||||
text: "⋯".into(),
|
||||
highlights: None,
|
||||
font: None,
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
let highlighted_segments = segments.into_iter().map(|segment| {
|
||||
let mut text_style = cx.text_style();
|
||||
if let Some(font) = segment.font {
|
||||
text_style.font_family = font.family;
|
||||
text_style.font_features = font.features;
|
||||
text_style.font_style = font.style;
|
||||
text_style.font_weight = font.weight;
|
||||
}
|
||||
text_style.color = Color::Muted.color(cx);
|
||||
|
||||
StyledText::new(segment.text.replace('\n', ""))
|
||||
|
||||
@@ -10568,6 +10568,11 @@ pub fn diagnostic_block_renderer(diagnostic: Diagnostic, _is_valid: bool) -> Ren
|
||||
|
||||
let mut text_style = cx.text_style().clone();
|
||||
text_style.color = diagnostic_style(diagnostic.severity, true, cx.theme().status());
|
||||
let theme_settings = ThemeSettings::get_global(cx);
|
||||
text_style.font_family = theme_settings.buffer_font.family.clone();
|
||||
text_style.font_style = theme_settings.buffer_font.style;
|
||||
text_style.font_features = theme_settings.buffer_font.features;
|
||||
text_style.font_weight = theme_settings.buffer_font.weight;
|
||||
|
||||
let multi_line_diagnostic = diagnostic.message.contains('\n');
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@ use std::{
|
||||
sync::Arc,
|
||||
};
|
||||
use text::{BufferId, Selection};
|
||||
use theme::Theme;
|
||||
use theme::{Theme, ThemeSettings};
|
||||
use ui::{h_flex, prelude::*, Label};
|
||||
use util::{paths::PathExt, ResultExt, TryFutureExt};
|
||||
use workspace::item::{BreadcrumbText, FollowEvent, FollowableItemHandle};
|
||||
@@ -824,13 +824,18 @@ impl Item for Editor {
|
||||
.map(|path| path.to_string_lossy().to_string())
|
||||
.unwrap_or_else(|| "untitled".to_string());
|
||||
|
||||
let settings = ThemeSettings::get_global(cx);
|
||||
|
||||
let mut breadcrumbs = vec![BreadcrumbText {
|
||||
text: filename,
|
||||
highlights: None,
|
||||
font: Some(settings.buffer_font.clone()),
|
||||
}];
|
||||
|
||||
breadcrumbs.extend(symbols.into_iter().map(|symbol| BreadcrumbText {
|
||||
text: symbol.text,
|
||||
highlights: Some(symbol.highlight_ranges),
|
||||
font: Some(settings.buffer_font.clone()),
|
||||
}));
|
||||
Some(breadcrumbs)
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ collections.workspace = true
|
||||
fs.workspace = true
|
||||
futures.workspace = true
|
||||
gpui.workspace = true
|
||||
isahc.workspace = true
|
||||
language.workspace = true
|
||||
log.workspace = true
|
||||
lsp.workspace = true
|
||||
|
||||
@@ -606,7 +606,23 @@ impl ExtensionStore {
|
||||
)
|
||||
.await?;
|
||||
|
||||
let decompressed_bytes = GzipDecoder::new(BufReader::new(response.body_mut()));
|
||||
let content_length = response
|
||||
.headers()
|
||||
.get(isahc::http::header::CONTENT_LENGTH)
|
||||
.and_then(|value| value.to_str().ok()?.parse::<usize>().ok());
|
||||
|
||||
let mut body = BufReader::new(response.body_mut());
|
||||
let mut tgz_bytes = Vec::new();
|
||||
body.read_to_end(&mut tgz_bytes).await?;
|
||||
|
||||
if let Some(content_length) = content_length {
|
||||
let actual_len = tgz_bytes.len();
|
||||
if content_length != actual_len {
|
||||
bail!("downloaded extension size {actual_len} does not match content length {content_length}");
|
||||
}
|
||||
}
|
||||
let decompressed_bytes = GzipDecoder::new(BufReader::new(tgz_bytes.as_slice()));
|
||||
// let decompressed_bytes = GzipDecoder::new(BufReader::new(tgz_bytes));
|
||||
let archive = Archive::new(decompressed_bytes);
|
||||
archive.unpack(extension_dir).await?;
|
||||
this.update(&mut cx, |this, cx| {
|
||||
|
||||
@@ -198,13 +198,15 @@ pub fn parse_wasm_extension_version(
|
||||
extension_id: &str,
|
||||
wasm_bytes: &[u8],
|
||||
) -> Result<SemanticVersion> {
|
||||
let mut version = None;
|
||||
|
||||
for part in wasmparser::Parser::new(0).parse_all(wasm_bytes) {
|
||||
if let wasmparser::Payload::CustomSection(s) = part? {
|
||||
if let wasmparser::Payload::CustomSection(s) =
|
||||
part.context("error parsing wasm extension")?
|
||||
{
|
||||
if s.name() == "zed:api-version" {
|
||||
let version = parse_wasm_extension_version_custom_section(s.data());
|
||||
if let Some(version) = version {
|
||||
return Ok(version);
|
||||
} else {
|
||||
version = parse_wasm_extension_version_custom_section(s.data());
|
||||
if version.is_none() {
|
||||
bail!(
|
||||
"extension {} has invalid zed:api-version section: {:?}",
|
||||
extension_id,
|
||||
@@ -214,7 +216,13 @@ pub fn parse_wasm_extension_version(
|
||||
}
|
||||
}
|
||||
}
|
||||
bail!("extension {} has no zed:api-version section", extension_id)
|
||||
|
||||
// The reason we wait until we're done parsing all of the Wasm bytes to return the version
|
||||
// is to work around a panic that can happen inside of Wasmtime when the bytes are invalid.
|
||||
//
|
||||
// By parsing the entirety of the Wasm bytes before we return, we're able to detect this problem
|
||||
// earlier as an `Err` rather than as a panic.
|
||||
version.ok_or_else(|| anyhow!("extension {} has no zed:api-version section", extension_id))
|
||||
}
|
||||
|
||||
fn parse_wasm_extension_version_custom_section(data: &[u8]) -> Option<SemanticVersion> {
|
||||
|
||||
@@ -334,7 +334,7 @@ impl MacTextSystemState {
|
||||
self.postscript_names_by_font_id
|
||||
.get(&font_id)
|
||||
.map_or(false, |postscript_name| {
|
||||
postscript_name == "AppleColorEmoji"
|
||||
postscript_name == "AppleColorEmoji" || postscript_name == ".AppleColorEmojiUI"
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -37,7 +37,9 @@ impl project::Item for ImageItem {
|
||||
.and_then(OsStr::to_str)
|
||||
.unwrap_or_default();
|
||||
|
||||
if Img::extensions().contains(&ext) {
|
||||
// Only open the item if it's a binary image (no SVGs, etc.)
|
||||
// Since we do not have a way to toggle to an editor
|
||||
if Img::extensions().contains(&ext) && !ext.contains("svg") {
|
||||
Some(cx.spawn(|mut cx| async move {
|
||||
let abs_path = project
|
||||
.read_with(&cx, |project, cx| project.absolute_path(&path, cx))?
|
||||
|
||||
@@ -113,8 +113,8 @@ impl BufferSearchBar {
|
||||
} else {
|
||||
color
|
||||
},
|
||||
font_family: settings.ui_font.family.clone(),
|
||||
font_features: settings.ui_font.features,
|
||||
font_family: settings.buffer_font.family.clone(),
|
||||
font_features: settings.buffer_font.features,
|
||||
font_size: rems(0.875).into(),
|
||||
font_weight: FontWeight::NORMAL,
|
||||
font_style: FontStyle::Normal,
|
||||
|
||||
@@ -1421,8 +1421,8 @@ impl ProjectSearchBar {
|
||||
} else {
|
||||
cx.theme().colors().text
|
||||
},
|
||||
font_family: settings.ui_font.family.clone(),
|
||||
font_features: settings.ui_font.features,
|
||||
font_family: settings.buffer_font.family.clone(),
|
||||
font_features: settings.buffer_font.features,
|
||||
font_size: rems(0.875).into(),
|
||||
font_weight: FontWeight::NORMAL,
|
||||
font_style: FontStyle::Normal,
|
||||
|
||||
@@ -2,7 +2,7 @@ use std::{path::PathBuf, sync::Arc};
|
||||
|
||||
use ::settings::Settings;
|
||||
use editor::Editor;
|
||||
use gpui::{AppContext, ViewContext, WeakView, WindowContext};
|
||||
use gpui::{AppContext, ViewContext, WindowContext};
|
||||
use language::{Language, Point};
|
||||
use modal::{Spawn, TasksModal};
|
||||
use project::{Location, WorktreeId};
|
||||
@@ -60,17 +60,17 @@ fn spawn_task_or_modal(workspace: &mut Workspace, action: &Spawn, cx: &mut ViewC
|
||||
fn spawn_task_with_name(name: String, cx: &mut ViewContext<Workspace>) {
|
||||
cx.spawn(|workspace, mut cx| async move {
|
||||
let did_spawn = workspace
|
||||
.update(&mut cx, |this, cx| {
|
||||
let (worktree, language) = active_item_selection_properties(&workspace, cx);
|
||||
let tasks = this.project().update(cx, |project, cx| {
|
||||
.update(&mut cx, |workspace, cx| {
|
||||
let (worktree, language) = active_item_selection_properties(workspace, cx);
|
||||
let tasks = workspace.project().update(cx, |project, cx| {
|
||||
project.task_inventory().update(cx, |inventory, cx| {
|
||||
inventory.list_tasks(language, worktree, false, cx)
|
||||
})
|
||||
});
|
||||
let (_, target_task) = tasks.into_iter().find(|(_, task)| task.name() == name)?;
|
||||
let cwd = task_cwd(this, cx).log_err().flatten();
|
||||
let task_context = task_context(this, cwd, cx);
|
||||
schedule_task(this, &target_task, task_context, false, cx);
|
||||
let cwd = task_cwd(workspace, cx).log_err().flatten();
|
||||
let task_context = task_context(workspace, cwd, cx);
|
||||
schedule_task(workspace, &target_task, task_context, false, cx);
|
||||
Some(())
|
||||
})
|
||||
.ok()
|
||||
@@ -88,13 +88,10 @@ fn spawn_task_with_name(name: String, cx: &mut ViewContext<Workspace>) {
|
||||
}
|
||||
|
||||
fn active_item_selection_properties(
|
||||
workspace: &WeakView<Workspace>,
|
||||
workspace: &Workspace,
|
||||
cx: &mut WindowContext,
|
||||
) -> (Option<WorktreeId>, Option<Arc<Language>>) {
|
||||
let active_item = workspace
|
||||
.update(cx, |workspace, cx| workspace.active_item(cx))
|
||||
.ok()
|
||||
.flatten();
|
||||
let active_item = workspace.active_item(cx);
|
||||
let worktree_id = active_item
|
||||
.as_ref()
|
||||
.and_then(|item| item.project_path(cx))
|
||||
|
||||
@@ -195,8 +195,13 @@ impl PickerDelegate for TasksModalDelegate {
|
||||
let Some(candidates) = picker
|
||||
.update(&mut cx, |picker, cx| {
|
||||
let candidates = picker.delegate.candidates.get_or_insert_with(|| {
|
||||
let (worktree, language) =
|
||||
active_item_selection_properties(&picker.delegate.workspace, cx);
|
||||
let Ok((worktree, language)) =
|
||||
picker.delegate.workspace.update(cx, |workspace, cx| {
|
||||
active_item_selection_properties(workspace, cx)
|
||||
})
|
||||
else {
|
||||
return Vec::new();
|
||||
};
|
||||
picker.delegate.inventory.update(cx, |inventory, cx| {
|
||||
inventory.list_tasks(language, worktree, true, cx)
|
||||
})
|
||||
@@ -376,6 +381,8 @@ mod tests {
|
||||
use project::{FakeFs, Project};
|
||||
use serde_json::json;
|
||||
|
||||
use crate::modal::Spawn;
|
||||
|
||||
use super::*;
|
||||
|
||||
#[gpui::test]
|
||||
@@ -514,13 +521,29 @@ mod tests {
|
||||
vec!["echo 4", "another one", "example task", "echo 40"],
|
||||
"Last recently used one show task should be listed last, as it is a fire-and-forget task"
|
||||
);
|
||||
|
||||
cx.dispatch_action(Spawn {
|
||||
task_name: Some("example task".to_string()),
|
||||
});
|
||||
let tasks_picker = workspace.update(cx, |workspace, cx| {
|
||||
workspace
|
||||
.active_modal::<TasksModal>(cx)
|
||||
.unwrap()
|
||||
.read(cx)
|
||||
.picker
|
||||
.clone()
|
||||
});
|
||||
assert_eq!(
|
||||
task_names(&tasks_picker, cx),
|
||||
vec!["echo 4", "another one", "example task", "echo 40"],
|
||||
);
|
||||
}
|
||||
|
||||
fn open_spawn_tasks(
|
||||
workspace: &View<Workspace>,
|
||||
cx: &mut VisualTestContext,
|
||||
) -> View<Picker<TasksModalDelegate>> {
|
||||
cx.dispatch_action(crate::modal::Spawn::default());
|
||||
cx.dispatch_action(Spawn::default());
|
||||
workspace.update(cx, |workspace, cx| {
|
||||
workspace
|
||||
.active_modal::<TasksModal>(cx)
|
||||
|
||||
@@ -866,6 +866,7 @@ impl Item for TerminalView {
|
||||
Some(vec![BreadcrumbText {
|
||||
text: self.terminal().read(cx).breadcrumb_text.clone(),
|
||||
highlights: None,
|
||||
font: None,
|
||||
}])
|
||||
}
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ use client::{
|
||||
use futures::{channel::mpsc, StreamExt};
|
||||
use gpui::{
|
||||
AnyElement, AnyView, AppContext, Entity, EntityId, EventEmitter, FocusHandle, FocusableView,
|
||||
HighlightStyle, Model, Pixels, Point, SharedString, Task, View, ViewContext, WeakView,
|
||||
Font, HighlightStyle, Model, Pixels, Point, SharedString, Task, View, ViewContext, WeakView,
|
||||
WindowContext,
|
||||
};
|
||||
use project::{Project, ProjectEntryId, ProjectPath};
|
||||
@@ -93,6 +93,7 @@ pub enum ItemEvent {
|
||||
pub struct BreadcrumbText {
|
||||
pub text: String,
|
||||
pub highlights: Option<Vec<(Range<usize>, HighlightStyle)>>,
|
||||
pub font: Option<Font>,
|
||||
}
|
||||
|
||||
pub trait Item: FocusableView + EventEmitter<Self::Event> {
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
description = "The fast, collaborative code editor."
|
||||
edition = "2021"
|
||||
name = "zed"
|
||||
version = "0.131.0"
|
||||
version = "0.131.4"
|
||||
publish = false
|
||||
license = "GPL-3.0-or-later"
|
||||
authors = ["Zed Team <hi@zed.dev>"]
|
||||
|
||||
@@ -1 +1 @@
|
||||
dev
|
||||
preview
|
||||
Reference in New Issue
Block a user