- Add a field `encoding` in both `Workspace` and `Project`

R Aadarsh created

- Pass encoding to `ProjectRegistry::open_path` and set the `encoding`
field in `Project`

Change summary

crates/fs/src/encodings.rs        |  2 +-
crates/project/src/project.rs     |  5 +++++
crates/workspace/src/workspace.rs | 28 +++++++++++++++++++++-------
3 files changed, 27 insertions(+), 8 deletions(-)

Detailed changes

crates/fs/src/encodings.rs 🔗

@@ -9,7 +9,7 @@ use encoding_rs::Encoding;
 
 /// A wrapper around `encoding_rs::Encoding` to implement `Send` and `Sync`.
 /// Since the reference is static, it is safe to send it across threads.
-pub struct EncodingWrapper(&'static Encoding);
+pub struct EncodingWrapper(pub &'static Encoding);
 
 impl Debug for EncodingWrapper {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {

crates/project/src/project.rs 🔗

@@ -26,6 +26,7 @@ mod project_tests;
 mod environment;
 use buffer_diff::BufferDiff;
 use context_server_store::ContextServerStore;
+use encoding_rs::Encoding;
 pub use environment::ProjectEnvironmentEvent;
 use git::repository::get_git_committer;
 use git_store::{Repository, RepositoryId};
@@ -215,6 +216,7 @@ pub struct Project {
     settings_observer: Entity<SettingsObserver>,
     toolchain_store: Option<Entity<ToolchainStore>>,
     agent_location: Option<AgentLocation>,
+    pub encoding: Arc<std::sync::Mutex<&'static Encoding>>,
 }
 
 #[derive(Clone, Debug, PartialEq, Eq)]
@@ -1225,6 +1227,7 @@ impl Project {
                 toolchain_store: Some(toolchain_store),
 
                 agent_location: None,
+                encoding: Arc::new(std::sync::Mutex::new(encoding_rs::UTF_8)),
             }
         })
     }
@@ -1410,6 +1413,7 @@ impl Project {
 
                 toolchain_store: Some(toolchain_store),
                 agent_location: None,
+                encoding: Arc::new(std::sync::Mutex::new(encoding_rs::UTF_8)),
             };
 
             // remote server -> local machine handlers
@@ -1663,6 +1667,7 @@ impl Project {
                 remotely_created_models: Arc::new(Mutex::new(RemotelyCreatedModels::default())),
                 toolchain_store: None,
                 agent_location: None,
+                encoding: Arc::new(std::sync::Mutex::new(encoding_rs::UTF_8)),
             };
             project.set_role(role, cx);
             for worktree in worktrees {

crates/workspace/src/workspace.rs 🔗

@@ -624,6 +624,7 @@ type BuildProjectItemForPathFn =
     fn(
         &Entity<Project>,
         &ProjectPath,
+        Option<EncodingWrapper>,
         &mut Window,
         &mut App,
     ) -> Option<Task<Result<(Option<ProjectEntryId>, WorkspaceItemBuilder)>>>;
@@ -645,8 +646,12 @@ impl ProjectItemRegistry {
             },
         );
         self.build_project_item_for_path_fns
-            .push(|project, project_path, window, cx| {
+            .push(|project, project_path, encoding, window, cx| {
                 let project_path = project_path.clone();
+                let EncodingWrapper(encoding) = encoding.unwrap_or_default();
+
+                project.update(cx, |project, _| {*project.encoding.lock().unwrap() = encoding});
+
                 let is_file = project
                     .read(cx)
                     .entry_for_path(&project_path, cx)
@@ -715,14 +720,17 @@ impl ProjectItemRegistry {
         &self,
         project: &Entity<Project>,
         path: &ProjectPath,
+        encoding: Option<EncodingWrapper>,
         window: &mut Window,
         cx: &mut App,
     ) -> Task<Result<(Option<ProjectEntryId>, WorkspaceItemBuilder)>> {
-        let Some(open_project_item) = self
-            .build_project_item_for_path_fns
-            .iter()
-            .rev()
-            .find_map(|open_project_item| open_project_item(project, path, window, cx))
+        let Some(open_project_item) =
+            self.build_project_item_for_path_fns
+                .iter()
+                .rev()
+                .find_map(|open_project_item| {
+                    open_project_item(project, path, encoding.clone(), window, cx)
+                })
         else {
             return Task::ready(Err(anyhow!("cannot open file {:?}", path.path)));
         };
@@ -3566,7 +3574,13 @@ impl Workspace {
         cx: &mut App,
     ) -> Task<Result<(Option<ProjectEntryId>, WorkspaceItemBuilder)>> {
         let registry = cx.default_global::<ProjectItemRegistry>().clone();
-        registry.open_path(self.project(), &path, window, cx)
+        registry.open_path(
+            self.project(),
+            &path,
+            Some(EncodingWrapper::new(*self.encoding.lock().unwrap())),
+            window,
+            cx,
+        )
     }
 
     pub fn find_project_item<T>(