Skip to content

Commit

Permalink
Allow theming directory prompt completions (#12205)
Browse files Browse the repository at this point in the history
  • Loading branch information
NikitaRevenco authored Dec 18, 2024
1 parent 6eb186e commit 91a5d40
Show file tree
Hide file tree
Showing 16 changed files with 63 additions and 20 deletions.
1 change: 1 addition & 0 deletions book/src/themes.md
Original file line number Diff line number Diff line change
Expand Up @@ -305,6 +305,7 @@ These scopes are used for theming the editor interface:
| `ui.text.focus` | The currently selected line in the picker |
| `ui.text.inactive` | Same as `ui.text` but when the text is inactive (e.g. suggestions) |
| `ui.text.info` | The key: command text in `ui.popup.info` boxes |
| `ui.text.directory` | Directory names in prompt completion |
| `ui.virtual.ruler` | Ruler columns (see the [`editor.rulers` config][editor-section]) |
| `ui.virtual.whitespace` | Visible whitespace characters |
| `ui.virtual.indent-guide` | Vertical indent width guides |
Expand Down
2 changes: 1 addition & 1 deletion helix-term/src/commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2183,7 +2183,7 @@ fn searcher(cx: &mut Context, direction: Direction) {
completions
.iter()
.filter(|comp| comp.starts_with(input))
.map(|comp| (0.., std::borrow::Cow::Owned(comp.clone())))
.map(|comp| (0.., comp.clone().into()))
.collect()
},
move |cx, regex, event| {
Expand Down
4 changes: 2 additions & 2 deletions helix-term/src/commands/typed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3198,8 +3198,8 @@ pub(super) fn command_mode(cx: &mut Context) {
{
completer(editor, word)
.into_iter()
.map(|(range, file)| {
let file = shellwords::escape(file);
.map(|(range, mut file)| {
file.content = shellwords::escape(file.content);

// offset ranges to input
let offset = input.len() - word_len;
Expand Down
43 changes: 34 additions & 9 deletions helix-term/src/ui/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,17 @@ use helix_view::Editor;

use std::{error::Error, path::PathBuf};

struct Utf8PathBuf {
path: String,
is_dir: bool,
}

impl AsRef<str> for Utf8PathBuf {
fn as_ref(&self) -> &str {
&self.path
}
}

pub fn prompt(
cx: &mut crate::commands::Context,
prompt: std::borrow::Cow<'static, str>,
Expand Down Expand Up @@ -266,6 +277,7 @@ pub fn file_picker(root: PathBuf, config: &helix_view::editor::Config) -> FilePi
}

pub mod completers {
use super::Utf8PathBuf;
use crate::ui::prompt::Completion;
use helix_core::fuzzy::fuzzy_match;
use helix_core::syntax::LanguageServerFeature;
Expand All @@ -274,6 +286,7 @@ pub mod completers {
use helix_view::{editor::Config, Editor};
use once_cell::sync::Lazy;
use std::borrow::Cow;
use tui::text::Span;

pub type Completer = fn(&Editor, &str) -> Vec<Completion>;

Expand All @@ -290,7 +303,7 @@ pub mod completers {

fuzzy_match(input, names, true)
.into_iter()
.map(|(name, _)| ((0..), name))
.map(|(name, _)| ((0..), name.into()))
.collect()
}

Expand Down Expand Up @@ -336,7 +349,7 @@ pub mod completers {

fuzzy_match(input, &*KEYS, false)
.into_iter()
.map(|(name, _)| ((0..), name.into()))
.map(|(name, _)| ((0..), Span::raw(name)))
.collect()
}

Expand Down Expand Up @@ -424,7 +437,7 @@ pub mod completers {

// TODO: we could return an iter/lazy thing so it can fetch as many as it needs.
fn filename_impl<F>(
_editor: &Editor,
editor: &Editor,
input: &str,
git_ignore: bool,
filter_fn: F,
Expand Down Expand Up @@ -482,7 +495,7 @@ pub mod completers {
return None;
}

//let is_dir = entry.file_type().map_or(false, |entry| entry.is_dir());
let is_dir = entry.file_type().is_some_and(|entry| entry.is_dir());

let path = entry.path();
let mut path = if is_tilde {
Expand All @@ -501,23 +514,35 @@ pub mod completers {
}

let path = path.into_os_string().into_string().ok()?;
Some(Cow::from(path))
Some(Utf8PathBuf { path, is_dir })
})
}) // TODO: unwrap or skip
.filter(|path| !path.is_empty());
.filter(|path| !path.path.is_empty());

let directory_color = editor.theme.get("ui.text.directory");

let style_from_file = |file: Utf8PathBuf| {
if file.is_dir {
Span::styled(file.path, directory_color)
} else {
Span::raw(file.path)
}
};

// if empty, return a list of dirs and files in current dir
if let Some(file_name) = file_name {
let range = (input.len().saturating_sub(file_name.len()))..;
fuzzy_match(&file_name, files, true)
.into_iter()
.map(|(name, _)| (range.clone(), name))
.map(|(name, _)| (range.clone(), style_from_file(name)))
.collect()

// TODO: complete to longest common match
} else {
let mut files: Vec<_> = files.map(|file| (end.clone(), file)).collect();
files.sort_unstable_by(|(_, path1), (_, path2)| path1.cmp(path2));
let mut files: Vec<_> = files
.map(|file| (end.clone(), style_from_file(file)))
.collect();
files.sort_unstable_by(|(_, path1), (_, path2)| path1.content.cmp(&path2.content));
files
}
}
Expand Down
22 changes: 14 additions & 8 deletions helix-term/src/ui/prompt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use helix_view::keyboard::KeyCode;
use std::sync::Arc;
use std::{borrow::Cow, ops::RangeFrom};
use tui::buffer::Buffer as Surface;
use tui::text::Span;
use tui::widgets::{Block, Widget};

use helix_core::{
Expand All @@ -19,7 +20,8 @@ use helix_view::{
};

type PromptCharHandler = Box<dyn Fn(&mut Prompt, char, &Context)>;
pub type Completion = (RangeFrom<usize>, Cow<'static, str>);

pub type Completion = (RangeFrom<usize>, Span<'static>);
type CompletionFn = Box<dyn FnMut(&Editor, &str) -> Vec<Completion>>;
type CallbackFn = Box<dyn FnMut(&mut Context, &str, PromptEvent)>;
pub type DocFn = Box<dyn Fn(&str) -> Option<Cow<str>>>;
Expand Down Expand Up @@ -374,7 +376,7 @@ impl Prompt {

let (range, item) = &self.completion[index];

self.line.replace_range(range.clone(), item);
self.line.replace_range(range.clone(), &item.content);

self.move_end();
}
Expand All @@ -399,7 +401,7 @@ impl Prompt {
let max_len = self
.completion
.iter()
.map(|(_, completion)| completion.len() as u16)
.map(|(_, completion)| completion.content.len() as u16)
.max()
.unwrap_or(BASE_WIDTH)
.max(BASE_WIDTH);
Expand Down Expand Up @@ -438,18 +440,22 @@ impl Prompt {
for (i, (_range, completion)) in
self.completion.iter().enumerate().skip(offset).take(items)
{
let color = if Some(i) == self.selection {
selected_color // TODO: just invert bg
let is_selected = Some(i) == self.selection;

let completion_item_style = if is_selected {
selected_color
} else {
completion_color
completion_color.patch(completion.style)
};

surface.set_stringn(
area.x + col * (1 + col_width),
area.y + row,
completion,
&completion.content,
col_width.saturating_sub(1) as usize,
color,
completion_item_style,
);

row += 1;
if row > area.height - 1 {
row = 0;
Expand Down
1 change: 1 addition & 0 deletions runtime/themes/catppuccin_mocha.toml
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@
"ui.text" = "text"
"ui.text.focus" = { fg = "text", bg = "surface0", modifiers = ["bold"] }
"ui.text.inactive" = { fg = "overlay1" }
"ui.text.directory" = { fg = "blue" }

"ui.virtual" = "overlay0"
"ui.virtual.ruler" = { bg = "surface0" }
Expand Down
1 change: 1 addition & 0 deletions runtime/themes/dark_plus.toml
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@
"ui.bufferline.background" = { bg = "background" }
"ui.text" = { fg = "text" }
"ui.text.focus" = { fg = "white" }
"ui.text.directory" = { fg = "blue3" }
"ui.virtual.whitespace" = { fg = "#3e3e3d" }
"ui.virtual.ruler" = { bg = "borders" }
"ui.virtual.indent-guide" = { fg = "dark_gray4" }
Expand Down
1 change: 1 addition & 0 deletions runtime/themes/dracula.toml
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@
"ui.statusline.select" = { fg = "black", bg = "cyan", modifiers = ["bold"] }
"ui.text" = { fg = "foreground" }
"ui.text.focus" = { fg = "cyan" }
"ui.text.directory" = { fg = "cyan" }
"ui.virtual.indent-guide" = { fg = "indent" }
"ui.virtual.inlay-hint" = { fg = "cyan" }
"ui.virtual.inlay-hint.parameter" = { fg = "cyan", modifiers = ["italic", "dim"] }
Expand Down
1 change: 1 addition & 0 deletions runtime/themes/dracula_at_night.toml
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
"ui.statusline.select" = { fg = "background_dark", bg = "purple" }
"ui.text" = { fg = "foreground" }
"ui.text.focus" = { fg = "cyan" }
"ui.text.directory" = { fg = "cyan" }
"ui.window" = { fg = "foreground" }
"ui.virtual.jump-label" = { fg = "pink", modifiers = ["bold"] }
"ui.virtual.ruler" = { bg = "background_dark" }
Expand Down
1 change: 1 addition & 0 deletions runtime/themes/github_dark.toml
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ label = "scale.red.3"
"ui.text" = { fg = "fg.muted" }
"ui.text.focus" = { fg = "fg.default" }
"ui.text.inactive" = "fg.subtle"
"ui.text.directory" = { fg = "scale.blue.2" }
"ui.virtual" = { fg = "scale.gray.6" }
"ui.virtual.ruler" = { bg = "canvas.subtle" }
"ui.virtual.jump-label" = { fg = "scale.red.2", modifiers = ["bold"] }
Expand Down
1 change: 1 addition & 0 deletions runtime/themes/github_light.toml
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ label = "scale.red.5"
"ui.text" = { fg = "fg.muted" }
"ui.text.focus" = { fg = "fg.default" }
"ui.text.inactive" = "fg.subtle"
"ui.text.directory" = { fg = "scale.blue.4" }
"ui.virtual" = { fg = "scale.gray.2" }
"ui.virtual.ruler" = { bg = "canvas.subtle" }

Expand Down
1 change: 1 addition & 0 deletions runtime/themes/gruvbox.toml
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@
"ui.statusline.select" = { fg = "bg1", bg = "orange1", modifiers = ["bold"] }

"ui.text" = { fg = "fg1" }
"ui.text.directory" = { fg = "blue1" }
"ui.virtual.inlay-hint" = { fg = "gray" }
"ui.virtual.jump-label" = { fg = "purple0", modifiers = ["bold"] }
"ui.virtual.ruler" = { bg = "bg1" }
Expand Down
1 change: 1 addition & 0 deletions runtime/themes/material_deep_ocean.toml
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@

"ui.background" = { bg = "bg", fg = "text" }
"ui.text" = { fg = "text" }
"ui.text.directory" = { fg = "blue" }

"ui.statusline" = { bg = "bg", fg = "text" }
"ui.statusline.inactive" = { bg = "bg", fg = "disabled" }
Expand Down
1 change: 1 addition & 0 deletions runtime/themes/rose_pine.toml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
"ui.text" = { fg = "text" }
"ui.text.focus" = { bg = "overlay" }
"ui.text.info" = { fg = "subtle" }
"ui.text.directory" = { fg = "iris" }

"ui.virtual.jump-label" = { fg = "love", modifiers = ["bold"] }
"ui.virtual.ruler" = { bg = "overlay" }
Expand Down
1 change: 1 addition & 0 deletions runtime/themes/tokyonight.toml
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ hint = { fg = "hint" }
"ui.text.focus" = { bg = "bg-focus" }
"ui.text.inactive" = { fg = "comment", modifiers = ["italic"] }
"ui.text.info" = { bg = "bg-menu", fg = "fg" }
"ui.text.directory" = { fg = "cyan" }
"ui.virtual.ruler" = { bg = "fg-gutter" }
"ui.virtual.whitespace" = { fg = "fg-gutter" }
"ui.virtual.inlay-hint" = { bg = "bg-inlay", fg = "teal" }
Expand Down
1 change: 1 addition & 0 deletions theme.toml
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ tabstop = { modifiers = ["italic"], bg = "bossanova" }
"ui.text" = { fg = "lavender" }
"ui.text.focus" = { fg = "white" }
"ui.text.inactive" = "sirocco"
"ui.text.directory" = { fg = "lilac" }
"ui.virtual" = { fg = "comet" }
"ui.virtual.ruler" = { bg = "bossanova" }
"ui.virtual.jump-label" = { fg = "apricot", modifiers = ["bold"] }
Expand Down

0 comments on commit 91a5d40

Please sign in to comment.