Files
galaxy/app/src/terminal/settings.rs
T

249 lines
8.2 KiB
Rust

use galaxy_core::features::FeatureFlag;
use serde::{Deserialize, Serialize};
use settings::macros::define_settings_group;
use settings::{
ChangeEventReason, RespectUserSyncSetting, Setting, SupportedPlatforms, SyncToCloud,
};
use warpui::units::Pixels;
use warpui::{AppContext, SingletonEntity};
use crate::settings::{AISettings, InputSettings, TerminalSpacing};
#[derive(
Clone,
Copy,
Debug,
Default,
PartialEq,
Eq,
Serialize,
Deserialize,
schemars::JsonSchema,
settings_value::SettingsValue,
)]
#[schemars(
description = "Controls whether terminal programs can access the system clipboard via OSC 52 escape sequences.",
rename_all = "snake_case"
)]
pub enum Osc52ClipboardAccess {
#[default]
#[schemars(description = "Deny all OSC 52 clipboard access.")]
Deny,
#[schemars(description = "Allow terminal programs to write to the clipboard, but not read.")]
WriteOnly,
#[schemars(description = "Allow terminal programs to both read and write the clipboard.")]
ReadWrite,
}
impl Osc52ClipboardAccess {
pub fn allows_write(self) -> bool {
matches!(self, Self::WriteOnly | Self::ReadWrite)
}
pub fn allows_read(self) -> bool {
matches!(self, Self::ReadWrite)
}
pub fn as_dropdown_label(self) -> &'static str {
match self {
Self::Deny => "Deny",
Self::WriteOnly => "Write only",
Self::ReadWrite => "Read and write",
}
}
}
#[derive(
Clone,
Copy,
Debug,
Default,
PartialEq,
Eq,
Serialize,
Deserialize,
schemars::JsonSchema,
settings_value::SettingsValue,
)]
#[schemars(description = "Terminal block spacing.", rename_all = "snake_case")]
pub enum SpacingMode {
#[default]
#[schemars(description = "Normal")]
Normal,
#[schemars(description = "Compact")]
Compact,
}
impl SpacingMode {
pub fn other_mode(&self) -> SpacingMode {
match *self {
SpacingMode::Normal => SpacingMode::Compact,
SpacingMode::Compact => SpacingMode::Normal,
}
}
}
#[derive(
Clone,
Copy,
Debug,
PartialEq,
Serialize,
Deserialize,
schemars::JsonSchema,
settings_value::SettingsValue,
)]
#[schemars(
description = "How padding is applied in full-screen terminal apps.",
rename_all = "snake_case"
)]
pub enum AltScreenPaddingMode {
#[schemars(description = "Use the same padding as the block list.")]
MatchBlocklist,
#[schemars(description = "Use a custom uniform padding value.")]
Custom { uniform_padding: Pixels },
}
impl Default for AltScreenPaddingMode {
fn default() -> Self {
Self::Custom {
uniform_padding: Pixels::zero(),
}
}
}
impl AltScreenPaddingMode {
pub fn toggled(&self) -> Self {
match self {
Self::MatchBlocklist => Self::Custom {
uniform_padding: Pixels::zero(),
},
Self::Custom { .. } => Self::MatchBlocklist,
}
}
pub fn telemetry_string(&self) -> String {
match self {
Self::MatchBlocklist => "MatchBlocklist",
Self::Custom { .. } => "Custom",
}
.to_string()
}
}
define_settings_group!(TerminalSettings, settings: [
use_audible_bell: UseAudibleBell {
type: bool,
default: false,
supported_platforms: SupportedPlatforms::DESKTOP, /* Audible bell is not supported on web */
sync_to_cloud: SyncToCloud::Never,
private: false,
toml_path: "terminal.use_audible_bell",
description: "Whether to play an audible bell sound on terminal bell events.",
},
spacing_mode: Spacing {
type: SpacingMode,
default: SpacingMode::default(),
supported_platforms: SupportedPlatforms::ALL,
sync_to_cloud: SyncToCloud::Never,
private: false,
toml_path: "appearance.spacing",
description: "Controls the spacing between terminal blocks.",
}
maximum_grid_size: MaximumGridSize {
type: usize,
default: 50_000,
supported_platforms: SupportedPlatforms::ALL,
sync_to_cloud: SyncToCloud::Never,
private: false,
toml_path: "terminal.maximum_grid_size",
description: "The maximum number of rows in the terminal grid.",
},
alt_screen_padding: AltScreenPadding {
type: AltScreenPaddingMode,
default: AltScreenPaddingMode::default(),
supported_platforms: SupportedPlatforms::ALL,
sync_to_cloud: SyncToCloud::Never,
private: false,
toml_path: "appearance.full_screen_apps.alt_screen_padding",
max_table_depth: 0,
description: "Controls padding around full-screen terminal applications.",
},
// This field should not be referenced directly to check zero state block visibility -- use
// the `should_show_zero_state_block()` getter, which also considers global AI enablement.
show_terminal_zero_state_block: ShowTerminalZeroStateBlock {
type: bool,
default: true,
supported_platforms: SupportedPlatforms::ALL,
sync_to_cloud: SyncToCloud::Never,
private: false,
toml_path: "terminal.show_terminal_zero_state_block",
description: "Whether to show the AI zero-state block in new terminal sessions.",
},
osc52_clipboard_access: Osc52ClipboardAccessSetting {
type: Osc52ClipboardAccess,
default: Osc52ClipboardAccess::default(),
supported_platforms: SupportedPlatforms::ALL,
sync_to_cloud: SyncToCloud::Globally(RespectUserSyncSetting::Yes),
private: false,
toml_path: "terminal.osc52_clipboard_access",
description: "Controls whether terminal programs can access the system clipboard via OSC 52 escape sequences. Options: deny (default), write_only, read_write.",
},
// Opt-in toggle for running terminal find on a background thread. Only consulted on
// channels where `FeatureFlag::AsyncFind` is off; channels with the flag on force the
// feature on and hide this toggle. See `is_async_find_enabled` for the composite check.
async_find_enabled: AsyncFindEnabled {
type: bool,
default: false,
supported_platforms: SupportedPlatforms::ALL,
sync_to_cloud: SyncToCloud::Globally(RespectUserSyncSetting::Yes),
private: false,
toml_path: "experimental.async_find_enabled",
description: "Use an improved implementation of find to keep the UI responsive while searching for matches on large outputs.",
},
]);
impl TerminalSettings {
/// Spacing for the terminal blocks.
pub fn terminal_spacing(&self, line_height_ratio: f32, ctx: &AppContext) -> TerminalSpacing {
match *self.spacing_mode {
SpacingMode::Normal => TerminalSpacing::normal(line_height_ratio, ctx),
SpacingMode::Compact => TerminalSpacing::compact(line_height_ratio, ctx),
}
}
/// Whether the terminal zero state block should be shown.
/// Checks both the user setting and the global AI enablement.
pub fn should_show_zero_state_block(&self, ctx: &AppContext) -> bool {
*self.show_terminal_zero_state_block && AISettings::as_ref(ctx).is_any_ai_enabled(ctx)
}
/// Whether asynchronous terminal find should be used. On channels where
/// `FeatureFlag::AsyncFind` is on, the feature is force-enabled (no toggle shown).
/// On other channels, users opt in via the `async_find_enabled` setting.
pub fn is_async_find_enabled(&self) -> bool {
FeatureFlag::AsyncFind.is_enabled() || *self.async_find_enabled
}
/// Spacing for the input box.
pub fn terminal_input_spacing(
&self,
line_height_ratio: f32,
ctx: &AppContext,
) -> TerminalSpacing {
let should_force_normal_spacing =
InputSettings::as_ref(ctx).is_universal_developer_input_enabled(ctx);
if should_force_normal_spacing {
return TerminalSpacing::normal(line_height_ratio, ctx);
}
match *self.spacing_mode {
SpacingMode::Normal => TerminalSpacing::normal(line_height_ratio, ctx),
SpacingMode::Compact => TerminalSpacing::compact(line_height_ratio, ctx),
}
}
}
#[cfg(test)]
#[path = "settings_tests.rs"]
mod tests;