Detailed changes
@@ -463,6 +463,97 @@ impl MessageEditor {
})
}
+ fn confirm_mention_for_directory(
+ &mut self,
+ abs_path: PathBuf,
+ cx: &mut Context<Self>,
+ ) -> Task<Result<Mention>> {
+ fn collect_files_in_path(worktree: &Worktree, path: &Path) -> Vec<(Arc<Path>, PathBuf)> {
+ let mut files = Vec::new();
+
+ for entry in worktree.child_entries(path) {
+ if entry.is_dir() {
+ files.extend(collect_files_in_path(worktree, &entry.path));
+ } else if entry.is_file() {
+ files.push((entry.path.clone(), worktree.full_path(&entry.path)));
+ }
+ }
+
+ files
+ }
+
+ let Some(project_path) = self
+ .project
+ .read(cx)
+ .project_path_for_absolute_path(&abs_path, cx)
+ else {
+ return Task::ready(Err(anyhow!("project path not found")));
+ };
+ let Some(entry) = self.project.read(cx).entry_for_path(&project_path, cx) else {
+ return Task::ready(Err(anyhow!("project entry not found")));
+ };
+ let directory_path = entry.path.clone();
+ let worktree_id = project_path.worktree_id;
+ let Some(worktree) = self.project.read(cx).worktree_for_id(worktree_id, cx) else {
+ return Task::ready(Err(anyhow!("worktree not found")));
+ };
+ let project = self.project.clone();
+ cx.spawn(async move |_, cx| {
+ let file_paths = worktree.read_with(cx, |worktree, _cx| {
+ collect_files_in_path(worktree, &directory_path)
+ })?;
+ let descendants_future = cx.update(|cx| {
+ join_all(file_paths.into_iter().map(|(worktree_path, full_path)| {
+ let rel_path = worktree_path
+ .strip_prefix(&directory_path)
+ .log_err()
+ .map_or_else(|| worktree_path.clone(), |rel_path| rel_path.into());
+
+ let open_task = project.update(cx, |project, cx| {
+ project.buffer_store().update(cx, |buffer_store, cx| {
+ let project_path = ProjectPath {
+ worktree_id,
+ path: worktree_path,
+ };
+ buffer_store.open_buffer(project_path, cx)
+ })
+ });
+
+ cx.spawn(async move |cx| {
+ let buffer = open_task.await.log_err()?;
+ let buffer_content = outline::get_buffer_content_or_outline(
+ buffer.clone(),
+ Some(&full_path),
+ &cx,
+ )
+ .await
+ .ok()?;
+
+ Some((rel_path, full_path, buffer_content.text, buffer))
+ })
+ }))
+ })?;
+
+ let contents = cx
+ .background_spawn(async move {
+ let (contents, tracked_buffers) = descendants_future
+ .await
+ .into_iter()
+ .flatten()
+ .map(|(rel_path, full_path, rope, buffer)| {
+ ((rel_path, full_path, rope), buffer)
+ })
+ .unzip();
+ Mention::Text {
+ content: render_directory_contents(contents),
+ tracked_buffers,
+ }
+ })
+ .await;
+ anyhow::Ok(contents)
+ })
+ }
+
fn confirm_mention_for_fetch(
&mut self,
url: url::Url,
@@ -287,7 +287,7 @@ impl DirectoryContextHandle {
let open_task = project.update(cx, |project, cx| {
project.buffer_store().update(cx, |buffer_store, cx| {
let project_path = ProjectPath { worktree_id, path };
- buffer_store.open_buffer(project_path, cx)
+ buffer_store.open_buffer(project_path, None, cx)
})
});
@@ -82,7 +82,7 @@ impl EncodingWrapper {
} else {
// If there were decoding errors, return an error.
Err(anyhow::anyhow!(
- "The file contains invalid bytes for the specified encoding: {}. This usually menas that the file is not a regular text file, or is encoded in a different encoding. Continuing to open it may result in data loss if saved.",
+ "The file contains invalid bytes for the specified encoding: {}.\nThis usually means that the file is not a regular text file, or is encoded in a different encoding.\nContinuing to open it may result in data loss if saved.",
self.0.name()
))
}
@@ -9,6 +9,7 @@ use client::Client;
use collections::{HashMap, HashSet, hash_map};
use fs::Fs;
use futures::{Future, FutureExt as _, StreamExt, channel::oneshot, future::Shared};
+use fs::{Fs, encodings::EncodingWrapper};
use gpui::{
App, AppContext as _, AsyncApp, Context, Entity, EventEmitter, Subscription, Task, WeakEntity,
};
@@ -631,11 +632,13 @@ impl LocalBufferStore {
&self,
path: Arc<RelPath>,
worktree: Entity<Worktree>,
+ encoding: Option<EncodingWrapper>,
cx: &mut Context<BufferStore>,
) -> Task<Result<Entity<Buffer>>> {
let load_buffer = worktree.update(cx, |worktree, cx| {
- let load_file = worktree.load_file(path.as_ref(), None, cx);
+ let load_file = worktree.load_file(path.as_ref(), encoding, cx);
let reservation = cx.reserve_entity();
+
let buffer_id = BufferId::from(reservation.entity_id().as_non_zero_u64());
let path = path.clone();
cx.spawn(async move |_, cx| {
@@ -655,11 +658,7 @@ impl LocalBufferStore {
cx.spawn(async move |this, cx| {
let buffer = match load_buffer.await {
- Ok(buffer) => {
- // Reload the buffer to trigger UTF-16 detection
- buffer.update(cx, |buffer, cx| buffer.reload(cx))?.await?;
- Ok(buffer)
- }
+ Ok(buffer) => Ok(buffer),
Err(error) if is_not_found_error(&error) => cx.new(|cx| {
let buffer_id = BufferId::from(cx.entity_id().as_non_zero_u64());
let text_buffer = text::Buffer::new(
@@ -834,6 +833,7 @@ impl BufferStore {
pub fn open_buffer(
&mut self,
project_path: ProjectPath,
+ encoding: Option<EncodingWrapper>,
cx: &mut Context<Self>,
) -> Task<Result<Entity<Buffer>>> {
if let Some(buffer) = self.get_by_path(&project_path) {
@@ -857,7 +857,7 @@ impl BufferStore {
return Task::ready(Err(anyhow!("no such worktree")));
};
let load_buffer = match &self.state {
- BufferStoreState::Local(this) => this.open_buffer(path, worktree, cx),
+ BufferStoreState::Local(this) => this.open_buffer(path, worktree, encoding, cx),
BufferStoreState::Remote(this) => this.open_buffer(path, worktree, cx),
};
@@ -796,7 +796,7 @@ impl BreakpointStore {
worktree_id: worktree.read(cx).id(),
path: relative_path,
};
- this.open_buffer(path, cx)
+ this.open_buffer(path, None, cx)
})?
.await;
let Ok(buffer) = buffer else {
@@ -8336,7 +8336,7 @@ impl LspStore {
lsp_store
.update(cx, |lsp_store, cx| {
lsp_store.buffer_store().update(cx, |buffer_store, cx| {
- buffer_store.open_buffer(project_path, cx)
+ buffer_store.open_buffer(project_path, None, cx)
})
})?
.await
@@ -91,7 +91,7 @@ pub fn cancel_flycheck(
let buffer = buffer_path.map(|buffer_path| {
project.update(cx, |project, cx| {
project.buffer_store().update(cx, |buffer_store, cx| {
- buffer_store.open_buffer(buffer_path, cx)
+ buffer_store.open_buffer(buffer_path, None, cx)
})
})
});
@@ -140,7 +140,7 @@ pub fn run_flycheck(
let buffer = buffer_path.map(|buffer_path| {
project.update(cx, |project, cx| {
project.buffer_store().update(cx, |buffer_store, cx| {
- buffer_store.open_buffer(buffer_path, cx)
+ buffer_store.open_buffer(buffer_path, None, cx)
})
})
});
@@ -198,7 +198,7 @@ pub fn clear_flycheck(
let buffer = buffer_path.map(|buffer_path| {
project.update(cx, |project, cx| {
project.buffer_store().update(cx, |buffer_store, cx| {
- buffer_store.open_buffer(buffer_path, cx)
+ buffer_store.open_buffer(buffer_path, None, cx)
})
})
});
@@ -28,6 +28,7 @@ use buffer_diff::BufferDiff;
use context_server_store::ContextServerStore;
use encoding_rs::Encoding;
pub use environment::ProjectEnvironmentEvent;
+use fs::encodings::EncodingWrapper;
use git::repository::get_git_committer;
use git_store::{Repository, RepositoryId};
pub mod search_history;
@@ -2717,7 +2718,11 @@ impl Project {
}
self.buffer_store.update(cx, |buffer_store, cx| {
- buffer_store.open_buffer(path.into(), cx)
+ buffer_store.open_buffer(
+ path.into(),
+ Some(EncodingWrapper::new(self.encoding.lock().as_ref().unwrap())),
+ cx,
+ )
})
}
@@ -506,7 +506,14 @@ impl HeadlessProject {
let (buffer_store, buffer) = this.update(&mut cx, |this, cx| {
let buffer_store = this.buffer_store.clone();
let buffer = this.buffer_store.update(cx, |buffer_store, cx| {
- buffer_store.open_buffer(ProjectPath { worktree_id, path }, cx)
+ buffer_store.open_buffer(
+ ProjectPath {
+ worktree_id,
+ path: Arc::<Path>::from_proto(message.payload.path),
+ },
+ None,
+ cx,
+ )
});
anyhow::Ok((buffer_store, buffer))
})??;
@@ -597,6 +604,7 @@ impl HeadlessProject {
worktree_id: worktree.read(cx).id(),
path: path,
},
+ None,
cx,
)
});
@@ -3416,6 +3416,7 @@ impl Workspace {
window: &mut Window,
cx: &mut Context<Self>,
) -> Task<anyhow::Result<Box<dyn ItemHandle>>> {
+ println!("{:?}", *self.encoding.lock().unwrap());
cx.spawn_in(window, async move |workspace, cx| {
let open_paths_task_result = workspace
.update_in(cx, |workspace, window, cx| {
@@ -710,7 +710,7 @@ impl Worktree {
pub fn load_file(
&self,
path: &Path,
- encoding: Option<Arc<std::sync::Mutex<&'static Encoding>>>,
+ encoding: Option<EncodingWrapper>,
cx: &Context<Worktree>,
) -> Task<Result<LoadedFile>> {
match self {
@@ -1324,7 +1324,7 @@ impl LocalWorktree {
fn load_file(
&self,
path: &Path,
- encoding: Option<Arc<std::sync::Mutex<&'static Encoding>>>,
+ encoding: Option<EncodingWrapper>,
cx: &Context<Worktree>,
) -> Task<Result<LoadedFile>> {
let path = Arc::from(path);
@@ -1353,7 +1353,7 @@ impl LocalWorktree {
.load_with_encoding(
&abs_path,
if let Some(encoding) = encoding {
- EncodingWrapper::new(*encoding.lock().unwrap())
+ encoding
} else {
EncodingWrapper::new(encoding_rs::UTF_8)
},