lib.rs

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