DEV Community

Cover image for Building my first CLI
Angela Lam
Angela Lam

Posted on

Building my first CLI

Introduction

About two months ago I started Flatiron's software engineering program. I basically had zero coding skills and knowledge coming into this program. Now that I've been learning Ruby for the past two months, I have built my first CLI. My CLI pulls from a makeup API to let the user browse specific tags that cater to the users specific needs. After selecting a tag, a list of product types for that tag is given to the user. Selecting a product type will give a detailed list of products with the brand, description, and website link.

This is my first project so there were some learning curves with github, environments, and coding in general. I came across a lot of useful things while building my CLI that I would like to share.

system("clear")

Alt Text
Alt Text

The best thing for a terminal app is implementing system("clear") in your code. I placed this code right after getting the user input, so the terminal window is cleared before the information that the user selected is displayed. This keeps your terminal looking clean and readable for the user after they put inputs into the terminal. Something so little made a huge difference to my CLI.

Iterators each, map/collect, select

Learning the common iterators and what they return and do is so useful for iterating over collections. I used .collect and .select to collect information from my API throughout building my CLI.

each

.each is generally used when you want to do something with each element of an array inside the block.

array = [1, 2, 3, 4, 5]
array.each {|x| puts x}
output => 
1
2
3
4
5
return =>
[1, 2, 3, 4, 5]
Enter fullscreen mode Exit fullscreen mode

One thing to note is that .each returns the original array object it was invoked upon. If you want to return an array with the results of the method you will have to create a new variable with an empty array and then push the results to that array.

array = [1, 2, 3, 4, 5]
new_arr = []
array.each {|x| new_arr << x*2}
new_arr
output => 

return =>
[2, 4, 6, 8, 10]
Enter fullscreen mode Exit fullscreen mode

An .each iterator I used a lot in my project is .each_with_index. This allowed me to iterate over my arrays of information to produce the list menus and the list of products in my CLI. The example below shows .each_with_index being used with an array to print a number list for each element of the array. The x represents each element of the array and i represents the index corresponding to each element. To print a numbered list, we have to add 1 to the index to account for the index starting at 0.

array = ["a", "b", "c", "d", "e"]
array.each_with_index {|x, i| puts "#{i + 1}. #{x}"}
output =>
1. a
2. b
3. c
4. d
5. e
return =>
["a", "b", "c", "d", "e"]
Enter fullscreen mode Exit fullscreen mode
map/collect

The .collect or .map method allows us to iterate through an array like .each, but .collect returns a new array with the results of our iterator. .collect and .map are the same and can be used interchangeably. This iterator was useful in my CLI to iterate over my array of collections to get new arrays with deeper information within the hash of my API.

array = [1, 2, 3, 4, 5]
new_arr = array.collect {|x| x*2}
new_arr
output => 

return =>
[2, 4, 6, 8, 10]
Enter fullscreen mode Exit fullscreen mode
select

The .select method iterates over an array and grabs all elements for which the specified statement in the block is true. This returns a new array with all the elements that satisfy the block.

array = [1, 2, 3, 4, 5]
new_arr = array.select {|x| x.even?}
new_arr
output => 

return =>
[2, 4]
Enter fullscreen mode Exit fullscreen mode
find

The .find method is similar to the .select method, but returns the first element that satisfies the block and stops iterating. It does not return an array and does not return all elements that satisfy the block. In the example below, the return is 2, not in an array, and 4 is not returned.

array = [1, 2, 3, 4, 5]
new_arr = array.select {|x| x.even?}
new_arr
output => 

return =>
2
Enter fullscreen mode Exit fullscreen mode

word_wrap gem

For my API, I pull a description for each item, which is a long string. An issue I ran into was the descriptions breaking in the middle of words when the string hit the edge of the terminal. The word_wrap gem is the gem that fixed this issue. The function of the gem is the name of the gem, it wraps your text to a set width in your terminal.

In the end...

After finishing my CLI, I realized there were different methods I could've gone about with my CLI. Having people look over my code, I realized I brute forced some parts of my CLI, but I'm still a beginner. I will probably go through it in the future to improve the code, but for now my finished CLI is a finished product and functions perfectly, and I feel accomplished with my first CLI.

Top comments (0)