Skip to content

Commit a473e02

Browse files
committed
feature: allow to close document from buffer picker
1 parent 74075bb commit a473e02

File tree

2 files changed

+59
-18
lines changed

2 files changed

+59
-18
lines changed

helix-term/src/commands.rs

Lines changed: 36 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ use helix_core::{
4646
};
4747
use helix_view::{
4848
document::{FormatterError, Mode, SCRATCH_BUFFER_NAME},
49-
editor::Action,
49+
editor::{Action, CloseError},
5050
expansion,
5151
info::Info,
5252
input::KeyEvent,
@@ -3157,8 +3157,6 @@ fn file_explorer_in_current_directory(cx: &mut Context) {
31573157
}
31583158

31593159
fn buffer_picker(cx: &mut Context) {
3160-
let current = view!(cx.editor).doc;
3161-
31623160
struct BufferMeta {
31633161
id: DocumentId,
31643162
path: Option<PathBuf>,
@@ -3167,23 +3165,30 @@ fn buffer_picker(cx: &mut Context) {
31673165
focused_at: std::time::Instant,
31683166
}
31693167

3170-
let new_meta = |doc: &Document| BufferMeta {
3171-
id: doc.id(),
3172-
path: doc.path().cloned(),
3173-
is_modified: doc.is_modified(),
3174-
is_current: doc.id() == current,
3175-
focused_at: doc.focused_at,
3176-
};
3168+
let get_items = |editor: &Editor| -> Vec<BufferMeta> {
3169+
let current = view!(editor).doc;
31773170

3178-
let mut items = cx
3179-
.editor
3180-
.documents
3181-
.values()
3182-
.map(new_meta)
3183-
.collect::<Vec<BufferMeta>>();
3171+
let new_meta = |doc: &Document| BufferMeta {
3172+
id: doc.id(),
3173+
path: doc.path().cloned(),
3174+
is_modified: doc.is_modified(),
3175+
is_current: doc.id() == current,
3176+
focused_at: doc.focused_at,
3177+
};
31843178

3185-
// mru
3186-
items.sort_unstable_by_key(|item| std::cmp::Reverse(item.focused_at));
3179+
let mut items = editor
3180+
.documents
3181+
.values()
3182+
.map(new_meta)
3183+
.collect::<Vec<BufferMeta>>();
3184+
3185+
// mru
3186+
items.sort_unstable_by_key(|item| std::cmp::Reverse(item.focused_at));
3187+
3188+
items
3189+
};
3190+
3191+
let items = get_items(cx.editor);
31873192

31883193
let columns = [
31893194
PickerColumn::new("id", |meta: &BufferMeta, _| meta.id.to_string().into()),
@@ -3234,6 +3239,19 @@ fn buffer_picker(cx: &mut Context) {
32343239
(cursor_line, cursor_line)
32353240
});
32363241
Some((meta.id.into(), lines))
3242+
})
3243+
.with_delete_item(move |editor, meta| {
3244+
if let Err(err) = editor.close_document(meta.id, false) {
3245+
editor.set_error(match err {
3246+
CloseError::BufferModified(s) => format!("Could not close modified buffer: {}", s),
3247+
CloseError::SaveError(s) => format!("Could not close buffer: {}", s),
3248+
CloseError::DoesNotExist => "Buffer does not exist".to_owned(),
3249+
});
3250+
} else {
3251+
editor.clear_status();
3252+
}
3253+
3254+
get_items(editor)
32373255
});
32383256
cx.push_layer(Box::new(overlaid(picker)));
32393257
}

helix-term/src/ui/picker.rs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,8 @@ pub struct Picker<T: 'static + Send + Sync, D: 'static> {
269269
/// An event handler for syntax highlighting the currently previewed file.
270270
preview_highlight_handler: Sender<Arc<Path>>,
271271
dynamic_query_handler: Option<Sender<DynamicQueryChange>>,
272+
/// Called to delete an item from the picker's list.
273+
delete_item_fn: Option<PickerDeleteItem<T>>,
272274
}
273275

274276
impl<T: 'static + Send + Sync, D: 'static + Send + Sync> Picker<T, D> {
@@ -394,6 +396,7 @@ impl<T: 'static + Send + Sync, D: 'static + Send + Sync> Picker<T, D> {
394396
file_fn: None,
395397
preview_highlight_handler: PreviewHighlightHandler::<T, D>::default().spawn(),
396398
dynamic_query_handler: None,
399+
delete_item_fn: None,
397400
}
398401
}
399402

@@ -434,6 +437,11 @@ impl<T: 'static + Send + Sync, D: 'static + Send + Sync> Picker<T, D> {
434437
self
435438
}
436439

440+
pub fn with_delete_item(mut self, f: impl Fn(&mut Editor, &T) -> Vec<T> + 'static) -> Self {
441+
self.delete_item_fn = Some(Box::new(f));
442+
self
443+
}
444+
437445
pub fn with_dynamic_query(
438446
mut self,
439447
callback: DynQueryCallback<T, D>,
@@ -1143,6 +1151,20 @@ impl<I: 'static + Send + Sync, D: 'static + Send + Sync> Component for Picker<I,
11431151
ctrl!('t') => {
11441152
self.toggle_preview();
11451153
}
1154+
alt!('d') | key!(Delete) => {
1155+
if let Some(option) = self.selection() {
1156+
if let Some(delete_fn) = &self.delete_item_fn {
1157+
let new_items = delete_fn(ctx.editor, option);
1158+
let new_len = new_items.len() as u32;
1159+
self.matcher.restart(false);
1160+
let injector = self.matcher.injector();
1161+
for item in new_items {
1162+
inject_nucleo_item(&injector, &self.columns, item, &self.editor_data);
1163+
}
1164+
self.cursor = self.cursor.min(new_len.saturating_sub(1));
1165+
}
1166+
}
1167+
}
11461168
_ => {
11471169
self.prompt_handle_event(event, ctx);
11481170
}
@@ -1187,3 +1209,4 @@ impl<T: 'static + Send + Sync, D> Drop for Picker<T, D> {
11871209
}
11881210

11891211
type PickerCallback<T> = Box<dyn Fn(&mut Context, &T, Action)>;
1212+
type PickerDeleteItem<T> = Box<dyn Fn(&mut Editor, &T) -> Vec<T>>;

0 commit comments

Comments
 (0)