tab: Add setting to hide the close button entirely (#23880)
Closes #23744 Release Notes: - Changed the `always_show_close_button` key to `show_close_button` and introduced a new `hidden` value, that allows never displaying the close button. --------- Co-authored-by: Peter Tripp <peter@zed.dev> Co-authored-by: Danilo Leal <daniloleal09@gmail.com> Co-authored-by: smit <0xtimsb@gmail.com>
This commit is contained in:
parent
ae6d350334
commit
0a4ff2f475
5 changed files with 149 additions and 28 deletions
|
@ -648,11 +648,19 @@
|
|||
// Show git status colors in the editor tabs.
|
||||
"git_status": false,
|
||||
// Position of the close button on the editor tabs.
|
||||
// One of: ["right", "left", "hidden"]
|
||||
"close_position": "right",
|
||||
// Whether to show the file icon for a tab.
|
||||
"file_icons": false,
|
||||
// Whether to always show the close button on tabs.
|
||||
"always_show_close_button": false,
|
||||
// Controls the appearance behavior of the tab's close button.
|
||||
//
|
||||
// 1. Show it just upon hovering the tab. (default)
|
||||
// "hover"
|
||||
// 2. Show it persistently.
|
||||
// "always"
|
||||
// 3. Never show it, even if hovering it.
|
||||
// "hidden"
|
||||
"show_close_button": "hover",
|
||||
// What to do after closing the current tab.
|
||||
//
|
||||
// 1. Activate the tab that was open previously (default)
|
||||
|
|
|
@ -72,7 +72,7 @@ pub fn migrate_edit_prediction_provider_settings(text: &str) -> Result<Option<St
|
|||
migrate(
|
||||
&text,
|
||||
&[(
|
||||
SETTINGS_REPLACE_NESTED_KEY,
|
||||
SETTINGS_NESTED_KEY_VALUE_PATTERN,
|
||||
replace_edit_prediction_provider_setting,
|
||||
)],
|
||||
&EDIT_PREDICTION_SETTINGS_MIGRATION_QUERY,
|
||||
|
@ -571,9 +571,17 @@ pub static ACTION_ARGUMENT_SNAKE_CASE_REPLACE: LazyLock<HashMap<&str, &str>> =
|
|||
const SETTINGS_MIGRATION_PATTERNS: MigrationPatterns = &[
|
||||
(SETTINGS_STRING_REPLACE_QUERY, replace_setting_name),
|
||||
(
|
||||
SETTINGS_REPLACE_NESTED_KEY,
|
||||
SETTINGS_NESTED_KEY_VALUE_PATTERN,
|
||||
replace_edit_prediction_provider_setting,
|
||||
),
|
||||
(
|
||||
SETTINGS_NESTED_KEY_VALUE_PATTERN,
|
||||
replace_tab_close_button_setting_key,
|
||||
),
|
||||
(
|
||||
SETTINGS_NESTED_KEY_VALUE_PATTERN,
|
||||
replace_tab_close_button_setting_value,
|
||||
),
|
||||
(
|
||||
SETTINGS_REPLACE_IN_LANGUAGES_QUERY,
|
||||
replace_setting_in_languages,
|
||||
|
@ -594,7 +602,7 @@ static SETTINGS_MIGRATION_QUERY: LazyLock<Query> = LazyLock::new(|| {
|
|||
static EDIT_PREDICTION_SETTINGS_MIGRATION_QUERY: LazyLock<Query> = LazyLock::new(|| {
|
||||
Query::new(
|
||||
&tree_sitter_json::LANGUAGE.into(),
|
||||
SETTINGS_REPLACE_NESTED_KEY,
|
||||
SETTINGS_NESTED_KEY_VALUE_PATTERN,
|
||||
)
|
||||
.unwrap()
|
||||
});
|
||||
|
@ -639,14 +647,14 @@ pub static SETTINGS_STRING_REPLACE: LazyLock<HashMap<&'static str, &'static str>
|
|||
])
|
||||
});
|
||||
|
||||
const SETTINGS_REPLACE_NESTED_KEY: &str = r#"
|
||||
const SETTINGS_NESTED_KEY_VALUE_PATTERN: &str = r#"
|
||||
(object
|
||||
(pair
|
||||
key: (string (string_content) @parent_key)
|
||||
value: (object
|
||||
(pair
|
||||
key: (string (string_content) @setting_name)
|
||||
value: (_) @value
|
||||
value: (_) @setting_value
|
||||
)
|
||||
)
|
||||
)
|
||||
|
@ -679,6 +687,73 @@ fn replace_edit_prediction_provider_setting(
|
|||
None
|
||||
}
|
||||
|
||||
fn replace_tab_close_button_setting_key(
|
||||
contents: &str,
|
||||
mat: &QueryMatch,
|
||||
query: &Query,
|
||||
) -> Option<(Range<usize>, String)> {
|
||||
let parent_object_capture_ix = query.capture_index_for_name("parent_key")?;
|
||||
let parent_object_range = mat
|
||||
.nodes_for_capture_index(parent_object_capture_ix)
|
||||
.next()?
|
||||
.byte_range();
|
||||
let parent_object_name = contents.get(parent_object_range.clone())?;
|
||||
|
||||
let setting_name_ix = query.capture_index_for_name("setting_name")?;
|
||||
let setting_range = mat
|
||||
.nodes_for_capture_index(setting_name_ix)
|
||||
.next()?
|
||||
.byte_range();
|
||||
let setting_name = contents.get(setting_range.clone())?;
|
||||
|
||||
if parent_object_name == "tabs" && setting_name == "always_show_close_button" {
|
||||
return Some((setting_range, "show_close_button".into()));
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
fn replace_tab_close_button_setting_value(
|
||||
contents: &str,
|
||||
mat: &QueryMatch,
|
||||
query: &Query,
|
||||
) -> Option<(Range<usize>, String)> {
|
||||
let parent_object_capture_ix = query.capture_index_for_name("parent_key")?;
|
||||
let parent_object_range = mat
|
||||
.nodes_for_capture_index(parent_object_capture_ix)
|
||||
.next()?
|
||||
.byte_range();
|
||||
let parent_object_name = contents.get(parent_object_range.clone())?;
|
||||
|
||||
let setting_name_ix = query.capture_index_for_name("setting_name")?;
|
||||
let setting_name_range = mat
|
||||
.nodes_for_capture_index(setting_name_ix)
|
||||
.next()?
|
||||
.byte_range();
|
||||
let setting_name = contents.get(setting_name_range.clone())?;
|
||||
|
||||
let setting_value_ix = query.capture_index_for_name("setting_value")?;
|
||||
let setting_value_range = mat
|
||||
.nodes_for_capture_index(setting_value_ix)
|
||||
.next()?
|
||||
.byte_range();
|
||||
let setting_value = contents.get(setting_value_range.clone())?;
|
||||
|
||||
if parent_object_name == "tabs" && setting_name == "always_show_close_button" {
|
||||
match setting_value {
|
||||
"true" => {
|
||||
return Some((setting_value_range, "\"always\"".to_string()));
|
||||
}
|
||||
"false" => {
|
||||
return Some((setting_value_range, "\"hover\"".to_string()));
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
const SETTINGS_REPLACE_IN_LANGUAGES_QUERY: &str = r#"
|
||||
(object
|
||||
(pair
|
||||
|
|
|
@ -42,7 +42,7 @@ pub struct ItemSettings {
|
|||
pub activate_on_close: ActivateOnClose,
|
||||
pub file_icons: bool,
|
||||
pub show_diagnostics: ShowDiagnostics,
|
||||
pub always_show_close_button: bool,
|
||||
pub show_close_button: ShowCloseButton,
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
|
@ -60,6 +60,15 @@ pub enum ClosePosition {
|
|||
Right,
|
||||
}
|
||||
|
||||
#[derive(Clone, Default, Serialize, Deserialize, JsonSchema)]
|
||||
#[serde(rename_all = "lowercase")]
|
||||
pub enum ShowCloseButton {
|
||||
Always,
|
||||
#[default]
|
||||
Hover,
|
||||
Hidden,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, Default, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub enum ShowDiagnostics {
|
||||
|
@ -104,7 +113,7 @@ pub struct ItemSettingsContent {
|
|||
/// Whether to always show the close button on tabs.
|
||||
///
|
||||
/// Default: false
|
||||
always_show_close_button: Option<bool>,
|
||||
show_close_button: Option<ShowCloseButton>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Default, Serialize, Deserialize, JsonSchema)]
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use crate::{
|
||||
item::{
|
||||
ActivateOnClose, ClosePosition, Item, ItemHandle, ItemSettings, PreviewTabsSettings,
|
||||
ShowDiagnostics, TabContentParams, TabTooltipContent, WeakItemHandle,
|
||||
ShowCloseButton, ShowDiagnostics, TabContentParams, TabTooltipContent, WeakItemHandle,
|
||||
},
|
||||
move_item,
|
||||
notifications::NotifyResultExt,
|
||||
|
@ -2269,7 +2269,7 @@ impl Pane {
|
|||
|
||||
let settings = ItemSettings::get_global(cx);
|
||||
let close_side = &settings.close_position;
|
||||
let always_show_close_button = settings.always_show_close_button;
|
||||
let show_close_button = &settings.show_close_button;
|
||||
let indicator = render_item_indicator(item.boxed_clone(), cx);
|
||||
let item_id = item.item_id();
|
||||
let is_first_item = ix == 0;
|
||||
|
@ -2373,18 +2373,21 @@ impl Pane {
|
|||
close_pinned: false,
|
||||
};
|
||||
end_slot_tooltip_text = "Close Tab";
|
||||
IconButton::new("close tab", IconName::Close)
|
||||
.when(!always_show_close_button, |button| {
|
||||
button.visible_on_hover("")
|
||||
})
|
||||
.shape(IconButtonShape::Square)
|
||||
.icon_color(Color::Muted)
|
||||
.size(ButtonSize::None)
|
||||
.icon_size(IconSize::XSmall)
|
||||
.on_click(cx.listener(move |pane, _, window, cx| {
|
||||
pane.close_item_by_id(item_id, SaveIntent::Close, window, cx)
|
||||
.detach_and_log_err(cx);
|
||||
}))
|
||||
match show_close_button {
|
||||
ShowCloseButton::Always => IconButton::new("close tab", IconName::Close),
|
||||
ShowCloseButton::Hover => {
|
||||
IconButton::new("close tab", IconName::Close).visible_on_hover("")
|
||||
}
|
||||
ShowCloseButton::Hidden => return this,
|
||||
}
|
||||
.shape(IconButtonShape::Square)
|
||||
.icon_color(Color::Muted)
|
||||
.size(ButtonSize::None)
|
||||
.icon_size(IconSize::XSmall)
|
||||
.on_click(cx.listener(move |pane, _, window, cx| {
|
||||
pane.close_item_by_id(item_id, SaveIntent::Close, window, cx)
|
||||
.detach_and_log_err(cx);
|
||||
}))
|
||||
}
|
||||
.map(|this| {
|
||||
if is_active {
|
||||
|
|
|
@ -784,7 +784,7 @@ List of `string` values
|
|||
"file_icons": false,
|
||||
"git_status": false,
|
||||
"activate_on_close": "history",
|
||||
"always_show_close_button": false
|
||||
"show_close_button": "hover"
|
||||
},
|
||||
```
|
||||
|
||||
|
@ -856,11 +856,37 @@ List of `string` values
|
|||
}
|
||||
```
|
||||
|
||||
### Always show the close button
|
||||
### Show close button
|
||||
|
||||
- Description: Whether to always show the close button on tabs.
|
||||
- Setting: `always_show_close_button`
|
||||
- Default: `false`
|
||||
- Description: Controls the appearance behavior of the tab's close button.
|
||||
- Setting: `show_close_button`
|
||||
- Default: `hover`
|
||||
|
||||
**Options**
|
||||
|
||||
1. Show it just upon hovering the tab:
|
||||
|
||||
```json
|
||||
{
|
||||
"show_close_button": "hover"
|
||||
}
|
||||
```
|
||||
|
||||
2. Show it persistently:
|
||||
|
||||
```json
|
||||
{
|
||||
"show_close_button": "always"
|
||||
}
|
||||
```
|
||||
|
||||
3. Never show it, even if hovering it:
|
||||
|
||||
```json
|
||||
{
|
||||
"show_close_button": "hidden"
|
||||
}
|
||||
```
|
||||
|
||||
## Editor Toolbar
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue