Pretty CLI Menus with TTY:Prompt!
Tags: ruby, beginners, easy
Published: 2020-03-03 00:31:16

Here's a quick one for you:

We were tasked with building a CLI application that demonstrated basic CRUD functionality. While getting CRUD to work well was an undertaking, making a basic interface for the user felt far more challenging.

The initial thought for having menu selections, displayed by:
```ruby
def menu_choices
choice = gets
   puts "1. Option 1"
   puts "2. Option 2"
   puts "3. Option 3"
   puts "4. Option 4"
```

You get the idea.
We would have this as an early method in our run file to display this to accept input from the user. The functionality technically works, but we have to ensure that the user does not input something OTHER than a number, or god forbid they input the wrong number.
That's where TTY:Prompt comes in!

[TTY](https://ttytoolkit.org/) is a really useful Ruby Gem specifically made for CLI apps. The Prompt component is just one of many available, and we're only going to scratch the surface.

First, we will need to install the gem using:
```ruby
gem install tty-prompt
```

or by including it in your gemfile. Make sure to $ bundle after!

The way it works is that it accepts an array of strings that are displayed as menu choices, to which the user can toggle between using their Up and Down arrow keys. Whichever option is selected is stored as a string that we can then use how we need.

Lets build a character creator as an example. Assuming we already have a Character class built that we can create new instance of..

First, we will have to define a variable as a new instance of the TTY::Prompt class.

```ruby
def create_a_character
    prompt = TTY::Prompt.new
```

We will call on this variable with a method called select that takes 2 arguments, but first, lets define an array that will hold our options for the user. Following the conventions of The Forgotten Realms, we will have options for a class type and a race.

```ruby
def create_a_character
    prompt = TTY::Prompt.new
    @classes_type = ["Barbarian", "Bard", "Cleric", "Druid", "Fighter", "Monk", 
    "Paladin", "Ranger", "Rogue", "Sorcerer", "Warlock", "Wizard"]
    @races = ["Human", "Dragonborn", "Dwarf", "Elf", "Half-Elf", "Gnome", 
    "Halfing", "Half-Orc", "Tiefling"]
```

Now, we add a line that establishes a variable for each prompt, so we can use the choice for instantiation of our new hero. We will make this variable but using prompt.select, to which we provide two arguments. The first is a string that the user sees, the second is an array of strings that are the options.

```ruby
    hero_class = prompt.select("What is your class?", @classes_type)
```

All together, this will now display the following:

![Imgur](https://i.imgur.com/dRSaREC.png)

Nice! 
Now, we can follow up with another select list for the user to select their race:

```ruby
    def create_a_character
        prompt = TTY::Prompt.new
        @classes_type = ["Barbarian", "Bard", "Cleric", "Druid", "Fighter", "Monk", "Paladin", "Ranger", "Rogue", "Sorcerer", "Warlock", "Wizard"]
        @races = ["Human", "Dragonborn", "Dwarf", "Elf", "Half-Elf", "Gnome", "Halfing", "Half-Orc", "Tiefling"]
        hero_class = prompt.select("What is your class?", @classes_type)
        hero_race = prompt.select("What is your race?", @races)
    end
```

TTY Prompt will give the next prompt once an option for the first is chosen.

![Imgur](https://i.imgur.com/cj26XXY.png)

With our variables defined by the choices made, we can finally ask the user for their character's name, and create a new instance using all of these variables.

```ruby
    def create_a_character
        prompt = TTY::Prompt.new
        @classes_type = ["Barbarian", "Bard", "Cleric", "Druid", "Fighter", "Monk", "Paladin", "Ranger", "Rogue", "Sorcerer", "Warlock", "Wizard"]
        @races = ["Human", "Dragonborn", "Dwarf", "Elf", "Half-Elf", "Gnome", "Halfing", "Half-Orc", "Tiefling"]
        hero_class = prompt.select("What is your class?", @classes_type)
        hero_race = prompt.select("What is your race?", @races)
        puts "What is your Name:"
        hero_name = gets.strip
        @@new_hero = Character.create(name: hero_name, character_class: hero_class, race: hero_race)
    end
```

And that's it! Again, this is barely scratching the surface, as [TTY Prompt](https://github.com/piotrmurach/tty-prompt) alone has a huge range of functionality, as does [TTY's other 21 components.](https://ttytoolkit.org/components/) If you're trying to make a CLI application, be sure to check it out!

Thanks for reading!