summaryrefslogtreecommitdiffstats
path: root/README.md
diff options
context:
space:
mode:
Diffstat (limited to 'README.md')
-rw-r--r--README.md341
1 files changed, 271 insertions, 70 deletions
diff --git a/README.md b/README.md
index d613834..b9aad82 100644
--- a/README.md
+++ b/README.md
@@ -1,31 +1,60 @@
-`bfs`
-=====
-
-[![License](http://img.shields.io/badge/license-0BSD-blue.svg)](https://github.com/tavianator/bfs/blob/main/LICENSE)
-[![Version](https://img.shields.io/github/v/tag/tavianator/bfs?label=version)](https://github.com/tavianator/bfs/releases)
-[![Linux CI Status](https://github.com/tavianator/bfs/actions/workflows/linux.yml/badge.svg?branch=main)](https://github.com/tavianator/bfs/actions/workflows/linux.yml)
-[![macOS CI Status](https://github.com/tavianator/bfs/actions/workflows/macos.yml/badge.svg?branch=main)](https://github.com/tavianator/bfs/actions/workflows/macos.yml)
-[![FreeBSD CI Status](https://github.com/tavianator/bfs/actions/workflows/freebsd.yml/badge.svg?branch=main)](https://github.com/tavianator/bfs/actions/workflows/freebsd.yml)
+<div align="center">
+
+<h1>
+<code>bfs</code>
+<br clear="all">
+<a href="https://github.com/tavianator/bfs/releases"><img src="https://img.shields.io/github/v/tag/tavianator/bfs?label=version" alt="Version" align="left"></a>
+<a href="/LICENSE"><img src="https://img.shields.io/badge/license-0BSD-blue.svg" alt="License" align="left"></a>
+<a href="https://github.com/tavianator/bfs/actions/workflows/ci.yml"><img src="https://github.com/tavianator/bfs/actions/workflows/ci.yml/badge.svg" alt="CI Status" align="right"></a>
+<a href="https://codecov.io/gh/tavianator/bfs"><img src="https://img.shields.io/codecov/c/github/tavianator/bfs?token=PpBVuozOVC" alt="Code coverage" align="right"/></a>
+</h1>
+
+**[Features]   •   [Installation]   •   [Usage]   •   [Building]   •   [Contributing]   •   [Changelog]**
+
+[Features]: #features
+[Installation]: #installation
+[Usage]: /docs/USAGE.md
+[Building]: /docs/BUILDING.md
+[Contributing]: /docs/CONTRIBUTING.md
+[Changelog]: /docs/CHANGELOG.md
+
+<picture>
+ <source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/tavianator/bfs/gh-pages/animation-dark.svg">
+ <source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/tavianator/bfs/gh-pages/animation-light.svg">
+ <img alt="Screencast" src="https://raw.githubusercontent.com/tavianator/bfs/gh-pages/animation-light.svg">
+</picture>
+<p></p>
+
+</div>
+
+`bfs` is a variant of the UNIX `find` command that operates [**breadth-first**](https://en.wikipedia.org/wiki/Breadth-first_search) rather than [**depth-first**](https://en.wikipedia.org/wiki/Depth-first_search).
+It is otherwise compatible with many versions of `find`, including
-Breadth-first search for your files.
+<div align="center">
-<img src="https://tavianator.github.io/bfs/animation.svg" alt="Screenshot" />
+**[POSIX]   •   [GNU]   •   [FreeBSD]   •   [OpenBSD]   •   [NetBSD]   •   [macOS]**
-`bfs` is a variant of the UNIX `find` command that operates [breadth-first](https://en.wikipedia.org/wiki/Breadth-first_search) rather than [depth-first](https://en.wikipedia.org/wiki/Depth-first_search).
-It is otherwise compatible with many versions of `find`, including
+[POSIX]: http://pubs.opengroup.org/onlinepubs/9699919799/utilities/find.html
+[GNU]: https://www.gnu.org/software/findutils/
+[FreeBSD]: https://www.freebsd.org/cgi/man.cgi?find(1)
+[OpenBSD]: https://man.openbsd.org/find.1
+[NetBSD]: https://man.netbsd.org/find.1
+[macOS]: https://ss64.com/osx/find.html
-- [POSIX `find`](http://pubs.opengroup.org/onlinepubs/9699919799/utilities/find.html)
-- [GNU `find`](https://www.gnu.org/software/findutils/)
-- {[Free](https://www.freebsd.org/cgi/man.cgi?find(1)),[Open](https://man.openbsd.org/find.1),[Net](https://man.netbsd.org/find.1)}BSD `find`
-- [macOS `find`](https://ss64.com/osx/find.html)
+</div>
If you're not familiar with `find`, the [GNU find manual](https://www.gnu.org/software/findutils/manual/html_mono/find.html) provides a good introduction.
-Breadth vs. depth
------------------
+Features
+--------
+
+<details>
+<summary>
+<code>bfs</code> operates breadth-first, which typically finds the file(s) you're looking for faster.
+</summary>
+<p></p>
-The advantage of breadth-first over depth first search is that it usually finds the file(s) you're looking for faster.
Imagine the following directory tree:
<pre>
@@ -41,112 +70,284 @@ haystack
</pre>
`find` will explore the entire `deep` directory tree before it ever gets to the `shallow` one that contains what you're looking for.
+On the other hand, `bfs` lists files from shallowest to deepest, so you never have to wait for it to explore an entire unrelated subtree.
-<pre>
-$ <strong>find</strong> haystack
+<table>
+<tbody>
+<tr><th><code>bfs</code></th><th><code>find</code></th></tr>
+<tr>
+<td width="506" valign="top">
+
+```console
+$ bfs haystack
haystack
haystack/deep
+haystack/shallow
haystack/deep/1
-haystack/deep/1/2
-haystack/deep/1/2/3
-haystack/deep/1/2/3/4
+haystack/shallow/needle
...
-haystack/shallow
-<strong>haystack/shallow/needle</strong>
-</pre>
+```
-On the other hand, `bfs` lists files from shallowest to deepest, so you never have to wait for it to explore an entire unrelated subtree.
+</td>
+<td width="506" valign="top">
-<pre>
-$ <strong>bfs</strong> haystack
+```console
+$ find haystack
haystack
haystack/deep
-haystack/shallow
haystack/deep/1
-<strong>haystack/shallow/needle</strong>
haystack/deep/1/2
haystack/deep/1/2/3
haystack/deep/1/2/3/4
...
-</pre>
+haystack/shallow
+haystack/shallow/needle
+```
+</td>
+</tr>
+</tbody>
+</table>
+</details>
-Easy
-----
+<details>
+<summary>
+<code>bfs</code> tries to be easier to use than <code>find</code>, while remaining compatible.
+</summary>
+<p></p>
-`bfs` tries to be easier to use than `find`, while remaining compatible.
For example, `bfs` is less picky about where you put its arguments:
-<pre>
-$ <strong>find</strong> -L -name 'needle' <em>haystack</em>
+<table>
+<tbody>
+<tr><th><code>bfs</code></th><th><code>find</code></th></tr>
+<tr>
+<td width="506">
+
+```console
+$ bfs -L -name 'needle' haystack
+haystack/needle
+
+$ bfs haystack -L -name 'needle'
+haystack/needle
+
+$ bfs -L haystack -name 'needle'
+haystack/needle
+```
+
+</td>
+<td width="506">
+
+```console
+$ find -L -name 'needle' haystack
find: paths must precede expression: haystack
-$ <strong>bfs</strong> -L -name 'needle' <em>haystack</em>
-<strong>haystack/needle</strong>
-$ <strong>find</strong> <em>haystack</em> -L -name 'needle'
+$ find haystack -L -name 'needle'
find: unknown predicate `-L'
-$ <strong>bfs</strong> <em>haystack</em> -L -name 'needle'
-<strong>haystack/needle</strong>
-$ <strong>find</strong> -L <em>haystack</em> -name 'needle'
-<strong>haystack/needle</strong>
-$ <strong>bfs</strong> -L <em>haystack</em> -name 'needle'
-<strong>haystack/needle</strong>
+$ find -L haystack -name 'needle'
+haystack/needle
+```
+
+</td>
+</tr>
+</tbody>
+</table>
+</details>
+
+<details>
+<summary>
+<code>bfs</code> gives helpful errors and warnings.
+</summary>
+<p></p>
+
+For example, `bfs` will detect and suggest corrections for typos:
+
+```console
+$ bfs -nam needle
+bfs: error: bfs -nam needle
+bfs: error: ~~~~
+bfs: error: Unknown argument; did you mean -name?
+```
+
+`bfs` also includes a powerful static analysis to help catch mistakes:
+
+```console
+$ bfs -print -name 'needle'
+bfs: warning: bfs -print -name needle
+bfs: warning: ~~~~~~~~~~~~
+bfs: warning: The result of this expression is ignored.
+```
+
+</details>
+
+<details>
+<summary>
+<code>bfs</code> adds some options that make common tasks easier.
+</summary>
+<p></p>
+
+For example, the `-exclude` operator skips over entire subtrees whenever an expression matches.
+`-exclude` is both more powerful and easier to use than the standard `-prune` action; compare
+
+<pre>
+$ bfs -name config <strong>-exclude -name .git</strong>
</pre>
-`bfs` also adds some extra options that make some common tasks easier.
-Compare
+to the equivalent
+
+<pre>
+$ find <strong>! \( -name .git -prune \)</strong> -name config
+</pre>
- bfs -name config -exclude -name .git
+As an additional shorthand, `-nohidden` skips over all hidden files and directories.
+See the [usage documentation](/docs/USAGE.md#extensions) for more about the extensions provided by `bfs`.
+</details>
-vs.
- find ! \( -name .git -prune \) -name config
+Installation
+------------
+<details open>
+<summary>
+<code>bfs</code> may already be packaged for your operating system.
+</summary>
+<p></p>
-Try it!
--------
+<table>
+<tbody>
+<tr><th>Linux</th><th>macOS</th></tr>
-`bfs` may already be packaged for your distribution of choice.
-For example:
+<tr>
+<td width="506" valign="top" rowspan="3">
<pre>
-<strong>Alpine Linux</strong>
+<strong><a href="https://pkgs.alpinelinux.org/packages?name=bfs">Alpine Linux</a></strong>
# apk add bfs
-<strong>Debian/Ubuntu</strong>
+<strong><a href="https://archlinux.org/packages/extra/x86_64/bfs/">Arch Linux</a></strong>
+# pacman -S bfs
+
+<strong><a href="https://packages.debian.org/sid/bfs">Debian</a>/<a href="https://packages.ubuntu.com/kinetic/bfs">Ubuntu</a></strong>
# apt install bfs
-<strong>NixOS</strong>
+<strong><a href="https://src.fedoraproject.org/rpms/bfs">Fedora Linux</a></strong>
+# dnf install bfs
+
+<strong><a href="https://packages.gentoo.org/packages/sys-apps/bfs">Gentoo</a></strong>
+# emerge sys-apps/bfs
+
+<strong><a href="https://packages.guix.gnu.org/packages/bfs/">GNU Guix</a></strong>
+# guix install bfs
+
+<strong><a href="https://search.nixos.org/packages?channel=unstable&show=bfs&from=0&size=1&sort=relevance&type=packages&query=bfs">NixOS</a></strong>
# nix-env -i bfs
-<strong>Void Linux</strong>
+<strong><a href="https://voidlinux.org/packages/?arch=x86_64&q=bfs">Void Linux</a></strong>
# xbps-install -S bfs
+</pre>
-<strong>FreeBSD</strong>
-# pkg install bfs
+</td>
+<td width="506" valign="top">
-<strong>MacPorts</strong>
+<pre>
+<strong><a href="https://formulae.brew.sh/formula/bfs">Homebrew</a></strong>
+$ brew install bfs
+
+<strong><a href="https://ports.macports.org/port/bfs/">MacPorts</a></strong>
# port install bfs
+</pre>
+
+</td>
+</tr>
+<tr><th height="1">BSD</th></tr>
+<tr>
+<td width="506" valign="top">
+
+<pre>
+<strong><a href="https://www.freshports.org/sysutils/bfs">FreeBSD</a></strong>
+# pkg install bfs
+
+<strong><a href="https://openports.pl/path/sysutils/bfs">OpenBSD</a></strong>
+# pkg_add bfs
+</pre>
+
+</td>
+</tr>
+</tbody>
+</table>
+</details>
+
+<details>
+<summary>
+To build <code>bfs</code> from source, you may need to install some dependencies.
+</summary>
+<p></p>
+
+The only absolute requirements for building `bfs` are a C compiler, [GNU make](https://www.gnu.org/software/make/), and [Bash](https://www.gnu.org/software/bash/).
+These are installed by default on many systems, and easy to install on most others.
+Refer to your operating system's documentation on building software.
+
+`bfs` also depends on some system libraries for some of its features.
+Here's how to install them on some common platforms:
+
+<pre>
+<strong>Alpine Linux</strong>
+# apk add acl{,-dev} attr libcap{,-dev} liburing-dev oniguruma-dev
+
+<strong>Arch Linux</strong>
+# pacman -S acl attr libcap liburing oniguruma
+
+<strong>Debian/Ubuntu</strong>
+# apt install acl libacl1-dev attr libattr1-dev libcap2-bin libcap-dev liburing-dev libonig-dev
+
+<strong>Fedora</strong>
+# dnf install acl libacl-devel attr libcap-devel liburing-devel oniguruma-devel
+
+<strong>NixOS</strong>
+# nix-env -i acl attr libcap liburing oniguruma
+
+<strong>Void Linux</strong>
+# xbps-install -S acl-{devel,progs} attr-progs libcap-{devel,progs} liburing-devel oniguruma-devel
<strong>Homebrew</strong>
-$ brew install tavianator/tap/bfs
+$ brew install oniguruma
+
+<strong>MacPorts</strong>
+# port install oniguruma6
+
+<strong>FreeBSD</strong>
+# pkg install oniguruma
</pre>
-To install `bfs` from source, download one of the [releases](https://github.com/tavianator/bfs/releases) or clone the [git repo](https://github.com/tavianator/bfs).
+These dependencies are technically optional, though strongly recommended.
+See the [build documentation](/docs/BUILDING.md#dependencies) for how to disable them.
+</details>
+
+<details>
+<summary>
+Once you have the dependencies, you can build <code>bfs</code>.
+</summary>
+<p></p>
+
+Download one of the [releases](https://github.com/tavianator/bfs/releases) or clone the [git repo](https://github.com/tavianator/bfs).
Then run
+ $ ./configure
$ make
-This will build the `bfs` binary in the current directory.
-You can test it out:
+This will build the `./bin/bfs` binary.
+Run the test suite to make sure it works correctly:
- $ ./bfs -nohidden
+ $ make check
If you're interested in speed, you may want to build the release version instead:
- $ make release
+ $ ./configure --enable-release
+ $ make
Finally, if you want to install it globally, run
- $ sudo make install
+ # make install
+
+</details>