diff --git a/Cargo.lock b/Cargo.lock index e6f1aabf84..8326916c01 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5194,6 +5194,70 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34aa73646ffb006b8f5147f3dc182bd4bcb190227ce861fc4a4844bf8e3cb2c0" +[[package]] +name = "encoding" +version = "0.2.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b0d943856b990d12d3b55b359144ff341533e516d94098b1d3fc1ac666d36ec" +dependencies = [ + "encoding-index-japanese", + "encoding-index-korean", + "encoding-index-simpchinese", + "encoding-index-singlebyte", + "encoding-index-tradchinese", +] + +[[package]] +name = "encoding-index-japanese" +version = "1.20141219.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04e8b2ff42e9a05335dbf8b5c6f7567e5591d0d916ccef4e0b1710d32a0d0c91" +dependencies = [ + "encoding_index_tests", +] + +[[package]] +name = "encoding-index-korean" +version = "1.20141219.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4dc33fb8e6bcba213fe2f14275f0963fd16f0a02c878e3095ecfdf5bee529d81" +dependencies = [ + "encoding_index_tests", +] + +[[package]] +name = "encoding-index-simpchinese" +version = "1.20141219.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d87a7194909b9118fc707194baa434a4e3b0fb6a5a757c73c3adb07aa25031f7" +dependencies = [ + "encoding_index_tests", +] + +[[package]] +name = "encoding-index-singlebyte" +version = "1.20141219.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3351d5acffb224af9ca265f435b859c7c01537c0849754d3db3fdf2bfe2ae84a" +dependencies = [ + "encoding_index_tests", +] + +[[package]] +name = "encoding-index-tradchinese" +version = "1.20141219.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd0e20d5688ce3cab59eb3ef3a2083a5c77bf496cb798dc6fcdb75f323890c18" +dependencies = [ + "encoding_index_tests", +] + +[[package]] +name = "encoding_index_tests" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a246d82be1c9d791c5dfde9a2bd045fc3cbba3fa2b11ad558f27d01712f00569" + [[package]] name = "encoding_rs" version = "0.8.35" @@ -5207,9 +5271,9 @@ dependencies = [ name = "encodings" version = "0.1.0" dependencies = [ + "editor", "fuzzy", "gpui", - "language", "picker", "ui", "util", @@ -6055,6 +6119,7 @@ dependencies = [ "async-trait", "cocoa 0.26.0", "collections", + "encoding", "fsevent", "futures 0.3.31", "git", @@ -9035,6 +9100,7 @@ dependencies = [ "ctor", "diffy", "ec4rs", + "encoding", "fs", "futures 0.3.31", "fuzzy", diff --git a/Cargo.toml b/Cargo.toml index e4d8638bc2..7ba19fdcd8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -238,7 +238,6 @@ activity_indicator = { path = "crates/activity_indicator" } agent_ui = { path = "crates/agent_ui" } agent_settings = { path = "crates/agent_settings" } agent_servers = { path = "crates/agent_servers" } -ai = { path = "crates/ai" } ai_onboarding = { path = "crates/ai_onboarding" } anthropic = { path = "crates/anthropic" } askpass = { path = "crates/askpass" } @@ -250,7 +249,6 @@ assistant_tool = { path = "crates/assistant_tool" } assistant_tools = { path = "crates/assistant_tools" } audio = { path = "crates/audio" } auto_update = { path = "crates/auto_update" } -auto_update_helper = { path = "crates/auto_update_helper" } auto_update_ui = { path = "crates/auto_update_ui" } aws_http_client = { path = "crates/aws_http_client" } bedrock = { path = "crates/bedrock" } @@ -264,7 +262,6 @@ clock = { path = "crates/clock" } cloud_api_client = { path = "crates/cloud_api_client" } cloud_api_types = { path = "crates/cloud_api_types" } cloud_llm_client = { path = "crates/cloud_llm_client" } -collab = { path = "crates/collab" } collab_ui = { path = "crates/collab_ui" } collections = { path = "crates/collections" } command_palette = { path = "crates/command_palette" } @@ -348,8 +345,6 @@ outline_panel = { path = "crates/outline_panel" } panel = { path = "crates/panel" } paths = { path = "crates/paths" } picker = { path = "crates/picker" } -plugin = { path = "crates/plugin" } -plugin_macros = { path = "crates/plugin_macros" } prettier = { path = "crates/prettier" } settings_profile_selector = { path = "crates/settings_profile_selector" } project = { path = "crates/project" } @@ -370,7 +365,6 @@ rope = { path = "crates/rope" } rpc = { path = "crates/rpc" } rules_library = { path = "crates/rules_library" } search = { path = "crates/search" } -semantic_index = { path = "crates/semantic_index" } semantic_version = { path = "crates/semantic_version" } session = { path = "crates/session" } settings = { path = "crates/settings" } @@ -381,7 +375,6 @@ snippets_ui = { path = "crates/snippets_ui" } sqlez = { path = "crates/sqlez" } sqlez_macros = { path = "crates/sqlez_macros" } story = { path = "crates/story" } -storybook = { path = "crates/storybook" } streaming_diff = { path = "crates/streaming_diff" } sum_tree = { path = "crates/sum_tree" } supermaven = { path = "crates/supermaven" } @@ -397,7 +390,6 @@ terminal_view = { path = "crates/terminal_view" } text = { path = "crates/text" } theme = { path = "crates/theme" } theme_extension = { path = "crates/theme_extension" } -theme_importer = { path = "crates/theme_importer" } theme_selector = { path = "crates/theme_selector" } time_format = { path = "crates/time_format" } title_bar = { path = "crates/title_bar" } @@ -469,7 +461,6 @@ ciborium = "0.2" circular-buffer = "1.0" clap = { version = "4.4", features = ["derive"] } cocoa = "0.26" -cocoa-foundation = "0.2.0" convert_case = "0.8.0" core-foundation = "0.10.0" core-foundation-sys = "0.8.6" @@ -545,7 +536,6 @@ pet = { git = "https://github.com/microsoft/python-environment-tools.git", rev = pet-conda = { git = "https://github.com/microsoft/python-environment-tools.git", rev = "845945b830297a50de0e24020b980a65e4820559" } pet-core = { git = "https://github.com/microsoft/python-environment-tools.git", rev = "845945b830297a50de0e24020b980a65e4820559" } pet-fs = { git = "https://github.com/microsoft/python-environment-tools.git", rev = "845945b830297a50de0e24020b980a65e4820559" } -pet-pixi = { git = "https://github.com/microsoft/python-environment-tools.git", rev = "845945b830297a50de0e24020b980a65e4820559" } pet-poetry = { git = "https://github.com/microsoft/python-environment-tools.git", rev = "845945b830297a50de0e24020b980a65e4820559" } pet-reporter = { git = "https://github.com/microsoft/python-environment-tools.git", rev = "845945b830297a50de0e24020b980a65e4820559" } portable-pty = "0.9.0" @@ -668,7 +658,6 @@ wasmtime = { version = "29", default-features = false, features = [ wasmtime-wasi = "29" which = "6.0.0" windows-core = "0.61" -wit-component = "0.221" workspace-hack = "0.1.0" yawc = "0.2.5" zstd = "0.11" @@ -742,11 +731,7 @@ codegen-units = 16 [profile.dev.package] taffy = { opt-level = 3 } cranelift-codegen = { opt-level = 3 } -cranelift-codegen-meta = { opt-level = 3 } -cranelift-codegen-shared = { opt-level = 3 } resvg = { opt-level = 3 } -rustybuzz = { opt-level = 3 } -ttf-parser = { opt-level = 3 } wasmtime-cranelift = { opt-level = 3 } wasmtime = { opt-level = 3 } # Build single-source-file crates with cg=1 as it helps make `cargo build` of a whole workspace a bit faster @@ -756,7 +741,6 @@ breadcrumbs = { codegen-units = 1 } collections = { codegen-units = 1 } command_palette = { codegen-units = 1 } command_palette_hooks = { codegen-units = 1 } -extension_cli = { codegen-units = 1 } feature_flags = { codegen-units = 1 } file_icons = { codegen-units = 1 } fsevent = { codegen-units = 1 } diff --git a/crates/encodings/Cargo.toml b/crates/encodings/Cargo.toml index d49dff06ec..2d75395810 100644 --- a/crates/encodings/Cargo.toml +++ b/crates/encodings/Cargo.toml @@ -9,9 +9,9 @@ ui.workspace = true workspace.workspace = true gpui.workspace = true picker.workspace = true -language.workspace = true util.workspace = true fuzzy.workspace = true +editor.workspace = true [lints] workspace = true diff --git a/crates/encodings/src/lib.rs b/crates/encodings/src/lib.rs index 23b7429526..bfecfceea3 100644 --- a/crates/encodings/src/lib.rs +++ b/crates/encodings/src/lib.rs @@ -1,194 +1,42 @@ -use std::sync::Weak; -use std::sync::atomic::AtomicBool; - -use fuzzy::{StringMatch, StringMatchCandidate}; -use gpui::{AppContext, ClickEvent, DismissEvent, Entity, EventEmitter, Focusable, WeakEntity}; -use language::Buffer; -use picker::{Picker, PickerDelegate}; -use ui::{ - Button, ButtonCommon, Context, Label, LabelSize, ListItem, Render, Styled, Tooltip, Window, - div, rems, v_flex, -}; +use editor::Editor; +use gpui::{ClickEvent, Entity, WeakEntity}; +use ui::{Button, ButtonCommon, Context, LabelSize, Render, Tooltip, Window, div}; use ui::{Clickable, ParentElement}; -use util::ResultExt; -use workspace::{ItemHandle, ModalView, StatusItemView, Workspace}; +use workspace::{ItemHandle, StatusItemView, Workspace}; + +use crate::selectors::save_or_reopen::{EncodingSaveOrReopenSelector, get_current_encoding}; pub enum Encoding { - Utf8(WeakEntity), + Utf8, + Iso8859_1, } impl Encoding { pub fn as_str(&self) -> &str { match &self { - Encoding::Utf8(_) => "UTF-8", + Encoding::Utf8 => "UTF-8", + Encoding::Iso8859_1 => "ISO 8859-1", } } } -impl EncodingSaveOrReopenSelector { - pub fn new(window: &mut Window, cx: &mut Context) -> Self { - let delegate = EncodingSaveOrReopenDelegate::new(cx.entity().downgrade()); - - let picker = cx.new(|cx| Picker::uniform_list(delegate, window, cx)); - - Self { picker } - } - - pub fn toggle(workspace: &mut Workspace, window: &mut Window, cx: &mut Context) { - workspace.toggle_modal(window, cx, |window, cx| { - EncodingSaveOrReopenSelector::new(window, cx) - }); - } +pub struct EncodingIndicator { + pub encoding: Encoding, + pub workspace: WeakEntity, } -pub struct EncodingSaveOrReopenSelector { - picker: Entity>, -} +pub mod selectors; -impl Focusable for EncodingSaveOrReopenSelector { - fn focus_handle(&self, cx: &ui::App) -> gpui::FocusHandle { - self.picker.focus_handle(cx) - } -} - -impl Render for EncodingSaveOrReopenSelector { - fn render(&mut self, _window: &mut Window, _cx: &mut Context) -> impl ui::IntoElement { - v_flex().w(rems(34.0)).child(self.picker.clone()) - } -} - -impl ModalView for EncodingSaveOrReopenSelector {} - -impl EventEmitter for EncodingSaveOrReopenSelector {} - -pub struct EncodingSaveOrReopenDelegate { - encoding_selector: WeakEntity, - current_selection: usize, - matches: Vec, - pub actions: Vec, -} - -impl EncodingSaveOrReopenDelegate { - pub fn new(selector: WeakEntity) -> Self { - Self { - encoding_selector: selector, - current_selection: 0, - matches: Vec::new(), - actions: vec![ - StringMatchCandidate::new(0, "Save with encoding"), - StringMatchCandidate::new(1, "Reopen with encoding"), - ], - } - } - - pub fn get_actions(&self) -> (&str, &str) { - (&self.actions[0].string, &self.actions[1].string) - } -} - -impl PickerDelegate for EncodingSaveOrReopenDelegate { - type ListItem = ListItem; - - fn match_count(&self) -> usize { - self.matches.len() - } - - fn selected_index(&self) -> usize { - self.current_selection - } - - fn set_selected_index( - &mut self, - ix: usize, - _window: &mut Window, - _cx: &mut Context>, - ) { - self.current_selection = ix; - } - - fn placeholder_text(&self, _window: &mut Window, _cx: &mut ui::App) -> std::sync::Arc { - "Select an action...".into() - } - - fn update_matches( - &mut self, - query: String, - window: &mut Window, - cx: &mut Context>, - ) -> gpui::Task<()> { - let executor = cx.background_executor().clone(); - let actions = self.actions.clone(); - - cx.spawn_in(window, async move |this, cx| { - let matches = if query.is_empty() { - actions - .into_iter() - .enumerate() - .map(|(index, value)| StringMatch { - candidate_id: index, - score: 0.0, - positions: vec![], - string: value.string, - }) - .collect::>() - } else { - fuzzy::match_strings( - &actions, - &query, - false, - false, - 2, - &AtomicBool::new(false), - executor, - ) - .await - }; - - this.update(cx, |picker, cx| { - let delegate = &mut picker.delegate; - delegate.current_selection = matches.len().saturating_sub(1); - delegate.matches = matches; - cx.notify(); - }) - .log_err(); - }) - } - - fn confirm(&mut self, secondary: bool, window: &mut Window, cx: &mut Context>) {} - - fn dismissed(&mut self, _window: &mut Window, cx: &mut Context>) { - self.encoding_selector - .update(cx, |_, cx| cx.emit(DismissEvent)) - .log_err(); - } - - fn render_match( - &self, - ix: usize, - selected: bool, - window: &mut Window, - cx: &mut Context>, - ) -> Option { - Some(ListItem::new(ix).child(Label::new(&self.matches[ix].string))) - } -} - -fn get_current_encoding() -> &'static str { - "UTF-8" -} - -impl Render for Encoding { +impl Render for EncodingIndicator { fn render(&mut self, _window: &mut Window, cx: &mut Context) -> impl ui::IntoElement { - let encoding_indicator = div(); + let status_element = div(); - encoding_indicator.child( + status_element.child( Button::new("encoding", get_current_encoding()) .label_size(LabelSize::Small) .tooltip(Tooltip::text("Select Encoding")) - .on_click(cx.listener(|encoding, _: &ClickEvent, window, cx| { - if let Some(workspace) = match encoding { - Encoding::Utf8(workspace) => workspace.upgrade(), - } { + .on_click(cx.listener(|indicator, _: &ClickEvent, window, cx| { + if let Some(workspace) = indicator.workspace.upgrade() { workspace.update(cx, |workspace, cx| { EncodingSaveOrReopenSelector::toggle(workspace, window, cx) }) @@ -199,7 +47,11 @@ impl Render for Encoding { } } -impl StatusItemView for Encoding { +impl EncodingIndicator { + pub fn get_current_encoding(&self, cx: &mut Context, editor: WeakEntity) {} +} + +impl StatusItemView for EncodingIndicator { fn set_active_pane_item( &mut self, _active_pane_item: Option<&dyn ItemHandle>, diff --git a/crates/encodings/src/selectors.rs b/crates/encodings/src/selectors.rs new file mode 100644 index 0000000000..368f85d584 --- /dev/null +++ b/crates/encodings/src/selectors.rs @@ -0,0 +1,331 @@ +pub mod save_or_reopen { + use gpui::Styled; + use gpui::{AppContext, ParentElement}; + use picker::Picker; + use picker::PickerDelegate; + use std::sync::atomic::AtomicBool; + use util::ResultExt; + + use fuzzy::{StringMatch, StringMatchCandidate}; + use gpui::{DismissEvent, Entity, EventEmitter, Focusable, WeakEntity}; + + use ui::{Context, Label, ListItem, Render, Window, rems, v_flex}; + use workspace::{ModalView, Workspace}; + + pub struct EncodingSaveOrReopenSelector { + picker: Entity>, + } + + impl EncodingSaveOrReopenSelector { + pub fn new(window: &mut Window, cx: &mut Context) -> Self { + let delegate = EncodingSaveOrReopenDelegate::new(cx.entity().downgrade()); + + let picker = cx.new(|cx| Picker::uniform_list(delegate, window, cx)); + + Self { picker } + } + + pub fn toggle(workspace: &mut Workspace, window: &mut Window, cx: &mut Context) { + workspace.toggle_modal(window, cx, |window, cx| { + EncodingSaveOrReopenSelector::new(window, cx) + }); + } + } + + impl Focusable for EncodingSaveOrReopenSelector { + fn focus_handle(&self, cx: &ui::App) -> gpui::FocusHandle { + self.picker.focus_handle(cx) + } + } + + impl Render for EncodingSaveOrReopenSelector { + fn render( + &mut self, + _window: &mut Window, + _cx: &mut Context, + ) -> impl ui::IntoElement { + v_flex().w(rems(34.0)).child(self.picker.clone()) + } + } + + impl ModalView for EncodingSaveOrReopenSelector {} + + impl EventEmitter for EncodingSaveOrReopenSelector {} + + pub struct EncodingSaveOrReopenDelegate { + encoding_selector: WeakEntity, + current_selection: usize, + matches: Vec, + pub actions: Vec, + } + + impl EncodingSaveOrReopenDelegate { + pub fn new(selector: WeakEntity) -> Self { + Self { + encoding_selector: selector, + current_selection: 0, + matches: Vec::new(), + actions: vec![ + StringMatchCandidate::new(0, "Save with encoding"), + StringMatchCandidate::new(1, "Reopen with encoding"), + ], + } + } + + pub fn get_actions(&self) -> (&str, &str) { + (&self.actions[0].string, &self.actions[1].string) + } + } + + impl PickerDelegate for EncodingSaveOrReopenDelegate { + type ListItem = ListItem; + + fn match_count(&self) -> usize { + self.matches.len() + } + + fn selected_index(&self) -> usize { + self.current_selection + } + + fn set_selected_index( + &mut self, + ix: usize, + _window: &mut Window, + _cx: &mut Context>, + ) { + self.current_selection = ix; + } + + fn placeholder_text(&self, _window: &mut Window, _cx: &mut ui::App) -> std::sync::Arc { + "Select an action...".into() + } + + fn update_matches( + &mut self, + query: String, + window: &mut Window, + cx: &mut Context>, + ) -> gpui::Task<()> { + let executor = cx.background_executor().clone(); + let actions = self.actions.clone(); + + cx.spawn_in(window, async move |this, cx| { + let matches = if query.is_empty() { + actions + .into_iter() + .enumerate() + .map(|(index, value)| StringMatch { + candidate_id: index, + score: 0.0, + positions: vec![], + string: value.string, + }) + .collect::>() + } else { + fuzzy::match_strings( + &actions, + &query, + false, + false, + 2, + &AtomicBool::new(false), + executor, + ) + .await + }; + + this.update(cx, |picker, cx| { + let delegate = &mut picker.delegate; + delegate.current_selection = matches.len().saturating_sub(1); + delegate.matches = matches; + cx.notify(); + }) + .log_err(); + }) + } + + fn confirm( + &mut self, + secondary: bool, + window: &mut Window, + cx: &mut Context>, + ) { + } + + fn dismissed(&mut self, _window: &mut Window, cx: &mut Context>) { + self.encoding_selector + .update(cx, |_, cx| cx.emit(DismissEvent)) + .log_err(); + } + + fn render_match( + &self, + ix: usize, + selected: bool, + window: &mut Window, + cx: &mut Context>, + ) -> Option { + Some(ListItem::new(ix).child(Label::new(&self.matches[ix].string))) + } + } + + pub fn get_current_encoding() -> &'static str { + "UTF-8" + } +} + +pub mod encoding { + use std::sync::atomic::AtomicBool; + + use fuzzy::{StringMatch, StringMatchCandidate}; + use gpui::{ + AppContext, BackgroundExecutor, DismissEvent, Entity, EventEmitter, Focusable, WeakEntity, + }; + use picker::{Picker, PickerDelegate}; + use ui::{Context, Label, ListItem, ParentElement, Render, Styled, Window, rems, v_flex}; + use util::{ResultExt, TryFutureExt}; + use workspace::{ModalView, Workspace}; + + pub struct EncodingSelector { + pub picker: Entity>, + } + + pub struct EncodingSelectorDelegate { + current_selection: usize, + encodings: Vec, + matches: Vec, + selector: WeakEntity, + } + + impl EncodingSelectorDelegate { + pub fn new(selector: WeakEntity) -> EncodingSelectorDelegate { + EncodingSelectorDelegate { + current_selection: 0, + encodings: vec![ + StringMatchCandidate::new(0, "UTF-8"), + StringMatchCandidate::new(1, "ISO 8859-1"), + ], + matches: Vec::new(), + selector, + } + } + } + + impl PickerDelegate for EncodingSelectorDelegate { + type ListItem = ListItem; + + fn match_count(&self) -> usize { + self.matches.len() + } + + fn selected_index(&self) -> usize { + self.current_selection + } + + fn set_selected_index( + &mut self, + ix: usize, + window: &mut Window, + cx: &mut Context>, + ) { + self.current_selection = ix; + } + + fn placeholder_text(&self, _window: &mut Window, _cx: &mut ui::App) -> std::sync::Arc { + "Select an encoding...".into() + } + + fn update_matches( + &mut self, + query: String, + window: &mut Window, + cx: &mut Context>, + ) -> gpui::Task<()> { + let executor = cx.background_executor().clone(); + let encodings = self.encodings.clone(); + let current_selection = self.current_selection; + + cx.spawn_in(window, async move |picker, cx| { + let matches: Vec; + + if query.is_empty() { + matches = encodings + .into_iter() + .enumerate() + .map(|(index, value)| StringMatch { + candidate_id: index, + score: 0.0, + positions: Vec::new(), + string: value.string, + }) + .collect(); + } else { + matches = fuzzy::match_strings( + &encodings, + &query, + false, + false, + 0, + &AtomicBool::new(false), + executor, + ) + .await + } + }) + } + + fn confirm( + &mut self, + secondary: bool, + window: &mut Window, + cx: &mut Context>, + ) { + } + + fn dismissed(&mut self, window: &mut Window, cx: &mut Context>) { + self.selector + .update(cx, |_, cx| cx.emit(DismissEvent)) + .log_err(); + } + + fn render_match( + &self, + ix: usize, + selected: bool, + window: &mut Window, + cx: &mut Context>, + ) -> Option { + Some(ListItem::new(ix).child(Label::new(&self.matches[ix].string))) + } + } + + impl EncodingSelector { + pub fn new(window: &mut Window, cx: &mut Context) -> EncodingSelector { + let delegate = EncodingSelectorDelegate::new(cx.entity().downgrade()); + let picker = cx.new(|cx| Picker::uniform_list(delegate, window, cx)); + + EncodingSelector { picker: picker } + } + + pub fn toggle(workspace: &mut Workspace, window: &mut Window, cx: &mut Context) { + workspace.toggle_modal(window, cx, |window, cx| EncodingSelector::new(window, cx)); + } + } + + impl EventEmitter for EncodingSelector {} + + impl Focusable for EncodingSelector { + fn focus_handle(&self, cx: &ui::App) -> gpui::FocusHandle { + cx.focus_handle() + } + } + + impl ModalView for EncodingSelector {} + + impl Render for EncodingSelector { + fn render(&mut self, _: &mut Window, _: &mut Context) -> impl ui::IntoElement { + v_flex().w(rems(34.0)).child(self.picker.clone()) + } + } +} diff --git a/crates/fs/Cargo.toml b/crates/fs/Cargo.toml index 1d4161134e..6476c67636 100644 --- a/crates/fs/Cargo.toml +++ b/crates/fs/Cargo.toml @@ -34,6 +34,8 @@ text.workspace = true time.workspace = true util.workspace = true workspace-hack.workspace = true +encoding = "0.2.33" + [target.'cfg(target_os = "macos")'.dependencies] fsevent.workspace = true diff --git a/crates/fs/src/encodings.rs b/crates/fs/src/encodings.rs new file mode 100644 index 0000000000..8fb38ff24f --- /dev/null +++ b/crates/fs/src/encodings.rs @@ -0,0 +1,21 @@ +use encoding::Encoding; + +pub enum CharacterEncoding { + Utf8, + Iso8859_1, + Cp865, +} + +pub fn to_utf8<'a>(input: Vec, encoding: &'a impl encoding::Encoding) -> String { + match encoding.decode(&input, encoding::DecoderTrap::Strict) { + Ok(v) => return v, + Err(_) => panic!(), + } +} + +pub fn to<'a>(input: String, target: &'a impl encoding::Encoding) -> Vec { + match target.encode(&input, encoding::EncoderTrap::Strict) { + Ok(v) => v, + Err(_) => panic!(), + } +} diff --git a/crates/language/Cargo.toml b/crates/language/Cargo.toml index 4ab56d6647..fafd1fdcb7 100644 --- a/crates/language/Cargo.toml +++ b/crates/language/Cargo.toml @@ -70,6 +70,7 @@ util.workspace = true watch.workspace = true workspace-hack.workspace = true diffy = "0.4.2" +encoding = "0.2.33" [dev-dependencies] collections = { workspace = true, features = ["test-support"] } diff --git a/crates/language/src/buffer.rs b/crates/language/src/buffer.rs index 4ddc2b3018..85c24ef0ac 100644 --- a/crates/language/src/buffer.rs +++ b/crates/language/src/buffer.rs @@ -127,6 +127,7 @@ pub struct Buffer { has_unsaved_edits: Cell<(clock::Global, bool)>, change_bits: Vec>>, _subscriptions: Vec, + encoding: &'static dyn encoding::Encoding, } #[derive(Copy, Clone, Debug, PartialEq, Eq)] @@ -958,6 +959,7 @@ impl Buffer { has_conflict: false, change_bits: Default::default(), _subscriptions: Vec::new(), + encoding: encoding::all::UTF_8, } } diff --git a/crates/zed/src/zed.rs b/crates/zed/src/zed.rs index e780d9d5a0..36189c1110 100644 --- a/crates/zed/src/zed.rs +++ b/crates/zed/src/zed.rs @@ -397,7 +397,10 @@ pub fn initialize_workspace( } }); - let encoding_indicator = cx.new(|_cx| encodings::Encoding::Utf8(workspace.weak_handle())); + let encoding_indicator = cx.new(|_cx| encodings::EncodingIndicator { + encoding: encodings::Encoding::Utf8, + workspace: workspace_handle.downgrade(), + }); let cursor_position = cx.new(|_| go_to_line::cursor_position::CursorPosition::new(workspace));