Skip to content

Commit 291fdf3

Browse files
committed
sort codeaction by their kind instead of alphabetically
1 parent 4d4be0e commit 291fdf3

File tree

3 files changed

+64
-25
lines changed

3 files changed

+64
-25
lines changed

helix-term/src/commands/lsp.rs

Lines changed: 56 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -452,43 +452,77 @@ pub fn code_action(cx: &mut Context) {
452452
cx.callback(
453453
future,
454454
move |editor, compositor, response: Option<lsp::CodeActionResponse>| {
455-
let actions = match response {
455+
let mut actions = match response {
456456
Some(a) => a,
457457
None => return,
458458
};
459+
459460
if actions.is_empty() {
460461
editor.set_status("No code actions available");
461462
return;
462463
}
463464

464-
let mut picker = ui::Menu::new(actions, (), move |editor, code_action, event| {
465-
if event != PromptEvent::Validate {
466-
return;
467-
}
465+
// sort by CodeActionKind
466+
// this ensures that the most relevant codeactions (quickfix) show up first
467+
// while more situational commands (like refactors) show up later
468+
// this behaviour is modeled after the behaviour of vscode (editor/contrib/codeAction/browser/codeActionWidget.ts)
469+
470+
let mut categories = vec![Vec::new(); 8];
471+
for action in actions.drain(..) {
472+
let category = match &action {
473+
lsp::CodeActionOrCommand::CodeAction(lsp::CodeAction {
474+
kind: Some(kind),
475+
..
476+
}) => match kind.as_str() {
477+
"quickfix" => 0,
478+
"refactor.extract" => 1,
479+
"refactor.inline" => 2,
480+
"refactor.rewrite" => 3,
481+
"refactor.move" => 4,
482+
"refactor.surround" => 5,
483+
"source" => 6,
484+
_ => 7,
485+
},
486+
_ => 7,
487+
};
488+
log::error!("{category}");
468489

469-
// always present here
470-
let code_action = code_action.unwrap();
490+
categories[category].push(action);
491+
}
492+
493+
for category in categories {
494+
actions.extend(category.into_iter())
495+
}
471496

472-
match code_action {
473-
lsp::CodeActionOrCommand::Command(command) => {
474-
log::debug!("code action command: {:?}", command);
475-
execute_lsp_command(editor, command.clone());
497+
let mut picker =
498+
ui::Menu::new(actions, false, (), move |editor, code_action, event| {
499+
if event != PromptEvent::Validate {
500+
return;
476501
}
477-
lsp::CodeActionOrCommand::CodeAction(code_action) => {
478-
log::debug!("code action: {:?}", code_action);
479-
if let Some(ref workspace_edit) = code_action.edit {
480-
log::debug!("edit: {:?}", workspace_edit);
481-
apply_workspace_edit(editor, offset_encoding, workspace_edit);
482-
}
483502

484-
// if code action provides both edit and command first the edit
485-
// should be applied and then the command
486-
if let Some(command) = &code_action.command {
503+
// always present here
504+
let code_action = code_action.unwrap();
505+
506+
match code_action {
507+
lsp::CodeActionOrCommand::Command(command) => {
508+
log::debug!("code action command: {:?}", command);
487509
execute_lsp_command(editor, command.clone());
488510
}
511+
lsp::CodeActionOrCommand::CodeAction(code_action) => {
512+
log::debug!("code action: {:?}", code_action);
513+
if let Some(ref workspace_edit) = code_action.edit {
514+
log::debug!("edit: {:?}", workspace_edit);
515+
apply_workspace_edit(editor, offset_encoding, workspace_edit);
516+
}
517+
518+
// if code action provides both edit and command first the edit
519+
// should be applied and then the command
520+
if let Some(command) = &code_action.command {
521+
execute_lsp_command(editor, command.clone());
522+
}
523+
}
489524
}
490-
}
491-
});
525+
});
492526
picker.move_down(); // pre-select the first item
493527

494528
let popup = Popup::new("code-action", picker);

helix-term/src/ui/completion.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ impl Completion {
9797
start_offset: usize,
9898
trigger_offset: usize,
9999
) -> Self {
100-
let menu = Menu::new(items, (), move |editor: &mut Editor, item, event| {
100+
let menu = Menu::new(items, true, (), move |editor: &mut Editor, item, event| {
101101
fn item_to_transaction(
102102
doc: &Document,
103103
item: &CompletionItem,

helix-term/src/ui/menu.rs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ impl<T: Item> Menu<T> {
7474
// rendering)
7575
pub fn new(
7676
options: Vec<T>,
77+
sort: bool,
7778
editor_data: <T as Item>::Data,
7879
callback_fn: impl Fn(&mut Editor, Option<&T>, MenuEvent) + 'static,
7980
) -> Self {
@@ -91,8 +92,12 @@ impl<T: Item> Menu<T> {
9192
recalculate: true,
9293
};
9394

94-
// TODO: scoring on empty input should just use a fastpath
95-
menu.score("");
95+
if sort {
96+
// TODO: scoring on empty input should just use a fastpath
97+
menu.score("");
98+
} else {
99+
menu.matches = (0..menu.options.len()).map(|i| (i, 0)).collect();
100+
}
96101

97102
menu
98103
}

0 commit comments

Comments
 (0)