Skip to content

Commit a1e2d6a

Browse files
authored
Add vi/search line indicator
This adds a new visual indicator which shows the position in history of either the display offset during search, or the vi mode cursor. To make it as unintrusive as possible, the overlay is hidden whenever the vi mode cursor collides with its position. Fixes alacritty#3984.
1 parent 8ed72cc commit a1e2d6a

File tree

5 files changed

+89
-36
lines changed

5 files changed

+89
-36
lines changed

Diff for: CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
1818
- Customizable keybindings for search
1919
- History for search mode, bound to ^P/^N/Up/Down by default
2020
- Default binding to cancel search on Ctrl+C
21+
- History position indicator for search and vi mode
2122

2223
### Changed
2324

Diff for: alacritty.yml

+20-10
Original file line numberDiff line numberDiff line change
@@ -211,16 +211,6 @@
211211
# text: CellBackground
212212
# cursor: CellForeground
213213

214-
# Selection colors
215-
#
216-
# Colors which should be used to draw the selection area.
217-
#
218-
# Allowed values are CellForeground and CellBackground, which reference the
219-
# affected cell, or hexadecimal colors like #ff00ff.
220-
#selection:
221-
# text: CellBackground
222-
# background: CellForeground
223-
224214
# Search colors
225215
#
226216
# Colors used for the search bar and match highlighting.
@@ -238,6 +228,26 @@
238228
# background: '#c5c8c6'
239229
# foreground: '#1d1f21'
240230

231+
# Line indicator
232+
#
233+
# Color used for the indicator displaying the position in history during
234+
# search and vi mode.
235+
#
236+
# By default, these will use the opposing primary color.
237+
#line_indicator:
238+
# foreground: None
239+
# background: None
240+
241+
# Selection colors
242+
#
243+
# Colors which should be used to draw the selection area.
244+
#
245+
# Allowed values are CellForeground and CellBackground, which reference the
246+
# affected cell, or hexadecimal colors like #ff00ff.
247+
#selection:
248+
# text: CellBackground
249+
# background: CellForeground
250+
241251
# Normal colors
242252
#normal:
243253
# black: '#1d1f21'

Diff for: alacritty/src/display.rs

+53-16
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,10 @@ use wayland_client::{Display as WaylandDisplay, EventQueue};
2323
use crossfont::{self, Rasterize, Rasterizer};
2424

2525
use alacritty_terminal::event::{EventListener, OnResize};
26-
use alacritty_terminal::index::{Column, Direction, Point};
26+
use alacritty_terminal::grid::Dimensions as _;
27+
use alacritty_terminal::index::{Column, Direction, Line, Point};
2728
use alacritty_terminal::selection::Selection;
28-
use alacritty_terminal::term::{SizeInfo, Term, TermMode};
29-
use alacritty_terminal::term::{MIN_COLS, MIN_SCREEN_LINES};
29+
use alacritty_terminal::term::{SizeInfo, Term, TermMode, MIN_COLS, MIN_SCREEN_LINES};
3030

3131
use crate::config::font::Font;
3232
use crate::config::window::Dimensions;
@@ -460,21 +460,19 @@ impl Display {
460460
let cursor = content.cursor();
461461

462462
let visual_bell_intensity = terminal.visual_bell.intensity();
463+
let display_offset = terminal.grid().display_offset();
463464
let background_color = terminal.background_color();
464465
let cursor_point = terminal.grid().cursor.point;
466+
let total_lines = terminal.grid().total_lines();
465467
let metrics = self.glyph_cache.font_metrics();
466-
let glyph_cache = &mut self.glyph_cache;
467468
let size_info = self.size_info;
468469

469470
let selection = !terminal.selection.as_ref().map(Selection::is_empty).unwrap_or(true);
470471
let mouse_mode = terminal.mode().intersects(TermMode::MOUSE_MODE)
471472
&& !terminal.mode().contains(TermMode::VI);
472473

473-
let vi_mode_cursor = if terminal.mode().contains(TermMode::VI) {
474-
Some(terminal.vi_mode_cursor)
475-
} else {
476-
None
477-
};
474+
let vi_mode = terminal.mode().contains(TermMode::VI);
475+
let vi_mode_cursor = if vi_mode { Some(terminal.vi_mode_cursor) } else { None };
478476

479477
// Drop terminal as early as possible to free lock.
480478
drop(terminal);
@@ -490,6 +488,7 @@ impl Display {
490488
{
491489
let _sampler = self.meter.sampler();
492490

491+
let glyph_cache = &mut self.glyph_cache;
493492
self.renderer.with_api(&config.ui_config, &size_info, |mut api| {
494493
// Iterate over all non-empty cells in the grid.
495494
for mut cell in grid_cells {
@@ -539,11 +538,19 @@ impl Display {
539538
}
540539
}
541540

542-
// Highlight URLs at the vi mode cursor position.
543541
if let Some(vi_mode_cursor) = vi_mode_cursor {
544-
if let Some(url) = self.urls.find_at(vi_mode_cursor.point) {
542+
// Highlight URLs at the vi mode cursor position.
543+
let vi_mode_point = vi_mode_cursor.point;
544+
if let Some(url) = self.urls.find_at(vi_mode_point) {
545545
rects.append(&mut url.rects(&metrics, &size_info));
546546
}
547+
548+
// Indicate vi mode by showing the cursor's position in the top right corner.
549+
let line = size_info.screen_lines() + display_offset - vi_mode_point.line - 1;
550+
self.draw_line_indicator(config, &size_info, total_lines, Some(vi_mode_point), line.0);
551+
} else if search_active {
552+
// Show current display offset in vi-less search to indicate match position.
553+
self.draw_line_indicator(config, &size_info, total_lines, None, display_offset);
547554
}
548555

549556
// Push the cursor rects for rendering.
@@ -574,13 +581,13 @@ impl Display {
574581
let start_line = size_info.screen_lines() + search_offset;
575582
let y = size_info.cell_height().mul_add(start_line.0 as f32, size_info.padding_y());
576583

577-
let color = match message.ty() {
584+
let bg = match message.ty() {
578585
MessageType::Error => config.colors.normal.red,
579586
MessageType::Warning => config.colors.normal.yellow,
580587
};
581588

582589
let message_bar_rect =
583-
RenderRect::new(0., y, size_info.width(), size_info.height() - y, color, 1.);
590+
RenderRect::new(0., y, size_info.width(), size_info.height() - y, bg, 1.);
584591

585592
// Push message_bar in the end, so it'll be above all other content.
586593
rects.push(message_bar_rect);
@@ -589,10 +596,12 @@ impl Display {
589596
self.renderer.draw_rects(&size_info, rects);
590597

591598
// Relay messages to the user.
599+
let glyph_cache = &mut self.glyph_cache;
592600
let fg = config.colors.primary.background;
593601
for (i, message_text) in text.iter().enumerate() {
602+
let point = Point::new(start_line + i, Column(0));
594603
self.renderer.with_api(&config.ui_config, &size_info, |mut api| {
595-
api.render_string(glyph_cache, start_line + i, &message_text, fg, None);
604+
api.render_string(glyph_cache, point, fg, bg, &message_text);
596605
});
597606
}
598607
} else {
@@ -681,10 +690,12 @@ impl Display {
681690
// Assure text length is at least num_cols.
682691
let text = format!("{:<1$}", text, num_cols);
683692

693+
let point = Point::new(size_info.screen_lines(), Column(0));
684694
let fg = config.colors.search_bar_foreground();
685695
let bg = config.colors.search_bar_background();
696+
686697
self.renderer.with_api(&config.ui_config, &size_info, |mut api| {
687-
api.render_string(glyph_cache, size_info.screen_lines(), &text, fg, Some(bg));
698+
api.render_string(glyph_cache, point, fg, bg, &text);
688699
});
689700
}
690701

@@ -693,17 +704,43 @@ impl Display {
693704
if !config.ui_config.debug.render_timer {
694705
return;
695706
}
707+
696708
let glyph_cache = &mut self.glyph_cache;
697709

698710
let timing = format!("{:.3} usec", self.meter.average());
711+
let point = Point::new(size_info.screen_lines() - 2, Column(0));
699712
let fg = config.colors.primary.background;
700713
let bg = config.colors.normal.red;
701714

702715
self.renderer.with_api(&config.ui_config, &size_info, |mut api| {
703-
api.render_string(glyph_cache, size_info.screen_lines() - 2, &timing[..], fg, Some(bg));
716+
api.render_string(glyph_cache, point, fg, bg, &timing);
704717
});
705718
}
706719

720+
/// Draw an indicator for the position of a line in history.
721+
fn draw_line_indicator(
722+
&mut self,
723+
config: &Config,
724+
size_info: &SizeInfo,
725+
total_lines: usize,
726+
vi_mode_point: Option<Point>,
727+
line: usize,
728+
) {
729+
let text = format!("[{}/{}]", line, total_lines - 1);
730+
let column = Column(size_info.cols().0.saturating_sub(text.len()));
731+
let colors = &config.colors;
732+
let fg = colors.line_indicator.foreground.unwrap_or(colors.primary.background);
733+
let bg = colors.line_indicator.background.unwrap_or(colors.primary.foreground);
734+
735+
// Do not render anything if it would obscure the vi mode cursor.
736+
if vi_mode_point.map_or(true, |point| point.line.0 != 0 || point.col < column) {
737+
let glyph_cache = &mut self.glyph_cache;
738+
self.renderer.with_api(&config.ui_config, &size_info, |mut api| {
739+
api.render_string(glyph_cache, Point::new(Line(0), column), fg, bg, &text);
740+
});
741+
}
742+
}
743+
707744
/// Requst a new frame for a window on Wayland.
708745
#[inline]
709746
#[cfg(all(feature = "wayland", not(any(target_os = "macos", windows))))]

Diff for: alacritty/src/renderer/mod.rs

+8-10
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ use fnv::FnvHasher;
1414
use log::{error, info};
1515
use unicode_width::UnicodeWidthChar;
1616

17-
use alacritty_terminal::index::{Column, Line};
17+
use alacritty_terminal::index::Point;
1818
use alacritty_terminal::term::cell::Flags;
1919
use alacritty_terminal::term::color::Rgb;
2020
use alacritty_terminal::term::render::RenderableCell;
@@ -820,25 +820,23 @@ impl<'a> RenderApi<'a> {
820820
pub fn render_string(
821821
&mut self,
822822
glyph_cache: &mut GlyphCache,
823-
line: Line,
824-
string: &str,
823+
point: Point,
825824
fg: Rgb,
826-
bg: Option<Rgb>,
825+
bg: Rgb,
826+
string: &str,
827827
) {
828-
let bg_alpha = bg.map(|_| 1.0).unwrap_or(0.0);
829-
830828
let cells = string
831829
.chars()
832830
.enumerate()
833831
.map(|(i, character)| RenderableCell {
834-
line,
835-
column: Column(i),
832+
line: point.line,
833+
column: point.col + i,
836834
character,
837835
zerowidth: None,
838836
flags: Flags::empty(),
839-
bg_alpha,
837+
bg_alpha: 1.0,
840838
fg,
841-
bg: bg.unwrap_or(Rgb { r: 0, g: 0, b: 0 }),
839+
bg,
842840
is_match: false,
843841
})
844842
.collect::<Vec<_>>();

Diff for: alacritty_terminal/src/config/colors.rs

+7
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ pub struct Colors {
1616
pub dim: Option<DimColors>,
1717
pub indexed_colors: Vec<IndexedColor>,
1818
pub search: SearchColors,
19+
pub line_indicator: LineIndicatorColors,
1920
}
2021

2122
impl Colors {
@@ -28,6 +29,12 @@ impl Colors {
2829
}
2930
}
3031

32+
#[derive(ConfigDeserialize, Copy, Clone, Default, Debug, PartialEq, Eq)]
33+
pub struct LineIndicatorColors {
34+
pub foreground: Option<Rgb>,
35+
pub background: Option<Rgb>,
36+
}
37+
3138
#[derive(Deserialize, Copy, Clone, Default, Debug, PartialEq, Eq)]
3239
pub struct IndexedColor {
3340
pub color: Rgb,

0 commit comments

Comments
 (0)