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

Changed file picker #5645

Merged
merged 15 commits into from Mar 31, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
67 changes: 67 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions book/src/themes.md
Expand Up @@ -251,6 +251,7 @@ We use a similar set of scopes as
- `gutter` - gutter indicator
- `delta` - modifications
- `moved` - renamed or moved files/changes
- `conflict` - merge conflicts
- `gutter` - gutter indicator

#### Interface
Expand Down
100 changes: 97 additions & 3 deletions helix-term/src/commands.rs
Expand Up @@ -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::{
Expand Down Expand Up @@ -39,6 +43,7 @@ use helix_view::{
info::Info,
input::KeyEvent,
keyboard::KeyCode,
theme::Style,
tree,
view::View,
Document, DocumentId, Editor, ViewId,
Expand All @@ -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};
Expand Down Expand Up @@ -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",
Expand Down Expand Up @@ -2994,6 +3000,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)),
),
};
Comment on lines +3024 to +3034
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For #9647 we will want to change the UI slightly. Like the symbol pickers instead of adding icons / glyphs for each kind of change I prefer words, so the symbols don't need a legend. I have this merged into my driver branch with a UI like this:

foo3

so that the symbols stay but are accompanied by a git status-like description of the change. But we can hash this out on #9647 once I rebase rather than here


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;

Expand Down
3 changes: 2 additions & 1 deletion helix-term/src/keymap/default.rs
Expand Up @@ -223,9 +223,10 @@ pub fn default() -> HashMap<Mode, KeyTrie> {
"S" => workspace_symbol_picker,
"d" => diagnostics_picker,
"D" => workspace_diagnostics_picker,
"g" => changed_file_picker,
"a" => code_action,
"'" => last_picker,
"g" => { "Debug (experimental)" sticky=true
"G" => { "Debug (experimental)" sticky=true
"l" => dap_launch,
"r" => dap_restart,
"b" => dap_toggle_breakpoint,
Expand Down
2 changes: 1 addition & 1 deletion helix-vcs/Cargo.toml
Expand Up @@ -19,7 +19,7 @@ tokio = { version = "1", features = ["rt", "rt-multi-thread", "time", "sync", "p
parking_lot = "0.12"
arc-swap = { version = "1.7.0" }

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

Expand Down