Add icon support for files without extensions (#8453)
Release Notes: - Added support for showing file icons for files without suffixes. Before: <img width="281" alt="image" src="https://github.com/zed-industries/zed/assets/25414681/ab4c00ed-72c7-458f-8dda-61c68165590f"> After: <img width="242" alt="Screenshot 2024-02-27 at 1 51 20 AM" src="https://github.com/zed-industries/zed/assets/25414681/8f3082c4-9424-4bc3-9100-a527b9adc315"> This screenshot is to show if the file has extension, then the extension takes precedence. <img width="193" alt="image" src="https://github.com/zed-industries/zed/assets/25414681/72fcebd1-361f-444b-8890-f59932963083"> <br> - Added icons for - Docker - https://www.svgrepo.com/svg/473589/docker - License - https://www.svgrepo.com/svg/477704/license-1 - Heroku - https://www.svgrepo.com/svg/341904/heroku - Updated tests
This commit is contained in:
parent
d545fe9fe4
commit
bd8896a3dc
5 changed files with 53 additions and 16 deletions
6
assets/icons/file_icons/docker.svg
Normal file
6
assets/icons/file_icons/docker.svg
Normal file
|
@ -0,0 +1,6 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="14px" height="14px" viewBox="0 0 14 14" version="1.1">
|
||||
<g id="surface1">
|
||||
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 13.421875 5.847656 C 13.152344 5.671875 12.824219 5.566406 12.46875 5.566406 C 12.429688 5.566406 12.390625 5.566406 12.351562 5.570312 L 12.355469 5.570312 C 12.160156 5.570312 11.96875 5.585938 11.785156 5.621094 L 11.804688 5.617188 C 11.699219 5.023438 11.355469 4.523438 10.875 4.21875 L 10.867188 4.214844 L 10.679688 4.105469 L 10.554688 4.285156 C 10.410156 4.507812 10.292969 4.769531 10.226562 5.050781 L 10.222656 5.066406 C 10.183594 5.207031 10.160156 5.371094 10.160156 5.539062 C 10.160156 5.902344 10.265625 6.242188 10.445312 6.527344 L 10.441406 6.519531 C 10.164062 6.648438 9.839844 6.734375 9.496094 6.75 L 0.859375 6.75 C 0.632812 6.75 0.449219 6.929688 0.449219 7.15625 C 0.449219 7.179688 0.449219 7.210938 0.449219 7.238281 C 0.449219 8.003906 0.585938 8.738281 0.839844 9.417969 L 0.828125 9.375 C 1.070312 10.089844 1.53125 10.675781 2.128906 11.070312 L 2.144531 11.078125 C 2.90625 11.476562 3.808594 11.707031 4.765625 11.707031 C 4.855469 11.707031 4.945312 11.703125 5.035156 11.699219 L 5.023438 11.699219 C 5.03125 11.699219 5.039062 11.699219 5.050781 11.699219 C 5.605469 11.699219 6.148438 11.648438 6.675781 11.546875 L 6.621094 11.554688 C 7.40625 11.410156 8.109375 11.144531 8.742188 10.78125 L 8.710938 10.796875 C 9.261719 10.476562 9.730469 10.085938 10.128906 9.636719 L 10.136719 9.628906 C 10.714844 8.949219 11.1875 8.152344 11.511719 7.28125 L 11.527344 7.226562 L 11.648438 7.226562 C 11.671875 7.230469 11.703125 7.230469 11.730469 7.230469 C 12.265625 7.230469 12.753906 7.019531 13.113281 6.675781 C 13.277344 6.519531 13.410156 6.332031 13.496094 6.117188 L 13.5 6.105469 L 13.550781 5.949219 Z M 1.65625 6.496094 L 2.816406 6.496094 C 2.871094 6.496094 2.917969 6.449219 2.917969 6.394531 L 2.917969 5.363281 C 2.917969 5.308594 2.871094 5.265625 2.816406 5.261719 L 1.65625 5.261719 C 1.601562 5.265625 1.558594 5.308594 1.558594 5.363281 L 1.558594 6.394531 C 1.558594 6.453125 1.601562 6.496094 1.65625 6.496094 C 1.65625 6.496094 1.65625 6.496094 1.660156 6.496094 Z M 3.253906 6.496094 L 4.410156 6.496094 C 4.464844 6.496094 4.511719 6.453125 4.511719 6.394531 L 4.511719 5.363281 C 4.511719 5.308594 4.464844 5.265625 4.410156 5.261719 L 3.25 5.261719 C 3.195312 5.261719 3.152344 5.308594 3.152344 5.363281 L 3.152344 6.394531 C 3.152344 6.453125 3.195312 6.496094 3.25 6.496094 Z M 4.871094 6.496094 L 6.027344 6.496094 C 6.082031 6.496094 6.128906 6.449219 6.128906 6.394531 L 6.128906 5.363281 C 6.128906 5.308594 6.082031 5.265625 6.027344 5.261719 L 4.871094 5.261719 C 4.816406 5.265625 4.769531 5.308594 4.769531 5.363281 L 4.769531 6.394531 C 4.769531 6.449219 4.816406 6.496094 4.871094 6.496094 Z M 6.46875 6.496094 L 7.625 6.496094 C 7.683594 6.496094 7.726562 6.453125 7.726562 6.394531 L 7.726562 5.363281 C 7.726562 5.308594 7.683594 5.261719 7.625 5.261719 L 6.46875 5.261719 C 6.414062 5.261719 6.367188 5.308594 6.367188 5.363281 L 6.367188 6.394531 C 6.367188 6.453125 6.414062 6.496094 6.46875 6.496094 Z M 3.253906 5.015625 L 4.410156 5.015625 C 4.464844 5.015625 4.511719 4.96875 4.511719 4.914062 L 4.511719 3.882812 C 4.511719 3.828125 4.464844 3.78125 4.410156 3.78125 L 3.253906 3.78125 C 3.195312 3.78125 3.152344 3.828125 3.152344 3.882812 L 3.152344 4.914062 C 3.152344 4.96875 3.195312 5.015625 3.253906 5.015625 Z M 4.871094 5.015625 L 6.027344 5.015625 C 6.082031 5.015625 6.128906 4.96875 6.128906 4.914062 L 6.128906 3.882812 C 6.128906 3.828125 6.082031 3.78125 6.027344 3.78125 L 4.871094 3.78125 C 4.816406 3.78125 4.769531 3.828125 4.769531 3.882812 L 4.769531 4.914062 C 4.769531 4.96875 4.816406 5.015625 4.871094 5.015625 Z M 6.46875 5.015625 L 7.625 5.015625 C 7.683594 5.015625 7.726562 4.96875 7.726562 4.914062 L 7.726562 3.882812 C 7.726562 3.828125 7.683594 3.78125 7.625 3.78125 L 6.46875 3.78125 C 6.414062 3.78125 6.367188 3.828125 6.367188 3.882812 L 6.367188 4.914062 C 6.367188 4.96875 6.414062 5.015625 6.46875 5.015625 Z M 6.46875 3.53125 L 7.625 3.53125 C 7.683594 3.53125 7.726562 3.488281 7.726562 3.429688 L 7.726562 2.398438 C 7.726562 2.34375 7.683594 2.296875 7.625 2.296875 L 6.46875 2.296875 C 6.414062 2.296875 6.367188 2.34375 6.367188 2.398438 L 6.367188 3.429688 C 6.367188 3.488281 6.414062 3.53125 6.46875 3.53125 Z M 8.082031 6.496094 L 9.238281 6.496094 C 9.296875 6.496094 9.339844 6.453125 9.339844 6.394531 L 9.339844 5.363281 C 9.339844 5.308594 9.296875 5.261719 9.238281 5.261719 L 8.082031 5.261719 C 8.027344 5.261719 7.980469 5.308594 7.980469 5.363281 L 7.980469 6.394531 C 7.980469 6.449219 8.027344 6.496094 8.082031 6.496094 Z M 8.082031 6.496094 "/>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 4.8 KiB |
|
@ -1,4 +1,9 @@
|
|||
{
|
||||
"stems": {
|
||||
"Podfile": "ruby",
|
||||
"Procfile": "heroku",
|
||||
"Dockerfile": "docker"
|
||||
},
|
||||
"suffixes": {
|
||||
"astro": "astro",
|
||||
"Emakefile": "erlang",
|
||||
|
@ -86,6 +91,7 @@
|
|||
"mdb": "storage",
|
||||
"mdf": "storage",
|
||||
"mdx": "document",
|
||||
"metadata": "code",
|
||||
"mkv": "video",
|
||||
"mjs": "code",
|
||||
"mka": "audio",
|
||||
|
@ -189,6 +195,9 @@
|
|||
"default": {
|
||||
"icon": "icons/file_icons/file.svg"
|
||||
},
|
||||
"docker": {
|
||||
"icon": "icons/file_icons/docker.svg"
|
||||
},
|
||||
"document": {
|
||||
"icon": "icons/file_icons/book.svg"
|
||||
},
|
||||
|
@ -216,6 +225,9 @@
|
|||
"haskell": {
|
||||
"icon": "icons/file_icons/haskell.svg"
|
||||
},
|
||||
"heroku": {
|
||||
"icon": "icons/file_icons/heroku.svg"
|
||||
},
|
||||
"go": {
|
||||
"icon": "icons/file_icons/go.svg"
|
||||
},
|
||||
|
@ -228,7 +240,7 @@
|
|||
"java": {
|
||||
"icon": "icons/file_icons/java.svg"
|
||||
},
|
||||
"kotlin":{
|
||||
"kotlin": {
|
||||
"icon": "icons/file_icons/kotlin.svg"
|
||||
},
|
||||
"lock": {
|
||||
|
|
6
assets/icons/file_icons/heroku.svg
Normal file
6
assets/icons/file_icons/heroku.svg
Normal file
|
@ -0,0 +1,6 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="14px" height="14px" viewBox="0 0 14 14" version="1.1">
|
||||
<g id="surface1">
|
||||
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 12.023438 0 L 1.976562 0 C 1.277344 0 0.71875 0.558594 0.71875 1.261719 L 0.71875 12.738281 C 0.71875 13.441406 1.277344 14 1.976562 14 L 12.023438 14 C 12.722656 14 13.28125 13.441406 13.28125 12.738281 L 13.28125 1.261719 C 13.28125 0.558594 12.722656 0 12.023438 0 Z M 12.582031 12.738281 C 12.582031 13.054688 12.335938 13.300781 12.023438 13.300781 L 1.976562 13.300781 C 1.664062 13.300781 1.417969 13.054688 1.417969 12.738281 L 1.417969 1.261719 C 1.417969 0.945312 1.664062 0.699219 1.976562 0.699219 L 12.023438 0.699219 C 12.335938 0.699219 12.582031 0.945312 12.582031 1.261719 Z M 3.867188 11.898438 L 5.441406 10.5 L 3.867188 9.101562 Z M 9.539062 6.230469 C 9.257812 5.949219 8.734375 5.601562 7.859375 5.601562 C 6.914062 5.601562 5.933594 5.84375 5.234375 6.089844 L 5.234375 2.101562 L 3.832031 2.101562 L 3.832031 8.15625 L 4.8125 7.699219 C 4.8125 7.699219 6.421875 6.964844 7.824219 6.964844 C 8.523438 6.964844 8.699219 7.351562 8.699219 7.699219 L 8.699219 11.898438 L 10.097656 11.898438 L 10.097656 7.699219 C 10.132812 7.59375 10.132812 6.824219 9.539062 6.230469 Z M 7.683594 4.375 L 9.082031 4.375 C 9.710938 3.640625 10.027344 2.90625 10.132812 2.101562 L 8.734375 2.101562 C 8.59375 2.90625 8.242188 3.640625 7.683594 4.375 Z M 7.683594 4.375 "/>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 1.5 KiB |
|
@ -13,6 +13,7 @@ struct TypeConfig {
|
|||
|
||||
#[derive(Deserialize, Debug)]
|
||||
pub struct FileAssociations {
|
||||
stems: HashMap<String, String>,
|
||||
suffixes: HashMap<String, String>,
|
||||
types: HashMap<String, TypeConfig>,
|
||||
}
|
||||
|
@ -38,6 +39,7 @@ impl FileAssociations {
|
|||
.map_err(Into::into)
|
||||
})
|
||||
.unwrap_or_else(|_| FileAssociations {
|
||||
stems: HashMap::default(),
|
||||
suffixes: HashMap::default(),
|
||||
types: HashMap::default(),
|
||||
})
|
||||
|
@ -49,7 +51,14 @@ impl FileAssociations {
|
|||
// FIXME: Associate a type with the languages and have the file's language
|
||||
// override these associations
|
||||
maybe!({
|
||||
let suffix = path.icon_suffix()?;
|
||||
let suffix = path.icon_stem_or_suffix()?;
|
||||
|
||||
if let Some(type_str) = this.stems.get(suffix) {
|
||||
return this
|
||||
.types
|
||||
.get(type_str)
|
||||
.map(|type_config| type_config.icon.clone());
|
||||
}
|
||||
|
||||
this.suffixes
|
||||
.get(suffix)
|
||||
|
|
|
@ -48,7 +48,7 @@ lazy_static::lazy_static! {
|
|||
|
||||
pub trait PathExt {
|
||||
fn compact(&self) -> PathBuf;
|
||||
fn icon_suffix(&self) -> Option<&str>;
|
||||
fn icon_stem_or_suffix(&self) -> Option<&str>;
|
||||
fn extension_or_hidden_file_name(&self) -> Option<&str>;
|
||||
fn try_from_bytes<'a>(bytes: &'a [u8]) -> anyhow::Result<Self>
|
||||
where
|
||||
|
@ -100,17 +100,17 @@ impl<T: AsRef<Path>> PathExt for T {
|
|||
}
|
||||
}
|
||||
|
||||
/// Returns a suffix of the path that is used to determine which file icon to use
|
||||
fn icon_suffix(&self) -> Option<&str> {
|
||||
let file_name = self.as_ref().file_name()?.to_str()?;
|
||||
|
||||
/// Returns either the suffix if available, or the file stem otherwise to determine which file icon to use
|
||||
fn icon_stem_or_suffix(&self) -> Option<&str> {
|
||||
let path = self.as_ref();
|
||||
let file_name = path.file_name()?.to_str()?;
|
||||
if file_name.starts_with('.') {
|
||||
return file_name.strip_prefix('.');
|
||||
}
|
||||
|
||||
self.as_ref()
|
||||
.extension()
|
||||
.and_then(|extension| extension.to_str())
|
||||
path.extension()
|
||||
.and_then(|e| e.to_str())
|
||||
.or_else(|| path.file_stem()?.to_str())
|
||||
}
|
||||
|
||||
/// Returns a file's extension or, if the file is hidden, its name without the leading dot
|
||||
|
@ -403,26 +403,30 @@ mod tests {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_icon_suffix() {
|
||||
fn test_icon_stem_or_suffix() {
|
||||
// No dots in name
|
||||
let path = Path::new("/a/b/c/file_name.rs");
|
||||
assert_eq!(path.icon_suffix(), Some("rs"));
|
||||
assert_eq!(path.icon_stem_or_suffix(), Some("rs"));
|
||||
|
||||
// Single dot in name
|
||||
let path = Path::new("/a/b/c/file.name.rs");
|
||||
assert_eq!(path.icon_suffix(), Some("rs"));
|
||||
assert_eq!(path.icon_stem_or_suffix(), Some("rs"));
|
||||
|
||||
// No suffix
|
||||
let path = Path::new("/a/b/c/file");
|
||||
assert_eq!(path.icon_stem_or_suffix(), Some("file"));
|
||||
|
||||
// Multiple dots in name
|
||||
let path = Path::new("/a/b/c/long.file.name.rs");
|
||||
assert_eq!(path.icon_suffix(), Some("rs"));
|
||||
assert_eq!(path.icon_stem_or_suffix(), Some("rs"));
|
||||
|
||||
// Hidden file, no extension
|
||||
let path = Path::new("/a/b/c/.gitignore");
|
||||
assert_eq!(path.icon_suffix(), Some("gitignore"));
|
||||
assert_eq!(path.icon_stem_or_suffix(), Some("gitignore"));
|
||||
|
||||
// Hidden file, with extension
|
||||
let path = Path::new("/a/b/c/.eslintrc.js");
|
||||
assert_eq!(path.icon_suffix(), Some("eslintrc.js"));
|
||||
assert_eq!(path.icon_stem_or_suffix(), Some("eslintrc.js"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue