feat(statusline): support display relative path

This commit is contained in:
roadup 2024-07-27 13:21:20 +08:00
parent a1e20a3426
commit 1869e50999
6 changed files with 85 additions and 11 deletions

View File

@ -614,16 +614,22 @@ fn get_preview<'picker, 'editor>(
(size, _) if size > MAX_FILE_SIZE_FOR_PREVIEW => {
CachedPreview::LargeFile
}
_ => Document::open(&path, None, None, editor.config.clone())
.map(|doc| {
// Asynchronously highlight the new document
helix_event::send_blocking(
&self.preview_highlight_handler,
path.clone(),
);
CachedPreview::Document(Box::new(doc))
})
.unwrap_or(CachedPreview::NotFound),
_ => Document::open(
&path,
None,
None,
editor.config.clone(),
&editor.diff_providers,
)
.map(|doc| {
// Asynchronously highlight the new document
helix_event::send_blocking(
&self.preview_highlight_handler,
path.clone(),
);
CachedPreview::Document(Box::new(doc))
})
.unwrap_or(CachedPreview::NotFound),
},
)
.unwrap_or(CachedPreview::NotFound);

View File

@ -143,6 +143,7 @@ fn get_render_function<F>(element_id: StatusLineElementID) -> impl Fn(&mut Rende
helix_view::editor::StatusLineElement::FileBaseName => render_file_base_name,
helix_view::editor::StatusLineElement::FileName => render_file_name,
helix_view::editor::StatusLineElement::FileAbsolutePath => render_file_absolute_path,
helix_view::editor::StatusLineElement::FileRelativePath => render_file_relative_path,
helix_view::editor::StatusLineElement::FileModificationIndicator => {
render_file_modification_indicator
}
@ -447,6 +448,27 @@ fn render_file_absolute_path<F>(context: &mut RenderContext, write: F)
write(context, title, None);
}
fn render_file_relative_path<F>(context: &mut RenderContext, write: F)
where
F: Fn(&mut RenderContext, String, Option<Style>) + Copy,
{
let title = {
let path = context.doc.path();
let root = &context.doc.repo_root_dir;
let path = path
.as_ref()
.map(|p| {
p.strip_prefix(root.as_path())
.unwrap_or(p)
.to_string_lossy()
})
.unwrap_or_else(|| SCRATCH_BUFFER_NAME.into());
format!(" {} ", path)
};
write(context, title, None);
}
fn render_file_modification_indicator<F>(context: &mut RenderContext, write: F)
where
F: Fn(&mut RenderContext, String, Option<Style>) + Copy,

View File

@ -1,8 +1,9 @@
use anyhow::{bail, Context, Result};
use arc_swap::ArcSwap;
use gix::filter::plumbing::driver::apply::Delay;
use gix::path::env;
use std::io::Read;
use std::path::Path;
use std::path::{Path, PathBuf};
use std::sync::Arc;
use gix::bstr::ByteSlice;
@ -117,6 +118,24 @@ fn open_repo(path: &Path) -> Result<ThreadSafeRepository> {
Ok(res)
}
pub fn get_repo_root_dir(file: &Path) -> Result<Arc<PathBuf>> {
debug_assert!(!file.exists() || file.is_file());
debug_assert!(file.is_absolute());
let repo_dir = file.parent().context("file has no parent directory")?;
Ok(Arc::new(match open_repo(repo_dir) {
Ok(repo) => repo
.work_dir()
.unwrap_or_else(|| Path::new("/"))
.to_path_buf(),
Err(_) => match env::home_dir() {
Some(p) => p,
None => PathBuf::from("/"),
},
}))
}
/// Emulates the result of running `git status` from the command line.
fn status(repo: &Repository, f: impl Fn(Result<FileChange>) -> bool) -> Result<()> {
let work_dir = repo

View File

@ -66,6 +66,15 @@ pub fn for_each_changed_file(
}
});
}
pub fn get_repo_root(&self, cwd: &Path) -> Arc<PathBuf> {
self.providers
.iter()
.find_map(|provider| match provider.get_repo_root_dir(cwd) {
Ok(res) => Some(res),
Err(_) => None,
})
.unwrap_or_else(|| Arc::new(PathBuf::from("/")))
}
}
impl Default for DiffProviderRegistry {
@ -119,4 +128,12 @@ fn for_each_changed_file(
Self::None => bail!("No diff support compiled in"),
}
}
fn get_repo_root_dir(&self, cwd: &Path) -> Result<Arc<PathBuf>> {
match self {
#[cfg(feature = "git")]
DiffProvider::Git => git::get_repo_root_dir(cwd),
DiffProvider::None => bail!("No diff support compiled in"),
}
}
}

View File

@ -191,6 +191,8 @@ pub struct Document {
pub focused_at: std::time::Instant,
pub readonly: bool,
pub repo_root_dir: Arc<PathBuf>,
}
/// Inlay hints for a single `(Document, View)` combo.
@ -683,6 +685,7 @@ pub fn from(
focused_at: std::time::Instant::now(),
readonly: false,
jump_labels: HashMap::new(),
repo_root_dir: Arc::new(PathBuf::from("/")),
}
}
@ -700,6 +703,7 @@ pub fn open(
encoding: Option<&'static Encoding>,
config_loader: Option<Arc<ArcSwap<syntax::Loader>>>,
config: Arc<dyn DynAccess<Config>>,
provider_registry: &DiffProviderRegistry,
) -> Result<Self, DocumentOpenError> {
// If the path is not a regular file (e.g.: /dev/random) it should not be opened.
if path
@ -729,6 +733,8 @@ pub fn open(
doc.detect_indent_and_line_ending();
doc.repo_root_dir = provider_registry.get_repo_root(path);
Ok(doc)
}

View File

@ -530,6 +530,9 @@ pub enum StatusLineElement {
/// The file absolute path
FileAbsolutePath,
/// The file relative path base on repo or home dir
FileRelativePath,
// The file modification indicator
FileModificationIndicator,
@ -1698,6 +1701,7 @@ pub fn open(&mut self, path: &Path, action: Action) -> Result<DocumentId, Docume
None,
Some(self.syn_loader.clone()),
self.config.clone(),
&self.diff_providers,
)?;
let diagnostics =