mirror of https://github.com/helix-editor/helix
Show path in file picker and explorer
The file picker and explorer can each be opened in several ways, each causing it to have a different root path. What's more, the file explorer can change its path while you have it open. This can make it very difficult to keep track of the root directory for these pickers, so we add it as a header. If desired, we could alternatively make this a configuration option, but I see little downside to always including it.pull/12806/head
parent
0815b52e09
commit
9dc6fb8216
|
@ -32,6 +32,7 @@ pub use text::Text;
|
|||
use helix_view::Editor;
|
||||
use tui::text::{Span, Spans};
|
||||
|
||||
use std::borrow::Cow;
|
||||
use std::path::Path;
|
||||
use std::{error::Error, path::PathBuf};
|
||||
|
||||
|
@ -185,6 +186,23 @@ pub fn raw_regex_prompt(
|
|||
cx.push_layer(Box::new(prompt));
|
||||
}
|
||||
|
||||
/// Get the relative directory as a string.
|
||||
///
|
||||
/// NOTE: Assumes the given path is a directory, and will always output wiht a
|
||||
/// trailing slash.
|
||||
fn get_relative_dir(path: &Path) -> Cow<'static, str> {
|
||||
let path = helix_stdx::path::get_relative_path(path);
|
||||
if path.components().next().is_none() {
|
||||
"./".into()
|
||||
} else {
|
||||
let mut str = path.to_string_lossy().into_owned();
|
||||
if !str.ends_with('/') {
|
||||
str.push('/');
|
||||
}
|
||||
str.into()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct FilePickerData {
|
||||
root: PathBuf,
|
||||
|
@ -246,7 +264,7 @@ pub fn file_picker(editor: &Editor, root: PathBuf) -> FilePicker {
|
|||
log::debug!("file_picker init {:?}", Instant::now().duration_since(now));
|
||||
|
||||
let columns = [PickerColumn::new(
|
||||
"path",
|
||||
get_relative_dir(&root),
|
||||
|item: &PathBuf, data: &FilePickerData| {
|
||||
let path = item.strip_prefix(&data.root).unwrap_or(item);
|
||||
let mut spans = Vec::with_capacity(3);
|
||||
|
@ -274,6 +292,7 @@ pub fn file_picker(editor: &Editor, root: PathBuf) -> FilePicker {
|
|||
cx.editor.set_error(err);
|
||||
}
|
||||
})
|
||||
.always_show_headers()
|
||||
.with_preview(|_editor, path| Some((path.as_path().into(), None)));
|
||||
let injector = picker.injector();
|
||||
let timeout = std::time::Instant::now() + std::time::Duration::from_millis(30);
|
||||
|
@ -307,7 +326,7 @@ pub fn file_explorer(root: PathBuf, editor: &Editor) -> Result<FileExplorer, std
|
|||
let directory_content = directory_content(&root)?;
|
||||
|
||||
let columns = [PickerColumn::new(
|
||||
"path",
|
||||
get_relative_dir(&root),
|
||||
|(path, is_dir): &(PathBuf, bool), (root, directory_style): &(PathBuf, Style)| {
|
||||
let name = path.strip_prefix(root).unwrap_or(path).to_string_lossy();
|
||||
if *is_dir {
|
||||
|
@ -345,6 +364,7 @@ pub fn file_explorer(root: PathBuf, editor: &Editor) -> Result<FileExplorer, std
|
|||
}
|
||||
},
|
||||
)
|
||||
.always_show_headers()
|
||||
.with_preview(|_editor, (path, _is_dir)| Some((path.as_path().into(), None)));
|
||||
|
||||
Ok(picker)
|
||||
|
|
|
@ -241,6 +241,7 @@ type DynQueryCallback<T, D> =
|
|||
pub struct Picker<T: 'static + Send + Sync, D: 'static> {
|
||||
columns: Arc<[Column<T, D>]>,
|
||||
primary_column: usize,
|
||||
always_show_headers: bool,
|
||||
editor_data: Arc<D>,
|
||||
version: Arc<AtomicUsize>,
|
||||
matcher: Nucleo<T>,
|
||||
|
@ -373,6 +374,7 @@ impl<T: 'static + Send + Sync, D: 'static + Send + Sync> Picker<T, D> {
|
|||
Self {
|
||||
columns,
|
||||
primary_column: default_column,
|
||||
always_show_headers: false,
|
||||
matcher,
|
||||
editor_data,
|
||||
version,
|
||||
|
@ -424,6 +426,11 @@ impl<T: 'static + Send + Sync, D: 'static + Send + Sync> Picker<T, D> {
|
|||
self
|
||||
}
|
||||
|
||||
pub fn always_show_headers(mut self) -> Self {
|
||||
self.always_show_headers = true;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_dynamic_query(
|
||||
mut self,
|
||||
callback: DynQueryCallback<T, D>,
|
||||
|
@ -818,7 +825,7 @@ impl<T: 'static + Send + Sync, D: 'static + Send + Sync> Picker<T, D> {
|
|||
.widths(&self.widths);
|
||||
|
||||
// -- Header
|
||||
if self.columns.len() > 1 {
|
||||
if self.always_show_headers || self.columns.len() > 1 {
|
||||
let active_column = self.query.active_column(self.prompt.position());
|
||||
let header_style = cx.editor.theme.get("ui.picker.header");
|
||||
let header_column_style = cx.editor.theme.get("ui.picker.header.column");
|
||||
|
|
Loading…
Reference in New Issue