SlideShare une entreprise Scribd logo
1  sur  63
Ruby on Rails In Practice
Apartment List and Thoughtbot
San Francisco, September 2012




                    Getting started with
               Command Line Applications
Ruby on Rails In Practice
Apartment List and Thoughtbot
San Francisco, September 2012




                    Getting started with
               Command Line Applications




                                Nikhil Mungel
                                    @hyfather
Why CLI ?
CLI
Scriptable



CLI        Lightweight



 Consistent UX
Why Ruby?
•   Textual Manipulation


•   OO & FP Abstractions


•   Plethora of CLI gems


• Examples to learn from
The Structure
Input   Execution   Output
Input   Execution   Output




 STDIO = UI/UX
Input



        STDIN
Input


        ARGV/ENV

          STDIN
Input


        ARGV/ENV

          STDIN
Input


        ARGV/ENV

          STDIN
Input
        OptionParser

        ARGV/ENV

          STDIN
Input
        OptionParser

        ARGV/ENV

          STDIN
Input   Libraries
        OptionParser

        ARGV/ENV

          STDIN
Input   Libraries
        OptionParser

        ARGV/ENV

          STDIN
Input   Libraries
        OptionParser

        ARGV/ENV

          STDIN
options = {}
OptionParser.new do |opts|
  opts.banner = "Usage: example.rb [options]"

  opts.on("-v", "--[no-]verbose", "Run verbosely") do |v|
    options[:verbose] = v
  end
end.parse!
options = {}
OptionParser.new do |opts|
  opts.banner = "Usage: example.rb [options]"

  opts.on("-v", "--[no-]verbose", "Run verbosely") do |v|
    options[:verbose] = v
  end
end.parse!




~ > ./opt.rb --help
Usage: example.rb [options]
   -v, --[no-]verbose               Run verbosely
options = {}
OptionParser.new do |opts|
  opts.banner = "Usage: example.rb [options]"

  opts.on("-v", "--[no-]verbose", "Run verbosely") do |v|
    options[:verbose] = v
  end
end.parse!




~ > ./opt.rb --help
Usage: example.rb [options]
   -v, --[no-]verbose               Run verbosely
options = {}
OptionParser.new do |opts|
  opts.banner = "Usage: example.rb [options]"

  opts.on("-v", "--[no-]verbose", "Run verbosely") do |v|
    options[:verbose] = v
  end
end.parse!




~ > ./opt.rb --help
Usage: example.rb [options]
   -v, --[no-]verbose               Run verbosely
options = {}
OptionParser.new do |opts|
  opts.banner = "Usage: example.rb [options]"

  opts.on("-v", "--[no-]verbose", "Run verbosely") do |v|
    options[:verbose] = v
  end
end.parse!




~ > ./opt.rb --help
Usage: example.rb [options]
   -v, --[no-]verbose               Run verbosely
The Mixlib Suite
class MyCLIApp
  include Mixlib::CLI

  option :config_file,
    :short => "-c CONFIG",
    :description => "Configuration file",
    :required => true
end




~ > ./mycliapp.rb --help
Usage: ./mix.rb (options)
    -c, --config CONFIG      Configuration file (required)
    -h, --help               Show this message
class MyCLIApp
  include Mixlib::CLI

  option :config_file,
    :short => "-c CONFIG",
    :description => "Configuration file",
    :required => true
end




~ > ./mycliapp.rb --help
Usage: ./mix.rb (options)
    -c, --config CONFIG      Configuration file (required)
    -h, --help               Show this message
class MyCLIApp
  include Mixlib::CLI

  option :config_file,
    :short => "-c CONFIG",
    :description => "Configuration file",
    :required => true
end




~ > ./mycliapp.rb --help
Usage: ./mix.rb (options)
    -c, --config CONFIG      Configuration file (required)
    -h, --help               Show this message
config.rb
server_url “http://server.remote”
username   “elvis”
password   “hotdog”
config.rb
server_url “http://server.remote”
username   “elvis”
password   “hotdog”



class MyConfig
  extend(Mixlib::Config)

  server_url 'http://server.local'
  username   'king'
  password   'burger'
end
MyConfig.from_file(‘config.rb’)



irb> MyConfig.server_url
# ‘http://server.remote’
config.rb
server_url “http://server.remote”
username   “elvis”
password   “hotdog”



class MyConfig
  extend(Mixlib::Config)

  server_url 'http://server.local'
  username   'king'
  password   'burger'
end
MyConfig.from_file(‘config.rb’)



irb> MyConfig.server_url
# ‘http://server.remote’
Thor
class Test < Thor
  desc " FILE", "an example task"
  method_option :delete,
                :aliases => "-d",
                :desc => "Delete the file"
  def example(file)
  end
end
class Test < Thor
  desc " FILE", "an example task"
  method_option :delete,
                :aliases => "-d",
                :desc => "Delete the file"
  def example(file)
  end
end




~ > myapp help test:example
Usage:
  thor test:example FILE

Options:
  -d, [--delete=DELETE]   # Delete the file after parsing it

an example task
class Test < Thor
  desc " FILE", "an example task"
  method_option :delete,
                :aliases => "-d",
                :desc => "Delete the file"
  def example(file)
  end
end




~ > myapp help test:example
Usage:
  thor test:example FILE

Options:
  -d, [--delete=DELETE]   # Delete the file after parsing it

an example task
class Test < Thor
  desc " FILE", "an example task"
  method_option :delete,
                :aliases => "-d",
                :desc => "Delete the file"
  def example(file)
  end
end




~ > myapp help test:example
Usage:
  thor test:example FILE

Options:
  -d, [--delete=DELETE]   # Delete the file after parsing it

an example task
class Test < Thor
  desc " FILE", "an example task"
  method_option :delete,
                :aliases => "-d",
                :desc => "Delete the file"
  def example(file)
  end
end




~ > myapp help test:example
Usage:
  thor test:example FILE

Options:
  -d, [--delete=DELETE]   # Delete the file after parsing it

an example task
class Test < Thor
  desc " FILE", "an example task"
  method_option :delete,
                :aliases => "-d",
                :desc => "Delete the file"
  def example(file)
  end
end




~ > myapp help test:example
Usage:
  thor test:example FILE

Options:
  -d, [--delete=DELETE]   # Delete the file after parsing it

an example task
class Test < Thor
  desc " FILE", "an example task"
  method_option :delete,
                :aliases => "-d",
                :desc => "Delete the file"
  def example(file)
  end
end




~ > myapp help test:example
Usage:
  thor test:example FILE

Options:
  -d, [--delete=DELETE]   # Delete the file after parsing it

an example task
class Test < Thor
  desc " FILE", "an example task"
  method_option :delete,
                :aliases => "-d",
                :desc => "Delete the file"
  def example(file)
  end
end




~ > myapp help test:example
Usage:
  thor test:example FILE

Options:
  -d, [--delete=DELETE]   # Delete the file after parsing it

an example task
Testing!
Input   Execution   Output
Input   Execution   Output
Input   Execution   Output




Mostly third party libraries
Input   Execution   Output




Test::Unit, rspec etc.
Input   Execution   Output

         System
System
System


File System    Network   Process
Isolated
 Environments




File System   Network   Process
Isolated
        Environments
User
                                   Container




                     Application



       File System     Network     Process
Streams & Signals
STDO
          UT/S
                 TDER
                        R
                            CLI
User
                            App
       STDIN
STDO
          UT/S
                 TDER
                        R
                            CLI
User
                            App
       STDIN

                                    STDOUT &
                                     STDERR
                            STDIN
                                    Another
                                      App
STDO
          UT/S
                 TDER
                        R
                            CLI
User
                            App
       STDIN

                                    STDOUT &
                                     STDERR
                            STDIN
                                    Another
                                      App
Mixlib::Shellout
> ls = Mixlib::ShellOut.new("ls")
> ls.run_command
> ls.stdout
“init.elnREADME.mdn”




           Nikhil Mungel
   www.hyfather.com     @hyfather
Mixlib::Shellout
> ls = Mixlib::ShellOut.new("ls")
> ls.run_command
> ls.stdout
“init.elnREADME.mdn”




           Nikhil Mungel
   www.hyfather.com     @hyfather
Nikhil Mungel
www.hyfather.com     @hyfather
IO#tty?



        Nikhil Mungel
www.hyfather.com     @hyfather
Output

$stdout    TRACE DEBUG INFO

$stderr    WARN ERROR FATAL



        Nikhil Mungel
www.hyfather.com     @hyfather
Thanks!
I am currently a Grad Student at
         San Jose State

Formerly at ThoughtWorks Studios

       slidesha.re/rubycli
         Nikhil Mungel
 www.hyfather.com     @hyfather

Contenu connexe

Tendances

Symfony2 Service Container: Inject me, my friend
Symfony2 Service Container: Inject me, my friendSymfony2 Service Container: Inject me, my friend
Symfony2 Service Container: Inject me, my friend
Kirill Chebunin
 
ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 2, Dependency I...
ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 2, Dependency I...ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 2, Dependency I...
ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 2, Dependency I...
ZFConf Conference
 
PHP traits, treat or threat?
PHP traits, treat or threat?PHP traits, treat or threat?
PHP traits, treat or threat?
Nick Belhomme
 

Tendances (20)

BSDM with BASH: Command Interpolation
BSDM with BASH: Command InterpolationBSDM with BASH: Command Interpolation
BSDM with BASH: Command Interpolation
 
Symfony2 Service Container: Inject me, my friend
Symfony2 Service Container: Inject me, my friendSymfony2 Service Container: Inject me, my friend
Symfony2 Service Container: Inject me, my friend
 
用 Go 語言打造多台機器 Scale 架構
用 Go 語言打造多台機器 Scale 架構用 Go 語言打造多台機器 Scale 架構
用 Go 語言打造多台機器 Scale 架構
 
Beaker: Automated, Cloud-Based Acceptance Testing - PuppetConf 2014
Beaker: Automated, Cloud-Based Acceptance Testing - PuppetConf 2014Beaker: Automated, Cloud-Based Acceptance Testing - PuppetConf 2014
Beaker: Automated, Cloud-Based Acceptance Testing - PuppetConf 2014
 
Shared Object images in Docker: What you need is what you want.
Shared Object images in Docker: What you need is what you want.Shared Object images in Docker: What you need is what you want.
Shared Object images in Docker: What you need is what you want.
 
Unit Testing Lots of Perl
Unit Testing Lots of PerlUnit Testing Lots of Perl
Unit Testing Lots of Perl
 
BASH Variables Part 1: Basic Interpolation
BASH Variables Part 1: Basic InterpolationBASH Variables Part 1: Basic Interpolation
BASH Variables Part 1: Basic Interpolation
 
On UnQLite
On UnQLiteOn UnQLite
On UnQLite
 
ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 2, Dependency I...
ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 2, Dependency I...ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 2, Dependency I...
ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 2, Dependency I...
 
Hypers and Gathers and Takes! Oh my!
Hypers and Gathers and Takes! Oh my!Hypers and Gathers and Takes! Oh my!
Hypers and Gathers and Takes! Oh my!
 
Diving into HHVM Extensions (PHPNW Conference 2015)
Diving into HHVM Extensions (PHPNW Conference 2015)Diving into HHVM Extensions (PHPNW Conference 2015)
Diving into HHVM Extensions (PHPNW Conference 2015)
 
Construire son JDK en 10 étapes
Construire son JDK en 10 étapesConstruire son JDK en 10 étapes
Construire son JDK en 10 étapes
 
Laravel 4 package development
Laravel 4 package developmentLaravel 4 package development
Laravel 4 package development
 
The $path to knowledge: What little it take to unit-test Perl.
The $path to knowledge: What little it take to unit-test Perl.The $path to knowledge: What little it take to unit-test Perl.
The $path to knowledge: What little it take to unit-test Perl.
 
Smoking docker
Smoking dockerSmoking docker
Smoking docker
 
ZFConf 2012: Dependency Management в PHP и Zend Framework 2 (Кирилл Чебунин)
ZFConf 2012: Dependency Management в PHP и Zend Framework 2 (Кирилл Чебунин)ZFConf 2012: Dependency Management в PHP и Zend Framework 2 (Кирилл Чебунин)
ZFConf 2012: Dependency Management в PHP и Zend Framework 2 (Кирилл Чебунин)
 
PHP traits, treat or threat?
PHP traits, treat or threat?PHP traits, treat or threat?
PHP traits, treat or threat?
 
Keeping objects healthy with Object::Exercise.
Keeping objects healthy with Object::Exercise.Keeping objects healthy with Object::Exercise.
Keeping objects healthy with Object::Exercise.
 
Information security programming in ruby
Information security programming in rubyInformation security programming in ruby
Information security programming in ruby
 
Getting Testy With Perl6
Getting Testy With Perl6Getting Testy With Perl6
Getting Testy With Perl6
 

En vedette

Railsguide
RailsguideRailsguide
Railsguide
lanlau
 
Rails 3 generators
Rails 3 generatorsRails 3 generators
Rails 3 generators
joshsmoore
 
Rails Text Mate Cheats
Rails Text Mate CheatsRails Text Mate Cheats
Rails Text Mate Cheats
dezarrolla
 

En vedette (15)

Railsguide
RailsguideRailsguide
Railsguide
 
Making CLI app in ruby
Making CLI app in rubyMaking CLI app in ruby
Making CLI app in ruby
 
Command Line Applications with Ruby
Command Line Applications with RubyCommand Line Applications with Ruby
Command Line Applications with Ruby
 
Slides with notes from Ruby Conf 2014 on using simple techniques to create sl...
Slides with notes from Ruby Conf 2014 on using simple techniques to create sl...Slides with notes from Ruby Conf 2014 on using simple techniques to create sl...
Slides with notes from Ruby Conf 2014 on using simple techniques to create sl...
 
Rails 3 generators
Rails 3 generatorsRails 3 generators
Rails 3 generators
 
Rails Text Mate Cheats
Rails Text Mate CheatsRails Text Mate Cheats
Rails Text Mate Cheats
 
Rest and Rails
Rest and RailsRest and Rails
Rest and Rails
 
Ruby on Rails Training - Module 1
Ruby on Rails Training - Module 1Ruby on Rails Training - Module 1
Ruby on Rails Training - Module 1
 
Rails01
Rails01Rails01
Rails01
 
Ruby on Rails Kickstart 103 & 104
Ruby on Rails Kickstart 103 & 104Ruby on Rails Kickstart 103 & 104
Ruby on Rails Kickstart 103 & 104
 
Ruby on Rails 101
Ruby on Rails 101Ruby on Rails 101
Ruby on Rails 101
 
Rails 3 Beginner to Builder 2011 Week 3
Rails 3 Beginner to Builder 2011 Week 3Rails 3 Beginner to Builder 2011 Week 3
Rails 3 Beginner to Builder 2011 Week 3
 
Developing cross platform desktop application with Ruby
Developing cross platform desktop application with RubyDeveloping cross platform desktop application with Ruby
Developing cross platform desktop application with Ruby
 
Ruby on Rails 101 - Presentation Slides for a Five Day Introductory Course
Ruby on Rails 101 - Presentation Slides for a Five Day Introductory CourseRuby on Rails 101 - Presentation Slides for a Five Day Introductory Course
Ruby on Rails 101 - Presentation Slides for a Five Day Introductory Course
 
Ruby on Rails for beginners
Ruby on Rails for beginnersRuby on Rails for beginners
Ruby on Rails for beginners
 

Similaire à Introducing Command Line Applications with Ruby

Django’s nasal passage
Django’s nasal passageDjango’s nasal passage
Django’s nasal passage
Erik Rose
 

Similaire à Introducing Command Line Applications with Ruby (20)

Building robust and friendly command line applications in go
Building robust and friendly command line applications in goBuilding robust and friendly command line applications in go
Building robust and friendly command line applications in go
 
Devel::hdb debugger talk
Devel::hdb debugger talkDevel::hdb debugger talk
Devel::hdb debugger talk
 
Living With Legacy Code
Living With Legacy CodeLiving With Legacy Code
Living With Legacy Code
 
The GO Language : From Beginners to Gophers
The GO Language : From Beginners to GophersThe GO Language : From Beginners to Gophers
The GO Language : From Beginners to Gophers
 
TypeScript for Java Developers
TypeScript for Java DevelopersTypeScript for Java Developers
TypeScript for Java Developers
 
Pemrograman Python untuk Pemula
Pemrograman Python untuk PemulaPemrograman Python untuk Pemula
Pemrograman Python untuk Pemula
 
How To Structure Go Applications - Paul Bellamy - Codemotion Milan 2016
How To Structure Go Applications - Paul Bellamy - Codemotion Milan 2016How To Structure Go Applications - Paul Bellamy - Codemotion Milan 2016
How To Structure Go Applications - Paul Bellamy - Codemotion Milan 2016
 
Kubernetes walkthrough
Kubernetes walkthroughKubernetes walkthrough
Kubernetes walkthrough
 
Elixir on Containers
Elixir on ContainersElixir on Containers
Elixir on Containers
 
Course 102: Lecture 8: Composite Commands
Course 102: Lecture 8: Composite Commands Course 102: Lecture 8: Composite Commands
Course 102: Lecture 8: Composite Commands
 
Docopt, beautiful command-line options for R, user2014
Docopt, beautiful command-line options for R,  user2014Docopt, beautiful command-line options for R,  user2014
Docopt, beautiful command-line options for R, user2014
 
Practical pig
Practical pigPractical pig
Practical pig
 
Text mining on the command line - Introduction to linux for bioinformatics
Text mining on the command line - Introduction to linux for bioinformaticsText mining on the command line - Introduction to linux for bioinformatics
Text mining on the command line - Introduction to linux for bioinformatics
 
PyCon AU 2012 - Debugging Live Python Web Applications
PyCon AU 2012 - Debugging Live Python Web ApplicationsPyCon AU 2012 - Debugging Live Python Web Applications
PyCon AU 2012 - Debugging Live Python Web Applications
 
May The Nodejs Be With You
May The Nodejs Be With YouMay The Nodejs Be With You
May The Nodejs Be With You
 
Django’s nasal passage
Django’s nasal passageDjango’s nasal passage
Django’s nasal passage
 
Pluggin creation
Pluggin creationPluggin creation
Pluggin creation
 
Easy R
Easy REasy R
Easy R
 
Z ray plugins for dummies
Z ray plugins for dummiesZ ray plugins for dummies
Z ray plugins for dummies
 
CMake Tutorial
CMake TutorialCMake Tutorial
CMake Tutorial
 

Dernier

Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Victor Rentea
 
Architecting Cloud Native Applications
Architecting Cloud Native ApplicationsArchitecting Cloud Native Applications
Architecting Cloud Native Applications
WSO2
 

Dernier (20)

Exploring Multimodal Embeddings with Milvus
Exploring Multimodal Embeddings with MilvusExploring Multimodal Embeddings with Milvus
Exploring Multimodal Embeddings with Milvus
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
 
Manulife - Insurer Transformation Award 2024
Manulife - Insurer Transformation Award 2024Manulife - Insurer Transformation Award 2024
Manulife - Insurer Transformation Award 2024
 
Boost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfBoost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdf
 
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost SavingRepurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
 
MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024
 
Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...
 
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
 
DBX First Quarter 2024 Investor Presentation
DBX First Quarter 2024 Investor PresentationDBX First Quarter 2024 Investor Presentation
DBX First Quarter 2024 Investor Presentation
 
presentation ICT roal in 21st century education
presentation ICT roal in 21st century educationpresentation ICT roal in 21st century education
presentation ICT roal in 21st century education
 
Strategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherStrategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a Fresher
 
FWD Group - Insurer Innovation Award 2024
FWD Group - Insurer Innovation Award 2024FWD Group - Insurer Innovation Award 2024
FWD Group - Insurer Innovation Award 2024
 
Biography Of Angeliki Cooney | Senior Vice President Life Sciences | Albany, ...
Biography Of Angeliki Cooney | Senior Vice President Life Sciences | Albany, ...Biography Of Angeliki Cooney | Senior Vice President Life Sciences | Albany, ...
Biography Of Angeliki Cooney | Senior Vice President Life Sciences | Albany, ...
 
Architecting Cloud Native Applications
Architecting Cloud Native ApplicationsArchitecting Cloud Native Applications
Architecting Cloud Native Applications
 
AWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of TerraformAWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of Terraform
 
EMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWER
EMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWEREMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWER
EMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWER
 
Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...
Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...
Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...
 
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...
 
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
 

Introducing Command Line Applications with Ruby

  • 1. Ruby on Rails In Practice Apartment List and Thoughtbot San Francisco, September 2012 Getting started with Command Line Applications
  • 2. Ruby on Rails In Practice Apartment List and Thoughtbot San Francisco, September 2012 Getting started with Command Line Applications Nikhil Mungel @hyfather
  • 4. CLI
  • 5. Scriptable CLI Lightweight Consistent UX
  • 7.
  • 8. Textual Manipulation • OO & FP Abstractions • Plethora of CLI gems • Examples to learn from
  • 10.
  • 11. Input Execution Output
  • 12. Input Execution Output STDIO = UI/UX
  • 13. Input STDIN
  • 14. Input ARGV/ENV STDIN
  • 15. Input ARGV/ENV STDIN
  • 16. Input ARGV/ENV STDIN
  • 17. Input OptionParser ARGV/ENV STDIN
  • 18. Input OptionParser ARGV/ENV STDIN
  • 19. Input Libraries OptionParser ARGV/ENV STDIN
  • 20. Input Libraries OptionParser ARGV/ENV STDIN
  • 21. Input Libraries OptionParser ARGV/ENV STDIN
  • 22. options = {} OptionParser.new do |opts| opts.banner = "Usage: example.rb [options]" opts.on("-v", "--[no-]verbose", "Run verbosely") do |v| options[:verbose] = v end end.parse!
  • 23. options = {} OptionParser.new do |opts| opts.banner = "Usage: example.rb [options]" opts.on("-v", "--[no-]verbose", "Run verbosely") do |v| options[:verbose] = v end end.parse! ~ > ./opt.rb --help Usage: example.rb [options]    -v, --[no-]verbose               Run verbosely
  • 24. options = {} OptionParser.new do |opts| opts.banner = "Usage: example.rb [options]" opts.on("-v", "--[no-]verbose", "Run verbosely") do |v| options[:verbose] = v end end.parse! ~ > ./opt.rb --help Usage: example.rb [options]    -v, --[no-]verbose               Run verbosely
  • 25. options = {} OptionParser.new do |opts| opts.banner = "Usage: example.rb [options]" opts.on("-v", "--[no-]verbose", "Run verbosely") do |v| options[:verbose] = v end end.parse! ~ > ./opt.rb --help Usage: example.rb [options]    -v, --[no-]verbose               Run verbosely
  • 26. options = {} OptionParser.new do |opts| opts.banner = "Usage: example.rb [options]" opts.on("-v", "--[no-]verbose", "Run verbosely") do |v| options[:verbose] = v end end.parse! ~ > ./opt.rb --help Usage: example.rb [options]    -v, --[no-]verbose               Run verbosely
  • 28. class MyCLIApp include Mixlib::CLI option :config_file, :short => "-c CONFIG", :description => "Configuration file", :required => true end ~ > ./mycliapp.rb --help Usage: ./mix.rb (options) -c, --config CONFIG Configuration file (required) -h, --help Show this message
  • 29. class MyCLIApp include Mixlib::CLI option :config_file, :short => "-c CONFIG", :description => "Configuration file", :required => true end ~ > ./mycliapp.rb --help Usage: ./mix.rb (options) -c, --config CONFIG Configuration file (required) -h, --help Show this message
  • 30. class MyCLIApp include Mixlib::CLI option :config_file, :short => "-c CONFIG", :description => "Configuration file", :required => true end ~ > ./mycliapp.rb --help Usage: ./mix.rb (options) -c, --config CONFIG Configuration file (required) -h, --help Show this message
  • 31. config.rb server_url “http://server.remote” username “elvis” password “hotdog”
  • 32. config.rb server_url “http://server.remote” username “elvis” password “hotdog” class MyConfig extend(Mixlib::Config) server_url 'http://server.local' username 'king' password 'burger' end MyConfig.from_file(‘config.rb’) irb> MyConfig.server_url # ‘http://server.remote’
  • 33. config.rb server_url “http://server.remote” username “elvis” password “hotdog” class MyConfig extend(Mixlib::Config) server_url 'http://server.local' username 'king' password 'burger' end MyConfig.from_file(‘config.rb’) irb> MyConfig.server_url # ‘http://server.remote’
  • 34. Thor
  • 35. class Test < Thor desc " FILE", "an example task" method_option :delete, :aliases => "-d", :desc => "Delete the file" def example(file) end end
  • 36. class Test < Thor desc " FILE", "an example task" method_option :delete, :aliases => "-d", :desc => "Delete the file" def example(file) end end ~ > myapp help test:example Usage: thor test:example FILE Options: -d, [--delete=DELETE] # Delete the file after parsing it an example task
  • 37. class Test < Thor desc " FILE", "an example task" method_option :delete, :aliases => "-d", :desc => "Delete the file" def example(file) end end ~ > myapp help test:example Usage: thor test:example FILE Options: -d, [--delete=DELETE] # Delete the file after parsing it an example task
  • 38. class Test < Thor desc " FILE", "an example task" method_option :delete, :aliases => "-d", :desc => "Delete the file" def example(file) end end ~ > myapp help test:example Usage: thor test:example FILE Options: -d, [--delete=DELETE] # Delete the file after parsing it an example task
  • 39. class Test < Thor desc " FILE", "an example task" method_option :delete, :aliases => "-d", :desc => "Delete the file" def example(file) end end ~ > myapp help test:example Usage: thor test:example FILE Options: -d, [--delete=DELETE] # Delete the file after parsing it an example task
  • 40. class Test < Thor desc " FILE", "an example task" method_option :delete, :aliases => "-d", :desc => "Delete the file" def example(file) end end ~ > myapp help test:example Usage: thor test:example FILE Options: -d, [--delete=DELETE] # Delete the file after parsing it an example task
  • 41. class Test < Thor desc " FILE", "an example task" method_option :delete, :aliases => "-d", :desc => "Delete the file" def example(file) end end ~ > myapp help test:example Usage: thor test:example FILE Options: -d, [--delete=DELETE] # Delete the file after parsing it an example task
  • 42. class Test < Thor desc " FILE", "an example task" method_option :delete, :aliases => "-d", :desc => "Delete the file" def example(file) end end ~ > myapp help test:example Usage: thor test:example FILE Options: -d, [--delete=DELETE] # Delete the file after parsing it an example task
  • 44.
  • 45. Input Execution Output
  • 46. Input Execution Output
  • 47. Input Execution Output Mostly third party libraries
  • 48. Input Execution Output Test::Unit, rspec etc.
  • 49. Input Execution Output System
  • 51. System File System Network Process
  • 53. Isolated Environments User Container Application File System Network Process
  • 55. STDO UT/S TDER R CLI User App STDIN
  • 56. STDO UT/S TDER R CLI User App STDIN STDOUT & STDERR STDIN Another App
  • 57. STDO UT/S TDER R CLI User App STDIN STDOUT & STDERR STDIN Another App
  • 58. Mixlib::Shellout > ls = Mixlib::ShellOut.new("ls") > ls.run_command > ls.stdout “init.elnREADME.mdn” Nikhil Mungel www.hyfather.com @hyfather
  • 59. Mixlib::Shellout > ls = Mixlib::ShellOut.new("ls") > ls.run_command > ls.stdout “init.elnREADME.mdn” Nikhil Mungel www.hyfather.com @hyfather
  • 61. IO#tty? Nikhil Mungel www.hyfather.com @hyfather
  • 62. Output $stdout TRACE DEBUG INFO $stderr WARN ERROR FATAL Nikhil Mungel www.hyfather.com @hyfather
  • 63. Thanks! I am currently a Grad Student at San Jose State Formerly at ThoughtWorks Studios slidesha.re/rubycli Nikhil Mungel www.hyfather.com @hyfather

Notes de l'éditeur

  1. \n
  2. \n
  3. \n
  4. \n
  5. \n
  6. \n
  7. \n
  8. \n
  9. \n
  10. \n
  11. \n
  12. Input - command line -&gt; Option Parsing\n\nOutput - status code, stdout, stderr\n
  13. Input - command line -&gt; Option Parsing\n\nOutput - status code, stdout, stderr\n
  14. Input - command line -&gt; Option Parsing\n\nOutput - status code, stdout, stderr\n
  15. Input - command line -&gt; Option Parsing\n\nOutput - status code, stdout, stderr\n
  16. Input - command line -&gt; Option Parsing\n\nOutput - status code, stdout, stderr\n
  17. Input - command line -&gt; Option Parsing\n\nOutput - status code, stdout, stderr\n
  18. Input - command line -&gt; Option Parsing\n\nOutput - status code, stdout, stderr\n
  19. Input - command line -&gt; Option Parsing\n\nOutput - status code, stdout, stderr\n
  20. Input - command line -&gt; Option Parsing\n\nOutput - status code, stdout, stderr\n
  21. Input - command line -&gt; Option Parsing\n\nOutput - status code, stdout, stderr\n
  22. Input - command line -&gt; Option Parsing\n\nOutput - status code, stdout, stderr\n
  23. \n
  24. \n
  25. \n
  26. \n
  27. \n
  28. \n
  29. \n
  30. \n
  31. \n
  32. \n
  33. \n
  34. \n
  35. \n
  36. \n
  37. \n
  38. \n
  39. \n
  40. \n
  41. \n
  42. \n
  43. Enforces OO\nAutomatic rake style tasks\n
  44. Enforces OO\nAutomatic rake style tasks\n
  45. Enforces OO\nAutomatic rake style tasks\n
  46. Convention -- \nfirst arg to the description becomes the input \nsecond arg is the banner\n
  47. Convention -- \nfirst arg to the description becomes the input \nsecond arg is the banner\n
  48. Convention -- \nfirst arg to the description becomes the input \nsecond arg is the banner\n
  49. Option Parsing\nInbuilt support for help and banners\nSupports standard invocations of help on the shell\n
  50. Option Parsing\nInbuilt support for help and banners\nSupports standard invocations of help on the shell\n
  51. \n
  52. \n
  53. \n
  54. \n
  55. Input - mostly handled by the third party library.\nTesting that would be testing the gem. Not a good idea.\n\n
  56. Input - mostly handled by the third party library.\nTesting that would be testing the gem. Not a good idea.\n\n
  57. Standard Ruby classes. Libraries like test/unit, rspec.\nMocking and proxy layers for 3rd party services etc.\nLike any other app.\n\n
  58. \n
  59. Mocking\n&amp;#xA0; mocha works out well.&amp;#xA0;\n&amp;#xA0; For filesystem, MockFS lets you mock the entire file system.&amp;#xA0;\n\nTesting CLI apps that manipulate filesystem. Mocking is good. But if we mock every call to FileUtils, test becomes very tightly coupled. So even if behaviour doesn&apos;t change but the command changes the test breaks.\n&amp;#xA0;- one use FakeFS\n\n
  60. Mocking\n&amp;#xA0; mocha works out well.&amp;#xA0;\n&amp;#xA0; For filesystem, MockFS lets you mock the entire file system.&amp;#xA0;\n\nTesting CLI apps that manipulate filesystem. Mocking is good. But if we mock every call to FileUtils, test becomes very tightly coupled. So even if behaviour doesn&apos;t change but the command changes the test breaks.\n&amp;#xA0;- one use FakeFS\n\n
  61. Isolate environment of its own.\nIf its is cheap and scriptable to spin up the environment. Then we can have behaviour testing&amp;#xA0;\n&amp;#xA0; - powerful machines.\n&amp;#xA0; - strong virtualizations (inbuilt)\nvagrant, lxc, openvz\n
  62. Isolate environment of its own.\nIf its is cheap and scriptable to spin up the environment. Then we can have behaviour testing&amp;#xA0;\n&amp;#xA0; - powerful machines.\n&amp;#xA0; - strong virtualizations (inbuilt)\nvagrant, lxc, openvz\n
  63. Isolate environment of its own.\nIf its is cheap and scriptable to spin up the environment. Then we can have behaviour testing&amp;#xA0;\n&amp;#xA0; - powerful machines.\n&amp;#xA0; - strong virtualizations (inbuilt)\nvagrant, lxc, openvz\n
  64. Isolate environment of its own.\nIf its is cheap and scriptable to spin up the environment. Then we can have behaviour testing&amp;#xA0;\n&amp;#xA0; - powerful machines.\n&amp;#xA0; - strong virtualizations (inbuilt)\nvagrant, lxc, openvz\n
  65. Isolate environment of its own.\nIf its is cheap and scriptable to spin up the environment. Then we can have behaviour testing&amp;#xA0;\n&amp;#xA0; - powerful machines.\n&amp;#xA0; - strong virtualizations (inbuilt)\nvagrant, lxc, openvz\n
  66. 2 distinct sections -- your and subprocesses\n\nbackticks and system ruby calls not versatile. Doesn&amp;#x2019;t give you full control over the Input/Output/Error stream\nMixLib::Shellout and POpen3 are better alternatives.\nRespect exit status 0 -for success, rest all failures while writing your CLI.\nYour CLI should write error to stderr and not stdout. ruby provides $stdout, $stdin, $stderr\n\n
  67. backticks and system ruby calls not versatile. Doesn&amp;#x2019;t give you full control over the Input/Output/Error stream\nMixLib::Shellout and POpen3 are better alternatives.\n\nRespect exit status 0 -for success, rest all failures while writing your CLI.\nYour CLI should write error to stderr and not stdout. ruby provides $stdout, $stdin, $stderr\n
  68. backticks and system ruby calls not versatile. Doesn&amp;#x2019;t give you full control over the Input/Output/Error stream\nMixLib::Shellout and POpen3 are better alternatives.\n\nRespect exit status 0 -for success, rest all failures while writing your CLI.\nYour CLI should write error to stderr and not stdout. ruby provides $stdout, $stdin, $stderr\n
  69. Compatible with windows.\nUses the select(2) system call. \nGives abstractions over umask, cwd etc.\n
  70. Compatible with windows.\nUses the select(2) system call. \nGives abstractions over umask, cwd etc.\n
  71. \n
  72. STDOUT could be the default. But should be configurable to a file. \n\nLog at correct level. Apply to all apps but worth mentioning.\n\nyou may want to support -v and -vv for falling back to :info or :debug and -q falls back fatal.\n
  73. \n