Compare commits
19 Commits
test-threa
...
v0.130.6
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
636e084d1d | ||
|
|
0c9d07f7b3 | ||
|
|
bda5713151 | ||
|
|
778e1ad7ab | ||
|
|
044b04a104 | ||
|
|
b038248540 | ||
|
|
fbfbc68db4 | ||
|
|
67b52968ff | ||
|
|
f7fe065f5f | ||
|
|
d4a59f69bb | ||
|
|
4976d8f6bc | ||
|
|
03d06412a3 | ||
|
|
d43f95db5f | ||
|
|
07b70cd4a1 | ||
|
|
77bd4dc413 | ||
|
|
b6fd9487eb | ||
|
|
b33f7c64f6 | ||
|
|
e950a992fd | ||
|
|
8c05d7875e |
3
Cargo.lock
generated
3
Cargo.lock
generated
@@ -3507,6 +3507,7 @@ dependencies = [
|
||||
"fs",
|
||||
"futures 0.3.28",
|
||||
"gpui",
|
||||
"isahc",
|
||||
"language",
|
||||
"log",
|
||||
"lsp",
|
||||
@@ -12379,7 +12380,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "zed"
|
||||
version = "0.130.0"
|
||||
version = "0.130.6"
|
||||
dependencies = [
|
||||
"activity_indicator",
|
||||
"anyhow",
|
||||
|
||||
@@ -4641,9 +4641,16 @@ async fn test_references(
|
||||
let active_call_a = cx_a.read(ActiveCall::global);
|
||||
|
||||
client_a.language_registry().add(rust_lang());
|
||||
let mut fake_language_servers = client_a
|
||||
.language_registry()
|
||||
.register_fake_lsp_adapter("Rust", Default::default());
|
||||
let mut fake_language_servers = client_a.language_registry().register_fake_lsp_adapter(
|
||||
"Rust",
|
||||
FakeLspAdapter {
|
||||
capabilities: lsp::ServerCapabilities {
|
||||
references_provider: Some(lsp::OneOf::Left(true)),
|
||||
..Default::default()
|
||||
},
|
||||
..Default::default()
|
||||
},
|
||||
);
|
||||
|
||||
client_a
|
||||
.fs()
|
||||
|
||||
@@ -433,7 +433,10 @@ impl DisplaySnapshot {
|
||||
} else if range.start.row == self.max_buffer_row()
|
||||
|| (range.end.column > 0 && range.end.row == self.max_buffer_row())
|
||||
{
|
||||
Point::new(range.start.row - 1, self.line_len(range.start.row - 1))
|
||||
Point::new(
|
||||
range.start.row - 1,
|
||||
self.buffer_snapshot.line_len(range.start.row - 1),
|
||||
)
|
||||
} else {
|
||||
self.prev_line_boundary(range.start).0
|
||||
};
|
||||
|
||||
@@ -7096,22 +7096,13 @@ impl Editor {
|
||||
.line_comment_prefixes()
|
||||
.filter(|prefixes| !prefixes.is_empty())
|
||||
{
|
||||
// Split the comment prefix's trailing whitespace into a separate string,
|
||||
// as that portion won't be used for detecting if a line is a comment.
|
||||
struct Comment {
|
||||
full_prefix: Arc<str>,
|
||||
trimmed_prefix_len: usize,
|
||||
}
|
||||
let prefixes: SmallVec<[Comment; 4]> = full_comment_prefixes
|
||||
let first_prefix = full_comment_prefixes
|
||||
.first()
|
||||
.expect("prefixes is non-empty");
|
||||
let prefix_trimmed_lengths = full_comment_prefixes
|
||||
.iter()
|
||||
.map(|full_prefix| {
|
||||
let trimmed_prefix_len = full_prefix.trim_end_matches(' ').len();
|
||||
Comment {
|
||||
trimmed_prefix_len,
|
||||
full_prefix: full_prefix.clone(),
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
.map(|p| p.trim_end_matches(' ').len())
|
||||
.collect::<SmallVec<[usize; 4]>>();
|
||||
|
||||
let mut all_selection_lines_are_comments = true;
|
||||
|
||||
@@ -7120,28 +7111,25 @@ impl Editor {
|
||||
continue;
|
||||
}
|
||||
|
||||
let Some((prefix, prefix_range)) = prefixes
|
||||
let prefix_range = full_comment_prefixes
|
||||
.iter()
|
||||
.map(|prefix| {
|
||||
(
|
||||
prefix,
|
||||
comment_prefix_range(
|
||||
snapshot.deref(),
|
||||
row,
|
||||
&prefix.full_prefix[..prefix.trimmed_prefix_len],
|
||||
&prefix.full_prefix[prefix.trimmed_prefix_len..],
|
||||
),
|
||||
.zip(prefix_trimmed_lengths.iter().copied())
|
||||
.map(|(prefix, trimmed_prefix_len)| {
|
||||
comment_prefix_range(
|
||||
snapshot.deref(),
|
||||
row,
|
||||
&prefix[..trimmed_prefix_len],
|
||||
&prefix[trimmed_prefix_len..],
|
||||
)
|
||||
})
|
||||
.max_by_key(|(_, range)| range.end.column - range.start.column)
|
||||
else {
|
||||
// There has to be at least one prefix.
|
||||
break;
|
||||
};
|
||||
.max_by_key(|range| range.end.column - range.start.column)
|
||||
.expect("prefixes is non-empty");
|
||||
|
||||
if prefix_range.is_empty() {
|
||||
all_selection_lines_are_comments = false;
|
||||
}
|
||||
selection_edit_ranges.push((prefix_range, prefix.full_prefix.clone()));
|
||||
|
||||
selection_edit_ranges.push(prefix_range);
|
||||
}
|
||||
|
||||
if all_selection_lines_are_comments {
|
||||
@@ -7149,17 +7137,17 @@ impl Editor {
|
||||
selection_edit_ranges
|
||||
.iter()
|
||||
.cloned()
|
||||
.map(|(range, _)| (range, empty_str.clone())),
|
||||
.map(|range| (range, empty_str.clone())),
|
||||
);
|
||||
} else {
|
||||
let min_column = selection_edit_ranges
|
||||
.iter()
|
||||
.map(|(range, _)| range.start.column)
|
||||
.map(|range| range.start.column)
|
||||
.min()
|
||||
.unwrap_or(0);
|
||||
edits.extend(selection_edit_ranges.iter().map(|(range, prefix)| {
|
||||
edits.extend(selection_edit_ranges.iter().map(|range| {
|
||||
let position = Point::new(range.start.row, min_column);
|
||||
(position..position, prefix.clone())
|
||||
(position..position, first_prefix.clone())
|
||||
}));
|
||||
}
|
||||
} else if let Some((full_comment_prefix, comment_suffix)) =
|
||||
|
||||
@@ -6507,7 +6507,7 @@ async fn test_toggle_comment(cx: &mut gpui::TestAppContext) {
|
||||
let mut cx = EditorTestContext::new(cx).await;
|
||||
let language = Arc::new(Language::new(
|
||||
LanguageConfig {
|
||||
line_comments: vec!["// ".into()],
|
||||
line_comments: vec!["// ".into(), "//! ".into(), "/// ".into()],
|
||||
..Default::default()
|
||||
},
|
||||
Some(tree_sitter_rust::language()),
|
||||
@@ -6601,6 +6601,25 @@ async fn test_toggle_comment(cx: &mut gpui::TestAppContext) {
|
||||
// c();ˇ»
|
||||
}
|
||||
"});
|
||||
|
||||
// If a selection includes multiple comment prefixes, all lines are uncommented.
|
||||
cx.set_state(indoc! {"
|
||||
fn a() {
|
||||
«// a();
|
||||
/// b();
|
||||
//! c();ˇ»
|
||||
}
|
||||
"});
|
||||
|
||||
cx.update_editor(|e, cx| e.toggle_comments(&ToggleComments::default(), cx));
|
||||
|
||||
cx.assert_editor_state(indoc! {"
|
||||
fn a() {
|
||||
«a();
|
||||
b();
|
||||
c();ˇ»
|
||||
}
|
||||
"});
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
|
||||
@@ -705,31 +705,38 @@ impl Item for Editor {
|
||||
.await?;
|
||||
}
|
||||
|
||||
// Only format and save the buffers with changes. For clean buffers,
|
||||
// we simulate saving by calling `Buffer::did_save`, so that language servers or
|
||||
// other downstream listeners of save events get notified.
|
||||
let (dirty_buffers, clean_buffers) = buffers.into_iter().partition(|buffer| {
|
||||
buffer
|
||||
.update(&mut cx, |buffer, _| {
|
||||
buffer.is_dirty() || buffer.has_conflict()
|
||||
})
|
||||
.unwrap_or(false)
|
||||
});
|
||||
if buffers.len() == 1 {
|
||||
// Apply full save routine for singleton buffers, to allow to `touch` the file via the editor.
|
||||
project
|
||||
.update(&mut cx, |project, cx| project.save_buffers(buffers, cx))?
|
||||
.await?;
|
||||
} else {
|
||||
// For multi-buffers, only format and save the buffers with changes.
|
||||
// For clean buffers, we simulate saving by calling `Buffer::did_save`,
|
||||
// so that language servers or other downstream listeners of save events get notified.
|
||||
let (dirty_buffers, clean_buffers) = buffers.into_iter().partition(|buffer| {
|
||||
buffer
|
||||
.update(&mut cx, |buffer, _| {
|
||||
buffer.is_dirty() || buffer.has_conflict()
|
||||
})
|
||||
.unwrap_or(false)
|
||||
});
|
||||
|
||||
project
|
||||
.update(&mut cx, |project, cx| {
|
||||
project.save_buffers(dirty_buffers, cx)
|
||||
})?
|
||||
.await?;
|
||||
for buffer in clean_buffers {
|
||||
buffer
|
||||
.update(&mut cx, |buffer, cx| {
|
||||
let version = buffer.saved_version().clone();
|
||||
let fingerprint = buffer.saved_version_fingerprint();
|
||||
let mtime = buffer.saved_mtime();
|
||||
buffer.did_save(version, fingerprint, mtime, cx);
|
||||
})
|
||||
.ok();
|
||||
project
|
||||
.update(&mut cx, |project, cx| {
|
||||
project.save_buffers(dirty_buffers, cx)
|
||||
})?
|
||||
.await?;
|
||||
for buffer in clean_buffers {
|
||||
buffer
|
||||
.update(&mut cx, |buffer, cx| {
|
||||
let version = buffer.saved_version().clone();
|
||||
let fingerprint = buffer.saved_version_fingerprint();
|
||||
let mtime = buffer.saved_mtime();
|
||||
buffer.did_save(version, fingerprint, mtime, cx);
|
||||
})
|
||||
.ok();
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -64,7 +64,9 @@ impl LspAdapter for ExtensionLspAdapter {
|
||||
// We can remove once the following extension versions no longer see any use:
|
||||
// - toml@0.0.2
|
||||
// - zig@0.0.1
|
||||
if ["toml", "zig"].contains(&self.extension.manifest.id.as_ref()) {
|
||||
if ["toml", "zig"].contains(&self.extension.manifest.id.as_ref())
|
||||
&& path.starts_with(&self.host.work_dir)
|
||||
{
|
||||
#[cfg(not(windows))]
|
||||
{
|
||||
use std::fs::{self, Permissions};
|
||||
|
||||
@@ -605,7 +605,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| {
|
||||
|
||||
@@ -183,13 +183,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,
|
||||
@@ -199,7 +201,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> {
|
||||
|
||||
@@ -1848,16 +1848,17 @@ extern "C" fn accepts_first_mouse(this: &Object, _: Sel, _: id) -> BOOL {
|
||||
|
||||
extern "C" fn dragging_entered(this: &Object, _: Sel, dragging_info: id) -> NSDragOperation {
|
||||
let window_state = unsafe { get_window_state(this) };
|
||||
if send_new_event(&window_state, {
|
||||
let position = drag_event_position(&window_state, dragging_info);
|
||||
let paths = external_paths_from_event(dragging_info);
|
||||
PlatformInput::FileDrop(FileDropEvent::Entered { position, paths })
|
||||
}) {
|
||||
window_state.lock().external_files_dragged = true;
|
||||
NSDragOperationCopy
|
||||
} else {
|
||||
NSDragOperationNone
|
||||
let position = drag_event_position(&window_state, dragging_info);
|
||||
let paths = external_paths_from_event(dragging_info);
|
||||
if let Some(event) =
|
||||
paths.map(|paths| PlatformInput::FileDrop(FileDropEvent::Entered { position, paths }))
|
||||
{
|
||||
if send_new_event(&window_state, event) {
|
||||
window_state.lock().external_files_dragged = true;
|
||||
return NSDragOperationCopy;
|
||||
}
|
||||
}
|
||||
NSDragOperationNone
|
||||
}
|
||||
|
||||
extern "C" fn dragging_updated(this: &Object, _: Sel, dragging_info: id) -> NSDragOperation {
|
||||
@@ -1895,10 +1896,13 @@ extern "C" fn perform_drag_operation(this: &Object, _: Sel, dragging_info: id) -
|
||||
}
|
||||
}
|
||||
|
||||
fn external_paths_from_event(dragging_info: *mut Object) -> ExternalPaths {
|
||||
fn external_paths_from_event(dragging_info: *mut Object) -> Option<ExternalPaths> {
|
||||
let mut paths = SmallVec::new();
|
||||
let pasteboard: id = unsafe { msg_send![dragging_info, draggingPasteboard] };
|
||||
let filenames = unsafe { NSPasteboard::propertyListForType(pasteboard, NSFilenamesPboardType) };
|
||||
if filenames == nil {
|
||||
return None;
|
||||
}
|
||||
for file in unsafe { filenames.iter() } {
|
||||
let path = unsafe {
|
||||
let f = NSString::UTF8String(file);
|
||||
@@ -1906,7 +1910,7 @@ fn external_paths_from_event(dragging_info: *mut Object) -> ExternalPaths {
|
||||
};
|
||||
paths.push(PathBuf::from(path))
|
||||
}
|
||||
ExternalPaths(paths)
|
||||
Some(ExternalPaths(paths))
|
||||
}
|
||||
|
||||
extern "C" fn conclude_drag_operation(this: &Object, _: Sel, _: id) {
|
||||
|
||||
@@ -2777,10 +2777,13 @@ impl BufferSnapshot {
|
||||
range.start + self.line_len(start.row as u32) as usize - start.column;
|
||||
}
|
||||
|
||||
buffer_ranges.push((range, node_is_name));
|
||||
if !range.is_empty() {
|
||||
buffer_ranges.push((range, node_is_name));
|
||||
}
|
||||
}
|
||||
|
||||
if buffer_ranges.is_empty() {
|
||||
matches.advance();
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
name = "Rust"
|
||||
grammar = "rust"
|
||||
path_suffixes = ["rs"]
|
||||
line_comments = [ "/// ", "//! ", "// "]
|
||||
line_comments = ["// ", "/// ", "//! "]
|
||||
autoclose_before = ";:.,=}])>"
|
||||
brackets = [
|
||||
{ start = "{", end = "}", close = true, newline = true },
|
||||
|
||||
@@ -896,6 +896,14 @@ impl LspCommand for GetReferences {
|
||||
type LspRequest = lsp::request::References;
|
||||
type ProtoRequest = proto::GetReferences;
|
||||
|
||||
fn check_capabilities(&self, capabilities: &ServerCapabilities) -> bool {
|
||||
match &capabilities.references_provider {
|
||||
Some(OneOf::Left(has_support)) => *has_support,
|
||||
Some(OneOf::Right(_)) => true,
|
||||
None => false,
|
||||
}
|
||||
}
|
||||
|
||||
fn to_lsp(
|
||||
&self,
|
||||
path: &Path,
|
||||
|
||||
@@ -4,7 +4,7 @@ use std::{
|
||||
sync::Arc,
|
||||
};
|
||||
|
||||
use anyhow::Context;
|
||||
use anyhow::{anyhow, Context, Result};
|
||||
use collections::HashSet;
|
||||
use fs::Fs;
|
||||
use futures::{
|
||||
@@ -46,51 +46,48 @@ pub(super) async fn format_with_prettier(
|
||||
project: &WeakModel<Project>,
|
||||
buffer: &Model<Buffer>,
|
||||
cx: &mut AsyncAppContext,
|
||||
) -> Option<FormatOperation> {
|
||||
if let Some((prettier_path, prettier_task)) = project
|
||||
) -> Option<Result<FormatOperation>> {
|
||||
let prettier_instance = project
|
||||
.update(cx, |project, cx| {
|
||||
project.prettier_instance_for_buffer(buffer, cx)
|
||||
})
|
||||
.ok()?
|
||||
.await
|
||||
{
|
||||
match prettier_task.await {
|
||||
Ok(prettier) => {
|
||||
let buffer_path = buffer
|
||||
.update(cx, |buffer, cx| {
|
||||
File::from_dyn(buffer.file()).map(|file| file.abs_path(cx))
|
||||
})
|
||||
.ok()?;
|
||||
match prettier.format(buffer, buffer_path, cx).await {
|
||||
Ok(new_diff) => return Some(FormatOperation::Prettier(new_diff)),
|
||||
Err(e) => {
|
||||
match prettier_path {
|
||||
Some(prettier_path) => log::error!(
|
||||
"Prettier instance from path {prettier_path:?} failed to format a buffer: {e:#}"
|
||||
),
|
||||
None => log::error!(
|
||||
"Default prettier instance failed to format a buffer: {e:#}"
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(e) => project
|
||||
.await;
|
||||
|
||||
let Some((prettier_path, prettier_task)) = prettier_instance else {
|
||||
return None;
|
||||
};
|
||||
|
||||
let prettier_description = match prettier_path.as_ref() {
|
||||
Some(path) => format!("prettier at {path:?}"),
|
||||
None => "default prettier instance".to_string(),
|
||||
};
|
||||
|
||||
match prettier_task.await {
|
||||
Ok(prettier) => {
|
||||
let buffer_path = buffer
|
||||
.update(cx, |buffer, cx| {
|
||||
File::from_dyn(buffer.file()).map(|file| file.abs_path(cx))
|
||||
})
|
||||
.ok()?;
|
||||
|
||||
let format_result = prettier
|
||||
.format(buffer, buffer_path, cx)
|
||||
.await
|
||||
.map(FormatOperation::Prettier)
|
||||
.with_context(|| format!("{} failed to format buffer", prettier_description));
|
||||
|
||||
Some(format_result)
|
||||
}
|
||||
Err(error) => {
|
||||
project
|
||||
.update(cx, |project, _| {
|
||||
let instance_to_update = match prettier_path {
|
||||
Some(prettier_path) => {
|
||||
log::error!(
|
||||
"Prettier instance from path {prettier_path:?} failed to spawn: {e:#}"
|
||||
);
|
||||
project.prettier_instances.get_mut(&prettier_path)
|
||||
}
|
||||
None => {
|
||||
log::error!("Default prettier instance failed to spawn: {e:#}");
|
||||
match &mut project.default_prettier.prettier {
|
||||
PrettierInstallation::NotInstalled { .. } => None,
|
||||
PrettierInstallation::Installed(instance) => Some(instance),
|
||||
}
|
||||
}
|
||||
Some(prettier_path) => project.prettier_instances.get_mut(&prettier_path),
|
||||
None => match &mut project.default_prettier.prettier {
|
||||
PrettierInstallation::NotInstalled { .. } => None,
|
||||
PrettierInstallation::Installed(instance) => Some(instance),
|
||||
},
|
||||
};
|
||||
|
||||
if let Some(instance) = instance_to_update {
|
||||
@@ -98,11 +95,14 @@ pub(super) async fn format_with_prettier(
|
||||
instance.prettier = None;
|
||||
}
|
||||
})
|
||||
.ok()?,
|
||||
.log_err();
|
||||
|
||||
Some(Err(anyhow!(
|
||||
"{} failed to spawn: {error:#}",
|
||||
prettier_description
|
||||
)))
|
||||
}
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
pub struct DefaultPrettier {
|
||||
|
||||
@@ -4628,10 +4628,11 @@ impl Project {
|
||||
}
|
||||
}
|
||||
(Formatter::Auto, FormatOnSave::On | FormatOnSave::Off) => {
|
||||
if let Some(new_operation) =
|
||||
prettier_support::format_with_prettier(&project, buffer, &mut cx).await
|
||||
{
|
||||
format_operation = Some(new_operation);
|
||||
let prettier =
|
||||
prettier_support::format_with_prettier(&project, buffer, &mut cx).await;
|
||||
|
||||
if let Some(operation) = prettier {
|
||||
format_operation = Some(operation?);
|
||||
} else if let Some((language_server, buffer_abs_path)) = server_and_buffer {
|
||||
format_operation = Some(FormatOperation::Lsp(
|
||||
Self::format_via_lsp(
|
||||
@@ -4648,10 +4649,11 @@ impl Project {
|
||||
}
|
||||
}
|
||||
(Formatter::Prettier, FormatOnSave::On | FormatOnSave::Off) => {
|
||||
if let Some(new_operation) =
|
||||
prettier_support::format_with_prettier(&project, buffer, &mut cx).await
|
||||
{
|
||||
format_operation = Some(new_operation);
|
||||
let prettier =
|
||||
prettier_support::format_with_prettier(&project, buffer, &mut cx).await;
|
||||
|
||||
if let Some(operation) = prettier {
|
||||
format_operation = Some(operation?);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -307,8 +307,8 @@ impl PickerDelegate for TasksModalDelegate {
|
||||
cx: &mut ViewContext<picker::Picker<Self>>,
|
||||
) -> Option<Self::ListItem> {
|
||||
let candidates = self.candidates.as_ref()?;
|
||||
let hit = &self.matches[ix];
|
||||
let (source_kind, _) = &candidates[hit.candidate_id];
|
||||
let hit = &self.matches.get(ix)?;
|
||||
let (source_kind, _) = &candidates.get(hit.candidate_id)?;
|
||||
let details = match source_kind {
|
||||
TaskSourceKind::UserInput => "user input".to_string(),
|
||||
TaskSourceKind::Buffer => "language extension".to_string(),
|
||||
|
||||
@@ -634,6 +634,25 @@ async fn test_folds_panic(cx: &mut gpui::TestAppContext) {
|
||||
cx.simulate_shared_keystrokes(["g", "g"]).await;
|
||||
cx.simulate_shared_keystrokes(["5", "d", "j"]).await;
|
||||
cx.assert_shared_state(indoc! { "ˇ"}).await;
|
||||
|
||||
cx.set_shared_state(indoc! { "
|
||||
fn boop() {
|
||||
ˇbarp()
|
||||
bazp()
|
||||
}
|
||||
"})
|
||||
.await;
|
||||
cx.simulate_shared_keystrokes(["shift-v", "j", "j", "z", "f"])
|
||||
.await;
|
||||
cx.simulate_shared_keystrokes(["escape"]).await;
|
||||
cx.simulate_shared_keystrokes(["shift-g", "shift-v"]).await;
|
||||
cx.assert_shared_state(indoc! { "
|
||||
fn boop() {
|
||||
barp()
|
||||
bazp()
|
||||
}
|
||||
ˇ"})
|
||||
.await;
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
@@ -1038,12 +1057,3 @@ async fn test_undo(cx: &mut gpui::TestAppContext) {
|
||||
3"})
|
||||
.await;
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
async fn test_command_palette(cx: &mut gpui::TestAppContext) {
|
||||
let mut cx = VimTestContext::new(cx, true).await;
|
||||
cx.simulate_keystroke(":");
|
||||
cx.simulate_input("go to definition");
|
||||
assert!(cx.debug_bounds("KEY_BINDING-f12").is_none());
|
||||
assert!(cx.debug_bounds("KEY_BINDING-g d").is_some());
|
||||
}
|
||||
|
||||
@@ -11,3 +11,13 @@
|
||||
{"Key":"d"}
|
||||
{"Key":"j"}
|
||||
{"Get":{"state":"ˇ","mode":"Normal"}}
|
||||
{"Put":{"state":"fn boop() {\n ˇbarp()\n bazp()\n}\n"}}
|
||||
{"Key":"shift-v"}
|
||||
{"Key":"j"}
|
||||
{"Key":"j"}
|
||||
{"Key":"z"}
|
||||
{"Key":"f"}
|
||||
{"Key":"escape"}
|
||||
{"Key":"shift-g"}
|
||||
{"Key":"shift-v"}
|
||||
{"Get":{"state":"fn boop() {\n barp()\n bazp()\n}\nˇ","mode":"VisualLine"}}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
description = "The fast, collaborative code editor."
|
||||
edition = "2021"
|
||||
name = "zed"
|
||||
version = "0.130.0"
|
||||
version = "0.130.6"
|
||||
publish = false
|
||||
license = "GPL-3.0-or-later"
|
||||
authors = ["Zed Team <hi@zed.dev>"]
|
||||
|
||||
@@ -1 +1 @@
|
||||
dev
|
||||
stable
|
||||
Reference in New Issue
Block a user