Add rudimentary nerdfonts support

pull/11/head
trivernis 1 year ago
parent 82adbb35ab
commit 7ccbea2a31
Signed by: Trivernis
GPG Key ID: DFFFCC2C7A02DB45

@ -1,10 +1,11 @@
use super::{Prompt, TreeOp, TreeView, TreeViewItem};
use super::{tree::TreeIcons, Prompt, TreeOp, TreeView, TreeViewItem};
use crate::{
compositor::{Component, Context, EventResult},
ctrl, key, shift, ui,
};
use anyhow::{bail, ensure, Result};
use helix_core::Position;
use helix_view::{
editor::{Action, ExplorerPosition},
graphics::{CursorKind, Rect},
@ -13,9 +14,9 @@ use helix_view::{
theme::Modifier,
Editor,
};
use std::cmp::Ordering;
use std::path::{Path, PathBuf};
use std::{borrow::Cow, fs::DirEntry};
use std::{cmp::Ordering, sync::Arc};
use tui::{
buffer::Buffer as Surface,
widgets::{Block, Borders, Widget},
@ -172,7 +173,7 @@ impl Explorer {
.unwrap_or_else(|_| "./".into())
.canonicalize()?;
Ok(Self {
tree: Self::new_tree_view(current_root.clone())?,
tree: Self::new_tree_view(current_root.clone(), Self::get_tree_icons(cx))?,
history: vec![],
show_help: false,
state: State::new(true, current_root),
@ -182,10 +183,51 @@ impl Explorer {
})
}
fn get_tree_icons(cx: &Context) -> TreeIcons {
let icons = cx.editor.icons.clone();
let defaults = TreeIcons::default();
let file_icon = icons
.ui
.as_ref()
.and_then(|s| s.get("file").cloned())
.map(|i| i.icon_char.to_string())
.unwrap_or(defaults.item);
let item = file_icon.clone();
let tree_closed = icons
.ui
.as_ref()
.and_then(|s| s.get("folder").cloned())
.map(|i| i.icon_char.to_string())
.unwrap_or(defaults.tree_closed);
let tree_opened = icons
.ui
.as_ref()
.and_then(|s| s.get("folder_opened").cloned())
.map(|i| i.icon_char.to_string())
.unwrap_or(defaults.tree_opened);
TreeIcons {
tree_closed,
tree_opened,
item,
icon_fn: Some(Arc::new(move |item| {
if let Some(file_type) = PathBuf::from(item).extension() {
icons
.icon_from_filetype(&file_type.to_string_lossy())
.map(|i| i.icon_char.to_string())
.unwrap_or_else(|| file_icon.to_owned())
} else {
file_icon.to_owned()
}
})),
}
}
#[cfg(test)]
fn from_path(root: PathBuf, column_width: u16) -> Result<Self> {
Ok(Self {
tree: Self::new_tree_view(root.clone())?,
tree: Self::new_tree_view(root.clone(), TreeIcons::default())?,
history: vec![],
show_help: false,
state: State::new(true, root),
@ -195,9 +237,11 @@ impl Explorer {
})
}
fn new_tree_view(root: PathBuf) -> Result<TreeView<FileInfo>> {
fn new_tree_view(root: PathBuf, icons: TreeIcons) -> Result<TreeView<FileInfo>> {
let root = FileInfo::root(root);
Ok(TreeView::build_tree(root)?.with_enter_fn(Self::toggle_current))
Ok(TreeView::build_tree(root)?
.with_enter_fn(Self::toggle_current)
.icons(icons))
}
fn push_history(&mut self, tree_view: TreeView<FileInfo>, current_root: PathBuf) {
@ -213,7 +257,7 @@ impl Explorer {
if self.state.current_root.eq(&root) {
return Ok(());
}
let tree = Self::new_tree_view(root.clone())?;
let tree = Self::new_tree_view(root.clone(), self.tree.icons.clone())?;
let old_tree = std::mem::replace(&mut self.tree, tree);
self.push_history(old_tree, self.state.current_root.clone());
self.state.current_root = root;

@ -1,4 +1,4 @@
use std::cmp::Ordering;
use std::{cmp::Ordering, sync::Arc};
use anyhow::Result;
use helix_view::theme::Modifier;
@ -290,6 +290,7 @@ pub struct TreeView<T: TreeViewItem> {
max_len: usize,
count: usize,
tree_symbol_style: String,
pub icons: TreeIcons,
#[allow(clippy::type_complexity)]
pre_render: Option<Box<dyn Fn(&mut Self, Rect) + 'static>>,
@ -325,6 +326,7 @@ impl<T: TreeViewItem> TreeView<T> {
on_next_key: None,
search_prompt: None,
search_str: "".into(),
icons: TreeIcons::default(),
})
}
@ -349,6 +351,11 @@ impl<T: TreeViewItem> TreeView<T> {
self
}
pub fn icons(mut self, icons: TreeIcons) -> Self {
self.icons = icons;
self
}
/// Reveal item in the tree based on the given `segments`.
///
/// The name of the root should be excluded.
@ -781,6 +788,26 @@ struct RenderTreeParams<'a, T> {
prefix: &'a String,
level: usize,
selected: usize,
icons: &'a TreeIcons,
}
#[derive(Clone)]
pub struct TreeIcons {
pub tree_closed: String,
pub tree_opened: String,
pub item: String,
pub icon_fn: Option<Arc<dyn Fn(&str) -> String>>,
}
impl Default for TreeIcons {
fn default() -> Self {
Self {
tree_closed: String::from("⏵"),
tree_opened: String::from("⏷"),
item: String::from(" "),
icon_fn: None,
}
}
}
fn render_tree<T: TreeViewItem>(
@ -789,23 +816,33 @@ fn render_tree<T: TreeViewItem>(
prefix,
level,
selected,
icons,
}: RenderTreeParams<T>,
) -> Vec<RenderedLine> {
let name = tree.item.name();
let indent = if level > 0 {
let indicator = if tree.item().is_parent() {
if tree.is_opened {
"⏷"
icons.tree_opened.to_owned()
} else {
"⏵"
icons.tree_closed.to_owned()
}
} else {
" "
if let Some(icon_fn) = icons.icon_fn.as_ref() {
icon_fn(&name)
} else {
icons.item.to_owned()
}
};
format!("{}{} ", prefix, indicator)
} else {
"".to_string()
if let Some(icon_fn) = icons.icon_fn.as_ref() {
icon_fn(&name)
} else {
icons.item.clone()
}
};
let name = tree.item.name();
let head = RenderedLine {
indent,
selected: selected == tree.index,
@ -821,6 +858,7 @@ fn render_tree<T: TreeViewItem>(
prefix: &prefix,
level: level + 1,
selected,
icons,
})
}))
.collect()
@ -915,6 +953,7 @@ impl<T: TreeViewItem + Clone> TreeView<T> {
prefix: &"".to_string(),
level: 0,
selected: self.selected,
icons: &self.icons,
};
let lines = render_tree(params);

Loading…
Cancel
Save