Make the status bar encoding indicator update the encoding when an encoding from the selector is chosen.

R Aadarsh created

Change summary

Cargo.lock                        |   1 
crates/encodings/Cargo.toml       |   1 
crates/encodings/src/lib.rs       | 100 ++++++++++++++++++++++++++++++++
crates/encodings/src/selectors.rs |  55 ++++++++++++++---
4 files changed, 144 insertions(+), 13 deletions(-)

Detailed changes

Cargo.lock 🔗

@@ -5592,6 +5592,7 @@ dependencies = [
  "encoding",
  "fuzzy",
  "gpui",
+ "language",
  "picker",
  "ui",
  "util",

crates/encodings/Cargo.toml 🔗

@@ -13,6 +13,7 @@ util.workspace = true
 fuzzy.workspace = true
 editor.workspace = true
 encoding = "0.2.33"
+language.workspace = true
 
 [lints]
 workspace = true

crates/encodings/src/lib.rs 🔗

@@ -1,5 +1,12 @@
 use editor::Editor;
 use encoding::Encoding;
+use encoding::all::{
+    BIG5_2003, EUC_JP, GB18030, GBK, HZ, IBM866, ISO_2022_JP, ISO_8859_1, ISO_8859_2, ISO_8859_3,
+    ISO_8859_4, ISO_8859_5, ISO_8859_6, ISO_8859_7, ISO_8859_8, ISO_8859_10, ISO_8859_13,
+    ISO_8859_14, ISO_8859_15, ISO_8859_16, KOI8_R, KOI8_U, MAC_CYRILLIC, MAC_ROMAN, UTF_8,
+    UTF_16BE, UTF_16LE, WINDOWS_874, WINDOWS_949, WINDOWS_1250, WINDOWS_1251, WINDOWS_1252,
+    WINDOWS_1253, WINDOWS_1254, WINDOWS_1255, WINDOWS_1256, WINDOWS_1257, WINDOWS_1258,
+};
 use gpui::{ClickEvent, Entity, Subscription, WeakEntity};
 use ui::{Button, ButtonCommon, Context, LabelSize, Render, Tooltip, Window, div};
 use ui::{Clickable, ParentElement};
@@ -20,7 +27,7 @@ impl Render for EncodingIndicator {
         let status_element = div();
 
         status_element.child(
-            Button::new("encoding", get_current_encoding())
+            Button::new("encoding", encoding_name(self.encoding.unwrap_or(UTF_8)))
                 .label_size(LabelSize::Small)
                 .tooltip(Tooltip::text("Select Encoding"))
                 .on_click(cx.listener(|indicator, _: &ClickEvent, window, cx| {
@@ -85,3 +92,94 @@ impl StatusItemView for EncodingIndicator {
         }
     }
 }
+
+pub fn encoding_name(encoding: &'static dyn Encoding) -> String {
+    let name = encoding.name();
+
+    match () {
+        () if name == UTF_8.name() => "UTF-8",
+        () if name == UTF_16LE.name() => "UTF-16 LE",
+        () if name == UTF_16BE.name() => "UTF-16 BE",
+        () if name == IBM866.name() => "IBM866",
+        () if name == ISO_8859_1.name() => "ISO 8859-1",
+        () if name == ISO_8859_2.name() => "ISO 8859-2",
+        () if name == ISO_8859_3.name() => "ISO 8859-3",
+        () if name == ISO_8859_4.name() => "ISO 8859-4",
+        () if name == ISO_8859_5.name() => "ISO 8859-5",
+        () if name == ISO_8859_6.name() => "ISO 8859-6",
+        () if name == ISO_8859_7.name() => "ISO 8859-7",
+        () if name == ISO_8859_8.name() => "ISO 8859-8",
+        () if name == ISO_8859_10.name() => "ISO 8859-10",
+        () if name == ISO_8859_13.name() => "ISO 8859-13",
+        () if name == ISO_8859_14.name() => "ISO 8859-14",
+        () if name == ISO_8859_15.name() => "ISO 8859-15",
+        () if name == ISO_8859_16.name() => "ISO 8859-16",
+        () if name == KOI8_R.name() => "KOI8-R",
+        () if name == KOI8_U.name() => "KOI8-U",
+        () if name == MAC_ROMAN.name() => "MacRoman",
+        () if name == MAC_CYRILLIC.name() => "Mac Cyrillic",
+        () if name == WINDOWS_874.name() => "Windows-874",
+        () if name == WINDOWS_1250.name() => "Windows-1250",
+        () if name == WINDOWS_1251.name() => "Windows-1251",
+        () if name == WINDOWS_1252.name() => "Windows-1252",
+        () if name == WINDOWS_1253.name() => "Windows-1253",
+        () if name == WINDOWS_1254.name() => "Windows-1254",
+        () if name == WINDOWS_1255.name() => "Windows-1255",
+        () if name == WINDOWS_1256.name() => "Windows-1256",
+        () if name == WINDOWS_1257.name() => "Windows-1257",
+        () if name == WINDOWS_1258.name() => "Windows-1258",
+        () if name == WINDOWS_949.name() => "Windows-949",
+        () if name == EUC_JP.name() => "EUC-JP",
+        () if name == ISO_2022_JP.name() => "ISO 2022-JP",
+        () if name == GBK.name() => "GBK",
+        () if name == GB18030.name() => "GB18030",
+        () if name == BIG5_2003.name() => "Big5",
+        () if name == HZ.name() => "HZ-GB-2312",
+        _ => "",
+    }
+    .to_string()
+}
+
+pub fn encoding_from_index(index: usize) -> &'static dyn Encoding {
+    match index {
+        0 => UTF_8,
+        1 => UTF_16LE,
+        2 => UTF_16BE,
+        3 => IBM866,
+        4 => ISO_8859_1,
+        5 => ISO_8859_2,
+        6 => ISO_8859_3,
+        7 => ISO_8859_4,
+        8 => ISO_8859_5,
+        9 => ISO_8859_6,
+        10 => ISO_8859_7,
+        11 => ISO_8859_8,
+        12 => ISO_8859_10,
+        13 => ISO_8859_13,
+        14 => ISO_8859_14,
+        15 => ISO_8859_15,
+        16 => ISO_8859_16,
+        17 => KOI8_R,
+        18 => KOI8_U,
+        19 => MAC_ROMAN,
+        20 => MAC_CYRILLIC,
+        21 => WINDOWS_874,
+        22 => WINDOWS_1250,
+        23 => WINDOWS_1251,
+        24 => WINDOWS_1252,
+        25 => WINDOWS_1253,
+        26 => WINDOWS_1254,
+        27 => WINDOWS_1255,
+        28 => WINDOWS_1256,
+        29 => WINDOWS_1257,
+        30 => WINDOWS_1258,
+        31 => WINDOWS_949,
+        32 => EUC_JP,
+        33 => ISO_2022_JP,
+        34 => GBK,
+        35 => GB18030,
+        36 => BIG5_2003,
+        37 => HZ,
+        _ => UTF_8,
+    }
+}

crates/encodings/src/selectors.rs 🔗

@@ -1,4 +1,5 @@
 pub mod save_or_reopen {
+    use editor::Editor;
     use gpui::Styled;
     use gpui::{AppContext, ParentElement};
     use picker::Picker;
@@ -103,24 +104,40 @@ pub mod save_or_reopen {
             &self,
             cx: &mut Context<Picker<EncodingSaveOrReopenDelegate>>,
             window: &mut Window,
-        ) {
+        ) -> Option<()> {
             if self.current_selection == 0 {
                 if let Some(workspace) = self.workspace.upgrade() {
+                    let (_, buffer, _) = workspace
+                        .read(cx)
+                        .active_item(cx)?
+                        .act_as::<Editor>(cx)?
+                        .read(cx)
+                        .active_excerpt(cx)?;
+
                     workspace.update(cx, |workspace, cx| {
                         workspace.toggle_modal(window, cx, |window, cx| {
-                            EncodingSelector::new(window, cx, Action::Save)
+                            EncodingSelector::new(window, cx, Action::Save, buffer.downgrade())
                         })
                     });
                 }
             } else if self.current_selection == 1 {
                 if let Some(workspace) = self.workspace.upgrade() {
+                    let (_, buffer, _) = workspace
+                        .read(cx)
+                        .active_item(cx)?
+                        .act_as::<Editor>(cx)?
+                        .read(cx)
+                        .active_excerpt(cx)?;
+
                     workspace.update(cx, |workspace, cx| {
                         workspace.toggle_modal(window, cx, |window, cx| {
-                            EncodingSelector::new(window, cx, Action::Reopen)
+                            EncodingSelector::new(window, cx, Action::Reopen, buffer.downgrade())
                         })
                     });
                 }
             }
+
+            Some(())
         }
     }
 
@@ -253,6 +270,7 @@ pub mod encoding {
         AppContext, BackgroundExecutor, DismissEvent, Entity, EventEmitter, Focusable, Length,
         WeakEntity, actions,
     };
+    use language::Buffer;
     use picker::{Picker, PickerDelegate};
     use ui::{
         Context, DefiniteLength, HighlightedLabel, Label, ListItem, ListItemSpacing, ParentElement,
@@ -261,6 +279,8 @@ pub mod encoding {
     use util::{ResultExt, TryFutureExt};
     use workspace::{ModalView, Workspace};
 
+    use crate::encoding_from_index;
+
     pub struct EncodingSelector {
         picker: Entity<Picker<EncodingSelectorDelegate>>,
         action: Action,
@@ -271,10 +291,14 @@ pub mod encoding {
         encodings: Vec<StringMatchCandidate>,
         matches: Vec<StringMatch>,
         selector: WeakEntity<EncodingSelector>,
+        buffer: WeakEntity<Buffer>,
     }
 
     impl EncodingSelectorDelegate {
-        pub fn new(selector: WeakEntity<EncodingSelector>) -> EncodingSelectorDelegate {
+        pub fn new(
+            selector: WeakEntity<EncodingSelector>,
+            buffer: WeakEntity<Buffer>,
+        ) -> EncodingSelectorDelegate {
             EncodingSelectorDelegate {
                 current_selection: 0,
                 encodings: vec![
@@ -309,17 +333,17 @@ pub mod encoding {
                     StringMatchCandidate::new(28, "Windows-1256"),
                     StringMatchCandidate::new(29, "Windows-1257"),
                     StringMatchCandidate::new(30, "Windows-1258"),
-                    StringMatchCandidate::new(31, "EUC-KR"),
+                    StringMatchCandidate::new(31, "Windows-949"),
                     StringMatchCandidate::new(32, "EUC-JP"),
-                    StringMatchCandidate::new(33, "Shift_JIS"),
-                    StringMatchCandidate::new(34, "ISO 2022-JP"),
-                    StringMatchCandidate::new(35, "GBK"),
-                    StringMatchCandidate::new(36, "GB18030"),
-                    StringMatchCandidate::new(37, "Big5"),
-                    StringMatchCandidate::new(38, "HZ-GB-2312"),
+                    StringMatchCandidate::new(33, "ISO 2022-JP"),
+                    StringMatchCandidate::new(34, "GBK"),
+                    StringMatchCandidate::new(35, "GB18030"),
+                    StringMatchCandidate::new(36, "Big5"),
+                    StringMatchCandidate::new(37, "HZ-GB-2312"),
                 ],
                 matches: Vec::new(),
                 selector,
+                buffer,
             }
         }
     }
@@ -403,6 +427,12 @@ pub mod encoding {
             window: &mut Window,
             cx: &mut Context<Picker<Self>>,
         ) {
+            if let Some(buffer) = self.buffer.upgrade() {
+                buffer.update(cx, |buffer, cx| {
+                    buffer.encoding = encoding_from_index(self.current_selection)
+                });
+            }
+            self.dismissed(window, cx);
         }
 
         fn dismissed(&mut self, window: &mut Window, cx: &mut Context<Picker<Self>>) {
@@ -439,8 +469,9 @@ pub mod encoding {
             window: &mut Window,
             cx: &mut Context<EncodingSelector>,
             action: Action,
+            buffer: WeakEntity<Buffer>,
         ) -> EncodingSelector {
-            let delegate = EncodingSelectorDelegate::new(cx.entity().downgrade());
+            let delegate = EncodingSelectorDelegate::new(cx.entity().downgrade(), buffer);
             let picker = cx.new(|cx| Picker::uniform_list(delegate, window, cx));
 
             EncodingSelector { picker, action }