Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow theming directory prompt completions #12205

Merged
merged 21 commits into from
Dec 18, 2024
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
4affa69
feat: add invert method for Color
NikitaRevenco Dec 6, 2024
13d53e8
fix: use None for Style temporarily
NikitaRevenco Dec 6, 2024
697c5a8
feat: complete implementation of colored directories
NikitaRevenco Dec 6, 2024
16c0d8f
feat: revert addition of invert color method
NikitaRevenco Dec 6, 2024
335e1bb
perf: check if path ends with a slash instead of using syscall
NikitaRevenco Dec 7, 2024
3565741
refactor: remove unused imports + use char instead of str
NikitaRevenco Dec 7, 2024
e0b6528
refactor: move comment to correct place
NikitaRevenco Dec 7, 2024
30d5f40
feat: use Span instead of adding an ew tuple member
NikitaRevenco Dec 7, 2024
a73e1fd
refactor: do not unnecesserily evaluate completion_color
NikitaRevenco Dec 7, 2024
032bd5e
refactor: remove unnecessary comments
NikitaRevenco Dec 7, 2024
5aca6f3
refactor: more readable variable name: default_completion_color
NikitaRevenco Dec 7, 2024
f907313
feat: use `ui.text.directory`
NikitaRevenco Dec 17, 2024
e3ac89e
feat: add keys for several themes
NikitaRevenco Dec 17, 2024
1e24775
docs: info on `ui.text.directory`
NikitaRevenco Dec 17, 2024
5e4ed5d
revert: unformat file
NikitaRevenco Dec 17, 2024
2cd6c90
docs: be more concise
NikitaRevenco Dec 17, 2024
ee8162d
perf: do not make unnecessary evaluation of has_custom_style
NikitaRevenco Dec 17, 2024
0f254ee
refactor: do not use unnecessary Span::raw
NikitaRevenco Dec 17, 2024
cefa10d
refactor: use .patch method
NikitaRevenco Dec 17, 2024
b45d3eb
feat: use Utf8PathBuf struct instead of checking for end of file
NikitaRevenco Dec 17, 2024
2eca8df
minor style nits
the-mikedavis Dec 18, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion helix-term/src/commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2164,7 +2164,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.., Span::raw(comp.clone())))
.collect()
},
move |cx, regex, event| {
Expand Down
6 changes: 3 additions & 3 deletions helix-term/src/commands/typed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3178,7 +3178,7 @@ pub(super) fn command_mode(cx: &mut Context) {
false,
)
.into_iter()
.map(|(name, _)| (0.., name.into()))
.map(|(name, _)| (0.., Span::raw(name)))
.collect()
} else {
// Otherwise, use the command's completer and the last shellword
Expand All @@ -3197,8 +3197,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
36 changes: 25 additions & 11 deletions helix-term/src/ui/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -270,10 +270,11 @@ pub mod completers {
use helix_core::fuzzy::fuzzy_match;
use helix_core::syntax::LanguageServerFeature;
use helix_view::document::SCRATCH_BUFFER_NAME;
use helix_view::theme;
use helix_view::theme::{self};
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 +291,7 @@ pub mod completers {

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

Expand All @@ -306,7 +307,7 @@ pub mod completers {

fuzzy_match(input, names, false)
.into_iter()
.map(|(name, _)| ((0..), name.into()))
.map(|(name, _)| ((0..), Span::raw(name)))
NikitaRevenco marked this conversation as resolved.
Show resolved Hide resolved
.collect()
}

Expand Down Expand Up @@ -336,7 +337,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 @@ -371,7 +372,7 @@ pub mod completers {

fuzzy_match(input, language_ids, false)
.into_iter()
.map(|(name, _)| ((0..), name.to_owned().into()))
.map(|(name, _)| ((0..), Span::raw(name.to_owned())))
.collect()
}

Expand All @@ -387,7 +388,7 @@ pub mod completers {

fuzzy_match(input, commands, false)
.into_iter()
.map(|(name, _)| ((0..), name.to_owned().into()))
.map(|(name, _)| ((0..), Span::raw(name.to_owned())))
.collect()
}

Expand Down Expand Up @@ -424,7 +425,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 @@ -506,18 +507,31 @@ pub mod completers {
}) // TODO: unwrap or skip
.filter(|path| !path.is_empty());

// TODO: use a custom theme key e.g. "ui.text.directory"
let directory_color = editor.theme.get("function");

let style_from_file = |file: Cow<'static, str>| {
if file.ends_with(std::path::MAIN_SEPARATOR) {
NikitaRevenco marked this conversation as resolved.
Show resolved Hide resolved
Span::styled(file, directory_color)
} else {
Span::raw(file)
}
};

// 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 All @@ -532,7 +546,7 @@ pub mod completers {

fuzzy_match(input, iter, false)
.into_iter()
.map(|(name, _)| ((0..), name.into()))
.map(|(name, _)| ((0..), Span::raw(name)))
.collect()
}
}
30 changes: 20 additions & 10 deletions helix-term/src/ui/prompt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,11 @@ use helix_core::syntax;
use helix_view::document::Mode;
use helix_view::input::KeyEvent;
use helix_view::keyboard::KeyCode;
use helix_view::theme::Style;
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 +21,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 @@ -382,7 +385,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 @@ -398,7 +401,7 @@ impl Prompt {
pub fn render_prompt(&self, area: Rect, surface: &mut Surface, cx: &mut Context) {
let theme = &cx.editor.theme;
let prompt_color = theme.get("ui.text");
let completion_color = theme.get("ui.menu");
let default_completion_color = theme.get("ui.menu");
let selected_color = theme.get("ui.menu.selected");
let suggestion_color = theme.get("ui.text.inactive");
let background = theme.get("ui.background");
Expand All @@ -407,7 +410,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 @@ -446,18 +449,25 @@ 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 has_custom_style = completion.style != Style::default();

let completion_item_style = if is_selected {
selected_color
} else if has_custom_style {
completion.style
} else {
completion_color
default_completion_color
NikitaRevenco marked this conversation as resolved.
Show resolved Hide resolved
};

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 Expand Up @@ -654,7 +664,7 @@ impl Component for Prompt {
.editor
.registers
.iter_preview()
.map(|(ch, preview)| (0.., format!("{} {}", ch, &preview).into()))
.map(|(ch, preview)| (0.., Span::raw(format!("{} {}", ch, &preview))))
.collect();
self.next_char_handler = Some(Box::new(|prompt, c, context| {
prompt.insert_str(
Expand Down
Loading