Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'helix-term/src/commands.rs')
| -rw-r--r-- | helix-term/src/commands.rs | 100 |
1 files changed, 97 insertions, 3 deletions
diff --git a/helix-term/src/commands.rs b/helix-term/src/commands.rs index d927d3f4..d0b9047c 100644 --- a/helix-term/src/commands.rs +++ b/helix-term/src/commands.rs @@ -3,10 +3,14 @@ pub(crate) mod lsp; pub(crate) mod typed; pub use dap::*; +use helix_event::status; use helix_stdx::rope::{self, RopeSliceExt}; -use helix_vcs::Hunk; +use helix_vcs::{FileChange, Hunk}; pub use lsp::*; -use tui::widgets::Row; +use tui::{ + text::Span, + widgets::{Cell, Row}, +}; pub use typed::*; use helix_core::{ @@ -39,6 +43,7 @@ use helix_view::{ info::Info, input::KeyEvent, keyboard::KeyCode, + theme::Style, tree, view::View, Document, DocumentId, Editor, ViewId, @@ -54,7 +59,7 @@ use crate::{ filter_picker_entry, job::Callback, keymap::ReverseKeymap, - ui::{self, overlay::overlaid, Picker, Popup, Prompt, PromptEvent}, + ui::{self, menu::Item, overlay::overlaid, Picker, Popup, Prompt, PromptEvent}, }; use crate::job::{self, Jobs}; @@ -324,6 +329,7 @@ impl MappableCommand { buffer_picker, "Open buffer picker", jumplist_picker, "Open jumplist picker", symbol_picker, "Open symbol picker", + changed_file_picker, "Open changed file picker", select_references_to_symbol_under_cursor, "Select symbol references", workspace_symbol_picker, "Open workspace symbol picker", diagnostics_picker, "Open diagnostic picker", @@ -2996,6 +3002,94 @@ fn jumplist_picker(cx: &mut Context) { cx.push_layer(Box::new(overlaid(picker))); } +fn changed_file_picker(cx: &mut Context) { + pub struct FileChangeData { + cwd: PathBuf, + style_untracked: Style, + style_modified: Style, + style_conflict: Style, + style_deleted: Style, + style_renamed: Style, + } + + impl Item for FileChange { + type Data = FileChangeData; + + fn format(&self, data: &Self::Data) -> Row { + let process_path = |path: &PathBuf| { + path.strip_prefix(&data.cwd) + .unwrap_or(path) + .display() + .to_string() + }; + + let (sign, style, content) = match self { + Self::Untracked { path } => ("[+]", data.style_untracked, process_path(path)), + Self::Modified { path } => ("[~]", data.style_modified, process_path(path)), + Self::Conflict { path } => ("[x]", data.style_conflict, process_path(path)), + Self::Deleted { path } => ("[-]", data.style_deleted, process_path(path)), + Self::Renamed { from_path, to_path } => ( + "[>]", + data.style_renamed, + format!("{} -> {}", process_path(from_path), process_path(to_path)), + ), + }; + + Row::new([Cell::from(Span::styled(sign, style)), Cell::from(content)]) + } + } + + let cwd = helix_stdx::env::current_working_dir(); + if !cwd.exists() { + cx.editor + .set_error("Current working directory does not exist"); + return; + } + + let added = cx.editor.theme.get("diff.plus"); + let modified = cx.editor.theme.get("diff.delta"); + let conflict = cx.editor.theme.get("diff.delta.conflict"); + let deleted = cx.editor.theme.get("diff.minus"); + let renamed = cx.editor.theme.get("diff.delta.moved"); + + let picker = Picker::new( + Vec::new(), + FileChangeData { + cwd: cwd.clone(), + style_untracked: added, + style_modified: modified, + style_conflict: conflict, + style_deleted: deleted, + style_renamed: renamed, + }, + |cx, meta: &FileChange, action| { + let path_to_open = meta.path(); + if let Err(e) = cx.editor.open(path_to_open, action) { + let err = if let Some(err) = e.source() { + format!("{}", err) + } else { + format!("unable to open \"{}\"", path_to_open.display()) + }; + cx.editor.set_error(err); + } + }, + ) + .with_preview(|_editor, meta| Some((meta.path().to_path_buf().into(), None))); + let injector = picker.injector(); + + cx.editor + .diff_providers + .clone() + .for_each_changed_file(cwd, move |change| match change { + Ok(change) => injector.push(change).is_ok(), + Err(err) => { + status::report_blocking(err); + true + } + }); + cx.push_layer(Box::new(overlaid(picker))); +} + impl ui::menu::Item for MappableCommand { type Data = ReverseKeymap; |