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

Implement change picker #7990

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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
1 change: 1 addition & 0 deletions book/src/keymap.md
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,7 @@ This layer is a kludge of mappings, mostly pickers.
| `S` | Open workspace symbol picker (**LSP**) | `workspace_symbol_picker` |
| `d` | Open document diagnostics picker (**LSP**) | `diagnostics_picker` |
| `D` | Open workspace diagnostics picker (**LSP**) | `workspace_diagnostics_picker` |
| `c` | Open change picker | `change_picker` |
| `r` | Rename symbol (**LSP**) | `rename_symbol` |
| `a` | Apply code action (**LSP**) | `code_action` |
| `h` | Select symbol references (**LSP**) | `select_references_to_symbol_under_cursor` |
Expand Down
78 changes: 77 additions & 1 deletion helix-term/src/commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -316,6 +316,7 @@ impl MappableCommand {
select_references_to_symbol_under_cursor, "Select symbol references",
workspace_symbol_picker, "Open workspace symbol picker",
diagnostics_picker, "Open diagnostic picker",
change_picker, "Open change picker",
workspace_diagnostics_picker, "Open workspace diagnostic picker",
last_picker, "Open last picker",
insert_at_line_start, "Insert at start of line",
Expand Down Expand Up @@ -2619,6 +2620,81 @@ fn file_picker_in_current_directory(cx: &mut Context) {
cx.push_layer(Box::new(overlaid(picker)));
}

fn change_picker(cx: &mut Context) {
struct ChangeMeta {
document_id: DocumentId,
line_number: usize,
text: String,
range: Range,
}

impl ui::menu::Item for ChangeMeta {
type Data = ();

fn format(&self, _data: &Self::Data) -> Row {
Row::new([self.line_number.to_string(), self.text.to_owned()])
}
}

let doc_id = view!(cx.editor).doc;
let document = cx.editor.documents.get(&doc_id);

let items = match (document, document.and_then(|d| d.diff_handle())) {
(Some(document), Some(handle)) => {
let diff = handle.load();
let hunks_count = diff.len();
let mut items: Vec<ChangeMeta> = vec![];

for i in 0..hunks_count {
let current_hunk = diff.nth_hunk(i);
let text = document.text().slice(..);
let current_range = hunk_range(current_hunk.clone(), text);
let position = current_range.cursor(text);
let current_line = text.char_to_line(position);

items.push(ChangeMeta {
document_id: document.id(),
line_number: current_line + 1,
text: document.text().line(current_line).to_string(),
range: current_range,
})
}

items
}
_ => vec![],
};

if items.is_empty() {
cx.editor.set_status("No changes in the current buffer.");
return;
}

let picker = Picker::new(items, (), |cx, item, action| {
let config = cx.editor.config();
let (view, doc) = current!(cx.editor);

doc.set_selection(
view.id,
Selection::single(item.range.anchor, item.range.head),
);

if action.align_view(view, doc.id()) {
view.ensure_cursor_in_view_center(doc, config.scrolloff);
}
})
.with_preview(|editor, meta| {
let doc = &editor.documents.get(&meta.document_id)?;
let text = doc.text().slice(..);
let line_number_start = text.char_to_line(meta.range.from());
let line_number_end = text.char_to_line(meta.range.to()) - 1;

Some((doc.id().into(), Some((line_number_start, line_number_end))))
});

cx.push_layer(Box::new(overlaid(picker)));
}

fn buffer_picker(cx: &mut Context) {
let current = view!(cx.editor).doc;

Expand Down Expand Up @@ -2859,7 +2935,7 @@ pub fn command_palette(cx: &mut Context) {
}

fn last_picker(cx: &mut Context) {
// TODO: last picker does not seem to work well with buffer_picker
// TODO: last picker does not seem to work well with buffer_picker and change_picker
cx.callback = Some(Box::new(|compositor, cx| {
if let Some(picker) = compositor.last_picker.take() {
compositor.push(picker);
Expand Down
1 change: 1 addition & 0 deletions helix-term/src/keymap/default.rs
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,7 @@ pub fn default() -> HashMap<Mode, KeyTrie> {
"S" => workspace_symbol_picker,
"d" => diagnostics_picker,
"D" => workspace_diagnostics_picker,
"c" => change_picker,
"a" => code_action,
"'" => last_picker,
"g" => { "Debug (experimental)" sticky=true
Expand Down