<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Fabiano</title>
    <description>The latest articles on DEV Community by Fabiano (@fbzga).</description>
    <link>https://dev.to/fbzga</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F35738%2F51e80cae-6d11-4e0e-ab2a-5a40d38b74dc.jpg</url>
      <title>DEV Community: Fabiano</title>
      <link>https://dev.to/fbzga</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/fbzga"/>
    <language>en</language>
    <item>
      <title>How to write your first CLI with Thor</title>
      <dc:creator>Fabiano</dc:creator>
      <pubDate>Wed, 04 Oct 2017 17:21:50 +0000</pubDate>
      <link>https://dev.to/fbzga/how-to-write-your-first-cli-with-thor-bam</link>
      <guid>https://dev.to/fbzga/how-to-write-your-first-cli-with-thor-bam</guid>
      <description>&lt;p&gt;At Magnetis we are moving our cloud infrastructure to Kubernetes. To do so I started creating a bunch of shell scripts inside our app. There is no problem with it, but as soon as i got 5 different shell script files it started to get messy.&lt;br&gt;
In one of pair programming sessions that we do in our hiring process, a candidate chose Thor to write the test project. It was organized and seemed easy to get started. So connecting the dots I thought that our scripts probably would be much more expressive with Thor.&lt;br&gt;
Command lines are already part of our everyday living: git, bundler and rails to name a few. Creating one helps you to organize and better share the utilities for daily work.&lt;br&gt;
In this article we will write a simple example inspired by one of the best Breaking Bad scenes. But apart of its simplicity, it is the same process to create a CLI for really anything you want.&lt;/p&gt;
&lt;h2&gt;
  
  
  Creating a newÂ gem
&lt;/h2&gt;

&lt;p&gt;Let’s get started by creating a new gem, that will make it easier to distribute our software, in this case the executable file.&lt;br&gt;
To create a new gem, bundler has a handy command (bundler itself is crafted with Thor):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;bundle gem &lt;span class="nt"&gt;--exe&lt;/span&gt; walter
This will generate a skeleton as follows:
 create walter/Gemfile
 create walter/lib/walter.rb
 create walter/lib/walter/version.rb
 create walter/walter.gemspec
 create walter/Rakefile
 create walter/README.md
 create walter/bin/console
 create walter/bin/setup
 create walter/.gitignore
 create walter/.travis.yml
 create walter/.rspec
 create walter/spec/spec_helper.rb
 create walter/spec/walter_spec.rb
 create walter/LICENSE.txt
 create walter/exe/walter
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we need to add the Thor as a dependency to our project, open up walter.gemspec and add:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;spec.add_dependency "thor", "~&amp;gt; 0.20"&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;We will also need to remove the TODO items in the gemspec file, so go ahead and edit the values for summary, description and homepage. Run the bundle install command and it is all setup to write some Thor lines.&lt;br&gt;
Enter Thor&lt;br&gt;
Open up lib/walter.rb and let’s add some code, first thing you need to require and inherit from Thor:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'walter'&lt;/span&gt;
&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'thor'&lt;/span&gt;
&lt;span class="k"&gt;module&lt;/span&gt; &lt;span class="nn"&gt;Walter&lt;/span&gt;
 &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CLI&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;Thor&lt;/span&gt;
   &lt;span class="c1"&gt;# ...&lt;/span&gt;
 &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, let’s add a simple hello world:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CLI&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;Thor&lt;/span&gt;
  &lt;span class="n"&gt;desc&lt;/span&gt; &lt;span class="s2"&gt;"hello world"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"my first cli yay"&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;hello&lt;/span&gt;
    &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"Hello world"&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Come on, hello world in 2017? Let’s make it a Hello Heisenberg!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CLI&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;Thor&lt;/span&gt;
  &lt;span class="n"&gt;desc&lt;/span&gt; &lt;span class="s2"&gt;"hello [name]"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"say my name"&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;hello&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nb"&gt;name&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;"Heisenberg"&lt;/span&gt;
      &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"you are goddman right"&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;
      &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"say my name"&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We are almost there, last thing is to call our lib from the binary file.&lt;br&gt;
The binary&lt;br&gt;
The exe directive we used to create the gem, generated a walter binary at our project. First thing you need to do is to change the permissions so we can actually execute the file:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;chmod +x exe/walter&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Now, we are able to call it:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;$ bundle exec exe/walter&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This will give no output, but don’t worry. This is expected. Open up exe/walter in your favorite editor and let’s append this:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Walter::CLI.start(ARGV)&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;We are calling the CLI we just created, and passing the arguments received. Now let’s call it again:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;bundle &lt;span class="nb"&gt;exec &lt;/span&gt;exe/walter
  walter hello &lt;span class="o"&gt;[&lt;/span&gt;name]    &lt;span class="c"&gt;# say hello&lt;/span&gt;
  walter &lt;span class="nb"&gt;help&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;COMMAND]  &lt;span class="c"&gt;# Describe available commands or one specific command&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Thor list all the commands this CLI has available, so sweet.&lt;br&gt;
If you try to call our hello command without the name:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;bundle &lt;span class="nb"&gt;exec &lt;/span&gt;exe/walter hello
ERROR: “walter hello was called with no arguments
Usage: “walter hello &lt;span class="o"&gt;[&lt;/span&gt;name]”
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Yeah, it tell us how to use it. Making this in shell script would require some conditionals, but Thor has this built-in.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;bundle &lt;span class="nb"&gt;exec &lt;/span&gt;exe/walter hello Heisenberg
you are goddman right.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Installing and publishing
&lt;/h2&gt;

&lt;p&gt;To install the gem to your system, this way you can it it from anywhere:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;rake &lt;span class="nb"&gt;install&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Call it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;walter hello Jesse
say my name
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you want to release it to rubygems, just run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;rake release
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Ruby ecosystem is beautiful, isn’t it?&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Thor makes daily scripts much more expressive and meaningful. It is a nice addition to a team that is already using Ruby as an official language, since all the team members can contribute to make your commands even better.&lt;br&gt;
In our case, it was used to create commands to bring up kubernetes clusters and to deploy our app for the staging environment. You can use to automate some internal process or workflow you have in your company!&lt;br&gt;
To finish this up, some final tips:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;whenever possible try to use command methods that are common to other CLIs: init, status, new, create, update.&lt;/li&gt;
&lt;li&gt;try to expose as CLI the least amount of methods possible, so you can encapsulate  things that are only needed inside the code.&lt;/li&gt;
&lt;li&gt;if you need to write some config file use &lt;code&gt;$HOME/.&amp;lt;yourcli&amp;gt;&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you want to go deeper into the subject, here are the &lt;a href="http://whatisthor.com/"&gt;official docs.&lt;/a&gt;&lt;br&gt;
Happy Thor!&lt;/p&gt;

&lt;p&gt;Previously &lt;a href="https://medium.com/magnetis-backstage/how-to-write-your-first-cli-with-thor-9da6636bf744"&gt;posted at medium&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ruby</category>
      <category>thor</category>
      <category>cli</category>
    </item>
  </channel>
</rss>
