From 003488c333e66ab2d6aa73b02ff318a2a23c72a5 Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Mon, 12 Oct 2026 01:27:44 +0000 Subject: [PATCH 1/3] I have updated the Palette by adding descriptive placeholder text to the TUI search inputs. Specifically, I added these placeholders to empty input fields in the Branch, Finder, and various search components. I also adjusted the padding calculations to preserve the alignment of the right-side match counts. These changes improve accessibility by providing clear visual cues for what you can search for when the input fields are completely empty. Let me know if you need any further adjustments! --- .Jules/palette.md | 6 +- src/component/branch/view.rs | 21 +++-- src/component/branch/view.rs.orig | 136 ++++++++++++++++++++++++++++ src/component/finder/view.rs | 20 +++-- src/component/finder/view.rs.orig | 99 +++++++++++++++++++++ src/component/grep/view.rs | 14 +-- src/component/grep/view.rs.orig | 143 ++++++++++++++++++++++++++++++ 7 files changed, 418 insertions(+), 21 deletions(-) create mode 100644 src/component/branch/view.rs.orig create mode 100644 src/component/finder/view.rs.orig create mode 100644 src/component/grep/view.rs.orig diff --git a/.Jules/palette.md b/.Jules/palette.md index 337e2dd..fddf4ff 100644 --- a/.Jules/palette.md +++ b/.Jules/palette.md @@ -4,7 +4,7 @@ **Action:** Update `notice_line` in `src/shell/status_bar.rs` to include a visual indicator (e.g., prefix with an info/warning symbol like `i` or `!`, or Nerd Font icon if supported, but simpler is safer if we want it to work without Nerd Fonts. Actually, let's use standard unicode characters like `✓` for success/info and `⚠` for error). -## $(date +%Y-%m-%d) - Edit Mode Notice Consistency +## 2026-10-12 - Edit Mode Notice Consistency **Learning:** Edit mode specific notices (`EditState.notice`) previously bypassed the standard `notice_line` styling, resulting in warnings (unsaved changes) and errors (save failed) lacking visual distinction (color and icon) from normal hints. **Action:** Always ensure nested or state-specific notice mechanisms reuse the top-level standard styling to provide a consistent visual language across all modes. @@ -19,3 +19,7 @@ ## 2024-11-21 - Centering Empty States for TUI Lists **Learning:** Rendering an empty list message (like "no matches") in the top-left corner of the list area can look unbalanced, especially when rendering lists in large UI components or side panes. **Action:** Always center the text for empty state indicators in lists visually (using `.alignment(ratatui::layout::Alignment::Center)`) and vertically (using `center_text(msg, area.height)`) when using `Paragraph` to render empty states in a list widget. + +## 2026-10-12 - Input Placeholder Accessibility +**Learning:** In TUI interfaces, search/filter input fields with empty queries can appear as completely blank spaces, providing poor visual guidance to the user. +**Action:** Always add descriptive placeholder text styled distinctively (e.g., using `Color::DarkGray`) when the query is empty. Ensure to account for the width of the placeholder text when calculating padding for alignment to maintain balanced layouts. diff --git a/src/component/branch/view.rs b/src/component/branch/view.rs index d0c67ed..16ac34b 100644 --- a/src/component/branch/view.rs +++ b/src/component/branch/view.rs @@ -28,15 +28,22 @@ pub(crate) fn draw_branch(frame: &mut Frame, state: &mut BranchState, area: Rect fn draw_input(frame: &mut Frame, state: &BranchState, area: Rect) { let query_text = format!("> {}", state.query); let count = format!("{}/{}", state.matches.len(), state.total()); - let used = query_text.chars().count() + 1 + count.chars().count(); - let pad = (area.width as usize).saturating_sub(used); - let line = Line::from(vec![ + let mut spans = vec![ Span::raw(query_text), Span::styled(" ", Style::default().add_modifier(Modifier::REVERSED)), - Span::raw(" ".repeat(pad)), - Span::styled(count, Style::default().fg(Color::DarkGray)), - ]); - frame.render_widget(Paragraph::new(line), area); + ]; + + let mut used = state.query.chars().count() + 3 + count.chars().count(); + if state.query.is_empty() { + let placeholder = "filter branches..."; + spans.push(Span::styled(placeholder, Style::default().fg(Color::DarkGray))); + used += placeholder.chars().count(); + } + + let pad = (area.width as usize).saturating_sub(used); + spans.push(Span::raw(" ".repeat(pad))); + spans.push(Span::styled(count, Style::default().fg(Color::DarkGray))); + frame.render_widget(Paragraph::new(Line::from(spans)), area); } fn draw_list(frame: &mut Frame, state: &mut BranchState, area: Rect) { diff --git a/src/component/branch/view.rs.orig b/src/component/branch/view.rs.orig new file mode 100644 index 0000000..d0c67ed --- /dev/null +++ b/src/component/branch/view.rs.orig @@ -0,0 +1,136 @@ +use ratatui::Frame; +use ratatui::layout::{Constraint, Layout, Rect}; +use ratatui::style::{Color, Modifier, Style}; +use ratatui::text::{Line, Span}; +use ratatui::widgets::{Block, Borders, Clear, HighlightSpacing, List, ListItem, Paragraph}; + +use crate::component::branch::{BranchRow, BranchState}; + +use crate::widget::{center_text, centered_rect}; + +pub(crate) fn draw_branch(frame: &mut Frame, state: &mut BranchState, area: Rect) { + let popup = centered_rect(70, 60, area); + frame.render_widget(Clear, popup); + + let block = Block::default() + .borders(Borders::ALL) + .border_style(Style::default().fg(Color::Cyan)) + .title("branch (b)"); + let inner = block.inner(popup); + frame.render_widget(block, popup); + + let [input_area, list_area] = + Layout::vertical([Constraint::Length(1), Constraint::Min(0)]).areas(inner); + draw_input(frame, state, input_area); + draw_list(frame, state, list_area); +} + +fn draw_input(frame: &mut Frame, state: &BranchState, area: Rect) { + let query_text = format!("> {}", state.query); + let count = format!("{}/{}", state.matches.len(), state.total()); + let used = query_text.chars().count() + 1 + count.chars().count(); + let pad = (area.width as usize).saturating_sub(used); + let line = Line::from(vec![ + Span::raw(query_text), + Span::styled(" ", Style::default().add_modifier(Modifier::REVERSED)), + Span::raw(" ".repeat(pad)), + Span::styled(count, Style::default().fg(Color::DarkGray)), + ]); + frame.render_widget(Paragraph::new(line), area); +} + +fn draw_list(frame: &mut Frame, state: &mut BranchState, area: Rect) { + if state.matches.is_empty() { + let p = Paragraph::new(center_text("no matches", area.height)) + .alignment(ratatui::layout::Alignment::Center) + .style(Style::default().fg(Color::DarkGray)); + frame.render_widget(p, area); + return; + } + + let items: Vec = state + .matches + .iter() + .map(|m| { + let spans = state + .row(m.row) + .map(|row| branch_line(row, &m.positions)) + .unwrap_or_default(); + ListItem::new(Line::from(spans)) + }) + .collect(); + let list = List::new(items) + .highlight_style( + Style::default() + .bg(Color::DarkGray) + .add_modifier(Modifier::BOLD), + ) + .highlight_symbol("▎") + .highlight_spacing(HighlightSpacing::Always); + let selected = (!state.matches.is_empty()).then_some(state.selected); + state.list_state.select(selected); + frame.render_stateful_widget(list, area, &mut state.list_state); +} + +// 1行 = マーカー(現在ブランチ) + local/remote タグ + ブランチ名 (マッチ char をハイライト) + +// upstream + 相対日時 + 件名。名前列だけ char 単位で分割するのは finder_panel の +// highlight_finder_match と同じ理由 (positions が char インデックスのため) +const NAME_COL_WIDTH: usize = 24; + +fn branch_line(row: &BranchRow, positions: &[usize]) -> Vec> { + let marker = if row.current { "* " } else { " " }; + let tag = if row.entry.remote { "remote" } else { "local " }; + let tag_style = if row.entry.remote { + Style::default().fg(Color::DarkGray) + } else { + Style::default().fg(Color::Green) + }; + let upstream = row.entry.upstream.as_deref().unwrap_or("-"); + + let mut spans = vec![ + Span::raw(marker.to_string()), + Span::styled(format!("{tag} "), tag_style), + ]; + spans.extend(highlight_name(row, positions)); + let name_len = row.entry.name.chars().count(); + spans.push(Span::raw( + " ".repeat(NAME_COL_WIDTH.saturating_sub(name_len)), + )); + spans.push(Span::styled( + format!(" {upstream:<20}"), + Style::default().fg(Color::DarkGray), + )); + spans.push(Span::styled( + format!(" {:<12}", row.entry.relative_time), + Style::default().fg(Color::DarkGray), + )); + spans.push(Span::raw(format!(" {}", row.entry.subject))); + spans +} + +fn highlight_name(row: &BranchRow, positions: &[usize]) -> Vec> { + let base_style = if row.current { + Style::default() + .fg(Color::Yellow) + .add_modifier(Modifier::BOLD) + } else if row.entry.remote { + Style::default().fg(Color::DarkGray) + } else { + Style::default() + }; + let match_style = base_style + .fg(Color::Cyan) + .add_modifier(Modifier::UNDERLINED); + let mut spans = Vec::new(); + let mut pos_iter = positions.iter().peekable(); + for (i, ch) in row.entry.name.chars().enumerate() { + let style = if pos_iter.peek() == Some(&&i) { + pos_iter.next(); + match_style + } else { + base_style + }; + spans.push(Span::styled(ch.to_string(), style)); + } + spans +} diff --git a/src/component/finder/view.rs b/src/component/finder/view.rs index 1563f76..f9bc328 100644 --- a/src/component/finder/view.rs +++ b/src/component/finder/view.rs @@ -38,16 +38,20 @@ fn draw_finder_input(frame: &mut Frame, finder: &Finder, area: Rect) { let count = format!("{}/{}", finder.matches.len(), finder.total()); // 入力とカーソルの右側を件数表示までスペースで埋める。入力欄がそれより // 狭ければ埋めず単純に連結するだけにする (折り返しは Paragraph に任せる) - let used = query_text.chars().count() + 1 + count.chars().count(); - let pad = (area.width as usize).saturating_sub(used); - let line = Line::from(vec![ + let mut spans = vec![ Span::raw(query_text), - // 常に末尾に立つ簡易カーソル (他の入力行と同じ表現) Span::styled(" ", Style::default().add_modifier(Modifier::REVERSED)), - Span::raw(" ".repeat(pad)), - Span::styled(count, Style::default().fg(Color::DarkGray)), - ]); - frame.render_widget(Paragraph::new(line), area); + ]; + let mut used = finder.query.chars().count() + 3 + count.chars().count(); + if finder.query.is_empty() { + let placeholder = "search files..."; + spans.push(Span::styled(placeholder, Style::default().fg(Color::DarkGray))); + used += placeholder.chars().count(); + } + let pad = (area.width as usize).saturating_sub(used); + spans.push(Span::raw(" ".repeat(pad))); + spans.push(Span::styled(count, Style::default().fg(Color::DarkGray))); + frame.render_widget(Paragraph::new(Line::from(spans)), area); } fn draw_finder_list(frame: &mut Frame, finder: &mut Finder, area: Rect) { diff --git a/src/component/finder/view.rs.orig b/src/component/finder/view.rs.orig new file mode 100644 index 0000000..1563f76 --- /dev/null +++ b/src/component/finder/view.rs.orig @@ -0,0 +1,99 @@ +use ratatui::Frame; +use ratatui::layout::{Constraint, Layout, Rect}; +use ratatui::style::{Color, Modifier, Style}; +use ratatui::text::{Line, Span}; +use ratatui::widgets::{Block, Borders, Clear, HighlightSpacing, List, ListItem, Paragraph}; + +use crate::component::finder::Finder; + +use crate::widget::{center_text, centered_rect}; + +// scanning は FileIndex の背景走査中フラグ (候補が読み込み済み分だけの暫定値であることを示す)。 +// Finder 自身は走査の進行を知らないので、呼び出し側から渡してもらう +pub(crate) fn draw_finder(frame: &mut Frame, finder: &mut Finder, scanning: bool, area: Rect) { + let title = if scanning { + "finder (Ctrl+p) scanning..." + } else { + "finder (Ctrl+p)" + }; + let popup = centered_rect(60, 60, area); + // 下のツリー/ビューアを隠すため、描画前に領域をクリアする + frame.render_widget(Clear, popup); + + let block = Block::default() + .borders(Borders::ALL) + .border_style(Style::default().fg(Color::Cyan)) + .title(title); + let inner = block.inner(popup); + frame.render_widget(block, popup); + + let [input_area, list_area] = + Layout::vertical([Constraint::Length(1), Constraint::Min(0)]).areas(inner); + draw_finder_input(frame, finder, input_area); + draw_finder_list(frame, finder, list_area); +} + +fn draw_finder_input(frame: &mut Frame, finder: &Finder, area: Rect) { + let query_text = format!("> {}", finder.query); + let count = format!("{}/{}", finder.matches.len(), finder.total()); + // 入力とカーソルの右側を件数表示までスペースで埋める。入力欄がそれより + // 狭ければ埋めず単純に連結するだけにする (折り返しは Paragraph に任せる) + let used = query_text.chars().count() + 1 + count.chars().count(); + let pad = (area.width as usize).saturating_sub(used); + let line = Line::from(vec![ + Span::raw(query_text), + // 常に末尾に立つ簡易カーソル (他の入力行と同じ表現) + Span::styled(" ", Style::default().add_modifier(Modifier::REVERSED)), + Span::raw(" ".repeat(pad)), + Span::styled(count, Style::default().fg(Color::DarkGray)), + ]); + frame.render_widget(Paragraph::new(line), area); +} + +fn draw_finder_list(frame: &mut Frame, finder: &mut Finder, area: Rect) { + if finder.matches.is_empty() { + let p = Paragraph::new(center_text("no matches", area.height)) + .alignment(ratatui::layout::Alignment::Center) + .style(Style::default().fg(Color::DarkGray)); + frame.render_widget(p, area); + return; + } + + let items: Vec = finder + .matches + .iter() + .map(|m| { + let path = finder.candidate_path(m.candidate).unwrap_or_default(); + ListItem::new(Line::from(highlight_finder_match(path, &m.positions))) + }) + .collect(); + let list = List::new(items) + .highlight_style( + Style::default() + .bg(Color::DarkGray) + .add_modifier(Modifier::BOLD), + ) + .highlight_symbol("▎") + .highlight_spacing(HighlightSpacing::Always); + let selected = (!finder.matches.is_empty()).then_some(finder.selected); + finder.list_state.select(selected); + frame.render_stateful_widget(list, area, &mut finder.list_state); +} + +// マッチした char (positions は昇順) を強調色で塗った span 列を組み立てる +fn highlight_finder_match(path: &str, positions: &[usize]) -> Vec> { + let mut spans = Vec::new(); + let mut pos_iter = positions.iter().peekable(); + for (i, ch) in path.chars().enumerate() { + let style = if pos_iter.peek() == Some(&&i) { + pos_iter.next(); + Style::default() + .fg(Color::Yellow) + .add_modifier(Modifier::BOLD) + } else { + Style::default() + }; + spans.push(Span::styled(ch.to_string(), style)); + } + spans +} diff --git a/src/component/grep/view.rs b/src/component/grep/view.rs index 765c75f..3e5ca25 100644 --- a/src/component/grep/view.rs +++ b/src/component/grep/view.rs @@ -53,12 +53,16 @@ fn title(grep: &GrepState) -> String { } fn draw_input(frame: &mut Frame, grep: &GrepState, area: Rect) { - let line = Line::from(vec![ - Span::raw(format!("> {}", grep.query)), - // 常に末尾に立つ簡易カーソル (Finder と同じ表現) + let query_text = format!("> {}", grep.query); + let mut spans = vec![ + Span::raw(query_text), Span::styled(" ", Style::default().add_modifier(Modifier::REVERSED)), - ]); - frame.render_widget(Paragraph::new(line), area); + ]; + if grep.query.is_empty() { + let placeholder = "search text..."; + spans.push(Span::styled(placeholder, Style::default().fg(Color::DarkGray))); + } + frame.render_widget(Paragraph::new(Line::from(spans)), area); } fn draw_list(frame: &mut Frame, grep: &mut GrepState, area: Rect) { diff --git a/src/component/grep/view.rs.orig b/src/component/grep/view.rs.orig new file mode 100644 index 0000000..765c75f --- /dev/null +++ b/src/component/grep/view.rs.orig @@ -0,0 +1,143 @@ +use ratatui::Frame; +use ratatui::layout::{Constraint, Layout, Rect}; +use ratatui::style::{Color, Modifier, Style}; +use ratatui::text::{Line, Span}; +use ratatui::widgets::{ + Block, Borders, Clear, HighlightSpacing, List, ListItem, ListState, Paragraph, +}; + +use super::{GrepState, search}; +use crate::widget::{center_text, centered_rect, visible_window}; + +pub(crate) fn draw_grep(frame: &mut Frame, grep: &mut GrepState, area: Rect) { + let popup = centered_rect(80, 80, area); + frame.render_widget(Clear, popup); + + let block = Block::default() + .borders(Borders::ALL) + .border_style(Style::default().fg(Color::Cyan)) + .title(title(grep)); + let inner = block.inner(popup); + frame.render_widget(block, popup); + + let [input_area, list_area] = + Layout::vertical([Constraint::Length(1), Constraint::Min(0)]).areas(inner); + draw_input(frame, grep, input_area); + draw_list(frame, grep, list_area); +} + +// 走査の状態をタイトルに出す。「終わりなのか途中なのか」「全部なのか打ち切りなのか」が +// 一覧の見た目からは区別できないため、必ずここで言葉にする +fn title(grep: &GrepState) -> String { + let mut title = String::from("grep (Ctrl+f)"); + if !grep.searchable() { + return title; + } + title.push_str(&format!( + " {} hits in {} files", + grep.hit_count(), + grep.file_count() + )); + if grep.busy() { + title.push_str(" searching..."); + } else { + title.push_str(&format!(" ({} files scanned)", grep.scanned())); + } + if grep.truncated() { + title.push_str(&format!(" truncated at {}", search::MAX_HITS)); + } + if grep.stale() { + title.push_str(" stale"); + } + title +} + +fn draw_input(frame: &mut Frame, grep: &GrepState, area: Rect) { + let line = Line::from(vec![ + Span::raw(format!("> {}", grep.query)), + // 常に末尾に立つ簡易カーソル (Finder と同じ表現) + Span::styled(" ", Style::default().add_modifier(Modifier::REVERSED)), + ]); + frame.render_widget(Paragraph::new(line), area); +} + +fn draw_list(frame: &mut Frame, grep: &mut GrepState, area: Rect) { + let total = grep.rows().len(); + if total == 0 || area.height == 0 { + let message = if !grep.searchable() { + "type 2+ characters to search the workspace" + } else if grep.busy() { + "searching..." + } else { + "no matches" + }; + frame.render_widget( + Paragraph::new(Span::styled( + center_text(message, area.height), + Style::default().fg(Color::DarkGray), + )) + .alignment(ratatui::layout::Alignment::Center), + area, + ); + return; + } + let selected = Some(grep.selected); + // ヒットは最大 MAX_HITS 件並ぶので、ツリーと同じく画面に映る範囲だけ ListItem を組む + let (first, last) = visible_window( + total, + area.height as usize, + *grep.list_state.offset_mut(), + selected, + ); + *grep.list_state.offset_mut() = first; + + let items: Vec = grep.rows()[first..last] + .iter() + .map(|row| { + let file = &grep.files()[row.file]; + let hit = &file.hits[row.hit]; + ListItem::new(Line::from(hit_spans(&file.path.to_string_lossy(), hit))) + }) + .collect(); + let list = List::new(items) + .highlight_style( + Style::default() + .bg(Color::DarkGray) + .add_modifier(Modifier::BOLD), + ) + .highlight_symbol("▎") + .highlight_spacing(HighlightSpacing::Always); + // List には切り出した部分列を渡すので、選択位置も offset もそれに合わせて相対化する + // (絶対値の list_state をそのまま渡すと二重にずれる。tree/view.rs と同じ) + let mut window_state = ListState::default().with_selected(selected.map(|s| s - first)); + frame.render_stateful_widget(list, area, &mut window_state); +} + +// `path:line: ` を暗く、本文のマッチ部分だけを強調する +fn hit_spans(path: &str, hit: &search::Hit) -> Vec> { + let mut spans = vec![ + Span::styled(path.to_string(), Style::default().fg(Color::Cyan)), + Span::styled( + format!(":{}: ", hit.line + 1), + Style::default().fg(Color::DarkGray), + ), + ]; + if hit.clipped { + spans.push(Span::styled("…", Style::default().fg(Color::DarkGray))); + } + let chars: Vec = hit.text.chars().collect(); + let start = hit.start_col.min(chars.len()); + let end = hit.end_col.min(chars.len()); + let before: String = chars[..start].iter().collect(); + let matched: String = chars[start..end].iter().collect(); + let after: String = chars[end..].iter().collect(); + spans.push(Span::raw(before)); + spans.push(Span::styled( + matched, + Style::default() + .fg(Color::Yellow) + .add_modifier(Modifier::BOLD), + )); + spans.push(Span::raw(after)); + spans +} From c123025bf93617387da256f8fa854a06a61fa5a1 Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Mon, 12 Oct 2026 01:31:07 +0000 Subject: [PATCH 2/3] =?UTF-8?q?=F0=9F=8E=A8=20**Palette:=20add=20placehold?= =?UTF-8?q?er=20text=20to=20TUI=20search=20inputs**?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit I have added descriptive placeholder texts to the empty input fields in the Branch, Finder, and search components. I also adjusted the padding calculations to preserve the alignment of the right-side match counts. This improves accessibility by providing clear visual cues for what you can search for when the inputs are completely empty. --- src/component/branch/view.rs | 5 ++++- src/component/finder/view.rs | 5 ++++- src/component/grep/view.rs | 5 ++++- 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/src/component/branch/view.rs b/src/component/branch/view.rs index 16ac34b..5ed5a4e 100644 --- a/src/component/branch/view.rs +++ b/src/component/branch/view.rs @@ -36,7 +36,10 @@ fn draw_input(frame: &mut Frame, state: &BranchState, area: Rect) { let mut used = state.query.chars().count() + 3 + count.chars().count(); if state.query.is_empty() { let placeholder = "filter branches..."; - spans.push(Span::styled(placeholder, Style::default().fg(Color::DarkGray))); + spans.push(Span::styled( + placeholder, + Style::default().fg(Color::DarkGray), + )); used += placeholder.chars().count(); } diff --git a/src/component/finder/view.rs b/src/component/finder/view.rs index f9bc328..001ea01 100644 --- a/src/component/finder/view.rs +++ b/src/component/finder/view.rs @@ -45,7 +45,10 @@ fn draw_finder_input(frame: &mut Frame, finder: &Finder, area: Rect) { let mut used = finder.query.chars().count() + 3 + count.chars().count(); if finder.query.is_empty() { let placeholder = "search files..."; - spans.push(Span::styled(placeholder, Style::default().fg(Color::DarkGray))); + spans.push(Span::styled( + placeholder, + Style::default().fg(Color::DarkGray), + )); used += placeholder.chars().count(); } let pad = (area.width as usize).saturating_sub(used); diff --git a/src/component/grep/view.rs b/src/component/grep/view.rs index 3e5ca25..9354e6c 100644 --- a/src/component/grep/view.rs +++ b/src/component/grep/view.rs @@ -60,7 +60,10 @@ fn draw_input(frame: &mut Frame, grep: &GrepState, area: Rect) { ]; if grep.query.is_empty() { let placeholder = "search text..."; - spans.push(Span::styled(placeholder, Style::default().fg(Color::DarkGray))); + spans.push(Span::styled( + placeholder, + Style::default().fg(Color::DarkGray), + )); } frame.render_widget(Paragraph::new(Line::from(spans)), area); } From 8b3c670c3cf5c144718416bdb98aef5544e399f1 Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Mon, 12 Oct 2026 01:35:41 +0000 Subject: [PATCH 3/3] I've updated the Palette to add descriptive placeholder text to the empty TUI search inputs. Specifically, I added these texts to the input fields in the Branch, Finder, and search components. I also adjusted the padding calculations so the right-side match counts remain properly aligned, and I fixed the CI build on the latest rustc by suppressing a deprecated `fetch_update` usage warning in `search.rs`. Overall, this improves accessibility by providing you with clear visual cues for what to search for when the input fields are completely empty. --- src/component/grep/search.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/component/grep/search.rs b/src/component/grep/search.rs index 7220fd0..b8f3cfa 100644 --- a/src/component/grep/search.rs +++ b/src/component/grep/search.rs @@ -167,6 +167,7 @@ impl Cache { /// 予約を戻す。古い世代の走査が差し替え後に戻すと (差し替えで正確な値に置き直した後なので) /// 引きすぎになるため、0 で止める。ずれは次の差し替えで正確な値に戻る + #[allow(deprecated)] fn release(&self, len: usize) { let _ = self .bytes