diff --git a/assets/using-clap/1.png b/assets/using-clap/1.png new file mode 100644 index 0000000..86b3ac3 Binary files /dev/null and b/assets/using-clap/1.png differ diff --git a/blog/benchmarking-dwarfs.html b/blog/benchmarking-dwarfs.html index 93931ce..110eea9 100644 --- a/blog/benchmarking-dwarfs.html +++ b/blog/benchmarking-dwarfs.html @@ -20,7 +20,7 @@

The datasets being used for this test will be the following:

diff --git a/blog/benchmarking-dwarfs.md b/blog/benchmarking-dwarfs.md index 1fca903..ec0d102 100644 --- a/blog/benchmarking-dwarfs.md +++ b/blog/benchmarking-dwarfs.md @@ -6,12 +6,12 @@ DwarFS is a filesystem developed by the user mhx on GitHub [1], which is self-de The datasets being used for this test will be the following: -- 25 GB of null data (just `000000000000` in binary) +- 25 GB of null data (just `00000000` in binary) - 25 GB of random data[^1] - Data for a 100 million-sided regular polygon; ~29 GB[^2] - The current Linux longterm release source ([6.6.58](https://cdn.kernel.org/pub/linux/kernel/v6.x/linux-6.6.58.tar.xz) [2]); ~1.5 GB - For some rough latency testing: - - 1000 4 kilobyte files filled with null data (again, just `0000000` in binary) + - 1000 4 kilobyte files filled with null data (again, just `00000000` in binary) - 1000 4 kilobyte files filled with random data All this data should cover both latency and read speed testing for data that compresses differently - extremely compressible files with null data, decently compressible files, and random data which can't be compressed well. diff --git a/blog/using-clap.html b/blog/using-clap.html new file mode 100644 index 0000000..ab3f202 --- /dev/null +++ b/blog/using-clap.html @@ -0,0 +1,195 @@ + + + + + Using `clap` + + + + +

Using clap

+

Clap stands for Command Line Argument Parser, and put simply, + it's a great library for making command-line stuff with Rust. + Even Cargo, Rust's package manager, depends on it [4], and it's + been downloaded over 300 million times [5].

+

Rather than going over everything clap can do, I'll go over + how I've used it in my disk-read-benchmark program + I'll be using in my next blog post.

+

Basics

+

First off, we need to install clap; make sure to + enable its derive feature as that's what we'll be + using.

+
cargo add clap --features derive
+

First off, we need to get a bit of code just to start + off:

+
use clap::{Parser, Subcommand};
+
+#[derive(Parser)]
+#[command(version, about, long_about = None)]
+pub struct Cli {
+    #[command(subcommand)]
+    pub command: Commands,
+}
+

This has the built-in "version" and "about" options, with the + long "about" option disabled.

+

Next, we need to list all out commands we'll have:

+
#[derive(Subcommand)]
+pub enum Commands {
+    ///Run this thing
+    Run,
+    ///Delete the stuff that thing does
+    Delete,
+}
+

The documentation comments (///) should + not have a space after the slashes, as otherwise the + program will have an extra space where it shouldn't.

+

Finally, we create the main() function. First it + parses everything, then checks what command was run and runs the + relevant code.

+
fn main() {
+    let cli = Cli::parse();
+
+    match cli.command {
+        Commands::Run {
+            run();
+        }
+        Commands::Delete {
+            delete();
+        }
+    }
+}
+

That's all you need to know to use clap at a + very basic level; for more details, check out the docs [1]. But, + you probably don't want to have to type in the entire command + automatically, autocomplete would be nice. So I'll also go over + how to use clap_complete as well.

+

clap_complete

+

Searching through the documentation [2], you'll notice that + the docs don't cover how to use it with clap's derive at all. + Instead, after some Googling, I found an example script in + clap's repository [3], which I then adapted and played + around with a bit until I got it figured out.

+

Anyways, again, we need to install clap_complete + first:

+
cargo add clap_complete
+

Then, add the relevant imports. We'll just being doing it for + the fish shell since that's what I use, so we'll only import + Fish; Bash, Zsh, PowerShell, and Elvish are also + supported.

+
use clap_complete::aot::{generate, Fish};
+

Then, we need to add a command to generate the + completion:

+
#[derive(Subcommand)]
+pub enum Commands {
+    ///Run this thing
+    Run,
+    ///Delete the stuff that thing does
+    Delete,
+    ///Generate fish completions
+    FishCompletions,
+}
+

Next, we actually generate the completion, adding it like + it's another command:

+
    match cli.command {
+        Commands::Run {
+            run();
+        }
+        Commands::Delete {
+            delete();
+        }
+        Commands::GenerateFishCompletions => {
+            generate(
+                Fish,
+                &mut Cli::command(),
+                "example-program",
+                &mut stdout(),
+            );
+        }
+    }
+

To explain the options for generate():

+ +

As an example of all this, here's my + disk-read-benchmark program, running using all + this. The commands have formatting I can't do, so it looks even + better than I can even show here.

+
~> disk-read-benchmark
+Usage: disk-read-benchmark <COMMAND>
+
+Commands:
+  generate-bash-completions  Generate bash completions
+  generate-zsh-completions   Generate zsh completions
+  generate-fish-completions  Generate fish completions
+  grab-data                  Grabs the datasets used for benchmarking
+  benchmark                  Runs the benchmark
+  prep-dirs                  Prepares the directories so other programs can prepare their datasets
+  run                        Runs it all
+  help                       Print this message or the help of the given subcommand(s)
+
+Options:
+  -h, --help     Print help
+  -V, --version  Print version
+~> disk-read-benchmark generate-fish-completions | source
+~> disk-read-benchmark benchmark --help
+Runs the benchmark
+
+Usage: disk-read-benchmark benchmark
+
+Options:
+  -h, --help  Print help
+

To better see how great it looks, here's a screenshot:

+ The same output, but with very nice formatting - underlining and bolding for headers and the tables +

Pressing tab twice after entering + disk-read-benchmark displays the completions, which + I can select and use like any other program's.

+
~> disk-read-benchmark
+benchmark                         (Runs the benchmark)  grab-data                               (Grabs the datasets used for benchmarking)
+generate-bash-completions  (Generate bash completions)  help                   (Print this message or the help of the given subcommand(s))
+generate-fish-completions  (Generate fish completions)  prep-dirs  (Prepares the directories so other programs can prepare their datasets)
+generate-zsh-completions    (Generate zsh completions)  run                                                                  (Runs it all)
+

Sources

+
    +
  1. https://docs.rs/clap/latest/clap/
  2. +
  3. https://docs.rs/clap_complete/latest/clap_complete/
  4. +
  5. https://github.com/clap-rs/clap/blob/master/clap_complete/examples/completion-derive.rs
  6. +
  7. https://github.com/rust-lang/cargo/blob/master/Cargo.toml
  8. +
  9. https://crates.io/crates/clap
  10. +
+ + + + + diff --git a/blog/using-clap.md b/blog/using-clap.md new file mode 100644 index 0000000..d029366 --- /dev/null +++ b/blog/using-clap.md @@ -0,0 +1,170 @@ +# Using `clap` + +Clap stands for Command Line Argument Parser, and put simply, it's a great library for making command-line stuff with Rust. Even Cargo, Rust's package manager, depends on it [4], and it's been downloaded over 300 million times [5]. + +Rather than going over everything clap can do, I'll go over how I've used it in my `disk-read-benchmark` program I'll be using in my next blog post. + +## Basics + +First off, we need to install `clap`; make sure to enable its `derive` feature as that's what we'll be using. + +```sh +cargo add clap --features derive +``` + +First off, we need to get a bit of code just to start off: + +```rust +use clap::{Parser, Subcommand}; + +#[derive(Parser)] +#[command(version, about, long_about = None)] +pub struct Cli { + #[command(subcommand)] + pub command: Commands, +} +``` + +This has the built-in "version" and "about" options, with the long "about" option disabled. + +Next, we need to list all out commands we'll have: + +```rust +#[derive(Subcommand)] +pub enum Commands { + ///Run this thing + Run, + ///Delete the stuff that thing does + Delete, +} +``` + +The documentation comments (`///`) should *not* have a space after the slashes, as otherwise the program will have an extra space where it shouldn't. + +Finally, we create the `main()` function. First it parses everything, then checks what command was run and runs the relevant code. + +```rust +fn main() { + let cli = Cli::parse(); + + match cli.command { + Commands::Run { + run(); + } + Commands::Delete { + delete(); + } + } +} +``` + +That's all you need to know to use `clap` at a very basic level; for more details, check out the docs [1]. But, you probably don't want to have to type in the entire command automatically, autocomplete would be nice. So I'll also go over how to use `clap_complete` as well. + +## `clap_complete` + +Searching through the documentation [2], you'll notice that the docs don't cover how to use it with clap's derive at all. Instead, after some Googling, I found an example script in *clap*'s repository [3], which I then adapted and played around with a bit until I got it figured out. + +Anyways, again, we need to install `clap_complete` first: + +```sh +cargo add clap_complete +``` + +Then, add the relevant imports. We'll just being doing it for the fish shell since that's what I use, so we'll only import `Fish`; Bash, Zsh, PowerShell, and Elvish are also supported. + +```rust +use clap_complete::aot::{generate, Fish}; +``` + +Then, we need to add a command to generate the completion: + +```rust +#[derive(Subcommand)] +pub enum Commands { + ///Run this thing + Run, + ///Delete the stuff that thing does + Delete, + ///Generate fish completions + FishCompletions, +} +``` + +Next, we actually generate the completion, adding it like it's another command: + +```rust + match cli.command { + Commands::Run { + run(); + } + Commands::Delete { + delete(); + } + Commands::GenerateFishCompletions => { + generate( + Fish, + &mut Cli::command(), + "example-program", + &mut stdout(), + ); + } + } +``` + +To explain the options for `generate()`: + +- `Fish`: The shell we're using. +- `&mut Cli::command()`: I don't actually know what this does, but understanding ths library fully this is beyond my pay grade, especially given the somewhat lacking docs. +- `"example-program"`: The name of our program +- `&mut stdout()`: `stdout`, so that it can print the completions. Why does it do it this way? I don't know, it doesn't make sense to me. Why doesn't it just return it as a String? I don't know. But it works, I suppose. + +As an example of all this, here's my `disk-read-benchmark` program, running using all this. The commands have formatting I can't do, so it looks even better than I can even show here. + +```txt +~> disk-read-benchmark +Usage: disk-read-benchmark + +Commands: + generate-bash-completions Generate bash completions + generate-zsh-completions Generate zsh completions + generate-fish-completions Generate fish completions + grab-data Grabs the datasets used for benchmarking + benchmark Runs the benchmark + prep-dirs Prepares the directories so other programs can prepare their datasets + run Runs it all + help Print this message or the help of the given subcommand(s) + +Options: + -h, --help Print help + -V, --version Print version +~> disk-read-benchmark generate-fish-completions | source +~> disk-read-benchmark benchmark --help +Runs the benchmark + +Usage: disk-read-benchmark benchmark + +Options: + -h, --help Print help +``` + +To better see how great it looks, here's a screenshot: + +![The same output, but with very nice formatting - underlining and bolding for headers and the tables](/assets/using-clap/1.png) + +Pressing tab twice after entering `disk-read-benchmark` displays the completions, which I can select and use like any other program's. + +```txt +~> disk-read-benchmark +benchmark (Runs the benchmark) grab-data (Grabs the datasets used for benchmarking) +generate-bash-completions (Generate bash completions) help (Print this message or the help of the given subcommand(s)) +generate-fish-completions (Generate fish completions) prep-dirs (Prepares the directories so other programs can prepare their datasets) +generate-zsh-completions (Generate zsh completions) run (Runs it all) +``` + +## Sources + +1. +2. +3. +4. +5. diff --git a/feed.xml b/feed.xml index f906c91..4bd2990 100644 --- a/feed.xml +++ b/feed.xml @@ -5,10 +5,10 @@ eng.askiiart.net This is the feed for engl.askiiart.net, I guess https://askiiart.net - Fri, 04 Oct 2024 00:34:32 +0000 + Tue, 12 Nov 2024 21:14:09 +0000 - Checking out blendOS - https://engl.askiiart.net/blog/blendos.html + Benchmarking and comparing DwarFS + https://engl.askiiart.net/blog/benchmarking-dwarfs.html Building blendOS (and its packages) @@ -18,6 +18,14 @@ OCI Images as a "Filesystem": Vanilla OS https://engl.askiiart.net/blog/vanilla-os.html + + Checking out blendOS + https://engl.askiiart.net/blog/blendos.html + + + Using `clap` + https://engl.askiiart.net/blog/using-clap.html + Glossary https://engl.askiiart.net/glossary.html diff --git a/glossary.html b/glossary.html index 25390ae..d9f804e 100644 --- a/glossary.html +++ b/glossary.html @@ -98,6 +98,8 @@ using FUSE). On Linux, device drivers are usually in the kernel directly, rather than being installed separately like on Windows. +
  • Shell: The program which is the command-line + interface.
  • diff --git a/glossary.md b/glossary.md index ff33e4f..749462d 100644 --- a/glossary.md +++ b/glossary.md @@ -30,4 +30,5 @@ - `PKGBUILD`: A file defining how to build a package which can be install by `pacman`. - `iso` file: A disk image file, can be "burned" to a USB flash drive (or any other disk) and booted off of, often used for Linux installers and/or live images. - FUSE: A filesystem interface used for running filesystems in userspace (i.e. not in the kernel) -- Kernel: The very core of an operating system, with all its most essential functions, like filesystems (aside from those using FUSE). On Linux, device drivers are usually in the kernel directly, rather than being installed separately like on Windows. \ No newline at end of file +- Kernel: The very core of an operating system, with all its most essential functions, like filesystems (aside from those using FUSE). On Linux, device drivers are usually in the kernel directly, rather than being installed separately like on Windows. +- Shell: The program which *is* the command-line interface. diff --git a/sitemap.xml b/sitemap.xml index f782624..9366855 100644 --- a/sitemap.xml +++ b/sitemap.xml @@ -1,7 +1,9 @@ +https://engl.askiiart.net/blog/using-clap.html https://engl.askiiart.net/blog/blendos.html https://engl.askiiart.net/blog/building-blendos.html https://engl.askiiart.net/blog/vanilla-os.html +https://engl.askiiart.net/blog/benchmarking-dwarfs.html https://engl.askiiart.net/glossary.html https://engl.askiiart.net/index.html https://engl.askiiart.net/about.html diff --git a/style.css b/style.css index 535171c..53d9b9b 100644 --- a/style.css +++ b/style.css @@ -34,8 +34,7 @@ body { } li { - font-family: 'Atkinson Hyperlegible'; -} + font: 18px/1.35 'Atkinson Hyperlegible', sans-serif;} p, footer {