/crates/icon/src/lib.rs
https://github.com/liuchengxu/vim-clap · Rust · 144 lines · 112 code · 20 blank · 12 comment · 7 complexity · e8b7c688c3c7fdf20578f67dcb647c79 MD5 · raw file
- mod constants;
- pub use constants::*;
- use std::path::Path;
- use structopt::clap::arg_enum;
- pub const DEFAULT_ICON: char = '';
- pub const FOLDER_ICON: char = '';
- pub const DEFAULT_FILER_ICON: char = '';
- // Each added icon length is 4 bytes.
- pub const ICON_LEN: usize = 4;
- /// The type used to represent icons.
- ///
- /// This could be changed into different type later,
- /// so functions take and return this type, not `char` or `&str` directly.
- type Icon = char;
- /// Return appropriate icon for the path. If no icon matched, return the specified default one.
- ///
- /// Try matching the exactmatch map against the file name, and then the extension map.
- #[inline]
- pub fn get_icon_or(path: &Path, default: Icon) -> Icon {
- path.file_name()
- .and_then(std::ffi::OsStr::to_str)
- .and_then(|filename| {
- bsearch_icon_table(&filename.to_lowercase().as_str(), EXACTMATCH_ICON_TABLE)
- .map(|idx| EXACTMATCH_ICON_TABLE[idx].1)
- })
- .unwrap_or_else(|| {
- path.extension()
- .and_then(std::ffi::OsStr::to_str)
- .and_then(|ext| {
- bsearch_icon_table(ext, EXTENSION_ICON_TABLE)
- .map(|idx| EXTENSION_ICON_TABLE[idx].1)
- })
- .unwrap_or(default)
- })
- }
- fn icon_for(line: &str) -> Icon {
- let path = Path::new(line);
- get_icon_or(&path, DEFAULT_ICON)
- }
- pub fn prepend_icon(line: &str) -> String {
- format!("{} {}", icon_for(line), line)
- }
- #[inline]
- pub fn icon_for_filer(path: &Path) -> Icon {
- if path.is_dir() {
- FOLDER_ICON
- } else {
- get_icon_or(path, DEFAULT_FILER_ICON)
- }
- }
- pub fn prepend_filer_icon(path: &Path, line: &str) -> String {
- format!("{} {}", icon_for_filer(path), line)
- }
- fn get_tagkind_icon(line: &str) -> Icon {
- pattern::extract_proj_tags_kind(line)
- .and_then(|kind| {
- bsearch_icon_table(kind, TAGKIND_ICON_TABLE).map(|idx| TAGKIND_ICON_TABLE[idx].1)
- })
- .unwrap_or(DEFAULT_ICON)
- }
- #[inline]
- fn grep_icon_for(line: &str) -> Icon {
- pattern::extract_fpath_from_grep_line(line)
- .map(|fpath| icon_for(fpath))
- .unwrap_or(DEFAULT_ICON)
- }
- /// Prepend an icon to the output line of ripgrep.
- pub fn prepend_grep_icon(line: &str) -> String {
- format!("{} {}", grep_icon_for(line), line)
- }
- arg_enum! {
- /// Prepend an icon for various kind of output line.
- #[derive(Clone, Debug)]
- pub enum IconPainter {
- File,
- Grep,
- ProjTags
- }
- }
- impl IconPainter {
- /// Returns a `String` of raw str with icon added.
- pub fn paint(&self, raw_str: &str) -> String {
- match *self {
- Self::File => prepend_icon(raw_str),
- Self::Grep => prepend_grep_icon(raw_str),
- Self::ProjTags => format!("{} {}", get_tagkind_icon(raw_str), raw_str),
- }
- }
- /// Returns appropriate icon for the given text.
- pub fn get_icon(&self, text: &str) -> Icon {
- match *self {
- Self::File => icon_for(text),
- Self::Grep => grep_icon_for(text),
- Self::ProjTags => get_tagkind_icon(text),
- }
- }
- }
- #[cfg(test)]
- mod tests {
- use super::*;
- #[test]
- fn test_trim_trailing() {
- let empty_iconized_line = " ";
- assert_eq!(empty_iconized_line.len(), 4);
- assert!(empty_iconized_line.chars().next().unwrap() == DEFAULT_ICON);
- }
- #[test]
- fn test_icon_length() {
- for table in [EXTENSION_ICON_TABLE, EXACTMATCH_ICON_TABLE].iter() {
- for (_, i) in table.iter() {
- let icon = format!("{} ", i);
- assert_eq!(icon.len(), 4);
- }
- }
- }
- #[test]
- fn test_tagkind_icon() {
- let line = r#"Blines:19 [implementation@crates/maple_cli/src/cmd/blines.rs] impl Blines {"#;
- let icon_for = |kind: &str| {
- bsearch_icon_table(kind, TAGKIND_ICON_TABLE).map(|idx| TAGKIND_ICON_TABLE[idx].1)
- };
- assert_eq!(icon_for("implementation").unwrap(), get_tagkind_icon(line));
- }
- }