Make file preview callback optional
When Picker and FilePicker are merged, not all Pickers will be able to show a preview. Co-authored-by: Gokul Soumya <gokulps15@gmail.com>
This commit is contained in:
parent
fc111213b5
commit
545acfda88
5 changed files with 119 additions and 136 deletions
|
@ -2184,11 +2184,9 @@ fn global_search(cx: &mut Context) {
|
|||
|
||||
doc.set_selection(view.id, Selection::single(start, end));
|
||||
align_view(doc, view, Align::Center);
|
||||
},
|
||||
|_editor, FileResult { path, line_num }| {
|
||||
}).with_preview(|_editor, FileResult { path, line_num }| {
|
||||
Some((path.clone().into(), Some((*line_num, *line_num))))
|
||||
},
|
||||
);
|
||||
});
|
||||
compositor.push(Box::new(overlaid(picker)));
|
||||
},
|
||||
));
|
||||
|
@ -2579,22 +2577,18 @@ fn buffer_picker(cx: &mut Context) {
|
|||
// mru
|
||||
items.sort_unstable_by_key(|item| std::cmp::Reverse(item.focused_at));
|
||||
|
||||
let picker = FilePicker::new(
|
||||
items,
|
||||
(),
|
||||
|cx, meta, action| {
|
||||
cx.editor.switch(meta.id, action);
|
||||
},
|
||||
|editor, meta| {
|
||||
let doc = &editor.documents.get(&meta.id)?;
|
||||
let &view_id = doc.selections().keys().next()?;
|
||||
let line = doc
|
||||
.selection(view_id)
|
||||
.primary()
|
||||
.cursor_line(doc.text().slice(..));
|
||||
Some((meta.id.into(), Some((line, line))))
|
||||
},
|
||||
);
|
||||
let picker = FilePicker::new(items, (), |cx, meta, action| {
|
||||
cx.editor.switch(meta.id, action);
|
||||
})
|
||||
.with_preview(|editor, meta| {
|
||||
let doc = &editor.documents.get(&meta.id)?;
|
||||
let &view_id = doc.selections().keys().next()?;
|
||||
let line = doc
|
||||
.selection(view_id)
|
||||
.primary()
|
||||
.cursor_line(doc.text().slice(..));
|
||||
Some((meta.id.into(), Some((line, line))))
|
||||
});
|
||||
cx.push_layer(Box::new(overlaid(picker)));
|
||||
}
|
||||
|
||||
|
@ -2678,12 +2672,12 @@ fn jumplist_picker(cx: &mut Context) {
|
|||
doc.set_selection(view.id, meta.selection.clone());
|
||||
view.ensure_cursor_in_view_center(doc, config.scrolloff);
|
||||
},
|
||||
|editor, meta| {
|
||||
let doc = &editor.documents.get(&meta.id)?;
|
||||
let line = meta.selection.primary().cursor_line(doc.text().slice(..));
|
||||
Some((meta.id.into(), Some((line, line))))
|
||||
},
|
||||
);
|
||||
)
|
||||
.with_preview(|editor, meta| {
|
||||
let doc = &editor.documents.get(&meta.id)?;
|
||||
let line = meta.selection.primary().cursor_line(doc.text().slice(..));
|
||||
Some((meta.id.into(), Some((line, line))))
|
||||
});
|
||||
cx.push_layer(Box::new(overlaid(picker)));
|
||||
}
|
||||
|
||||
|
|
|
@ -73,21 +73,19 @@ fn thread_picker(
|
|||
let debugger = debugger!(editor);
|
||||
|
||||
let thread_states = debugger.thread_states.clone();
|
||||
let picker = FilePicker::new(
|
||||
threads,
|
||||
thread_states,
|
||||
move |cx, thread, _action| callback_fn(cx.editor, thread),
|
||||
move |editor, thread| {
|
||||
let frames = editor.debugger.as_ref()?.stack_frames.get(&thread.id)?;
|
||||
let frame = frames.get(0)?;
|
||||
let path = frame.source.as_ref()?.path.clone()?;
|
||||
let pos = Some((
|
||||
frame.line.saturating_sub(1),
|
||||
frame.end_line.unwrap_or(frame.line).saturating_sub(1),
|
||||
));
|
||||
Some((path.into(), pos))
|
||||
},
|
||||
);
|
||||
let picker = FilePicker::new(threads, thread_states, move |cx, thread, _action| {
|
||||
callback_fn(cx.editor, thread)
|
||||
})
|
||||
.with_preview(move |editor, thread| {
|
||||
let frames = editor.debugger.as_ref()?.stack_frames.get(&thread.id)?;
|
||||
let frame = frames.get(0)?;
|
||||
let path = frame.source.as_ref()?.path.clone()?;
|
||||
let pos = Some((
|
||||
frame.line.saturating_sub(1),
|
||||
frame.end_line.unwrap_or(frame.line).saturating_sub(1),
|
||||
));
|
||||
Some((path.into(), pos))
|
||||
});
|
||||
compositor.push(Box::new(picker));
|
||||
},
|
||||
);
|
||||
|
@ -728,39 +726,35 @@ pub fn dap_switch_stack_frame(cx: &mut Context) {
|
|||
|
||||
let frames = debugger.stack_frames[&thread_id].clone();
|
||||
|
||||
let picker = FilePicker::new(
|
||||
frames,
|
||||
(),
|
||||
move |cx, frame, _action| {
|
||||
let debugger = debugger!(cx.editor);
|
||||
// TODO: this should be simpler to find
|
||||
let pos = debugger.stack_frames[&thread_id]
|
||||
.iter()
|
||||
.position(|f| f.id == frame.id);
|
||||
debugger.active_frame = pos;
|
||||
let picker = FilePicker::new(frames, (), move |cx, frame, _action| {
|
||||
let debugger = debugger!(cx.editor);
|
||||
// TODO: this should be simpler to find
|
||||
let pos = debugger.stack_frames[&thread_id]
|
||||
.iter()
|
||||
.position(|f| f.id == frame.id);
|
||||
debugger.active_frame = pos;
|
||||
|
||||
let frame = debugger.stack_frames[&thread_id]
|
||||
.get(pos.unwrap_or(0))
|
||||
.cloned();
|
||||
if let Some(frame) = &frame {
|
||||
jump_to_stack_frame(cx.editor, frame);
|
||||
}
|
||||
},
|
||||
move |_editor, frame| {
|
||||
frame
|
||||
.source
|
||||
.as_ref()
|
||||
.and_then(|source| source.path.clone())
|
||||
.map(|path| {
|
||||
(
|
||||
path.into(),
|
||||
Some((
|
||||
frame.line.saturating_sub(1),
|
||||
frame.end_line.unwrap_or(frame.line).saturating_sub(1),
|
||||
)),
|
||||
)
|
||||
})
|
||||
},
|
||||
);
|
||||
let frame = debugger.stack_frames[&thread_id]
|
||||
.get(pos.unwrap_or(0))
|
||||
.cloned();
|
||||
if let Some(frame) = &frame {
|
||||
jump_to_stack_frame(cx.editor, frame);
|
||||
}
|
||||
})
|
||||
.with_preview(move |_editor, frame| {
|
||||
frame
|
||||
.source
|
||||
.as_ref()
|
||||
.and_then(|source| source.path.clone())
|
||||
.map(|path| {
|
||||
(
|
||||
path.into(),
|
||||
Some((
|
||||
frame.line.saturating_sub(1),
|
||||
frame.end_line.unwrap_or(frame.line).saturating_sub(1),
|
||||
)),
|
||||
)
|
||||
})
|
||||
});
|
||||
cx.push_layer(Box::new(picker))
|
||||
}
|
||||
|
|
|
@ -240,44 +240,40 @@ type SymbolPicker = FilePicker<SymbolInformationItem>;
|
|||
|
||||
fn sym_picker(symbols: Vec<SymbolInformationItem>, current_path: Option<lsp::Url>) -> SymbolPicker {
|
||||
// TODO: drop current_path comparison and instead use workspace: bool flag?
|
||||
FilePicker::new(
|
||||
symbols,
|
||||
current_path.clone(),
|
||||
move |cx, item, action| {
|
||||
let (view, doc) = current!(cx.editor);
|
||||
push_jump(view, doc);
|
||||
FilePicker::new(symbols, current_path.clone(), move |cx, item, action| {
|
||||
let (view, doc) = current!(cx.editor);
|
||||
push_jump(view, doc);
|
||||
|
||||
if current_path.as_ref() != Some(&item.symbol.location.uri) {
|
||||
let uri = &item.symbol.location.uri;
|
||||
let path = match uri.to_file_path() {
|
||||
Ok(path) => path,
|
||||
Err(_) => {
|
||||
let err = format!("unable to convert URI to filepath: {}", uri);
|
||||
cx.editor.set_error(err);
|
||||
return;
|
||||
}
|
||||
};
|
||||
if let Err(err) = cx.editor.open(&path, action) {
|
||||
let err = format!("failed to open document: {}: {}", uri, err);
|
||||
log::error!("{}", err);
|
||||
if current_path.as_ref() != Some(&item.symbol.location.uri) {
|
||||
let uri = &item.symbol.location.uri;
|
||||
let path = match uri.to_file_path() {
|
||||
Ok(path) => path,
|
||||
Err(_) => {
|
||||
let err = format!("unable to convert URI to filepath: {}", uri);
|
||||
cx.editor.set_error(err);
|
||||
return;
|
||||
}
|
||||
};
|
||||
if let Err(err) = cx.editor.open(&path, action) {
|
||||
let err = format!("failed to open document: {}: {}", uri, err);
|
||||
log::error!("{}", err);
|
||||
cx.editor.set_error(err);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
let (view, doc) = current!(cx.editor);
|
||||
let (view, doc) = current!(cx.editor);
|
||||
|
||||
if let Some(range) =
|
||||
lsp_range_to_range(doc.text(), item.symbol.location.range, item.offset_encoding)
|
||||
{
|
||||
// we flip the range so that the cursor sits on the start of the symbol
|
||||
// (for example start of the function).
|
||||
doc.set_selection(view.id, Selection::single(range.head, range.anchor));
|
||||
align_view(doc, view, Align::Center);
|
||||
}
|
||||
},
|
||||
move |_editor, item| Some(location_to_file_location(&item.symbol.location)),
|
||||
)
|
||||
if let Some(range) =
|
||||
lsp_range_to_range(doc.text(), item.symbol.location.range, item.offset_encoding)
|
||||
{
|
||||
// we flip the range so that the cursor sits on the start of the symbol
|
||||
// (for example start of the function).
|
||||
doc.set_selection(view.id, Selection::single(range.head, range.anchor));
|
||||
align_view(doc, view, Align::Center);
|
||||
}
|
||||
})
|
||||
.with_preview(move |_editor, item| Some(location_to_file_location(&item.symbol.location)))
|
||||
.truncate_start(false)
|
||||
}
|
||||
|
||||
|
@ -345,11 +341,11 @@ fn diag_picker(
|
|||
align_view(doc, view, Align::Center);
|
||||
}
|
||||
},
|
||||
move |_editor, PickerDiagnostic { url, diag, .. }| {
|
||||
let location = lsp::Location::new(url.clone(), diag.range);
|
||||
Some(location_to_file_location(&location))
|
||||
},
|
||||
)
|
||||
.with_preview(move |_editor, PickerDiagnostic { url, diag, .. }| {
|
||||
let location = lsp::Location::new(url.clone(), diag.range);
|
||||
Some(location_to_file_location(&location))
|
||||
})
|
||||
.truncate_start(false)
|
||||
}
|
||||
|
||||
|
@ -1047,14 +1043,10 @@ fn goto_impl(
|
|||
editor.set_error("No definition found.");
|
||||
}
|
||||
_locations => {
|
||||
let picker = FilePicker::new(
|
||||
locations,
|
||||
cwdir,
|
||||
move |cx, location, action| {
|
||||
jump_to_location(cx.editor, location, offset_encoding, action)
|
||||
},
|
||||
move |_editor, location| Some(location_to_file_location(location)),
|
||||
);
|
||||
let picker = FilePicker::new(locations, cwdir, move |cx, location, action| {
|
||||
jump_to_location(cx.editor, location, offset_encoding, action)
|
||||
})
|
||||
.with_preview(move |_editor, location| Some(location_to_file_location(location)));
|
||||
compositor.push(Box::new(overlaid(picker)));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -217,21 +217,17 @@ pub fn file_picker(root: PathBuf, config: &helix_view::editor::Config) -> FilePi
|
|||
|
||||
log::debug!("file_picker init {:?}", Instant::now().duration_since(now));
|
||||
|
||||
FilePicker::new(
|
||||
files,
|
||||
root,
|
||||
move |cx, path: &PathBuf, action| {
|
||||
if let Err(e) = cx.editor.open(path, action) {
|
||||
let err = if let Some(err) = e.source() {
|
||||
format!("{}", err)
|
||||
} else {
|
||||
format!("unable to open \"{}\"", path.display())
|
||||
};
|
||||
cx.editor.set_error(err);
|
||||
}
|
||||
},
|
||||
|_editor, path| Some((path.clone().into(), None)),
|
||||
)
|
||||
FilePicker::new(files, root, move |cx, path: &PathBuf, action| {
|
||||
if let Err(e) = cx.editor.open(path, action) {
|
||||
let err = if let Some(err) = e.source() {
|
||||
format!("{}", err)
|
||||
} else {
|
||||
format!("unable to open \"{}\"", path.display())
|
||||
};
|
||||
cx.editor.set_error(err);
|
||||
}
|
||||
})
|
||||
.with_preview(|_editor, path| Some((path.clone().into(), None)))
|
||||
}
|
||||
|
||||
pub mod completers {
|
||||
|
|
|
@ -141,7 +141,7 @@ pub struct FilePicker<T: Item> {
|
|||
preview_cache: HashMap<PathBuf, CachedPreview>,
|
||||
read_buffer: Vec<u8>,
|
||||
/// Given an item in the picker, return the file path and line number to display.
|
||||
file_fn: FileCallback<T>,
|
||||
file_fn: Option<FileCallback<T>>,
|
||||
}
|
||||
|
||||
impl<T: Item + 'static> FilePicker<T> {
|
||||
|
@ -149,7 +149,6 @@ impl<T: Item + 'static> FilePicker<T> {
|
|||
options: Vec<T>,
|
||||
editor_data: T::Data,
|
||||
callback_fn: impl Fn(&mut Context, &T, Action) + 'static,
|
||||
preview_fn: impl Fn(&Editor, &T) -> Option<FileLocation> + 'static,
|
||||
) -> Self {
|
||||
let prompt = Prompt::new(
|
||||
"".into(),
|
||||
|
@ -173,7 +172,7 @@ impl<T: Item + 'static> FilePicker<T> {
|
|||
widths: Vec::new(),
|
||||
preview_cache: HashMap::new(),
|
||||
read_buffer: Vec::with_capacity(1024),
|
||||
file_fn: Box::new(preview_fn),
|
||||
file_fn: None,
|
||||
|
||||
picker: unimplemented!(),
|
||||
};
|
||||
|
@ -202,6 +201,14 @@ impl<T: Item + 'static> FilePicker<T> {
|
|||
self
|
||||
}
|
||||
|
||||
pub fn with_preview(
|
||||
mut self,
|
||||
preview_fn: impl Fn(&Editor, &T) -> Option<FileLocation> + 'static,
|
||||
) -> Self {
|
||||
self.file_fn = Some(Box::new(preview_fn));
|
||||
self
|
||||
}
|
||||
|
||||
pub fn set_options(&mut self, new_options: Vec<T>) {
|
||||
self.options = new_options;
|
||||
self.cursor = 0;
|
||||
|
@ -372,7 +379,7 @@ impl<T: Item + 'static> FilePicker<T> {
|
|||
fn current_file(&self, editor: &Editor) -> Option<FileLocation> {
|
||||
self.picker
|
||||
.selection()
|
||||
.and_then(|current| (self.file_fn)(editor, current))
|
||||
.and_then(|current| (self.file_fn.as_ref()?)(editor, current))
|
||||
.and_then(|(path_or_id, line)| path_or_id.get_canonicalized().ok().zip(Some(line)))
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue