ui: buffer picker on ctrl-b
This commit is contained in:
parent
ea502c8665
commit
3d3295bb75
6 changed files with 93 additions and 49 deletions
|
@ -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>>();
|
|
||||||
|
|
||||||
match parts.as_slice() {
|
|
||||||
&["q"] => editor.should_close = true,
|
|
||||||
&["o", path] => {
|
|
||||||
// TODO: make view()/view_mut() always contain a view.
|
|
||||||
let size = editor.view().unwrap().size;
|
|
||||||
editor.open(path.into(), size);
|
|
||||||
}
|
}
|
||||||
_ => (),
|
|
||||||
}
|
let parts = input.split_ascii_whitespace().collect::<Vec<&str>>();
|
||||||
},
|
|
||||||
);
|
match parts.as_slice() {
|
||||||
compositor.push(Box::new(prompt));
|
&["q"] => editor.should_close = true,
|
||||||
}));
|
&["o", path] => {
|
||||||
|
// TODO: make view()/view_mut() always contain a view.
|
||||||
|
let size = editor.view().unwrap().size;
|
||||||
|
editor.open(path.into(), size);
|
||||||
|
}
|
||||||
|
_ => (),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
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…
Add table
Reference in a new issue