diff --git a/crates/breadcrumbs2/src/breadcrumbs.rs b/crates/breadcrumbs2/src/breadcrumbs.rs index e579c8ded05d6532a2dcb1006da69f821044b667..da7182ec2c7394512e0ffafef2fcdf0c5cb7936f 100644 --- a/crates/breadcrumbs2/src/breadcrumbs.rs +++ b/crates/breadcrumbs2/src/breadcrumbs.rs @@ -11,10 +11,6 @@ use workspace::{ ToolbarItemEvent, ToolbarItemLocation, ToolbarItemView, }; -pub enum Event { - UpdateLocation, -} - pub struct Breadcrumbs { pane_focused: bool, active_item: Option>, @@ -31,7 +27,6 @@ impl Breadcrumbs { } } -impl EventEmitter for Breadcrumbs {} impl EventEmitter for Breadcrumbs {} impl Render for Breadcrumbs { @@ -39,15 +34,9 @@ impl Render for Breadcrumbs { fn render(&mut self, cx: &mut ViewContext) -> Self::Element { let element = h_stack().text_ui(); - - let Some(active_item) = &self - .active_item - .as_ref() - .filter(|item| item.downcast::().is_some()) - else { + let Some(active_item) = self.active_item.as_ref() else { return element; }; - let Some(segments) = active_item.breadcrumbs(cx.theme(), cx) else { return element; }; @@ -64,21 +53,24 @@ impl Render for Breadcrumbs { Label::new("›").color(Color::Muted).into_any_element() }); - let editor = active_item + let breadcrumbs_stack = h_stack().gap_1().children(breadcrumbs); + match active_item .downcast::() - .map(|editor| editor.downgrade()); - - element.child( - ButtonLike::new("toggle outline view") - .style(ButtonStyle::Subtle) - .child(h_stack().gap_1().children(breadcrumbs)) - .on_click(move |_, cx| { - if let Some(editor) = editor.as_ref().and_then(|editor| editor.upgrade()) { - outline::toggle(editor, &outline::Toggle, cx) - } - }) - .tooltip(|cx| Tooltip::for_action("Show symbol outline", &outline::Toggle, cx)), - ) + .map(|editor| editor.downgrade()) + { + Some(editor) => element.child( + ButtonLike::new("toggle outline view") + .child(breadcrumbs_stack) + .style(ButtonStyle::Subtle) + .on_click(move |_, cx| { + if let Some(editor) = editor.upgrade() { + outline::toggle(editor, &outline::Toggle, cx) + } + }) + .tooltip(|cx| Tooltip::for_action("Show symbol outline", &outline::Toggle, cx)), + ), + None => element.child(breadcrumbs_stack), + } } } @@ -97,7 +89,6 @@ impl ToolbarItemView for Breadcrumbs { Box::new(move |event, cx| { if let ItemEvent::UpdateBreadcrumbs = event { this.update(cx, |_, cx| { - cx.emit(Event::UpdateLocation); cx.notify(); }) .ok(); @@ -111,19 +102,6 @@ impl ToolbarItemView for Breadcrumbs { } } - // fn location_for_event( - // &self, - // _: &Event, - // current_location: ToolbarItemLocation, - // cx: &AppContext, - // ) -> ToolbarItemLocation { - // if let Some(active_item) = self.active_item.as_ref() { - // active_item.breadcrumb_location(cx) - // } else { - // current_location - // } - // } - fn pane_focus_update(&mut self, pane_focused: bool, _: &mut ViewContext) { self.pane_focused = pane_focused; } diff --git a/crates/file_finder2/src/file_finder.rs b/crates/file_finder2/src/file_finder.rs index 8ca7d46f2965b7452b86415d5817a8c67d6bc0c1..69deba6d2c0da701db779d7f5cc76e9fe5792448 100644 --- a/crates/file_finder2/src/file_finder.rs +++ b/crates/file_finder2/src/file_finder.rs @@ -546,7 +546,7 @@ impl PickerDelegate for FileFinderDelegate { fn separators_after_indices(&self) -> Vec { let history_items = self.matches.history.len(); - if history_items == 0 { + if history_items == 0 || self.matches.search.is_empty() { Vec::new() } else { vec![history_items - 1] diff --git a/crates/project2/src/terminals.rs b/crates/project2/src/terminals.rs index 1bf69aa8b5abae490e8c1b4ca9f08a0da01fc3bb..a816c0ddb2a464a9fcc6c0cc206257acc5b6822a 100644 --- a/crates/project2/src/terminals.rs +++ b/crates/project2/src/terminals.rs @@ -37,7 +37,6 @@ impl Project { Some(settings.blinking.clone()), settings.alternate_scroll, window, - |_, _| todo!("color_for_index"), ) .map(|builder| { let terminal_handle = cx.build_model(|cx| builder.subscribe(cx)); diff --git a/crates/project2/src/worktree.rs b/crates/project2/src/worktree.rs index a5cb322cb5f52beb71c1b4200f58f098c2f6d88a..22b3cd8c653054f9ec0b5b09e0945441e4ecf607 100644 --- a/crates/project2/src/worktree.rs +++ b/crates/project2/src/worktree.rs @@ -2184,7 +2184,6 @@ impl LocalSnapshot { ignore_stack } - #[allow(dead_code)] // todo!("remove this when we use it") #[cfg(test)] pub(crate) fn expanded_entries(&self) -> impl Iterator { self.entries_by_path diff --git a/crates/terminal2/src/terminal2.rs b/crates/terminal2/src/terminal2.rs index 9d3c00d81f95a019671a74c54fb6704a03a25e9d..b15bd7c6d659cc7794b770934e95775c0ae41507 100644 --- a/crates/terminal2/src/terminal2.rs +++ b/crates/terminal2/src/terminal2.rs @@ -35,6 +35,7 @@ use procinfo::LocalProcessInfo; use serde::{Deserialize, Serialize}; use settings::Settings; use terminal_settings::{AlternateScroll, Shell, TerminalBlink, TerminalSettings}; +use theme::{ActiveTheme, Theme}; use util::truncate_and_trailoff; use std::{ @@ -50,9 +51,9 @@ use std::{ use thiserror::Error; use gpui::{ - actions, px, AnyWindowHandle, AppContext, Bounds, ClipboardItem, EventEmitter, Hsla, Keystroke, - ModelContext, Modifiers, MouseButton, MouseDownEvent, MouseMoveEvent, MouseUpEvent, Pixels, - Point, ScrollWheelEvent, Size, Task, TouchPhase, + actions, black, px, red, AnyWindowHandle, AppContext, Bounds, ClipboardItem, EventEmitter, + Hsla, Keystroke, ModelContext, Modifiers, MouseButton, MouseDownEvent, MouseMoveEvent, + MouseUpEvent, Pixels, Point, Rgba, ScrollWheelEvent, Size, Task, TouchPhase, }; use crate::mappings::{colors::to_alac_rgb, keys::to_esc_str}; @@ -299,7 +300,6 @@ impl TerminalBuilder { blink_settings: Option, alternate_scroll: AlternateScroll, window: AnyWindowHandle, - color_for_index: impl Fn(usize, &mut AppContext) -> Hsla + Send + Sync + 'static, ) -> Result { let pty_config = { let alac_shell = match shell.clone() { @@ -405,7 +405,6 @@ impl TerminalBuilder { selection_phase: SelectionPhase::Ended, cmd_pressed: false, hovered_word: false, - color_for_index: Box::new(color_for_index), }; Ok(TerminalBuilder { @@ -562,8 +561,6 @@ pub struct Terminal { selection_phase: SelectionPhase, cmd_pressed: bool, hovered_word: bool, - // An implementation of the 8 bit ANSI color palette - color_for_index: Box Hsla + Send + Sync + 'static>, } impl Terminal { @@ -646,8 +643,9 @@ impl Terminal { ) { match event { InternalEvent::ColorRequest(index, format) => { - let color = term.colors()[*index] - .unwrap_or_else(|| to_alac_rgb((self.color_for_index)(*index, cx))); + let color = term.colors()[*index].unwrap_or_else(|| { + to_alac_rgb(get_color_at_index(*index, cx.theme().as_ref())) + }); self.write_to_pty(format(color)) } InternalEvent::Resize(mut new_size) => { @@ -1418,6 +1416,90 @@ fn content_index_for_mouse(pos: Point, size: &TerminalSize) -> usize { clamped_row * size.columns() + clamped_col } +///Converts an 8 bit ANSI color to it's GPUI equivalent. +///Accepts usize for compatibility with the alacritty::Colors interface, +///Other than that use case, should only be called with values in the [0,255] range +pub fn get_color_at_index(index: usize, theme: &Theme) -> Hsla { + let colors = theme.colors(); + + match index { + //0-15 are the same as the named colors above + 0 => colors.terminal_ansi_black, + 1 => colors.terminal_ansi_red, + 2 => colors.terminal_ansi_green, + 3 => colors.terminal_ansi_yellow, + 4 => colors.terminal_ansi_blue, + 5 => colors.terminal_ansi_magenta, + 6 => colors.terminal_ansi_cyan, + 7 => colors.terminal_ansi_white, + 8 => colors.terminal_ansi_bright_black, + 9 => colors.terminal_ansi_bright_red, + 10 => colors.terminal_ansi_bright_green, + 11 => colors.terminal_ansi_bright_yellow, + 12 => colors.terminal_ansi_bright_blue, + 13 => colors.terminal_ansi_bright_magenta, + 14 => colors.terminal_ansi_bright_cyan, + 15 => colors.terminal_ansi_bright_white, + //16-231 are mapped to their RGB colors on a 0-5 range per channel + 16..=231 => { + let (r, g, b) = rgb_for_index(&(index as u8)); //Split the index into it's ANSI-RGB components + let step = (u8::MAX as f32 / 5.).floor() as u8; //Split the RGB range into 5 chunks, with floor so no overflow + rgba_color(r * step, g * step, b * step) //Map the ANSI-RGB components to an RGB color + } + //232-255 are a 24 step grayscale from black to white + 232..=255 => { + let i = index as u8 - 232; //Align index to 0..24 + let step = (u8::MAX as f32 / 24.).floor() as u8; //Split the RGB grayscale values into 24 chunks + rgba_color(i * step, i * step, i * step) //Map the ANSI-grayscale components to the RGB-grayscale + } + //For compatibility with the alacritty::Colors interface + 256 => colors.text, + 257 => colors.background, + 258 => theme.players().local().cursor, + + // todo!(more colors) + 259 => red(), //style.dim_black, + 260 => red(), //style.dim_red, + 261 => red(), //style.dim_green, + 262 => red(), //style.dim_yellow, + 263 => red(), //style.dim_blue, + 264 => red(), //style.dim_magenta, + 265 => red(), //style.dim_cyan, + 266 => red(), //style.dim_white, + 267 => red(), //style.bright_foreground, + 268 => colors.terminal_ansi_black, //'Dim Background', non-standard color + + _ => black(), + } +} + +///Generates the rgb channels in [0, 5] for a given index into the 6x6x6 ANSI color cube +///See: [8 bit ansi color](https://en.wikipedia.org/wiki/ANSI_escape_code#8-bit). +/// +///Wikipedia gives a formula for calculating the index for a given color: +/// +///index = 16 + 36 × r + 6 × g + b (0 ≤ r, g, b ≤ 5) +/// +///This function does the reverse, calculating the r, g, and b components from a given index. +fn rgb_for_index(i: &u8) -> (u8, u8, u8) { + debug_assert!((&16..=&231).contains(&i)); + let i = i - 16; + let r = (i - (i % 36)) / 36; + let g = ((i % 36) - (i % 6)) / 6; + let b = (i % 36) % 6; + (r, g, b) +} + +pub fn rgba_color(r: u8, g: u8, b: u8) -> Hsla { + Rgba { + r: (r as f32 / 255.) as f32, + g: (g as f32 / 255.) as f32, + b: (b as f32 / 255.) as f32, + a: 1., + } + .into() +} + #[cfg(test)] mod tests { use alacritty_terminal::{ @@ -1427,7 +1509,18 @@ mod tests { use gpui::{point, size, Pixels}; use rand::{distributions::Alphanumeric, rngs::ThreadRng, thread_rng, Rng}; - use crate::{content_index_for_mouse, IndexedCell, TerminalContent, TerminalSize}; + use crate::{ + content_index_for_mouse, rgb_for_index, IndexedCell, TerminalContent, TerminalSize, + }; + + #[test] + fn test_rgb_for_index() { + //Test every possible value in the color cube + for i in 16..=231 { + let (r, g, b) = rgb_for_index(&(i as u8)); + assert_eq!(i, 16 + 36 * r + 6 * g + b); + } + } #[test] fn test_mouse_to_cell_test() { diff --git a/crates/terminal_view2/src/terminal_element.rs b/crates/terminal_view2/src/terminal_element.rs index fc87ac45bd9b21591195f51c2a659f48bbcf68a9..dcadc04e211c89aff672ee29b83f22a79898b5a6 100644 --- a/crates/terminal_view2/src/terminal_element.rs +++ b/crates/terminal_view2/src/terminal_element.rs @@ -1,12 +1,11 @@ use editor::{Cursor, HighlightedRange, HighlightedRangeLine}; use gpui::{ - black, div, fill, point, px, red, relative, AnyElement, AsyncWindowContext, AvailableSpace, + div, fill, point, px, red, relative, AnyElement, AsyncWindowContext, AvailableSpace, BorrowWindow, Bounds, DispatchPhase, Element, ElementId, ExternalPaths, FocusHandle, Font, FontStyle, FontWeight, HighlightStyle, Hsla, InteractiveElement, InteractiveElementState, Interactivity, IntoElement, LayoutId, Model, ModelContext, ModifiersChangedEvent, MouseButton, - Pixels, PlatformInputHandler, Point, Rgba, ShapedLine, StatefulInteractiveElement, - StyleRefinement, Styled, TextRun, TextStyle, TextSystem, UnderlineStyle, WhiteSpace, - WindowContext, + Pixels, PlatformInputHandler, Point, ShapedLine, StatefulInteractiveElement, StyleRefinement, + Styled, TextRun, TextStyle, TextSystem, UnderlineStyle, WhiteSpace, WindowContext, }; use itertools::Itertools; use language::CursorShape; @@ -1048,108 +1047,12 @@ fn convert_color(fg: &terminal::alacritty_terminal::ansi::Color, theme: &Theme) NamedColor::DimForeground => red(), }, //'True' colors - terminal::alacritty_terminal::ansi::Color::Spec(rgb) => rgba_color(rgb.r, rgb.g, rgb.b), + terminal::alacritty_terminal::ansi::Color::Spec(rgb) => { + terminal::rgba_color(rgb.r, rgb.g, rgb.b) + } //8 bit, indexed colors terminal::alacritty_terminal::ansi::Color::Indexed(i) => { - get_color_at_index(&(*i as usize), theme) - } - } -} - -///Converts an 8 bit ANSI color to it's GPUI equivalent. -///Accepts usize for compatibility with the alacritty::Colors interface, -///Other than that use case, should only be called with values in the [0,255] range -pub fn get_color_at_index(index: &usize, theme: &Theme) -> Hsla { - let colors = theme.colors(); - - match index { - //0-15 are the same as the named colors above - 0 => colors.terminal_ansi_black, - 1 => colors.terminal_ansi_red, - 2 => colors.terminal_ansi_green, - 3 => colors.terminal_ansi_yellow, - 4 => colors.terminal_ansi_blue, - 5 => colors.terminal_ansi_magenta, - 6 => colors.terminal_ansi_cyan, - 7 => colors.terminal_ansi_white, - 8 => colors.terminal_ansi_bright_black, - 9 => colors.terminal_ansi_bright_red, - 10 => colors.terminal_ansi_bright_green, - 11 => colors.terminal_ansi_bright_yellow, - 12 => colors.terminal_ansi_bright_blue, - 13 => colors.terminal_ansi_bright_magenta, - 14 => colors.terminal_ansi_bright_cyan, - 15 => colors.terminal_ansi_bright_white, - //16-231 are mapped to their RGB colors on a 0-5 range per channel - 16..=231 => { - let (r, g, b) = rgb_for_index(&(*index as u8)); //Split the index into it's ANSI-RGB components - let step = (u8::MAX as f32 / 5.).floor() as u8; //Split the RGB range into 5 chunks, with floor so no overflow - rgba_color(r * step, g * step, b * step) //Map the ANSI-RGB components to an RGB color - } - //232-255 are a 24 step grayscale from black to white - 232..=255 => { - let i = *index as u8 - 232; //Align index to 0..24 - let step = (u8::MAX as f32 / 24.).floor() as u8; //Split the RGB grayscale values into 24 chunks - rgba_color(i * step, i * step, i * step) //Map the ANSI-grayscale components to the RGB-grayscale - } - //For compatibility with the alacritty::Colors interface - 256 => colors.text, - 257 => colors.background, - 258 => theme.players().local().cursor, - - // todo!(more colors) - 259 => red(), //style.dim_black, - 260 => red(), //style.dim_red, - 261 => red(), //style.dim_green, - 262 => red(), //style.dim_yellow, - 263 => red(), //style.dim_blue, - 264 => red(), //style.dim_magenta, - 265 => red(), //style.dim_cyan, - 266 => red(), //style.dim_white, - 267 => red(), //style.bright_foreground, - 268 => colors.terminal_ansi_black, //'Dim Background', non-standard color - - _ => black(), - } -} - -///Generates the rgb channels in [0, 5] for a given index into the 6x6x6 ANSI color cube -///See: [8 bit ansi color](https://en.wikipedia.org/wiki/ANSI_escape_code#8-bit). -/// -///Wikipedia gives a formula for calculating the index for a given color: -/// -///index = 16 + 36 × r + 6 × g + b (0 ≤ r, g, b ≤ 5) -/// -///This function does the reverse, calculating the r, g, and b components from a given index. -fn rgb_for_index(i: &u8) -> (u8, u8, u8) { - debug_assert!((&16..=&231).contains(&i)); - let i = i - 16; - let r = (i - (i % 36)) / 36; - let g = ((i % 36) - (i % 6)) / 6; - let b = (i % 36) % 6; - (r, g, b) -} - -fn rgba_color(r: u8, g: u8, b: u8) -> Hsla { - Rgba { - r: (r as f32 / 255.) as f32, - g: (g as f32 / 255.) as f32, - b: (b as f32 / 255.) as f32, - a: 1., - } - .into() -} - -#[cfg(test)] -mod tests { - use crate::terminal_element::rgb_for_index; - - #[test] - fn test_rgb_for_index() { - //Test every possible value in the color cube - for i in 16..=231 { - let (r, g, b) = rgb_for_index(&(i as u8)); - assert_eq!(i, 16 + 36 * r + 6 * g + b); + terminal::get_color_at_index(*i as usize, theme) } } }