Skip to content

Commit b3b0c64

Browse files
xJonathanLEIwongjiahauthe-mikedavispascalkuthe
authored andcommitted
Changed file picker (helix-editor#5645)
Co-authored-by: WJH <[email protected]> Co-authored-by: Michael Davis <[email protected]> Co-authored-by: Pascal Kuthe <[email protected]>
1 parent 96b59d4 commit b3b0c64

File tree

9 files changed

+380
-24
lines changed

9 files changed

+380
-24
lines changed

Diff for: Cargo.lock

+67
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Diff for: book/src/themes.md

+1
Original file line numberDiff line numberDiff line change
@@ -251,6 +251,7 @@ We use a similar set of scopes as
251251
- `gutter` - gutter indicator
252252
- `delta` - modifications
253253
- `moved` - renamed or moved files/changes
254+
- `conflict` - merge conflicts
254255
- `gutter` - gutter indicator
255256

256257
#### Interface

Diff for: helix-term/src/commands.rs

+97-3
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,14 @@ pub(crate) mod lsp;
33
pub(crate) mod typed;
44

55
pub use dap::*;
6+
use helix_event::status;
67
use helix_stdx::rope::{self, RopeSliceExt};
7-
use helix_vcs::Hunk;
8+
use helix_vcs::{FileChange, Hunk};
89
pub use lsp::*;
9-
use tui::widgets::Row;
10+
use tui::{
11+
text::Span,
12+
widgets::{Cell, Row},
13+
};
1014
pub use typed::*;
1115

1216
use helix_core::{
@@ -39,6 +43,7 @@ use helix_view::{
3943
info::Info,
4044
input::KeyEvent,
4145
keyboard::KeyCode,
46+
theme::Style,
4247
tree,
4348
view::View,
4449
Document, DocumentId, Editor, ViewId,
@@ -54,7 +59,7 @@ use crate::{
5459
filter_picker_entry,
5560
job::Callback,
5661
keymap::ReverseKeymap,
57-
ui::{self, overlay::overlaid, Picker, Popup, Prompt, PromptEvent},
62+
ui::{self, menu::Item, overlay::overlaid, Picker, Popup, Prompt, PromptEvent},
5863
};
5964

6065
use crate::job::{self, Jobs};
@@ -324,6 +329,7 @@ impl MappableCommand {
324329
buffer_picker, "Open buffer picker",
325330
jumplist_picker, "Open jumplist picker",
326331
symbol_picker, "Open symbol picker",
332+
changed_file_picker, "Open changed file picker",
327333
select_references_to_symbol_under_cursor, "Select symbol references",
328334
workspace_symbol_picker, "Open workspace symbol picker",
329335
diagnostics_picker, "Open diagnostic picker",
@@ -2996,6 +3002,94 @@ fn jumplist_picker(cx: &mut Context) {
29963002
cx.push_layer(Box::new(overlaid(picker)));
29973003
}
29983004

3005+
fn changed_file_picker(cx: &mut Context) {
3006+
pub struct FileChangeData {
3007+
cwd: PathBuf,
3008+
style_untracked: Style,
3009+
style_modified: Style,
3010+
style_conflict: Style,
3011+
style_deleted: Style,
3012+
style_renamed: Style,
3013+
}
3014+
3015+
impl Item for FileChange {
3016+
type Data = FileChangeData;
3017+
3018+
fn format(&self, data: &Self::Data) -> Row {
3019+
let process_path = |path: &PathBuf| {
3020+
path.strip_prefix(&data.cwd)
3021+
.unwrap_or(path)
3022+
.display()
3023+
.to_string()
3024+
};
3025+
3026+
let (sign, style, content) = match self {
3027+
Self::Untracked { path } => ("[+]", data.style_untracked, process_path(path)),
3028+
Self::Modified { path } => ("[~]", data.style_modified, process_path(path)),
3029+
Self::Conflict { path } => ("[x]", data.style_conflict, process_path(path)),
3030+
Self::Deleted { path } => ("[-]", data.style_deleted, process_path(path)),
3031+
Self::Renamed { from_path, to_path } => (
3032+
"[>]",
3033+
data.style_renamed,
3034+
format!("{} -> {}", process_path(from_path), process_path(to_path)),
3035+
),
3036+
};
3037+
3038+
Row::new([Cell::from(Span::styled(sign, style)), Cell::from(content)])
3039+
}
3040+
}
3041+
3042+
let cwd = helix_stdx::env::current_working_dir();
3043+
if !cwd.exists() {
3044+
cx.editor
3045+
.set_error("Current working directory does not exist");
3046+
return;
3047+
}
3048+
3049+
let added = cx.editor.theme.get("diff.plus");
3050+
let modified = cx.editor.theme.get("diff.delta");
3051+
let conflict = cx.editor.theme.get("diff.delta.conflict");
3052+
let deleted = cx.editor.theme.get("diff.minus");
3053+
let renamed = cx.editor.theme.get("diff.delta.moved");
3054+
3055+
let picker = Picker::new(
3056+
Vec::new(),
3057+
FileChangeData {
3058+
cwd: cwd.clone(),
3059+
style_untracked: added,
3060+
style_modified: modified,
3061+
style_conflict: conflict,
3062+
style_deleted: deleted,
3063+
style_renamed: renamed,
3064+
},
3065+
|cx, meta: &FileChange, action| {
3066+
let path_to_open = meta.path();
3067+
if let Err(e) = cx.editor.open(path_to_open, action) {
3068+
let err = if let Some(err) = e.source() {
3069+
format!("{}", err)
3070+
} else {
3071+
format!("unable to open \"{}\"", path_to_open.display())
3072+
};
3073+
cx.editor.set_error(err);
3074+
}
3075+
},
3076+
)
3077+
.with_preview(|_editor, meta| Some((meta.path().to_path_buf().into(), None)));
3078+
let injector = picker.injector();
3079+
3080+
cx.editor
3081+
.diff_providers
3082+
.clone()
3083+
.for_each_changed_file(cwd, move |change| match change {
3084+
Ok(change) => injector.push(change).is_ok(),
3085+
Err(err) => {
3086+
status::report_blocking(err);
3087+
true
3088+
}
3089+
});
3090+
cx.push_layer(Box::new(overlaid(picker)));
3091+
}
3092+
29993093
impl ui::menu::Item for MappableCommand {
30003094
type Data = ReverseKeymap;
30013095

Diff for: helix-term/src/keymap/default.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -225,9 +225,10 @@ pub fn default() -> HashMap<Mode, KeyTrie> {
225225
"S" => workspace_symbol_picker,
226226
"d" => diagnostics_picker,
227227
"D" => workspace_diagnostics_picker,
228+
"g" => changed_file_picker,
228229
"a" => code_action,
229230
"'" => last_picker,
230-
"g" => { "Debug (experimental)" sticky=true
231+
"G" => { "Debug (experimental)" sticky=true
231232
"l" => dap_launch,
232233
"r" => dap_restart,
233234
"b" => dap_toggle_breakpoint,

Diff for: helix-vcs/Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ tokio = { version = "1", features = ["rt", "rt-multi-thread", "time", "sync", "p
1919
parking_lot = "0.12"
2020
arc-swap = { version = "1.7.1" }
2121

22-
gix = { version = "0.61.0", features = ["attributes"], default-features = false, optional = true }
22+
gix = { version = "0.61.0", features = ["attributes", "status"], default-features = false, optional = true }
2323
imara-diff = "0.1.5"
2424
anyhow = "1"
2525

0 commit comments

Comments
 (0)