ui: buffer picker on ctrl-b

pull/8/head
Blaž Hrastnik 4 years ago
parent ea502c8665
commit 3d3295bb75

@ -297,9 +297,11 @@ pub fn split_selection(cx: &mut Context) {
}, },
); );
cx.callback = Some(Box::new(move |compositor: &mut Compositor| { cx.callback = Some(Box::new(
compositor.push(Box::new(prompt)); move |compositor: &mut Compositor, editor: &mut Editor| {
})); compositor.push(Box::new(prompt));
},
));
} }
pub fn split_selection_on_newline(cx: &mut Context) { pub fn split_selection_on_newline(cx: &mut Context) {
@ -399,12 +401,13 @@ pub fn append_mode(cx: &mut Context) {
// TODO: I, A, o and O can share a lot of the primitives. // TODO: I, A, o and O can share a lot of the primitives.
pub fn command_mode(cx: &mut Context) { pub fn command_mode(cx: &mut Context) {
cx.callback = Some(Box::new(|compositor: &mut Compositor| { cx.callback = Some(Box::new(
let prompt = Prompt::new( |compositor: &mut Compositor, editor: &mut Editor| {
":".to_owned(), let prompt = Prompt::new(
|_input: &str| { ":".to_owned(),
// TODO: i need this duplicate list right now to avoid borrow checker issues |_input: &str| {
let command_list = vec![ // TODO: i need this duplicate list right now to avoid borrow checker issues
let command_list = vec![
String::from("q"), String::from("q"),
String::from("aaa"), String::from("aaa"),
String::from("bbb"), String::from("bbb"),
@ -437,37 +440,49 @@ pub fn command_mode(cx: &mut Context) {
String::from("ddd"), String::from("ddd"),
String::from("eee"), String::from("eee"),
]; ];
command_list command_list
.into_iter() .into_iter()
.filter(|command| command.contains(_input)) .filter(|command| command.contains(_input))
.collect() .collect()
}, // completion }, // completion
|editor: &mut Editor, input: &str, event: PromptEvent| { |editor: &mut Editor, input: &str, event: PromptEvent| {
if event != PromptEvent::Validate { if event != PromptEvent::Validate {
return; return;
} }
let parts = input.split_ascii_whitespace().collect::<Vec<&str>>(); let parts = input.split_ascii_whitespace().collect::<Vec<&str>>();
match parts.as_slice() { match parts.as_slice() {
&["q"] => editor.should_close = true, &["q"] => editor.should_close = true,
&["o", path] => { &["o", path] => {
// TODO: make view()/view_mut() always contain a view. // TODO: make view()/view_mut() always contain a view.
let size = editor.view().unwrap().size; let size = editor.view().unwrap().size;
editor.open(path.into(), size); editor.open(path.into(), size);
}
_ => (),
} }
_ => (), },
} );
}, compositor.push(Box::new(prompt));
); },
compositor.push(Box::new(prompt)); ));
}));
} }
pub fn file_picker(cx: &mut Context) { pub fn file_picker(cx: &mut Context) {
cx.callback = Some(Box::new(|compositor: &mut Compositor| { cx.callback = Some(Box::new(
let picker = ui::file_picker("./"); |compositor: &mut Compositor, editor: &mut Editor| {
compositor.push(Box::new(picker)); let picker = ui::file_picker("./");
})); compositor.push(Box::new(picker));
},
));
}
pub fn buffer_picker(cx: &mut Context) {
cx.callback = Some(Box::new(
|compositor: &mut Compositor, editor: &mut Editor| {
let picker = ui::buffer_picker(&editor.views, editor.focus);
compositor.push(Box::new(picker));
},
));
} }
// calculate line numbers for each selection range // calculate line numbers for each selection range

@ -19,7 +19,7 @@ use smol::Executor;
use tui::buffer::Buffer as Surface; use tui::buffer::Buffer as Surface;
use tui::layout::Rect; use tui::layout::Rect;
pub type Callback = Box<dyn FnOnce(&mut Compositor)>; pub type Callback = Box<dyn FnOnce(&mut Compositor, &mut Editor)>;
// --> EventResult should have a callback that takes a context with methods like .popup(), // --> EventResult should have a callback that takes a context with methods like .popup(),
// .prompt() etc. That way we can abstract it from the renderer. // .prompt() etc. That way we can abstract it from the renderer.
@ -128,7 +128,7 @@ impl Compositor {
if let Some(layer) = self.layers.last_mut() { if let Some(layer) = self.layers.last_mut() {
return match layer.handle_event(event, cx) { return match layer.handle_event(event, cx) {
EventResult::Consumed(Some(callback)) => { EventResult::Consumed(Some(callback)) => {
callback(self); callback(self, cx.editor);
true true
} }
EventResult::Consumed(None) => true, EventResult::Consumed(None) => true,

@ -185,6 +185,7 @@ pub fn default() -> Keymaps {
vec![ctrl!('d')] => commands::half_page_down, vec![ctrl!('d')] => commands::half_page_down,
vec![ctrl!('p')] => commands::file_picker, vec![ctrl!('p')] => commands::file_picker,
vec![ctrl!('b')] => commands::buffer_picker,
), ),
Mode::Insert => hashmap!( Mode::Insert => hashmap!(
vec![Key { vec![Key {

@ -15,7 +15,7 @@ pub fn text_color() -> Style {
Style::default().fg(Color::Rgb(219, 191, 239)) // lilac Style::default().fg(Color::Rgb(219, 191, 239)) // lilac
} }
use std::path::PathBuf; use std::path::{Path, PathBuf};
pub fn file_picker(root: &str) -> Picker<PathBuf> { pub fn file_picker(root: &str) -> Picker<PathBuf> {
use ignore::Walk; use ignore::Walk;
// TODO: determine root based on git root // TODO: determine root based on git root
@ -38,7 +38,7 @@ pub fn file_picker(root: &str) -> Picker<PathBuf> {
files.take(MAX).collect(), files.take(MAX).collect(),
|path: &PathBuf| { |path: &PathBuf| {
// format_fn // format_fn
path.strip_prefix("./").unwrap().to_str().unwrap() // TODO: render paths without ./ path.strip_prefix("./").unwrap().to_str().unwrap()
}, },
|editor: &mut Editor, path: &PathBuf| { |editor: &mut Editor, path: &PathBuf| {
let size = editor.view().unwrap().size; let size = editor.view().unwrap().size;
@ -46,3 +46,27 @@ pub fn file_picker(root: &str) -> Picker<PathBuf> {
}, },
) )
} }
use helix_view::View;
pub fn buffer_picker(views: &[View], current: usize) -> Picker<(Option<PathBuf>, usize)> {
use helix_view::Editor;
Picker::new(
views
.iter()
.enumerate()
.map(|(i, view)| (view.doc.relative_path().map(Path::to_path_buf), i))
.collect(),
|(path, index): &(Option<PathBuf>, usize)| {
// format_fn
match path {
Some(path) => path.to_str().unwrap(),
None => "[NEW]",
}
},
|editor: &mut Editor, &(_, index): &(Option<PathBuf>, usize)| {
if index < editor.views.len() {
editor.focus = index;
}
},
)
}

@ -123,10 +123,12 @@ impl<T> Component for Picker<T> {
_ => return EventResult::Ignored, _ => return EventResult::Ignored,
}; };
let close_fn = EventResult::Consumed(Some(Box::new(|compositor: &mut Compositor| { let close_fn = EventResult::Consumed(Some(Box::new(
// remove the layer |compositor: &mut Compositor, editor: &mut Editor| {
compositor.pop(); // remove the layer
}))); compositor.pop();
},
)));
match key_event { match key_event {
// KeyEvent { // KeyEvent {

@ -167,10 +167,12 @@ impl Component for Prompt {
_ => return EventResult::Ignored, _ => return EventResult::Ignored,
}; };
let close_fn = EventResult::Consumed(Some(Box::new(|compositor: &mut Compositor| { let close_fn = EventResult::Consumed(Some(Box::new(
// remove the layer |compositor: &mut Compositor, editor: &mut Editor| {
compositor.pop(); // remove the layer
}))); compositor.pop();
},
)));
match event { match event {
KeyEvent { KeyEvent {

Loading…
Cancel
Save