QGriffith Logo
Software,  Rust

Jot a CLI note taker in rust

Author

qgriffith

Date Published

rusty

I started to learn the rust programming language as a fun thing to do while the weather was not to great. I've taught myself Python, PHP and even Perl back in the day and I wanted to finally try a compiled language. I have created a few crates in the past, but this is my first binary program. I wanted to create something easy to take notes with out having the leave the command line. I use Obsidian as my daily note taker, but found myself often in the CLI wanting to jot something down, with out leaving the CLI to launch another app. So I created Jot. I can quickly create a new note, or append to a long running note. For things I want to keep, I move them into my Obsidian Vault. By default Jot treats everything as a markdown file. So it is quite easy to have Obsidian pick those up! I used this as an opportunity to learn about clap, a rust command line parser. With very little actual code, one can create a pretty verbose argument parser with built in help

1A ClI for jotting down notes
2
3Usage: jot [OPTIONS] <COMMAND>
4
5Commands:
6 new jot something new down
7 open Running jot doc that appends text to the same file
8 scratch Used as a scratch pad
9 search Search documents for a string of text. query can be passed several times
10 list List all files in your jot dir
11 help Print this message or the help of the given subcommand(s)
12
13Options:
14 -p, --jot-path <JOT_PATH> [env: JOT_PATH=]
15 -h, --help Print help
16 -V, --version Print version
17

The code to create that is pretty simple:

1#[derive(Parser, Debug)]
2#[clap(version)]
3struct Args {
4 #[clap(short = 'p', long, env)]
5 jot_path: Option<PathBuf>,
6
7 #[command(subcommand)]
8 cmd: Commands,
9}
10
11#[derive(Subcommand, Debug)]
12enum Commands {
13 /// jot something new down
14 ///
15 /// This command will open your $EDITOR, wait for you
16 /// to write something, and then save the file to your
17 /// jot. This is to create a new file and save it
18 New {
19 /// Optionally set a title for what you are going to write about
20 #[clap(short, long)]
21 title: Option<String>,
22 },
23 /// Running jot doc that appends text to the same file.
24 Open {
25 /// Open an existing file to write
26 #[clap(short, long)]
27 title: String,
28 },
29 /// Used as a scratch pad
30 ///
31 /// To get thoughts into quickly. Perfect to use as a reminder for something
32 /// to work out later. File name is _scratch.md
33 Scratch {
34 #[clap(short, long)]
35 message: String,
36 },
37 /// Search documents for a string of text. query can be passed several times
38 Search {
39 #[clap(short, long)]
40 query: Vec<String>,
41 },
42 /// List all files in your jot dir
43 List {},
44}

Clap takes in enum and allows you to set comments about what the option will do. It displays those comments to the user. The help and version flags are baked in. No need to add code for those options. It even takes the version right out of the Cargo.toml file. So anytime the crate is updated to a new version it will display that. I hope to piggy back off this learning to advance another project I have been working on, to expert fitness data out of various services so users can have access to their data.

Using Jot

To create a new note you can simply run

1jot new

This will launch what ever your EDITOR value is set to in your env. The file will automatically get # at the top. This is a header in markdown. When you save the file Jot will prompt you for a file name to save as. It will first attempt to save it as the string entered after the # in the first line, or offer you a chance to type in a name. Alternatively passing a flag to Jot will set the title and the name for you.

1jot new -t cool_file

To see all the files you have created Jot has a list feature

1jot list

If you want to open an exiting file, you only need to pass the name of the file and not the path or extension.

1jot open -t cool_file

Jot even comes with a basic string search that can search several strings at once

1jot search -q "test" -q "me"
2