Enable default status line indicators in TUI config (#12015)

Default statusline to something
<img width="307" height="83" alt="Screenshot 2026-02-17 at 18 16 12"
src="https://github.com/user-attachments/assets/44e16153-0aa2-4c1a-9b4a-02e2feb8b7f6"
/>
This commit is contained in:
jif-oai 2026-02-18 09:51:15 +00:00 committed by GitHub
parent 1946a4c48b
commit 0dcf8d9c8f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 32 additions and 41 deletions

View file

@ -1185,7 +1185,7 @@
},
"status_line": {
"default": null,
"description": "Ordered list of status line item identifiers.\n\nWhen set, the TUI renders the selected items as the status line.",
"description": "Ordered list of status line item identifiers.\n\nWhen set, the TUI renders the selected items as the status line. When unset, the TUI defaults to: `model-with-reasoning`, `context-remaining`, and `current-dir`.",
"items": {
"type": "string"
},

View file

@ -56,12 +56,6 @@ pub enum ConfigEdit {
}
pub fn status_line_items_edit(items: &[String]) -> ConfigEdit {
if items.is_empty() {
return ConfigEdit::ClearPath {
segments: vec!["tui".to_string(), "status_line".to_string()],
};
}
let mut array = toml_edit::Array::new();
for item in items {
array.push(item.clone());

View file

@ -258,6 +258,9 @@ pub struct Config {
pub tui_alternate_screen: AltScreenMode,
/// Ordered list of status line item identifiers for the TUI.
///
/// When unset, the TUI defaults to: `model-with-reasoning`, `context-remaining`, and
/// `current-dir`.
pub tui_status_line: Option<Vec<String>>,
/// The directory that should be treated as the current working directory

View file

@ -619,6 +619,8 @@ pub struct Tui {
/// Ordered list of status line item identifiers.
///
/// When set, the TUI renders the selected items as the status line.
/// When unset, the TUI defaults to: `model-with-reasoning`, `context-remaining`, and
/// `current-dir`.
#[serde(default)]
pub status_line: Option<Vec<String>>,
}

View file

@ -2516,11 +2516,7 @@ impl App {
.await;
match apply_result {
Ok(()) => {
self.config.tui_status_line = if ids.is_empty() {
None
} else {
Some(ids.clone())
};
self.config.tui_status_line = Some(ids.clone());
self.chat_widget.setup_status_line(items);
}
Err(err) => {

View file

@ -249,6 +249,8 @@ use strum::IntoEnumIterator;
const USER_SHELL_COMMAND_HELP_TITLE: &str = "Prefix a command with ! to run it locally";
const USER_SHELL_COMMAND_HELP_HINT: &str = "Example: !ls";
const DEFAULT_OPENAI_BASE_URL: &str = "https://api.openai.com/v1";
const DEFAULT_STATUS_LINE_ITEMS: [&str; 3] =
["model-with-reasoning", "context-remaining", "current-dir"];
// Track information about an in-flight exec command.
struct RunningCommand {
command: Vec<String>,
@ -953,12 +955,11 @@ impl ChatWidget {
/// Applies status-line item selection from the setup view to in-memory config.
///
/// An empty selection is normalized to `None` so the status line is fully disabled and the
/// behavior matches an unset `tui.status_line` config value.
/// An empty selection persists as an explicit empty list.
pub(crate) fn setup_status_line(&mut self, items: Vec<StatusLineItem>) {
tracing::info!("status line setup confirmed with items: {items:#?}");
let ids = items.iter().map(ToString::to_string).collect::<Vec<_>>();
self.config.tui_status_line = if ids.is_empty() { None } else { Some(ids) };
self.config.tui_status_line = Some(ids);
self.refresh_status_line();
}
@ -2692,13 +2693,9 @@ impl ChatWidget {
widget
.bottom_pane
.set_steer_enabled(widget.config.features.enabled(Feature::Steer));
widget.bottom_pane.set_status_line_enabled(
widget
.config
.tui_status_line
.as_ref()
.is_some_and(|items| !items.is_empty()),
);
widget
.bottom_pane
.set_status_line_enabled(!widget.configured_status_line_items().is_empty());
widget.bottom_pane.set_collaboration_modes_enabled(
widget.config.features.enabled(Feature::CollaborationModes),
);
@ -2859,13 +2856,9 @@ impl ChatWidget {
widget
.bottom_pane
.set_steer_enabled(widget.config.features.enabled(Feature::Steer));
widget.bottom_pane.set_status_line_enabled(
widget
.config
.tui_status_line
.as_ref()
.is_some_and(|items| !items.is_empty()),
);
widget
.bottom_pane
.set_status_line_enabled(!widget.configured_status_line_items().is_empty());
widget.bottom_pane.set_collaboration_modes_enabled(
widget.config.features.enabled(Feature::CollaborationModes),
);
@ -3015,13 +3008,9 @@ impl ChatWidget {
widget
.bottom_pane
.set_steer_enabled(widget.config.features.enabled(Feature::Steer));
widget.bottom_pane.set_status_line_enabled(
widget
.config
.tui_status_line
.as_ref()
.is_some_and(|items| !items.is_empty()),
);
widget
.bottom_pane
.set_status_line_enabled(!widget.configured_status_line_items().is_empty());
widget.bottom_pane.set_collaboration_modes_enabled(
widget.config.features.enabled(Feature::CollaborationModes),
);
@ -4349,8 +4338,9 @@ impl ChatWidget {
}
fn open_status_line_setup(&mut self) {
let configured_status_line_items = self.configured_status_line_items();
let view = StatusLineSetupView::new(
self.config.tui_status_line.as_deref(),
Some(configured_status_line_items.as_slice()),
self.app_event_tx.clone(),
);
self.bottom_pane.show_view(Box::new(view));
@ -4363,10 +4353,7 @@ impl ChatWidget {
let mut invalid = Vec::new();
let mut invalid_seen = HashSet::new();
let mut items = Vec::new();
let Some(config_items) = self.config.tui_status_line.as_ref() else {
return (items, invalid);
};
for id in config_items {
for id in self.configured_status_line_items() {
match id.parse::<StatusLineItem>() {
Ok(item) => items.push(item),
Err(_) => {
@ -4379,6 +4366,15 @@ impl ChatWidget {
(items, invalid)
}
fn configured_status_line_items(&self) -> Vec<String> {
self.config.tui_status_line.clone().unwrap_or_else(|| {
DEFAULT_STATUS_LINE_ITEMS
.iter()
.map(ToString::to_string)
.collect()
})
}
fn status_line_cwd(&self) -> &Path {
self.current_cwd.as_ref().unwrap_or(&self.config.cwd)
}