aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorOgulcan Celik <ogulcancelik@gmail.com>2026-05-09 23:16:24 +0300
committerOgulcan Celik <ogulcancelik@gmail.com>2026-05-09 23:16:24 +0300
commit9f210e973834700d14c6c0283ed750ed5b038e8b (patch)
treecd8c75755c59fdc47bf71ca6dc34e49ab0258ae6 /src
parent3a9888cd564dc45d23a7bdd0dba29a6ff1ef48a1 (diff)
chore: enable clippy linting
Diffstat (limited to 'src')
-rw-r--r--src/api/mod.rs14
-rw-r--r--src/app/input/mod.rs21
-rw-r--r--src/app/input/modal.rs12
-rw-r--r--src/app/input/settings.rs24
-rw-r--r--src/app/mod.rs2
-rw-r--r--src/app/runtime.rs9
-rw-r--r--src/app/state.rs9
-rw-r--r--src/cli.rs7
-rw-r--r--src/client/mod.rs10
-rw-r--r--src/config/model.rs8
-rw-r--r--src/ghostty/mod.rs8
-rw-r--r--src/main.rs97
-rw-r--r--src/pane.rs2
-rw-r--r--src/pane/state.rs4
-rw-r--r--src/pane/terminal.rs4
-rw-r--r--src/raw_input.rs17
-rw-r--r--src/server/client_transport.rs3
-rw-r--r--src/server/headless.rs4
-rw-r--r--src/ui/mobile.rs6
-rw-r--r--src/ui/panes.rs76
-rw-r--r--src/ui/sidebar.rs4
-rw-r--r--src/ui/tabs.rs8
22 files changed, 167 insertions, 182 deletions
diff --git a/src/api/mod.rs b/src/api/mod.rs
index f256e4a8..318a0ee7 100644
--- a/src/api/mod.rs
+++ b/src/api/mod.rs
@@ -368,7 +368,7 @@ fn output_match_read_source(
) -> crate::api::schema::ReadSource {
match source {
crate::api::schema::ReadSource::Recent => crate::api::schema::ReadSource::RecentUnwrapped,
- other => other.clone(),
+ other => *other,
}
}
@@ -741,14 +741,12 @@ impl ActiveSubscription {
let probe = pane_read(
format!("{request_id}:sub:{index}:probe"),
&pane_id,
- source.clone(),
+ source,
lines,
strip_ansi,
api_tx,
);
- if let Err(error) = probe {
- return Err(error);
- }
+ probe?;
Ok(Self::OutputMatched(ActiveOutputMatchedSubscription {
pane_id,
@@ -765,11 +763,7 @@ impl ActiveSubscription {
pane_id,
agent_status,
} => {
- let probe =
- match pane_get(format!("{request_id}:sub:{index}:probe"), &pane_id, api_tx) {
- Ok(probe) => probe,
- Err(error) => return Err(error),
- };
+ let probe = pane_get(format!("{request_id}:sub:{index}:probe"), &pane_id, api_tx)?;
Ok(Self::AgentStatusChanged(
ActiveAgentStatusChangedSubscription {
diff --git a/src/app/input/mod.rs b/src/app/input/mod.rs
index 56ad09a9..aa607c78 100644
--- a/src/app/input/mod.rs
+++ b/src/app/input/mod.rs
@@ -92,10 +92,13 @@ impl App {
pub(crate) fn handle_onboarding_key(&mut self, key: KeyEvent) {
match key.code {
KeyCode::Right | KeyCode::Char('l') => self.open_settings_from_onboarding(),
- _ => match modal_action_from_key(&key, ONBOARDING_WELCOME_ACTIONS) {
- Some(ModalAction::Continue) => self.open_settings_from_onboarding(),
- _ => {}
- },
+ _ => {
+ if let Some(ModalAction::Continue) =
+ modal_action_from_key(&key, ONBOARDING_WELCOME_ACTIONS)
+ {
+ self.open_settings_from_onboarding();
+ }
+ }
}
}
@@ -116,10 +119,12 @@ impl App {
notes.scroll = max_scroll;
}
}
- _ => match modal_action_from_key(&key, RELEASE_NOTES_ACTIONS) {
- Some(ModalAction::Close) => self.dismiss_release_notes(),
- _ => {}
- },
+ _ => {
+ if let Some(ModalAction::Close) = modal_action_from_key(&key, RELEASE_NOTES_ACTIONS)
+ {
+ self.dismiss_release_notes();
+ }
+ }
}
}
diff --git a/src/app/input/modal.rs b/src/app/input/modal.rs
index 998bb69b..a76576bf 100644
--- a/src/app/input/modal.rs
+++ b/src/app/input/modal.rs
@@ -261,13 +261,11 @@ pub(super) fn apply_rename_action(state: &mut AppState, action: ModalAction) {
state.name_input.trim().to_string()
};
match state.mode {
- Mode::RenameWorkspace if !state.workspaces.is_empty() => {
- if !new_name.is_empty() {
- let workspace_id = state.workspaces[state.selected].id.clone();
- state.workspaces[state.selected].set_custom_name(new_name);
- crate::logging::workspace_renamed(&workspace_id);
- state.mark_session_dirty();
- }
+ Mode::RenameWorkspace if !state.workspaces.is_empty() && !new_name.is_empty() => {
+ let workspace_id = state.workspaces[state.selected].id.clone();
+ state.workspaces[state.selected].set_custom_name(new_name);
+ crate::logging::workspace_renamed(&workspace_id);
+ state.mark_session_dirty();
}
Mode::RenameTab if state.creating_new_tab => {
state.request_new_tab = true;
diff --git a/src/app/input/settings.rs b/src/app/input/settings.rs
index 2c92bc63..67144a28 100644
--- a/src/app/input/settings.rs
+++ b/src/app/input/settings.rs
@@ -10,6 +10,8 @@ use crate::{
};
#[derive(Debug, Clone, PartialEq, Eq)]
+// The shared `Save` verb is semantic: these actions persist settings.
+#[allow(clippy::enum_variant_names)]
pub(super) enum SettingsAction {
SaveTheme(String),
SaveSound(bool),
@@ -135,10 +137,13 @@ pub(super) fn update_settings_state(state: &mut AppState, key: KeyEvent) -> Opti
state.settings.section = SettingsSection::Theme;
state.settings.list.selected = current_theme_index(&state.theme_name);
}
- _ => match super::modal::modal_action_from_key(&key, super::modal::SETTINGS_ACTIONS) {
- Some(super::modal::ModalAction::Close) => cancel_settings(state),
- _ => {}
- },
+ _ => {
+ if let Some(super::modal::ModalAction::Close) =
+ super::modal::modal_action_from_key(&key, super::modal::SETTINGS_ACTIONS)
+ {
+ cancel_settings(state);
+ }
+ }
},
SettingsSection::Toast => match key.code {
KeyCode::Up | KeyCode::Char('k') => state.settings.list.move_prev(),
@@ -155,10 +160,13 @@ pub(super) fn update_settings_state(state: &mut AppState, key: KeyEvent) -> Opti
state.settings.section = SettingsSection::Theme;
state.settings.list.selected = current_theme_index(&state.theme_name);
}
- _ => match super::modal::modal_action_from_key(&key, super::modal::SETTINGS_ACTIONS) {
- Some(super::modal::ModalAction::Close) => cancel_settings(state),
- _ => {}
- },
+ _ => {
+ if let Some(super::modal::ModalAction::Close) =
+ super::modal::modal_action_from_key(&key, super::modal::SETTINGS_ACTIONS)
+ {
+ cancel_settings(state);
+ }
+ }
},
}
diff --git a/src/app/mod.rs b/src/app/mod.rs
index 1ea315cf..60e38f5b 100644
--- a/src/app/mod.rs
+++ b/src/app/mod.rs
@@ -351,7 +351,7 @@ impl App {
toast_config: config.ui.toast.clone(),
keybinds: config.keybinds(),
spinner_tick: 0,
- palette: resolve_palette(&config),
+ palette: resolve_palette(config),
theme_name: config
.theme
.name
diff --git a/src/app/runtime.rs b/src/app/runtime.rs
index a4e93d3b..3c67c306 100644
--- a/src/app/runtime.rs
+++ b/src/app/runtime.rs
@@ -229,10 +229,11 @@ impl App {
}
pub(crate) fn start_git_status_refresh_if_due(&mut self, now: Instant) {
- if !self
- .git_refresh_deadline()
- .is_some_and(|deadline| now >= deadline)
- {
+ let Some(deadline) = self.git_refresh_deadline() else {
+ return;
+ };
+
+ if now < deadline {
return;
}
diff --git a/src/app/state.rs b/src/app/state.rs
index f7c4daa1..134d86bd 100644
--- a/src/app/state.rs
+++ b/src/app/state.rs
@@ -391,18 +391,13 @@ pub enum Mode {
KeybindHelp,
}
-#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
+#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
pub enum AgentPanelScope {
CurrentWorkspace,
+ #[default]
AllWorkspaces,
}
-impl Default for AgentPanelScope {
- fn default() -> Self {
- Self::AllWorkspaces
- }
-}
-
// ---------------------------------------------------------------------------
// Settings UI state
// ---------------------------------------------------------------------------
diff --git a/src/cli.rs b/src/cli.rs
index 1d3c29e2..a5ba8b1a 100644
--- a/src/cli.rs
+++ b/src/cli.rs
@@ -202,7 +202,7 @@ fn compatibility_label(protocol: Option<u32>) -> &'static str {
fn restart_needed_label(server: &ServerRuntimeStatus) -> &'static str {
match server {
ServerRuntimeStatus::Running { version, .. } => match version.as_deref() {
- Some(version) if version == env!("CARGO_PKG_VERSION") => "no",
+ Some(env!("CARGO_PKG_VERSION")) => "no",
Some(_) => "yes",
None => "unknown",
},
@@ -1391,10 +1391,7 @@ fn parse_session_name_and_json(args: &[String], usage: &str) -> Result<(String,
}
fn print_session_table(sessions: &[crate::session::SessionInfo]) {
- println!(
- "{:<20} {:<8} {:<48} {}",
- "name", "status", "directory", "socket"
- );
+ println!("{:<20} {:<8} {:<48} socket", "name", "status", "directory");
for session in sessions {
println!(
"{:<20} {:<8} {:<48} {}",
diff --git a/src/client/mod.rs b/src/client/mod.rs
index 1e0beded..475a079f 100644
--- a/src/client/mod.rs
+++ b/src/client/mod.rs
@@ -231,9 +231,8 @@ fn do_handshake(
rows,
requested_encoding,
};
- protocol::write_message(stream, &hello).map_err(|e| {
- ClientError::ConnectionFailed(io::Error::new(io::ErrorKind::Other, e.to_string()))
- })?;
+ protocol::write_message(stream, &hello)
+ .map_err(|e| ClientError::ConnectionFailed(io::Error::other(e.to_string())))?;
// Read Welcome.
stream
@@ -339,7 +338,7 @@ pub fn run_client() -> io::Result<()> {
let rt = tokio::runtime::Builder::new_current_thread()
.enable_all()
.build()
- .map_err(|e| io::Error::new(io::ErrorKind::Other, e))?;
+ .map_err(io::Error::other)?;
let should_quit = Arc::new(AtomicBool::new(false));
@@ -577,8 +576,7 @@ fn server_reader_thread(
/// Writes a message to the server stream (blocking).
fn write_to_server(stream: &mut UnixStream, msg: &ClientMessage) -> io::Result<()> {
- protocol::write_message(stream, msg)
- .map_err(|e| io::Error::new(io::ErrorKind::Other, e.to_string()))
+ protocol::write_message(stream, msg).map_err(|e| io::Error::other(e.to_string()))
}
// ---------------------------------------------------------------------------
diff --git a/src/config/model.rs b/src/config/model.rs
index 7e6c7382..a11192fb 100644
--- a/src/config/model.rs
+++ b/src/config/model.rs
@@ -209,11 +209,11 @@ impl<'de> Deserialize<'de> for ToastConfig {
}
let raw = RawToastConfig::deserialize(deserializer)?;
- let delivery = raw.delivery.unwrap_or_else(|| match raw.enabled {
+ let legacy_delivery = match raw.enabled {
Some(true) => ToastDelivery::Herdr,
- Some(false) => ToastDelivery::Off,
- None => ToastDelivery::Off,
- });
+ Some(false) | None => ToastDelivery::Off,
+ };
+ let delivery = raw.delivery.unwrap_or(legacy_delivery);
Ok(Self { delivery })
}
}
diff --git a/src/ghostty/mod.rs b/src/ghostty/mod.rs
index 27fcb6f9..02bae73f 100644
--- a/src/ghostty/mod.rs
+++ b/src/ghostty/mod.rs
@@ -234,8 +234,10 @@ impl CellWide {
}
}
+type WritePtyCallback = dyn FnMut(&[u8]) + Send;
+
struct WritePtyCallbackState {
- callback: Box<dyn FnMut(&[u8]) + Send>,
+ callback: Box<WritePtyCallback>,
}
unsafe extern "C" fn write_pty_trampoline(
@@ -1469,10 +1471,10 @@ mod tests {
);
render_state.update(&terminal).unwrap();
- assert_eq!(render_state.cursor_visible().unwrap(), true);
+ assert!(render_state.cursor_visible().unwrap());
terminal.write(b"\x1b[?25l");
render_state.update(&terminal).unwrap();
- assert_eq!(render_state.cursor_visible().unwrap(), false);
+ assert!(!render_state.cursor_visible().unwrap());
terminal.write(b"\x1b[?1049h\x1b[HALT");
assert_eq!(terminal.active_screen().unwrap(), ActiveScreen::Alternate);
diff --git a/src/main.rs b/src/main.rs
index ee2c30e4..c35a4084 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -243,57 +243,56 @@ fn main() -> io::Result<()> {
println!(" herdr integration <subcommand> ...");
println!();
println!("Common commands:");
- println!(
- " {:<32} {}",
- "herdr", "Launch or attach to the persistent session"
- );
- println!(
- " {:<32} {}",
- "herdr status [server|client]", "Show local client and running server status"
- );
- println!(
- " {:<32} {}",
- "herdr update", "Download and install the latest version"
- );
- println!(
- " {:<32} {}",
- "herdr server stop", "Stop the running server via the API socket"
- );
- println!(
- " {:<32} {}",
- "herdr server reload-config", "Reload config.toml in the running server"
- );
- println!(
- " {:<32} {}",
- "herdr workspace <subcommand>", "Workspace helpers over the socket API"
- );
- println!(
- " {:<32} {}",
- "herdr tab <subcommand>", "Tab helpers over the socket API"
- );
- println!(
- " {:<32} {}",
- "herdr pane <subcommand>", "Pane control helpers over the socket API"
- );
- println!(
- " {:<32} {}",
- "herdr wait <subcommand>", "Blocking wait helpers over the socket API"
- );
- println!(
- " {:<32} {}",
- "herdr session <subcommand>", "Manage named persistent sessions"
- );
- println!(
- " {:<32} {}",
- "herdr integration <subcommand>", "Manage built-in agent integrations"
- );
+ for (command, description) in [
+ ("herdr", "Launch or attach to the persistent session"),
+ (
+ "herdr status [server|client]",
+ "Show local client and running server status",
+ ),
+ ("herdr update", "Download and install the latest version"),
+ (
+ "herdr server stop",
+ "Stop the running server via the API socket",
+ ),
+ (
+ "herdr server reload-config",
+ "Reload config.toml in the running server",
+ ),
+ (
+ "herdr workspace <subcommand>",
+ "Workspace helpers over the socket API",
+ ),
+ ("herdr tab <subcommand>", "Tab helpers over the socket API"),
+ (
+ "herdr pane <subcommand>",
+ "Pane control helpers over the socket API",
+ ),
+ (
+ "herdr wait <subcommand>",
+ "Blocking wait helpers over the socket API",
+ ),
+ (
+ "herdr session <subcommand>",
+ "Manage named persistent sessions",
+ ),
+ (
+ "herdr integration <subcommand>",
+ "Manage built-in agent integrations",
+ ),
+ ] {
+ println!(" {command:<32} {description}");
+ }
println!();
println!("Advanced commands:");
- println!(" {:<32} {}", "herdr server", "Run as headless server");
- println!(
- " {:<32} {}",
- "herdr client", "Connect to a running server as a thin client"
- );
+ for (command, description) in [
+ ("herdr server", "Run as headless server"),
+ (
+ "herdr client",
+ "Connect to a running server as a thin client",
+ ),
+ ] {
+ println!(" {command:<32} {description}");
+ }
println!();
println!("Options:");
println!(" --no-session Run monolithically (no server/client, escape hatch)");
diff --git a/src/pane.rs b/src/pane.rs
index c741c04d..7d4ec729 100644
--- a/src/pane.rs
+++ b/src/pane.rs
@@ -602,6 +602,8 @@ impl PaneRuntime {
}
let pid = child_pid.load(Ordering::Acquire);
+ // Keep the terminal restore side effect separate from render notification state.
+ #[allow(clippy::collapsible_if)]
if pid > 0 && terminal.maybe_restore_host_terminal_theme(pane_id, pid) {
if !render_dirty.swap(true, Ordering::AcqRel) {
render_notify.notify_one();
diff --git a/src/pane/state.rs b/src/pane/state.rs
index aac80920..590f2025 100644
--- a/src/pane/state.rs
+++ b/src/pane/state.rs
@@ -104,9 +104,7 @@ impl PaneState {
source: &str,
agent_label: &str,
) -> Option<EffectiveStateChange> {
- let Some(current_agent_label) = self.effective_agent_label() else {
- return None;
- };
+ let current_agent_label = self.effective_agent_label()?;
if current_agent_label != agent_label {
return None;
}
diff --git a/src/pane/terminal.rs b/src/pane/terminal.rs
index 80f83915..ad040ba2 100644
--- a/src/pane/terminal.rs
+++ b/src/pane/terminal.rs
@@ -712,10 +712,12 @@ impl GhosttyPaneTerminal {
}
}
+type VisibleHyperlinks = Vec<((u16, u16), String, String)>;
+
fn ghostty_visible_hyperlinks(
core: &mut GhosttyPaneCore,
area: Rect,
-) -> Result<Vec<((u16, u16), String, String)>, crate::ghostty::Error> {
+) -> Result<VisibleHyperlinks, crate::ghostty::Error> {
let GhosttyPaneCore {
terminal,
render_state,
diff --git a/src/raw_input.rs b/src/raw_input.rs
index 6640ec29..0cf9d84b 100644
--- a/src/raw_input.rs
+++ b/src/raw_input.rs
@@ -39,10 +39,7 @@ pub fn parse_raw_input_bytes_with_ranges(data: &[u8]) -> Vec<RawInputEventWithRa
let mut events = Vec::new();
let mut offset = 0usize;
- loop {
- let Some((event, consumed)) = extract_one_event(&buffer) else {
- break;
- };
+ while let Some((event, consumed)) = extract_one_event(&buffer) {
buffer.drain(..consumed);
events.push(RawInputEventWithRange {
event,
@@ -85,10 +82,7 @@ pub fn parse_raw_input_bytes_sync(data: &[u8]) -> Vec<RawInputEvent> {
let mut buffer = data.to_vec();
let mut events = Vec::new();
- loop {
- let Some((event, consumed)) = extract_one_event(&buffer) else {
- break;
- };
+ while let Some((event, consumed)) = extract_one_event(&buffer) {
buffer.drain(..consumed);
events.push(event);
}
@@ -175,10 +169,7 @@ fn drain_buffer(buffer: &mut Vec<u8>, tx: &mpsc::Sender<RawInputEvent>) {
pub(crate) fn drain_complete_input_bytes(buffer: &mut Vec<u8>) -> Vec<Vec<u8>> {
let mut chunks = Vec::new();
- loop {
- let Some((_event, consumed)) = extract_one_event(buffer) else {
- break;
- };
+ while let Some((_event, consumed)) = extract_one_event(buffer) {
chunks.push(buffer[..consumed].to_vec());
buffer.drain(..consumed);
}
@@ -244,7 +235,7 @@ fn stdin_read_ready<R: AsRawFd>(_reader: &R, _timeout_ms: i32) -> Option<bool> {
#[cfg(unix)]
{
let fd = _reader.as_raw_fd();
- return poll_read_ready(fd, _timeout_ms);
+ poll_read_ready(fd, _timeout_ms)
}
}
diff --git a/src/server/client_transport.rs b/src/server/client_transport.rs
index 9f5183d9..ec1adf0b 100644
--- a/src/server/client_transport.rs
+++ b/src/server/client_transport.rs
@@ -158,8 +158,7 @@ pub(crate) fn handle_client_handshake(
encoding: render_encoding,
error: None,
};
- protocol::write_message(&mut stream, &welcome)
- .map_err(|e| io::Error::new(io::ErrorKind::Other, e.to_string()))?;
+ protocol::write_message(&mut stream, &welcome).map_err(|e| io::Error::other(e.to_string()))?;
// Clear read timeout for normal operation.
stream.set_read_timeout(None)?;
diff --git a/src/server/headless.rs b/src/server/headless.rs
index ffcb6bbb..7bd8638a 100644
--- a/src/server/headless.rs
+++ b/src/server/headless.rs
@@ -612,7 +612,7 @@ impl HeadlessServer {
crate::raw_input::RawInputEvent::OuterFocusLost => Some(false),
_ => None,
})
- .last();
+ .next_back();
let Some(next_focus) = next_focus else {
return;
@@ -1708,7 +1708,7 @@ pub fn run_server() -> io::Result<()> {
let rt = tokio::runtime::Builder::new_multi_thread()
.enable_all()
.build()
- .map_err(|e| io::Error::new(io::ErrorKind::Other, e))?;
+ .map_err(io::Error::other)?;
let result = rt.block_on(async {
// Create the App (with AppState, event channels, etc.).
diff --git a/src/ui/mobile.rs b/src/ui/mobile.rs
index 50cbed0c..41f29f89 100644
--- a/src/ui/mobile.rs
+++ b/src/ui/mobile.rs
@@ -745,11 +745,7 @@ fn render_left_scrollbar(
.max(1)
.min(track.height as usize) as u16;
let travel = track.height.saturating_sub(thumb_len);
- let thumb_top = if max_scroll == 0 {
- track.y
- } else {
- track.y + ((travel as usize * scroll.min(max_scroll)) / max_scroll) as u16
- };
+ let thumb_top = track.y + ((travel as usize * scroll.min(max_scroll)) / max_scroll) as u16;
for y in track.y..track.y + track.height {
let is_thumb = y >= thumb_top && y < thumb_top + thumb_len;
diff --git a/src/ui/panes.rs b/src/ui/panes.rs
index 82be8bf1..c4ba0c54 100644
--- a/src/ui/panes.rs
+++ b/src/ui/panes.rs
@@ -219,6 +219,44 @@ fn render_selection_highlight(
}
}
+fn render_empty(app: &AppState, frame: &mut Frame, area: Rect) {
+ let p = &app.palette;
+ let lines = vec![
+ Line::from(""),
+ Line::from(""),
+ Line::from(Span::styled(
+ " No workspaces yet",
+ Style::default().fg(p.overlay0),
+ )),
+ Line::from(""),
+ Line::from(Span::styled(
+ " A workspace is one project context.",
+ Style::default().fg(p.overlay1),
+ )),
+ Line::from(Span::styled(
+ " Its root pane (top-left) sets the default repo or folder name.",
+ Style::default().fg(p.overlay1),
+ )),
+ Line::from(""),
+ Line::from(vec![
+ Span::styled(" Press ", Style::default().fg(p.overlay0)),
+ Span::styled(
+ app.keybinds.new_workspace_label.to_string(),
+ Style::default().fg(p.accent).add_modifier(Modifier::BOLD),
+ ),
+ Span::styled(" to create one", Style::default().fg(p.overlay0)),
+ ]),
+ ];
+ frame.render_widget(
+ Paragraph::new(lines).block(
+ Block::default()
+ .borders(Borders::ALL)
+ .border_style(Style::default().fg(p.surface_dim)),
+ ),
+ area,
+ );
+}
+
#[cfg(test)]
mod tests {
use super::*;
@@ -315,41 +353,3 @@ mod tests {
assert_eq!(info.inner_rect, Rect::new(10, 3, 39, 8));
}
}
-
-fn render_empty(app: &AppState, frame: &mut Frame, area: Rect) {
- let p = &app.palette;
- let lines = vec![
- Line::from(""),
- Line::from(""),
- Line::from(Span::styled(
- " No workspaces yet",
- Style::default().fg(p.overlay0),
- )),
- Line::from(""),
- Line::from(Span::styled(
- " A workspace is one project context.",
- Style::default().fg(p.overlay1),
- )),
- Line::from(Span::styled(
- " Its root pane (top-left) sets the default repo or folder name.",
- Style::default().fg(p.overlay1),
- )),
- Line::from(""),
- Line::from(vec![
- Span::styled(" Press ", Style::default().fg(p.overlay0)),
- Span::styled(
- format!("{}", app.keybinds.new_workspace_label),
- Style::default().fg(p.accent).add_modifier(Modifier::BOLD),
- ),
- Span::styled(" to create one", Style::default().fg(p.overlay0)),
- ]),
- ];
- frame.render_widget(
- Paragraph::new(lines).block(
- Block::default()
- .borders(Borders::ALL)
- .border_style(Style::default().fg(p.surface_dim)),
- ),
- area,
- );
-}
diff --git a/src/ui/sidebar.rs b/src/ui/sidebar.rs
index 04a3acd9..83ceebe0 100644
--- a/src/ui/sidebar.rs
+++ b/src/ui/sidebar.rs
@@ -32,7 +32,7 @@ fn sidebar_section_heights(total_h: u16, split_ratio: f32) -> (u16, u16) {
}
if total_h < 6 {
- let ws_h = (total_h + 1) / 2;
+ let ws_h = total_h.div_ceil(2);
return (ws_h, total_h.saturating_sub(ws_h));
}
@@ -385,7 +385,7 @@ pub(crate) fn collapsed_sidebar_sections(area: Rect) -> (Rect, Option<u16>, Rect
}
let total_h = content.height as usize;
- let ws_h = (total_h + 1) / 2;
+ let ws_h = total_h.div_ceil(2);
let detail_h = total_h.saturating_sub(ws_h + 1);
if ws_h == 0 || detail_h == 0 {
return (content, None, Rect::default());
diff --git a/src/ui/tabs.rs b/src/ui/tabs.rs
index 400ee65f..a6ce0e68 100644
--- a/src/ui/tabs.rs
+++ b/src/ui/tabs.rs
@@ -33,14 +33,14 @@ fn layout_tab_hit_areas(ws: &crate::workspace::Workspace, area: Rect, scroll: us
let mut x = area.x;
let right = area.x + area.width;
- for idx in scroll..ws.tabs.len() {
+ for (idx, rect) in rects.iter_mut().enumerate().skip(scroll) {
if x >= right {
break;
}
let desired = tab_width(&ws.tabs[idx]);
let remaining = right.saturating_sub(x);
let width = desired.min(remaining).max(1);
- rects[idx] = Rect::new(x, area.y, width, 1);
+ *rect = Rect::new(x, area.y, width, 1);
x = x.saturating_add(width + 1);
}
rects
@@ -178,14 +178,14 @@ fn tab_drop_indicator_x(
ws: &crate::workspace::Workspace,
insert_idx: usize,
) -> Option<u16> {
- let visible_tabs = app
+ let mut visible_tabs = app
.view
.tab_hit_areas
.iter()
.enumerate()
.filter(|(_, rect)| rect.width > 0);
let first_visible = visible_tabs.clone().next()?;
- let last_visible = visible_tabs.last().unwrap_or(first_visible);
+ let last_visible = visible_tabs.next_back().unwrap_or(first_visible);
if insert_idx == 0 {
return Some(if first_visible.0 == 0 {