Merge branch 'master' into chesterliu/dev/win-support

This commit is contained in:
Chester Liu 2022-05-06 13:22:24 +08:00
commit d6732aea10
15 changed files with 139 additions and 56 deletions

View file

@ -28,7 +28,7 @@ jobs:
strategy: strategy:
matrix: matrix:
os: [ubuntu-latest, macos-latest] os: [ubuntu-latest, macos-latest]
rust: [1.48.0, stable, beta, nightly] rust: [1.56.1, stable, beta, nightly]
steps: steps:
- name: Checkout repository - name: Checkout repository

2
.gitignore vendored
View file

@ -3,7 +3,7 @@ target
# Vagrant stuff # Vagrant stuff
.vagrant .vagrant
ubuntu-xenial-16.04-cloudimg-console.log *.log
# Compiled artifacts # Compiled artifacts
# (see devtools/*-package-for-*.sh) # (see devtools/*-package-for-*.sh)

4
Cargo.lock generated
View file

@ -279,9 +279,9 @@ checksum = "1d51f5df5af43ab3f1360b429fa5e0152ac5ce8c0bd6485cae490332e96846a8"
[[package]] [[package]]
name = "term_grid" name = "term_grid"
version = "0.1.7" version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "230d3e804faaed5a39b08319efb797783df2fd9671b39b7596490cb486d702cf" checksum = "a7c9eb7705cb3f0fd71d3955b23db6d372142ac139e8c473952c93bf3c3dc4b7"
dependencies = [ dependencies = [
"unicode-width", "unicode-width",
] ]

View file

@ -27,7 +27,7 @@ natord = "1.0"
num_cpus = "1.10" num_cpus = "1.10"
number_prefix = "0.4" number_prefix = "0.4"
scoped_threadpool = "0.1" scoped_threadpool = "0.1"
term_grid = "0.1" term_grid = "0.2.0"
terminal_size = "0.1.16" terminal_size = "0.1.16"
unicode-width = "0.1" unicode-width = "0.1"
zoneinfo_compiled = "0.5.1" zoneinfo_compiled = "0.5.1"

View file

@ -105,74 +105,73 @@ More information on how to install exa is available on [the Installation page](h
On Alpine Linux, [enable community repository](https://wiki.alpinelinux.org/wiki/Enable_Community_Repository) and install the [`exa`](https://pkgs.alpinelinux.org/package/edge/community/x86_64/exa) package. On Alpine Linux, [enable community repository](https://wiki.alpinelinux.org/wiki/Enable_Community_Repository) and install the [`exa`](https://pkgs.alpinelinux.org/package/edge/community/x86_64/exa) package.
$ apk add exa apk add exa
### Arch Linux ### Arch Linux
On Arch, install the [`exa`](https://www.archlinux.org/packages/community/x86_64/exa/) package. On Arch, install the [`exa`](https://www.archlinux.org/packages/community/x86_64/exa/) package.
$ pacman -S exa pacman -S exa
### Android / Termux ### Android / Termux
On Android / Termux, install the [`exa`](https://github.com/termux/termux-packages/tree/master/packages/exa) package. On Android / Termux, install the [`exa`](https://github.com/termux/termux-packages/tree/master/packages/exa) package.
$ pkg install exa pkg install exa
### Debian ### Debian
On Debian, install the [`exa`](https://packages.debian.org/unstable/exa) package. On Debian, install the [`exa`](https://packages.debian.org/stable/exa) package.
For now, exa is in the _unstable_ repository.
$ apt install exa apt install exa
### Fedora ### Fedora
On Fedora, install the [`exa`](https://src.fedoraproject.org/modules/exa) package. On Fedora, install the [`exa`](https://src.fedoraproject.org/modules/exa) package.
$ dnf install exa dnf install exa
### Gentoo ### Gentoo
On Gentoo, install the [`sys-apps/exa`](https://packages.gentoo.org/packages/sys-apps/exa) package. On Gentoo, install the [`sys-apps/exa`](https://packages.gentoo.org/packages/sys-apps/exa) package.
$ emerge sys-apps/exa emerge sys-apps/exa
### Homebrew ### Homebrew
If youre using [Homebrew](https://brew.sh/) on macOS, install the [`exa`](http://formulae.brew.sh/formula/exa) formula. If youre using [Homebrew](https://brew.sh/) on macOS, install the [`exa`](http://formulae.brew.sh/formula/exa) formula.
$ brew install exa brew install exa
### MacPorts ### MacPorts
If you're using [MacPorts](https://www.macports.org/) on macOS, install the [`exa`](https://ports.macports.org/port/exa/summary) port. If you're using [MacPorts](https://www.macports.org/) on macOS, install the [`exa`](https://ports.macports.org/port/exa/summary) port.
$ port install exa port install exa
### Nix ### Nix
On nixOS, install the [`exa`](https://github.com/NixOS/nixpkgs/blob/master/pkgs/tools/misc/exa/default.nix) package. On nixOS, install the [`exa`](https://github.com/NixOS/nixpkgs/blob/master/pkgs/tools/misc/exa/default.nix) package.
$ nix-env -i exa nix-env -i exa
### openSUSE ### openSUSE
On openSUSE, install the [`exa`](https://software.opensuse.org/package/exa) package. On openSUSE, install the [`exa`](https://software.opensuse.org/package/exa) package.
$ zypper install exa zypper install exa
### Ubuntu ### Ubuntu
On Ubuntu 20.10 (Groovy Gorilla) and later, install the [`exa`](https://packages.ubuntu.com/groovy/exa) package. On Ubuntu 20.10 (Groovy Gorilla) and later, install the [`exa`](https://packages.ubuntu.com/groovy/exa) package.
$ sudo apt install exa sudo apt install exa
### Void Linux ### Void Linux
On Void Linux, install the [`exa`](https://github.com/void-linux/void-packages/blob/master/srcpkgs/exa/template) package. On Void Linux, install the [`exa`](https://github.com/void-linux/void-packages/blob/master/srcpkgs/exa/template) package.
$ xbps-install -S exa xbps-install -S exa
### Manual installation from GitHub ### Manual installation from GitHub
@ -185,7 +184,7 @@ For more information, see the [Manual Installation page](https://the.exa.website
If you already have a Rust environment set up, you can use the `cargo install` command: If you already have a Rust environment set up, you can use the `cargo install` command:
$ cargo install exa cargo install exa
Cargo will build the `exa` binary and place it in `$HOME/.cargo`. Cargo will build the `exa` binary and place it in `$HOME/.cargo`.
@ -197,8 +196,8 @@ To build without Git support, run `cargo install --no-default-features exa` is a
<a id="development"> <a id="development">
<h1>Development <h1>Development
<a href="https://blog.rust-lang.org/2020/08/03/Rust-1.45.2.html"> <a href="https://blog.rust-lang.org/2021/11/01/Rust-1.56.1.html">
<img src="https://img.shields.io/badge/rustc-1.45.2+-lightgray.svg" alt="Rust 1.45.2+" /> <img src="https://img.shields.io/badge/rustc-1.56.1+-lightgray.svg" alt="Rust 1.56.1+" />
</a> </a>
<a href="https://github.com/ogham/exa/blob/master/LICENCE"> <a href="https://github.com/ogham/exa/blob/master/LICENCE">
@ -207,16 +206,16 @@ To build without Git support, run `cargo install --no-default-features exa` is a
</h1></a> </h1></a>
exa is written in [Rust](https://www.rust-lang.org/). exa is written in [Rust](https://www.rust-lang.org/).
You will need rustc version 1.45.2 or higher. You will need rustc version 1.56.1 or higher.
The recommended way to install Rust for development is from the [official download page](https://www.rust-lang.org/tools/install), using rustup. The recommended way to install Rust for development is from the [official download page](https://www.rust-lang.org/tools/install), using rustup.
Once Rust is installed, you can compile exa with Cargo: Once Rust is installed, you can compile exa with Cargo:
$ cargo build cargo build
$ cargo test cargo test
- The [just](https://github.com/casey/just) command runner can be used to run some helpful development commands, in a manner similar to `make`. - The [just](https://github.com/casey/just) command runner can be used to run some helpful development commands, in a manner similar to `make`.
Run `just --tasks` to get an overview of whats available. Run `just --list` to get an overview of whats available.
- If you are compiling a copy for yourself, be sure to run `cargo build --release` or `just build-release` to benefit from release-mode optimisations. - If you are compiling a copy for yourself, be sure to run `cargo build --release` or `just build-release` to benefit from release-mode optimisations.
Copy the resulting binary, which will be in the `target/release` directory, into a folder in your `$PATH`. Copy the resulting binary, which will be in the `target/release` directory, into a folder in your `$PATH`.

View file

@ -224,6 +224,12 @@ Specifies the number of spaces to print between an icon (see the `--icons`
Different terminals display icons differently, as they usually take up more than one character width on screen, so theres no “standard” number of spaces that exa can use to separate an icon from text. One space may place the icon too close to the text, and two spaces may place it too far away. So the choice is left up to the user to configure depending on their terminal emulator. Different terminals display icons differently, as they usually take up more than one character width on screen, so theres no “standard” number of spaces that exa can use to separate an icon from text. One space may place the icon too close to the text, and two spaces may place it too far away. So the choice is left up to the user to configure depending on their terminal emulator.
## `NO_COLOR`
Disables colours in the output (regardless of its value). Can be overridden by `--color` option.
See `https://no-color.org/` for details.
## `LS_COLORS`, `EXA_COLORS` ## `LS_COLORS`, `EXA_COLORS`
Specifies the colour scheme used to highlight files based on their name and kind, as well as highlighting metadata and parts of the UI. Specifies the colour scheme used to highlight files based on their name and kind, as well as highlighting metadata and parts of the UI.

2
rust-toolchain.toml Normal file
View file

@ -0,0 +1,2 @@
[toolchain]
channel = "1.56.1"

View file

@ -38,7 +38,8 @@ impl FileExtensions {
"png", "jfi", "jfif", "jif", "jpe", "jpeg", "jpg", "gif", "bmp", "png", "jfi", "jfif", "jif", "jpe", "jpeg", "jpg", "gif", "bmp",
"tiff", "tif", "ppm", "pgm", "pbm", "pnm", "webp", "raw", "arw", "tiff", "tif", "ppm", "pgm", "pbm", "pnm", "webp", "raw", "arw",
"svg", "stl", "eps", "dvi", "ps", "cbr", "jpf", "cbz", "xpm", "svg", "stl", "eps", "dvi", "ps", "cbr", "jpf", "cbz", "xpm",
"ico", "cr2", "orf", "nef", "heif", "avif", "jxl", "ico", "cr2", "orf", "nef", "heif", "avif", "jxl", "j2k", "jp2",
"j2c", "jpx",
]) ])
} }
@ -80,7 +81,7 @@ impl FileExtensions {
file.extension_is_one_of( &[ file.extension_is_one_of( &[
"zip", "tar", "Z", "z", "gz", "bz2", "a", "ar", "7z", "zip", "tar", "Z", "z", "gz", "bz2", "a", "ar", "7z",
"iso", "dmg", "tc", "rar", "par", "tgz", "xz", "txz", "iso", "dmg", "tc", "rar", "par", "tgz", "xz", "txz",
"lz", "tlz", "lzma", "deb", "rpm", "zst", "lz4", "lz", "tlz", "lzma", "deb", "rpm", "zst", "lz4", "cpio",
]) ])
} }

View file

@ -18,7 +18,6 @@
#![allow(clippy::non_ascii_literal)] #![allow(clippy::non_ascii_literal)]
#![allow(clippy::option_if_let_else)] #![allow(clippy::option_if_let_else)]
#![allow(clippy::too_many_lines)] #![allow(clippy::too_many_lines)]
#![allow(clippy::unnested_or_patterns)] // TODO: remove this when we support Rust 1.53.0
#![allow(clippy::unused_self)] #![allow(clippy::unused_self)]
#![allow(clippy::upper_case_acronyms)] #![allow(clippy::upper_case_acronyms)]
#![allow(clippy::wildcard_imports)] #![allow(clippy::wildcard_imports)]
@ -50,6 +49,10 @@ mod theme;
fn main() { fn main() {
use std::process::exit; use std::process::exit;
unsafe {
libc::signal(libc::SIGPIPE, libc::SIG_DFL);
}
logger::configure(env::var_os(vars::EXA_DEBUG)); logger::configure(env::var_os(vars::EXA_DEBUG));
#[cfg(windows)] #[cfg(windows)]

View file

@ -5,7 +5,7 @@ use crate::theme::{Options, UseColours, ColourScale, Definitions};
impl Options { impl Options {
pub fn deduce<V: Vars>(matches: &MatchedFlags<'_>, vars: &V) -> Result<Self, OptionsError> { pub fn deduce<V: Vars>(matches: &MatchedFlags<'_>, vars: &V) -> Result<Self, OptionsError> {
let use_colours = UseColours::deduce(matches)?; let use_colours = UseColours::deduce(matches, vars)?;
let colour_scale = ColourScale::deduce(matches)?; let colour_scale = ColourScale::deduce(matches)?;
let definitions = if use_colours == UseColours::Never { let definitions = if use_colours == UseColours::Never {
@ -21,10 +21,15 @@ impl Options {
impl UseColours { impl UseColours {
fn deduce(matches: &MatchedFlags<'_>) -> Result<Self, OptionsError> { fn deduce<V: Vars>(matches: &MatchedFlags<'_>, vars: &V) -> Result<Self, OptionsError> {
let default_value = match vars.get(vars::NO_COLOR) {
Some(_) => Self::Never,
None => Self::Automatic,
};
let word = match matches.get_where(|f| f.matches(&flags::COLOR) || f.matches(&flags::COLOUR))? { let word = match matches.get_where(|f| f.matches(&flags::COLOR) || f.matches(&flags::COLOUR))? {
Some(w) => w, Some(w) => w,
None => return Ok(Self::Automatic), None => return Ok(default_value),
}; };
if word == "always" { if word == "always" {
@ -87,6 +92,16 @@ mod terminal_test {
} }
}; };
($name:ident: $type:ident <- $inputs:expr, $env:expr; $stricts:expr => $result:expr) => {
#[test]
fn $name() {
let env = $env;
for result in parse_for_test($inputs.as_ref(), TEST_ARGS, $stricts, |mf| $type::deduce(mf, &env)) {
assert_eq!(result, $result);
}
}
};
($name:ident: $type:ident <- $inputs:expr; $stricts:expr => err $result:expr) => { ($name:ident: $type:ident <- $inputs:expr; $stricts:expr => err $result:expr) => {
#[test] #[test]
fn $name() { fn $name() {
@ -95,11 +110,39 @@ mod terminal_test {
} }
} }
}; };
($name:ident: $type:ident <- $inputs:expr, $env:expr; $stricts:expr => err $result:expr) => {
#[test]
fn $name() {
let env = $env;
for result in parse_for_test($inputs.as_ref(), TEST_ARGS, $stricts, |mf| $type::deduce(mf, &env)) {
assert_eq!(result.unwrap_err(), $result);
}
}
};
} }
struct MockVars { struct MockVars {
ls: &'static str, ls: &'static str,
exa: &'static str, exa: &'static str,
no_color: &'static str,
}
impl MockVars {
fn empty() -> MockVars {
return MockVars {
ls: "",
exa: "",
no_color: "",
};
}
fn with_no_color() -> MockVars {
return MockVars {
ls: "",
exa: "",
no_color: "true",
};
}
} }
// Test impl that just returns the value it has. // Test impl that just returns the value it has.
@ -111,6 +154,9 @@ mod terminal_test {
else if name == vars::EXA_COLORS && ! self.exa.is_empty() { else if name == vars::EXA_COLORS && ! self.exa.is_empty() {
Some(OsString::from(self.exa.clone())) Some(OsString::from(self.exa.clone()))
} }
else if name == vars::NO_COLOR && ! self.no_color.is_empty() {
Some(OsString::from(self.no_color.clone()))
}
else { else {
None None
} }
@ -120,32 +166,33 @@ mod terminal_test {
// Default // Default
test!(empty: UseColours <- []; Both => Ok(UseColours::Automatic)); test!(empty: UseColours <- [], MockVars::empty(); Both => Ok(UseColours::Automatic));
test!(empty_with_no_color: UseColours <- [], MockVars::with_no_color(); Both => Ok(UseColours::Never));
// --colour // --colour
test!(u_always: UseColours <- ["--colour=always"]; Both => Ok(UseColours::Always)); test!(u_always: UseColours <- ["--colour=always"], MockVars::empty(); Both => Ok(UseColours::Always));
test!(u_auto: UseColours <- ["--colour", "auto"]; Both => Ok(UseColours::Automatic)); test!(u_auto: UseColours <- ["--colour", "auto"], MockVars::empty(); Both => Ok(UseColours::Automatic));
test!(u_never: UseColours <- ["--colour=never"]; Both => Ok(UseColours::Never)); test!(u_never: UseColours <- ["--colour=never"], MockVars::empty(); Both => Ok(UseColours::Never));
// --color // --color
test!(no_u_always: UseColours <- ["--color", "always"]; Both => Ok(UseColours::Always)); test!(no_u_always: UseColours <- ["--color", "always"], MockVars::empty(); Both => Ok(UseColours::Always));
test!(no_u_auto: UseColours <- ["--color=auto"]; Both => Ok(UseColours::Automatic)); test!(no_u_auto: UseColours <- ["--color=auto"], MockVars::empty(); Both => Ok(UseColours::Automatic));
test!(no_u_never: UseColours <- ["--color", "never"]; Both => Ok(UseColours::Never)); test!(no_u_never: UseColours <- ["--color", "never"], MockVars::empty(); Both => Ok(UseColours::Never));
// Errors // Errors
test!(no_u_error: UseColours <- ["--color=upstream"]; Both => err OptionsError::BadArgument(&flags::COLOR, OsString::from("upstream"))); // the error is for --color test!(no_u_error: UseColours <- ["--color=upstream"], MockVars::empty(); Both => err OptionsError::BadArgument(&flags::COLOR, OsString::from("upstream"))); // the error is for --color
test!(u_error: UseColours <- ["--colour=lovers"]; Both => err OptionsError::BadArgument(&flags::COLOR, OsString::from("lovers"))); // and so is this one! test!(u_error: UseColours <- ["--colour=lovers"], MockVars::empty(); Both => err OptionsError::BadArgument(&flags::COLOR, OsString::from("lovers"))); // and so is this one!
// Overriding // Overriding
test!(overridden_1: UseColours <- ["--colour=auto", "--colour=never"]; Last => Ok(UseColours::Never)); test!(overridden_1: UseColours <- ["--colour=auto", "--colour=never"], MockVars::empty(); Last => Ok(UseColours::Never));
test!(overridden_2: UseColours <- ["--color=auto", "--colour=never"]; Last => Ok(UseColours::Never)); test!(overridden_2: UseColours <- ["--color=auto", "--colour=never"], MockVars::empty(); Last => Ok(UseColours::Never));
test!(overridden_3: UseColours <- ["--colour=auto", "--color=never"]; Last => Ok(UseColours::Never)); test!(overridden_3: UseColours <- ["--colour=auto", "--color=never"], MockVars::empty(); Last => Ok(UseColours::Never));
test!(overridden_4: UseColours <- ["--color=auto", "--color=never"]; Last => Ok(UseColours::Never)); test!(overridden_4: UseColours <- ["--color=auto", "--color=never"], MockVars::empty(); Last => Ok(UseColours::Never));
test!(overridden_5: UseColours <- ["--colour=auto", "--colour=never"]; Complain => err OptionsError::Duplicate(Flag::Long("colour"), Flag::Long("colour"))); test!(overridden_5: UseColours <- ["--colour=auto", "--colour=never"], MockVars::empty(); Complain => err OptionsError::Duplicate(Flag::Long("colour"), Flag::Long("colour")));
test!(overridden_6: UseColours <- ["--color=auto", "--colour=never"]; Complain => err OptionsError::Duplicate(Flag::Long("color"), Flag::Long("colour"))); test!(overridden_6: UseColours <- ["--color=auto", "--colour=never"], MockVars::empty(); Complain => err OptionsError::Duplicate(Flag::Long("color"), Flag::Long("colour")));
test!(overridden_7: UseColours <- ["--colour=auto", "--color=never"]; Complain => err OptionsError::Duplicate(Flag::Long("colour"), Flag::Long("color"))); test!(overridden_7: UseColours <- ["--colour=auto", "--color=never"], MockVars::empty(); Complain => err OptionsError::Duplicate(Flag::Long("colour"), Flag::Long("color")));
test!(overridden_8: UseColours <- ["--color=auto", "--color=never"]; Complain => err OptionsError::Duplicate(Flag::Long("color"), Flag::Long("color"))); test!(overridden_8: UseColours <- ["--color=auto", "--color=never"], MockVars::empty(); Complain => err OptionsError::Duplicate(Flag::Long("color"), Flag::Long("color")));
test!(scale_1: ColourScale <- ["--color-scale", "--colour-scale"]; Last => Ok(ColourScale::Gradient)); test!(scale_1: ColourScale <- ["--color-scale", "--colour-scale"]; Last => Ok(ColourScale::Gradient));
test!(scale_2: ColourScale <- ["--color-scale", ]; Last => Ok(ColourScale::Gradient)); test!(scale_2: ColourScale <- ["--color-scale", ]; Last => Ok(ColourScale::Gradient));

View file

@ -15,6 +15,9 @@ pub static COLUMNS: &str = "COLUMNS";
/// Environment variable used to datetime format. /// Environment variable used to datetime format.
pub static TIME_STYLE: &str = "TIME_STYLE"; pub static TIME_STYLE: &str = "TIME_STYLE";
/// Environment variable used to disable colors.
/// See: https://no-color.org/
pub static NO_COLOR: &str = "NO_COLOR";
// exa-specific variables // exa-specific variables

View file

@ -147,7 +147,11 @@ impl<'a> AsRef<File<'a>> for Egg<'a> {
impl<'a> Render<'a> { impl<'a> Render<'a> {
pub fn render<W: Write>(mut self, w: &mut W) -> io::Result<()> { pub fn render<W: Write>(mut self, w: &mut W) -> io::Result<()> {
let mut pool = Pool::new(num_cpus::get() as u32); let n_cpus = match num_cpus::get() as u32 {
0 => 1,
n => n,
};
let mut pool = Pool::new(n_cpus);
let mut rows = Vec::new(); let mut rows = Vec::new();
if let Some(ref table) = self.opts.table { if let Some(ref table) = self.opts.table {

View file

@ -46,6 +46,7 @@ impl<'a> Render<'a> {
grid.add(tg::Cell { grid.add(tg::Cell {
contents: filename.strings().to_string(), contents: filename.strings().to_string(),
width: *filename.width(), width: *filename.width(),
alignment: tg::Alignment::Left,
}); });
} }

View file

@ -263,6 +263,7 @@ impl<'a> Render<'a> {
let cell = grid::Cell { let cell = grid::Cell {
contents: ANSIStrings(&column[row].contents).to_string(), contents: ANSIStrings(&column[row].contents).to_string(),
width: *column[row].width, width: *column[row].width,
alignment: grid::Alignment::Left,
}; };
grid.add(cell); grid.add(cell);
@ -276,6 +277,7 @@ impl<'a> Render<'a> {
let cell = grid::Cell { let cell = grid::Cell {
contents: ANSIStrings(&cell.contents).to_string(), contents: ANSIStrings(&cell.contents).to_string(),
width: *cell.width, width: *cell.width,
alignment: grid::Alignment::Left,
}; };
grid.add(cell); grid.add(cell);

View file

@ -69,7 +69,9 @@ lazy_static! {
m.insert("Dockerfile", '\u{f308}'); //  m.insert("Dockerfile", '\u{f308}'); // 
m.insert("ds_store", '\u{f179}'); //  m.insert("ds_store", '\u{f179}'); // 
m.insert("gitignore_global", '\u{f1d3}'); //  m.insert("gitignore_global", '\u{f1d3}'); // 
m.insert("gradle", '\u{e70e}'); //  m.insert("go.mod", '\u{e626}'); // 
m.insert("go.sum", '\u{e626}'); // 
m.insert("gradle", '\u{e256}'); // 
m.insert("gruntfile.coffee", '\u{e611}'); //  m.insert("gruntfile.coffee", '\u{e611}'); // 
m.insert("gruntfile.js", '\u{e611}'); //  m.insert("gruntfile.js", '\u{e611}'); // 
m.insert("gruntfile.ls", '\u{e611}'); //  m.insert("gruntfile.ls", '\u{e611}'); // 
@ -83,6 +85,7 @@ lazy_static! {
m.insert("Makefile", '\u{f489}'); //  m.insert("Makefile", '\u{f489}'); // 
m.insert("node_modules", '\u{e718}'); //  m.insert("node_modules", '\u{e718}'); // 
m.insert("npmignore", '\u{e71e}'); //  m.insert("npmignore", '\u{e71e}'); // 
m.insert("PKGBUILD", '\u{f303}'); // 
m.insert("rubydoc", '\u{e73b}'); //  m.insert("rubydoc", '\u{e73b}'); // 
m.insert("yarn.lock", '\u{e718}'); //  m.insert("yarn.lock", '\u{e718}'); // 
@ -118,6 +121,7 @@ pub fn icon_for_file(file: &File<'_>) -> char {
"bash_profile" => '\u{f489}', //  "bash_profile" => '\u{f489}', // 
"bashrc" => '\u{f489}', //  "bashrc" => '\u{f489}', // 
"bat" => '\u{f17a}', //  "bat" => '\u{f17a}', // 
"bats" => '\u{f489}', // 
"bmp" => '\u{f1c5}', //  "bmp" => '\u{f1c5}', // 
"bz" => '\u{f410}', //  "bz" => '\u{f410}', // 
"bz2" => '\u{f410}', //  "bz2" => '\u{f410}', // 
@ -134,6 +138,7 @@ pub fn icon_for_file(file: &File<'_>) -> char {
"coffee" => '\u{f0f4}', //  "coffee" => '\u{f0f4}', // 
"conf" => '\u{e615}', //  "conf" => '\u{e615}', // 
"cp" => '\u{e61d}', //  "cp" => '\u{e61d}', // 
"cpio" => '\u{f410}', // 
"cpp" => '\u{e61d}', //  "cpp" => '\u{e61d}', // 
"cs" => '\u{f81a}', //  "cs" => '\u{f81a}', // 
"csh" => '\u{f489}', //  "csh" => '\u{f489}', // 
@ -156,6 +161,7 @@ pub fn icon_for_file(file: &File<'_>) -> char {
"DS_store" => '\u{f179}', //  "DS_store" => '\u{f179}', // 
"dump" => '\u{f1c0}', //  "dump" => '\u{f1c0}', // 
"ebook" => '\u{e28b}', //  "ebook" => '\u{e28b}', // 
"ebuild" => '\u{f30d}', // 
"editorconfig" => '\u{e615}', //  "editorconfig" => '\u{e615}', // 
"ejs" => '\u{e618}', //  "ejs" => '\u{e618}', // 
"elm" => '\u{e62c}', //  "elm" => '\u{e62c}', // 
@ -185,7 +191,7 @@ pub fn icon_for_file(file: &File<'_>) -> char {
"gitignore" => '\u{f1d3}', //  "gitignore" => '\u{f1d3}', // 
"gitmodules" => '\u{f1d3}', //  "gitmodules" => '\u{f1d3}', // 
"go" => '\u{e626}', //  "go" => '\u{e626}', // 
"gradle" => '\u{e70e}', //  "gradle" => '\u{e256}', // 
"groovy" => '\u{e775}', //  "groovy" => '\u{e775}', // 
"gsheet" => '\u{f1c3}', //  "gsheet" => '\u{f1c3}', // 
"gslides" => '\u{f1c4}', //  "gslides" => '\u{f1c4}', // 
@ -204,15 +210,21 @@ pub fn icon_for_file(file: &File<'_>) -> char {
"ini" => '\u{f17a}', //  "ini" => '\u{f17a}', // 
"ipynb" => '\u{e606}', //  "ipynb" => '\u{e606}', // 
"iso" => '\u{e271}', //  "iso" => '\u{e271}', // 
"j2c" => '\u{f1c5}', // 
"j2k" => '\u{f1c5}', // 
"jad" => '\u{e256}', //  "jad" => '\u{e256}', // 
"jar" => '\u{e204}', //  "jar" => '\u{e256}', // 
"java" => '\u{e204}', //  "java" => '\u{e256}', // 
"jfi" => '\u{f1c5}', //  "jfi" => '\u{f1c5}', // 
"jfif" => '\u{f1c5}', //  "jfif" => '\u{f1c5}', // 
"jif" => '\u{f1c5}', //  "jif" => '\u{f1c5}', // 
"jl" => '\u{e624}', // 
"jmd" => '\u{f48a}', // 
"jp2" => '\u{f1c5}', // 
"jpe" => '\u{f1c5}', //  "jpe" => '\u{f1c5}', // 
"jpeg" => '\u{f1c5}', //  "jpeg" => '\u{f1c5}', // 
"jpg" => '\u{f1c5}', //  "jpg" => '\u{f1c5}', // 
"jpx" => '\u{f1c5}', // 
"js" => '\u{e74e}', //  "js" => '\u{e74e}', // 
"json" => '\u{e60b}', //  "json" => '\u{e60b}', // 
"jsx" => '\u{e7ba}', //  "jsx" => '\u{e7ba}', // 
@ -255,6 +267,7 @@ pub fn icon_for_file(file: &File<'_>) -> char {
"ogg" => '\u{f001}', //  "ogg" => '\u{f001}', // 
"ogv" => '\u{f03d}', //  "ogv" => '\u{f03d}', // 
"otf" => '\u{f031}', //  "otf" => '\u{f031}', // 
"part" => '\u{f43a}', // 
"patch" => '\u{f440}', //  "patch" => '\u{f440}', // 
"pdf" => '\u{f1c1}', //  "pdf" => '\u{f1c1}', // 
"php" => '\u{e73d}', //  "php" => '\u{e73d}', // 
@ -314,6 +327,7 @@ pub fn icon_for_file(file: &File<'_>) -> char {
"tiff" => '\u{f1c5}', //  "tiff" => '\u{f1c5}', // 
"tlz" => '\u{f410}', //  "tlz" => '\u{f410}', // 
"toml" => '\u{e615}', //  "toml" => '\u{e615}', // 
"torrent" => '\u{e275}', // 
"ts" => '\u{e628}', //  "ts" => '\u{e628}', // 
"tsv" => '\u{f1c3}', //  "tsv" => '\u{f1c3}', // 
"tsx" => '\u{e7ba}', //  "tsx" => '\u{e7ba}', // 
@ -336,8 +350,8 @@ pub fn icon_for_file(file: &File<'_>) -> char {
"xhtml" => '\u{f13b}', //  "xhtml" => '\u{f13b}', // 
"xls" => '\u{f1c3}', //  "xls" => '\u{f1c3}', // 
"xlsx" => '\u{f1c3}', //  "xlsx" => '\u{f1c3}', // 
"xml" => '\u{fabf}', // 謹 "xml" => '\u{f121}', // 
"xul" => '\u{fabf}', // 謹 "xul" => '\u{f121}', // 
"xz" => '\u{f410}', //  "xz" => '\u{f410}', // 
"yaml" => '\u{f481}', //  "yaml" => '\u{f481}', // 
"yml" => '\u{f481}', //  "yml" => '\u{f481}', // 
@ -345,6 +359,7 @@ pub fn icon_for_file(file: &File<'_>) -> char {
"zsh" => '\u{f489}', //  "zsh" => '\u{f489}', // 
"zsh-theme" => '\u{f489}', //  "zsh-theme" => '\u{f489}', // 
"zshrc" => '\u{f489}', //  "zshrc" => '\u{f489}', // 
"zst" => '\u{f410}', // 
_ => '\u{f15b}' //  _ => '\u{f15b}' // 
} }
} }