lib.rs

  1//! A crate for handling file encodings in the text editor.
  2use editor::{Editor, EditorSettings};
  3use encoding_rs::Encoding;
  4use gpui::{ClickEvent, Entity, Subscription, WeakEntity};
  5use settings::Settings;
  6use ui::{Button, ButtonCommon, Context, LabelSize, Render, Tooltip, Window, div};
  7use ui::{Clickable, ParentElement};
  8use workspace::{ItemHandle, StatusItemView, Workspace};
  9
 10use crate::selectors::save_or_reopen::EncodingSaveOrReopenSelector;
 11
 12/// A status bar item that shows the current file encoding and allows changing it.
 13pub struct EncodingIndicator {
 14    pub encoding: Option<&'static Encoding>,
 15    pub workspace: WeakEntity<Workspace>,
 16    observe: Option<Subscription>, // Subscription to observe changes in the active editor
 17    show: bool, // Whether to show the indicator or not, based on whether an editor is active
 18}
 19
 20pub mod selectors;
 21
 22impl Render for EncodingIndicator {
 23    fn render(&mut self, _window: &mut Window, cx: &mut Context<Self>) -> impl ui::IntoElement {
 24        let status_element = div();
 25
 26        if (!EditorSettings::get_global(cx).status_bar.encoding_indicator) || !self.show {
 27            return status_element;
 28        }
 29
 30        status_element.child(
 31            Button::new(
 32                "encoding",
 33                encoding_name(self.encoding.unwrap_or(encoding_rs::UTF_8)),
 34            )
 35            .label_size(LabelSize::Small)
 36            .tooltip(Tooltip::text("Select Encoding"))
 37            .on_click(cx.listener(|indicator, _: &ClickEvent, window, cx| {
 38                if let Some(workspace) = indicator.workspace.upgrade() {
 39                    workspace.update(cx, |workspace, cx| {
 40                        EncodingSaveOrReopenSelector::toggle(workspace, window, cx)
 41                    })
 42                } else {
 43                }
 44            })),
 45        )
 46    }
 47}
 48
 49impl EncodingIndicator {
 50    pub fn new(
 51        encoding: Option<&'static Encoding>,
 52        workspace: WeakEntity<Workspace>,
 53        observe: Option<Subscription>,
 54    ) -> EncodingIndicator {
 55        EncodingIndicator {
 56            encoding,
 57            workspace,
 58            observe,
 59            show: true,
 60        }
 61    }
 62
 63    pub fn update(
 64        &mut self,
 65        editor: Entity<Editor>,
 66        _: &mut Window,
 67        cx: &mut Context<EncodingIndicator>,
 68    ) {
 69        let editor = editor.read(cx);
 70        if let Some((_, buffer, _)) = editor.active_excerpt(cx) {
 71            let encoding = buffer.read(cx).encoding;
 72            self.encoding = Some(encoding);
 73        }
 74
 75        cx.notify();
 76    }
 77}
 78
 79impl StatusItemView for EncodingIndicator {
 80    fn set_active_pane_item(
 81        &mut self,
 82        active_pane_item: Option<&dyn ItemHandle>,
 83        window: &mut Window,
 84        cx: &mut Context<Self>,
 85    ) {
 86        match active_pane_item.and_then(|item| item.downcast::<Editor>()) {
 87            Some(editor) => {
 88                self.observe = Some(cx.observe_in(&editor, window, Self::update));
 89                self.update(editor, window, cx);
 90                self.show = true;
 91            }
 92            None => {
 93                self.encoding = None;
 94                self.observe = None;
 95                self.show = false;
 96            }
 97        }
 98    }
 99}
100
101/// Get a human-readable name for the given encoding.
102pub fn encoding_name(encoding: &'static Encoding) -> String {
103    let name = encoding.name();
104
105    match name {
106        "UTF-8" => "UTF-8",
107        "UTF-16LE" => "UTF-16 LE",
108        "UTF-16BE" => "UTF-16 BE",
109        "windows-1252" => "Windows-1252",
110        "windows-1251" => "Windows-1251",
111        "windows-1250" => "Windows-1250",
112        "ISO-8859-2" => "ISO 8859-2",
113        "ISO-8859-3" => "ISO 8859-3",
114        "ISO-8859-4" => "ISO 8859-4",
115        "ISO-8859-5" => "ISO 8859-5",
116        "ISO-8859-6" => "ISO 8859-6",
117        "ISO-8859-7" => "ISO 8859-7",
118        "ISO-8859-8" => "ISO 8859-8",
119        "ISO-8859-13" => "ISO 8859-13",
120        "ISO-8859-15" => "ISO 8859-15",
121        "KOI8-R" => "KOI8-R",
122        "KOI8-U" => "KOI8-U",
123        "macintosh" => "MacRoman",
124        "x-mac-cyrillic" => "Mac Cyrillic",
125        "windows-874" => "Windows-874",
126        "windows-1253" => "Windows-1253",
127        "windows-1254" => "Windows-1254",
128        "windows-1255" => "Windows-1255",
129        "windows-1256" => "Windows-1256",
130        "windows-1257" => "Windows-1257",
131        "windows-1258" => "Windows-1258",
132        "EUC-KR" => "Windows-949",
133        "EUC-JP" => "EUC-JP",
134        "ISO-2022-JP" => "ISO 2022-JP",
135        "GBK" => "GBK",
136        "gb18030" => "GB18030",
137        "Big5" => "Big5",
138        _ => name,
139    }
140    .to_string()
141}
142
143/// Get an encoding from its index in the predefined list.
144/// If the index is out of range, UTF-8 is returned as a default.
145pub fn encoding_from_index(index: usize) -> &'static Encoding {
146    match index {
147        0 => encoding_rs::UTF_8,
148        1 => encoding_rs::UTF_16LE,
149        2 => encoding_rs::UTF_16BE,
150        3 => encoding_rs::WINDOWS_1252,
151        4 => encoding_rs::WINDOWS_1251,
152        5 => encoding_rs::WINDOWS_1250,
153        6 => encoding_rs::ISO_8859_2,
154        7 => encoding_rs::ISO_8859_3,
155        8 => encoding_rs::ISO_8859_4,
156        9 => encoding_rs::ISO_8859_5,
157        10 => encoding_rs::ISO_8859_6,
158        11 => encoding_rs::ISO_8859_7,
159        12 => encoding_rs::ISO_8859_8,
160        13 => encoding_rs::ISO_8859_13,
161        14 => encoding_rs::ISO_8859_15,
162        15 => encoding_rs::KOI8_R,
163        16 => encoding_rs::KOI8_U,
164        17 => encoding_rs::MACINTOSH,
165        18 => encoding_rs::X_MAC_CYRILLIC,
166        19 => encoding_rs::WINDOWS_874,
167        20 => encoding_rs::WINDOWS_1253,
168        21 => encoding_rs::WINDOWS_1254,
169        22 => encoding_rs::WINDOWS_1255,
170        23 => encoding_rs::WINDOWS_1256,
171        24 => encoding_rs::WINDOWS_1257,
172        25 => encoding_rs::WINDOWS_1258,
173        26 => encoding_rs::EUC_KR,
174        27 => encoding_rs::EUC_JP,
175        28 => encoding_rs::ISO_2022_JP,
176        29 => encoding_rs::GBK,
177        30 => encoding_rs::GB18030,
178        31 => encoding_rs::BIG5,
179        _ => encoding_rs::UTF_8,
180    }
181}
182
183/// Get an encoding from its name.
184pub fn encoding_from_name(name: &str) -> &'static Encoding {
185    match name {
186        "UTF-8" => encoding_rs::UTF_8,
187        "UTF-16 LE" => encoding_rs::UTF_16LE,
188        "UTF-16 BE" => encoding_rs::UTF_16BE,
189        "Windows-1252" => encoding_rs::WINDOWS_1252,
190        "Windows-1251" => encoding_rs::WINDOWS_1251,
191        "Windows-1250" => encoding_rs::WINDOWS_1250,
192        "ISO 8859-2" => encoding_rs::ISO_8859_2,
193        "ISO 8859-3" => encoding_rs::ISO_8859_3,
194        "ISO 8859-4" => encoding_rs::ISO_8859_4,
195        "ISO 8859-5" => encoding_rs::ISO_8859_5,
196        "ISO 8859-6" => encoding_rs::ISO_8859_6,
197        "ISO 8859-7" => encoding_rs::ISO_8859_7,
198        "ISO 8859-8" => encoding_rs::ISO_8859_8,
199        "ISO 8859-13" => encoding_rs::ISO_8859_13,
200        "ISO 8859-15" => encoding_rs::ISO_8859_15,
201        "KOI8-R" => encoding_rs::KOI8_R,
202        "KOI8-U" => encoding_rs::KOI8_U,
203        "MacRoman" => encoding_rs::MACINTOSH,
204        "Mac Cyrillic" => encoding_rs::X_MAC_CYRILLIC,
205        "Windows-874" => encoding_rs::WINDOWS_874,
206        "Windows-1253" => encoding_rs::WINDOWS_1253,
207        "Windows-1254" => encoding_rs::WINDOWS_1254,
208        "Windows-1255" => encoding_rs::WINDOWS_1255,
209        "Windows-1256" => encoding_rs::WINDOWS_1256,
210        "Windows-1257" => encoding_rs::WINDOWS_1257,
211        "Windows-1258" => encoding_rs::WINDOWS_1258,
212        "Windows-949" => encoding_rs::EUC_KR,
213        "EUC-JP" => encoding_rs::EUC_JP,
214        "ISO 2022-JP" => encoding_rs::ISO_2022_JP,
215        "GBK" => encoding_rs::GBK,
216        "GB18030" => encoding_rs::GB18030,
217        "Big5" => encoding_rs::BIG5,
218        "HZ-GB-2312" => encoding_rs::UTF_8, // encoding_rs doesn't support HZ, fallback to UTF-8
219        _ => encoding_rs::UTF_8,            // Default to UTF-8 for unknown names
220    }
221}