diff --git a/assets/settings/default.json b/assets/settings/default.json index 327b35c4b197818c09a065e2b6203430a6150665..c110b169b7cd18098de9945b43f72ac1fa0cff19 100644 --- a/assets/settings/default.json +++ b/assets/settings/default.json @@ -1350,7 +1350,9 @@ // Whether to show the active language button in the status bar. "active_language_button": true, // Whether to show the cursor position button in the status bar. - "cursor_position_button": true + "cursor_position_button": true, + // Whether to show active line endings button in the status bar. + "line_endings_button": false }, // Settings specific to the terminal "terminal": { diff --git a/crates/line_ending_selector/src/line_ending_indicator.rs b/crates/line_ending_selector/src/line_ending_indicator.rs new file mode 100644 index 0000000000000000000000000000000000000000..042630056a4cad93497e7b35cab7c82c1ea643e3 --- /dev/null +++ b/crates/line_ending_selector/src/line_ending_indicator.rs @@ -0,0 +1,70 @@ +use editor::Editor; +use gpui::{Entity, Subscription, WeakEntity}; +use language::LineEnding; +use ui::{Tooltip, prelude::*}; +use workspace::{StatusBarSettings, StatusItemView, item::ItemHandle, item::Settings}; + +use crate::{LineEndingSelector, Toggle}; + +#[derive(Default)] +pub struct LineEndingIndicator { + line_ending: Option, + active_editor: Option>, + _observe_active_editor: Option, +} + +impl LineEndingIndicator { + fn update(&mut self, editor: Entity, _: &mut Window, cx: &mut Context) { + self.line_ending = None; + self.active_editor = None; + + if let Some((_, buffer, _)) = editor.read(cx).active_excerpt(cx) { + let line_ending = buffer.read(cx).line_ending(); + self.line_ending = Some(line_ending); + self.active_editor = Some(editor.downgrade()); + } + + cx.notify(); + } +} + +impl Render for LineEndingIndicator { + fn render(&mut self, _window: &mut Window, cx: &mut Context) -> impl IntoElement { + if !StatusBarSettings::get_global(cx).line_endings_button { + return div(); + } + + div().when_some(self.line_ending.as_ref(), |el, line_ending| { + el.child( + Button::new("change-line-ending", line_ending.label()) + .label_size(LabelSize::Small) + .on_click(cx.listener(|this, _, window, cx| { + if let Some(editor) = this.active_editor.as_ref() { + LineEndingSelector::toggle(editor, window, cx); + } + })) + .tooltip(|window, cx| { + Tooltip::for_action("Select Line Ending", &Toggle, window, cx) + }), + ) + }) + } +} + +impl StatusItemView for LineEndingIndicator { + fn set_active_pane_item( + &mut self, + active_pane_item: Option<&dyn ItemHandle>, + window: &mut Window, + cx: &mut Context, + ) { + if let Some(editor) = active_pane_item.and_then(|item| item.downcast::()) { + self._observe_active_editor = Some(cx.observe_in(&editor, window, Self::update)); + self.update(editor, window, cx); + } else { + self.line_ending = None; + self._observe_active_editor = None; + } + cx.notify(); + } +} diff --git a/crates/line_ending_selector/src/line_ending_selector.rs b/crates/line_ending_selector/src/line_ending_selector.rs index 7f75a1ebe3550595c8fa78643ef5446ab2fa3a44..504c327a349c97214e801f6bd375d61c7847f2be 100644 --- a/crates/line_ending_selector/src/line_ending_selector.rs +++ b/crates/line_ending_selector/src/line_ending_selector.rs @@ -1,6 +1,9 @@ +mod line_ending_indicator; + use editor::Editor; use gpui::{DismissEvent, Entity, EventEmitter, FocusHandle, Focusable, Task, WeakEntity, actions}; use language::{Buffer, LineEnding}; +pub use line_ending_indicator::LineEndingIndicator; use picker::{Picker, PickerDelegate}; use project::Project; use std::sync::Arc; @@ -9,7 +12,7 @@ use util::ResultExt; use workspace::ModalView; actions!( - line_ending, + line_ending_selector, [ /// Toggles the line ending selector modal. Toggle @@ -172,10 +175,7 @@ impl PickerDelegate for LineEndingSelectorDelegate { _: &mut Context>, ) -> Option { let line_ending = self.matches.get(ix)?; - let label = match line_ending { - LineEnding::Unix => "LF", - LineEnding::Windows => "CRLF", - }; + let label = line_ending.label(); let mut list_item = ListItem::new(ix) .inset(true) diff --git a/crates/settings/src/settings_content/workspace.rs b/crates/settings/src/settings_content/workspace.rs index 577f8fa4f996b2a808bdc785c56210e766dab2fb..a4e36ef8358487dbd4f3e5696eb52c5da9d28eb9 100644 --- a/crates/settings/src/settings_content/workspace.rs +++ b/crates/settings/src/settings_content/workspace.rs @@ -380,6 +380,10 @@ pub struct StatusBarSettingsContent { /// /// Default: true pub cursor_position_button: Option, + /// Whether to show active line endings button in the status bar. + /// + /// Default: false + pub line_endings_button: Option, } #[derive( diff --git a/crates/text/src/text.rs b/crates/text/src/text.rs index 42d9a48430590302f96a1476bdbc3b876ed8f2f6..d78dfbea7dc0d3ac65005855eaffadee37fda584 100644 --- a/crates/text/src/text.rs +++ b/crates/text/src/text.rs @@ -3267,6 +3267,13 @@ impl LineEnding { } } + pub fn label(&self) -> &'static str { + match self { + LineEnding::Unix => "LF", + LineEnding::Windows => "CRLF", + } + } + pub fn detect(text: &str) -> Self { let mut max_ix = cmp::min(text.len(), 1000); while !text.is_char_boundary(max_ix) { diff --git a/crates/workspace/src/workspace_settings.rs b/crates/workspace/src/workspace_settings.rs index 6ed2aeb5cb85ae5728f683b3c3d7dfbdf86f0c6a..f061227f2cb264b1be1234364ca1e8de7a462e86 100644 --- a/crates/workspace/src/workspace_settings.rs +++ b/crates/workspace/src/workspace_settings.rs @@ -126,6 +126,7 @@ pub struct StatusBarSettings { pub show: bool, pub active_language_button: bool, pub cursor_position_button: bool, + pub line_endings_button: bool, } impl Settings for StatusBarSettings { @@ -135,6 +136,7 @@ impl Settings for StatusBarSettings { show: status_bar.show.unwrap(), active_language_button: status_bar.active_language_button.unwrap(), cursor_position_button: status_bar.cursor_position_button.unwrap(), + line_endings_button: status_bar.line_endings_button.unwrap(), } } } diff --git a/crates/zed/src/zed.rs b/crates/zed/src/zed.rs index a9b28229de20b8d24e481482e1441482e5d36212..1416a74e1697324213c11e1bbc51fd2d8a6bf91b 100644 --- a/crates/zed/src/zed.rs +++ b/crates/zed/src/zed.rs @@ -417,6 +417,8 @@ pub fn initialize_workspace( let cursor_position = cx.new(|_| go_to_line::cursor_position::CursorPosition::new(workspace)); + let line_ending_indicator = + cx.new(|_| line_ending_selector::LineEndingIndicator::default()); workspace.status_bar().update(cx, |status_bar, cx| { status_bar.add_left_item(search_button, window, cx); status_bar.add_left_item(lsp_button, window, cx); @@ -425,6 +427,7 @@ pub fn initialize_workspace( status_bar.add_right_item(edit_prediction_button, window, cx); status_bar.add_right_item(active_buffer_language, window, cx); status_bar.add_right_item(active_toolchain_language, window, cx); + status_bar.add_right_item(line_ending_indicator, window, cx); status_bar.add_right_item(vim_mode_indicator, window, cx); status_bar.add_right_item(cursor_position, window, cx); status_bar.add_right_item(image_info, window, cx); @@ -4669,7 +4672,7 @@ mod tests { "keymap_editor", "keystroke_input", "language_selector", - "line_ending", + "line_ending_selector", "lsp_tool", "markdown", "menu", diff --git a/docs/src/configuring-zed.md b/docs/src/configuring-zed.md index 4fb65d14118d637d7123998e53da9aa40dc7a84c..efc4538c0e5286a053a89916c90548796ba619d0 100644 --- a/docs/src/configuring-zed.md +++ b/docs/src/configuring-zed.md @@ -1498,7 +1498,8 @@ Positive `integer` value between 1 and 32. Values outside of this range will be ```json [settings] "status_bar": { "active_language_button": true, - "cursor_position_button": true + "cursor_position_button": true, + "line_endings_button": false }, ``` diff --git a/docs/src/visual-customization.md b/docs/src/visual-customization.md index 89cb3ec1929e6c71f8f832818ef6c54c0219bff2..a31f4428cd9d554ce366e182da605a71eefe6eec 100644 --- a/docs/src/visual-customization.md +++ b/docs/src/visual-customization.md @@ -319,6 +319,10 @@ TBD: Centered layout related settings // Clicking the button brings up an input for jumping to a line and column. // Defaults to true. "cursor_position_button": true, + // Show/hide a button that displays the buffer's line-ending mode. + // Clicking the button brings up the line-ending selector. + // Defaults to false. + "line_endings_button": false }, "global_lsp_settings": { // Show/hide the LSP button in the status bar.