phradion/lgtm_hd

View on GitHub
lib/lgtm_hd/cli.rb

Summary

Maintainability
B
5 hrs
Test Coverage
require 'rubygems'
require 'commander'
require 'os'
require 'clipboard'
require 'catpix_mini'
require 'uri'

module LgtmHD
  class CLI
    include Commander::Methods

    CMD_RANDOM_SYNTAX = 'lgtm_hd random [options]'.freeze
    CMD_TRANSFORM_SYNTAX = 'lgtm_hd <URI|FILE> [options]'.freeze
    OPTIONS_SYNTAX = '[-i | --interactive] [-d | --destination <DIR>] [-p | --preview high|low|none]'

    def run
      program :name, LgtmHD::Configuration::PROGRAM_NAME
      program :version, LgtmHD::VERSION
      program :description, LgtmHD::Configuration::DESCRIPTION
      program :help_formatter, Commander::HelpFormatter::TerminalCompact

      default_command :transform
      global_option '-i', '--interactive', 'Turn on interactive Mode. In case you forgot all these super complexive args and options' do say "-- LGTM HD Interactive Mode --" end
      global_option '-d', '--dest DIR', String, 'Directory to export the LGTM image to. Default value is user\'s current working directory'
      global_option '-p', '--preview QUALITY', String, 'Quality of Image preview live on terminal at the end. Accepted values for QUALITY are [high, low, none]. Default value is high. Set to none for skipping'

      command :random do |c|
        c.syntax = CMD_RANDOM_SYNTAX
        c.summary = 'Fetch random images from LGTM.in'
        c.description = ''
        c.example 'Example', 'lgtm_hd random'

        c.action do |args, options|
          if options.interactive  # Interactive mode!
            options.dest ||= ask('Destination Directory (Enter to skip): ')
            options.preview ||= ask('Image Preview Quality? [high|low|none] (Enter to skip)')
          end
          dest_dir = CLI.destination_dir(options.dest)
          dest_file_prefix = CLI.destination_file_prefix
          check_uris(dest_dir)

          say_step "Fetching from lgtm.in"
          dest_uri,image_markdown = LgtmDotIn.fetch_random_image(dest_dir,dest_file_prefix) do |url, markdown|
            say_step "Loading image at #{url}"
          end

          say_ok "Exported image to #{dest_uri}"

          show_preview dest_uri, options.preview

          copy_file_to_clipboard(dest_uri)
          say "\nOr you can copy the markdown format below provided by lgtm.in"
          say_code_block "#{image_markdown}"
          say "\nIf the image does not have LGTM texts on it, run the cmd below"
          say_code_block "lgtm_hd #{dest_uri}"

        end
      end

      command :transform do |c|
        c.syntax = CMD_TRANSFORM_SYNTAX
        c.summary = 'Generate LGTM text on top of image URL or local image File'
        c.description = 'The command \e[3mtransform\e[0m is the default command hence you can skip typing it instead'
        c.example 'Example', 'lgtm_hd http://domain.com/image.png'

        c.action do |args, options|
          # ARGS validation!
          if args.length >= 1
            source_uri = args[0]
          elsif options.interactive  # Interactive mode!
            source_uri ||= ask('Source Image (URL or Path/to/file): ')
            options.dest ||= ask('Destination Directory (Enter to skip): ')
            options.preview ||= ask('Image Preview Quality [high|low|none] (Enter to skip): ')
          else
            # Since this is the default command so we will provide a little extra care for first-time user
            help_the_noobie
          end

          # Validate the inputs
          source_uri = CLI.source_uri(source_uri)
          dest_dir = CLI.destination_dir(options.dest)
          check_uris(dest_dir, source_uri)
          dest_file = File.join(dest_dir, CLI.destination_file_prefix + CLI.extname(source_uri))

          # Do stuff with our LGTM meme
          say_step "Reading and inspecting source at #{source_uri}"
          meme_generator = MemeGenerator.new(input_image_uri:source_uri, output_image_uri:dest_file)
          say_step "Transforming Image"
          meme_generator.draw

          # Export and play around with the clipboard
          say_step "Exporting to file"
          meme_generator.export do |output|
            say_ok "Exported LGTM image to #{output}."
            show_preview output, options.preview
            copy_file_to_clipboard output
          end # end of meme_generator.export block
        end # end of action
      end # end of command transform

      run!
    end # end run def

    def help_the_noobie
      say_step "\nTo add LGTM text to image:"
      say_code_block CLI::CMD_TRANSFORM_SYNTAX
      say_step "\nTo fetch random LGTM.IN image:"
      say_code_block CLI::CMD_RANDOM_SYNTAX
      say_step "\nGlobal Options:"
      say_code_block CLI::OPTIONS_SYNTAX
      say_step "\nMore Help:"
      say_code_block "lgtm_hd --help"
      say_step "\nVisit #{LgtmHD::Configuration::MORE_HELP_URL} for development purpose or more examples\n"
      exit
    end

    def show_preview(image_path, quality)
      quality ||= 'high'
      quality.downcase!
      if quality.eql? "none" then return end
      quality = 'high' unless quality.eql? 'low'

      say_step "\nImage Preview"
      CatpixMini::print_image image_path, {
        :limit_y => 1.0,
        :resolution => quality,
        :center_x => false,
        :center_y => true
      }
    end

    private

    def copy_file_to_clipboard(output_file)
      if OS.mac? then
        applescript "set the clipboard to (read (POSIX file \"#{output_file}\") as GIF picture)"
        say_ok "Copied file to OS's clipboard for direct pasting to Github comments or Slack"

        # Apple Script Command reference
        # Sample: `osascript -e 'set the clipboard to (read (POSIX file "#{output}") as JPEG picture)'`
        #
        # Currently Github allow pasting image directly to comment box.
        # However it does not support pure text content produced by pbcopy so we have to use direct Applescript
        # No Universal solution as for now.
        #
        # Apple Script reference: http://www.macosxautomation.com/applescript/imageevents/08.html
      else
        Clipboard.copy(output_file)
        say_ok "Copied file's path to OS's clipboard"
      end
    end

    def say_step(*args)
      args.each do |arg|
        say $terminal.color(arg, :magenta)
      end
    end

    def say_code_block(*args)
      args.each do |arg|
        say $terminal.color("#{arg}", :black, :on_white)
      end
    end

    def check_uris(dest_dir, source_uri = nil)
      begin
        raise ArgumentError, "Destination path for exporting image is invalid" unless File.exist?(dest_dir) && File.directory?(dest_dir)
        if !!source_uri
          raise ArgumentError, "Source image is neither proper URL nor FILE" unless source_uri =~ URI::regexp || File.exist?(source_uri)
        end
      rescue ArgumentError => e
        say_error e.message
        exit
      end
    end

    def self.source_uri(source_uri)
      source_uri =~ URI::regexp ? source_uri : File.expand_path(source_uri)
    end

    def self.extname(source_uri)
      ext = File.extname(source_uri)
      ext.gsub(/\?.*/, '')
    end

    def self.destination_dir(dest_dir)
      dest_dir ||= Dir.pwd
      File.expand_path(dest_dir)
    end

    def self.destination_file_prefix
      LgtmHD::Configuration::OUTPUT_PREFIX + Time.now.strftime('%Y%m%d%H%M%S')
    end

  end # end of Class
end # end of Module