[NEW] Provenance and Attribution: Minimize IP liability for GenAI output
Home / Blog /
Using Tabnine to build a CLI with Rust
//

Using Tabnine to build a CLI with Rust

//
Aydrian Howard /
4 minutes /
October 10, 2024

What do Prisma, Cloudflare, and Discord all have in common? Each of these companies uses the Rust programming language in production. From its creation in 2015, the low-level systems programming language has become beloved by developers from startups to large corporations, from embedded devices to scalable web services. Even Tabnine has selected Rust to help build the next generation of AI-powered software development tools.

Many command line interfaces (CLIs) have been written in Rust, so I decided to create one during an episode of Tabnine Labs. I set out to plan, create, and test a CLI that would display the current time and weather using the OpenWeather API for you and your coworkers. While I’m not completely new to programming in Rust, it was still nice to have Tabnine to assist me.

Check out the recording:

While we did technically end up with a CLI that met our specifications, the process didn’t go as smoothly as we had hoped. But have no fear, we learned a lot during the process and will share our course corrections and observations in this post.

Starting simple

When starting a new project that uses a language or libraries that are new to me, I like to begin by having a conversation with the chat. I ask questions to help me understand what I need to do and how to do it.

Here are some good questions to ask:

  • How would I create a CLI in Rust that does x? Please explain step-by-step.
  • What Rust crates are typically used in CLI projects?
  • What is the structure of a typical CLI written in Rust?

Using these questions, I created an initial CLI that used the OpenWeather API to display a current forecast for a city provided as an argument. Tabnine Chat guided me through creating a new cargo package that used the clap crate, a popular command line parser. Using the Tabnine Explain Agent helped me further familiarize myself with the generated code.

Before continuing on, I made sure the project was organized in the typical CLI project structure.

Using this structure allowed for a clean separation of concerns, making it easier to maintain and extend the CLI application as it grows. Doing this early cuts down on possible code refactoring later on and makes testing more straightforward.

The next change I made to this initial CLI was to include displaying the current time for the provided city. I expect this to be more of a challenge because working with time can be a nightmare. Many times you have to figure out time zones and do a lot of complicated time conversions that aren’t always straightforward. (Not so fun fact: Indian Standard Time [IST] is offset by half an hour, UTC+05:30.) With all this swirling in my head, I asked Tabnine Chat to also display the current time in the response. To my surprise, it knew that the location’s timezone was returned by the OpenWeather API and used it to calculate and display the time.

We’re off to a good start, but we’re only getting information for one city and we have to specify it each time.

Prompting for and persisting data

Most people work from the same location every day. We don’t want to force our users to specify a city every time they run our CLI. Many CLIs persist data using a config file stored in the user’s home directory. We’ll do the same to persist our data. There are a lot of different requirements when selecting, loading, and writing a config file, depending on the operating system and other environment factors. So before running off and trying to build your own, it’s a good idea to ask Tabnine Chat, “Are there any Rust crates that can help with managing and retrieving user-specific configuration data?” This is how I learned about the confy crate and how to add it to the project.

Now we can simply ask Tabnine chat to update our command to read the user’s city from a config file using comfy if one isn’t provided and to prompt the user for a city and store it in the config file if not available.

Adding subcommands

It’s time to include coworkers. To help with this, we’re going to use subcommands. The clap crate supports this out of the box. We’ll start by telling Tabnine the definition of a coworker and then ask it to explain step-by-step how to store a list of coworkers in the config and create subcommands to add, remove, and list them. Tabnine will respond with instructions on updating the config and how to add the subcommands in the commands folder.

Next, we’ll use Tabnine to help us update our print weather function to also display the current forecast and time for each coworker (if any exist) by asking in the chat.

Unit testing

Now that we have our basic functionality working, it’s a good time to start unit testing. By default, executing “cargo test” will run tests located in the tests folder of the project. If you’re unfamiliar with how testing works in Rust, I recommend asking Tabnine Chat, “How do I unit test this project?” It will help you get started with some basic tests.

Once you have basic testing set up, you can use the Tabnine Test Agent to generate additional unit tests to cover your functions. Do this by clicking the Test Agent icon in the chat window, selecting a function, and then clicking Generate test plan for code.

We were able to build this simple CLI quickly thanks to Tabnine. We didn’t need to look up how to make a request to the OpenWeather API or what values were returned. We were able to leverage popular crates without having to read pages of documentation.

There’s still so much that could be done, what if we need to update the user’s city? Can we make the output a little prettier? Just ask Tabnine Chat. What would you do next?

Are you building a CLI or some other application using Rust? Let us know how Tabnine is helping you. Not yet a Tabnine user? Sign up for a free 90-day trial of Tabnine Pro.