Add settings to configure terminal scroll limit (#8063)

Kirill Bulatov created

Fixes https://github.com/zed-industries/zed/issues/7550
Also set maximum allowed to runnables' terminals.


Release Notes:

- Added settings to configure terminal scroll limit
([7550](https://github.com/zed-industries/zed/issues/7550))

Change summary

assets/settings/default.json             |  5 ++++-
crates/project/src/terminals.rs          |  1 +
crates/terminal/src/terminal.rs          | 17 ++++++++++++++++-
crates/terminal/src/terminal_settings.rs |  9 +++++++++
4 files changed, 30 insertions(+), 2 deletions(-)

Detailed changes

assets/settings/default.json 🔗

@@ -451,7 +451,10 @@
     // Set the terminal's font family. If this option is not included,
     // the terminal will default to matching the buffer's font family.
     // "font_family": "Zed Mono",
-    // ---
+    // Sets the maximum number of lines in the terminal's scrollback buffer.
+    // Default: 10_000, maximum: 100_000 (all bigger values set will be treated as 100_000), 0 disables the scrolling.
+    // Existing terminals will not pick up this change until they are recreated.
+    // "max_scroll_history_lines": 10000,
   },
   // Difference settings for semantic_index
   "semantic_index": {

crates/project/src/terminals.rs 🔗

@@ -57,6 +57,7 @@ impl Project {
             env,
             Some(settings.blinking.clone()),
             settings.alternate_scroll,
+            settings.max_scroll_history_lines,
             window,
             completion_tx,
         )

crates/terminal/src/terminal.rs 🔗

@@ -290,6 +290,10 @@ pub struct SpawnRunnable {
     pub env: HashMap<String, String>,
 }
 
+// https://github.com/alacritty/alacritty/blob/cb3a79dbf6472740daca8440d5166c1d4af5029e/extra/man/alacritty.5.scd?plain=1#L207-L213
+const DEFAULT_SCROLL_HISTORY_LINES: usize = 10_000;
+const MAX_SCROLL_HISTORY_LINES: usize = 100_000;
+
 pub struct TerminalBuilder {
     terminal: Terminal,
     events_rx: UnboundedReceiver<AlacTermEvent>,
@@ -303,6 +307,7 @@ impl TerminalBuilder {
         env: HashMap<String, String>,
         blink_settings: Option<TerminalBlink>,
         alternate_scroll: AlternateScroll,
+        max_scroll_history_lines: Option<usize>,
         window: AnyWindowHandle,
         completion_tx: Sender<()>,
     ) -> Result<TerminalBuilder> {
@@ -335,8 +340,18 @@ impl TerminalBuilder {
         std::env::set_var("LC_ALL", "en_US.UTF-8");
         std::env::set_var("ZED_TERM", "true");
 
+        let scrolling_history = if runnable.is_some() {
+            // Runnables like `cargo build --all` may produce a lot of output, ergo allow maximum scrolling.
+            // After the runnable finishes, we do not allow appending to that terminal, so small runnables output should not
+            // cause excessive memory usage over time.
+            MAX_SCROLL_HISTORY_LINES
+        } else {
+            max_scroll_history_lines
+                .unwrap_or(DEFAULT_SCROLL_HISTORY_LINES)
+                .min(MAX_SCROLL_HISTORY_LINES)
+        };
         let config = Config {
-            scrolling_history: 10000,
+            scrolling_history,
             ..Config::default()
         };
 

crates/terminal/src/terminal_settings.rs 🔗

@@ -35,6 +35,7 @@ pub struct TerminalSettings {
     pub default_width: Pixels,
     pub default_height: Pixels,
     pub detect_venv: VenvSettings,
+    pub max_scroll_history_lines: Option<usize>,
 }
 
 #[derive(Clone, Debug, Default, Serialize, Deserialize, JsonSchema)]
@@ -146,6 +147,14 @@ pub struct TerminalSettingsContent {
     ///
     /// Default: on
     pub detect_venv: Option<VenvSettings>,
+    /// The maximum number of lines to keep in the scrollback history.
+    /// Maximum allowed value is 100_000, all values above that will be treated as 100_000.
+    /// 0 disables the scrolling.
+    /// Existing terminals will not pick up this change until they are recreated.
+    /// See <a href="https://github.com/alacritty/alacritty/blob/cb3a79dbf6472740daca8440d5166c1d4af5029e/extra/man/alacritty.5.scd?plain=1#L207-L213">Alacritty documentation</a> for more information.
+    ///
+    /// Default: 10_000
+    pub max_scroll_history_lines: Option<usize>,
 }
 
 impl settings::Settings for TerminalSettings {