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,7 +614,13 @@ fn get_preview<'picker, 'editor>(
(size, _) if size > MAX_FILE_SIZE_FOR_PREVIEW => { (size, _) if size > MAX_FILE_SIZE_FOR_PREVIEW => {
CachedPreview::LargeFile CachedPreview::LargeFile
} }
_ => Document::open(&path, None, None, editor.config.clone()) _ => Document::open(
&path,
None,
None,
editor.config.clone(),
&editor.diff_providers,
)
.map(|doc| { .map(|doc| {
// Asynchronously highlight the new document // Asynchronously highlight the new document
helix_event::send_blocking( helix_event::send_blocking(

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::FileBaseName => render_file_base_name,
helix_view::editor::StatusLineElement::FileName => render_file_name, helix_view::editor::StatusLineElement::FileName => render_file_name,
helix_view::editor::StatusLineElement::FileAbsolutePath => render_file_absolute_path, helix_view::editor::StatusLineElement::FileAbsolutePath => render_file_absolute_path,
helix_view::editor::StatusLineElement::FileRelativePath => render_file_relative_path,
helix_view::editor::StatusLineElement::FileModificationIndicator => { helix_view::editor::StatusLineElement::FileModificationIndicator => {
render_file_modification_indicator render_file_modification_indicator
} }
@ -447,6 +448,27 @@ fn render_file_absolute_path<F>(context: &mut RenderContext, write: F)
write(context, title, None); 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) fn render_file_modification_indicator<F>(context: &mut RenderContext, write: F)
where where
F: Fn(&mut RenderContext, String, Option<Style>) + Copy, F: Fn(&mut RenderContext, String, Option<Style>) + Copy,

View File

@ -1,8 +1,9 @@
use anyhow::{bail, Context, Result}; use anyhow::{bail, Context, Result};
use arc_swap::ArcSwap; use arc_swap::ArcSwap;
use gix::filter::plumbing::driver::apply::Delay; use gix::filter::plumbing::driver::apply::Delay;
use gix::path::env;
use std::io::Read; use std::io::Read;
use std::path::Path; use std::path::{Path, PathBuf};
use std::sync::Arc; use std::sync::Arc;
use gix::bstr::ByteSlice; use gix::bstr::ByteSlice;
@ -117,6 +118,24 @@ fn open_repo(path: &Path) -> Result<ThreadSafeRepository> {
Ok(res) 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. /// Emulates the result of running `git status` from the command line.
fn status(repo: &Repository, f: impl Fn(Result<FileChange>) -> bool) -> Result<()> { fn status(repo: &Repository, f: impl Fn(Result<FileChange>) -> bool) -> Result<()> {
let work_dir = repo 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 { impl Default for DiffProviderRegistry {
@ -119,4 +128,12 @@ fn for_each_changed_file(
Self::None => bail!("No diff support compiled in"), 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 focused_at: std::time::Instant,
pub readonly: bool, pub readonly: bool,
pub repo_root_dir: Arc<PathBuf>,
} }
/// Inlay hints for a single `(Document, View)` combo. /// Inlay hints for a single `(Document, View)` combo.
@ -683,6 +685,7 @@ pub fn from(
focused_at: std::time::Instant::now(), focused_at: std::time::Instant::now(),
readonly: false, readonly: false,
jump_labels: HashMap::new(), jump_labels: HashMap::new(),
repo_root_dir: Arc::new(PathBuf::from("/")),
} }
} }
@ -700,6 +703,7 @@ pub fn open(
encoding: Option<&'static Encoding>, encoding: Option<&'static Encoding>,
config_loader: Option<Arc<ArcSwap<syntax::Loader>>>, config_loader: Option<Arc<ArcSwap<syntax::Loader>>>,
config: Arc<dyn DynAccess<Config>>, config: Arc<dyn DynAccess<Config>>,
provider_registry: &DiffProviderRegistry,
) -> Result<Self, DocumentOpenError> { ) -> Result<Self, DocumentOpenError> {
// If the path is not a regular file (e.g.: /dev/random) it should not be opened. // If the path is not a regular file (e.g.: /dev/random) it should not be opened.
if path if path
@ -729,6 +733,8 @@ pub fn open(
doc.detect_indent_and_line_ending(); doc.detect_indent_and_line_ending();
doc.repo_root_dir = provider_registry.get_repo_root(path);
Ok(doc) Ok(doc)
} }

View File

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