class VimGolf::CLI

Public Class Methods

initialize_ui() click to toggle source
# File lib/vimgolf/cli.rb, line 28
def self.initialize_ui
  return if @ui_initialized
  Thor::Base.shell = VimGolf::CLI::UI
  VimGolf.ui = VimGolf::CLI::UI.new
  @ui_initialized = true
end
reset_ui() click to toggle source
# File lib/vimgolf/cli.rb, line 35
def self.reset_ui
  return unless @ui_initialized
  Thor::Base.shell = Thor::Shell::Color
  VimGolf.ui = nil
  @ui_initialized = false
end
start(*) click to toggle source
Calls superclass method
# File lib/vimgolf/cli.rb, line 42
def self.start(*)
  initialize_ui
  super
end

Public Instance Methods

local(infile, outfile) click to toggle source
# File lib/vimgolf/cli.rb, line 105
def local(infile, outfile)
  # make sure our files are sane
  if !(File.file?(infile) and File.file?(outfile))
    VimGolf.ui.error "INFILE and OUTFILE must exist and be regular files."
    exit 1
  end

  challenge = Challenge.new(infile) # use the filename as id
  challenge.local(infile, outfile)

  play(challenge)
end
put(id) click to toggle source
# File lib/vimgolf/cli.rb, line 90
def put(id)
  FileUtils.mkdir_p Config.put_path
  VimGolf.ui.warn "Downloading Vimgolf challenge: #{id}"
  VimGolf::Challenge.path(Config.put_path)
  challenge = Challenge.new(id)
  challenge.download

  play(challenge)
end
setup() click to toggle source
# File lib/vimgolf/cli.rb, line 65
def setup
  VimGolf.ui.info "\nLet's setup your VimGolf key..."
  VimGolf.ui.warn "1) Open vimgolf.com in your browser."
  VimGolf.ui.warn "2) Click \"Sign in with Twitter\"."
  VimGolf.ui.warn "3) Once signed in, copy your key (black box, top right)."

  key = VimGolf.ui.ask "\nPaste your VimGolf key:"

  if key =~ /[\w\d]{32}/
    FileUtils.mkdir_p Config.path
    FileUtils.mkdir_p Config.put_path
    Config.save({'key' => key})

    VimGolf.ui.info "Saved. Happy golfing!"
  else
    VimGolf.ui.error "Invalid key, please double check your key on vimgolf.com"
  end
end
version() click to toggle source
# File lib/vimgolf/cli.rb, line 52
def version
  VimGolf.ui.info "Client #{Vimgolf::VERSION}"
end

Private Instance Methods

debug(msg) click to toggle source
# File lib/vimgolf/cli.rb, line 239
def debug(msg)
  p [caller.first, msg] if GOLFDEBUG
end
play(challenge) click to toggle source
# File lib/vimgolf/cli.rb, line 120
    def play(challenge)
      begin
        challenge.start
        VimGolf.ui.warn "Launching VimGolf session for challenge: #{challenge.id}"
        # -Z         - restricted mode, utilities not allowed
        # -n         - no swap file, memory only editing
        # --noplugin - don't load any plugins, lets be fair!
        # --nofork   - otherwise GOLFVIM=gvim forks and returns immediately
        # -i NONE    - don't load .viminfo (for saved macros and the like)
        # +0         - always start on line 0
        # -u vimrc   - load vimgolf .vimrc to level the playing field
        # -U NONE    - don't load .gvimrc
        # -W logfile - keylog file (overwrites if already exists)
        vimcmd = GOLFVIM.shellsplit + %W{-Z -n --noplugin -i NONE +0 -u #{challenge.vimrc_path} -U NONE -W #{challenge.log_path} #{challenge.work_path}}
        if GOLFVIM == "gvim"
          vimcmd += %W{ --nofork}
        end
        debug(vimcmd)
        system(*vimcmd) # assembled as an array, bypasses the shell

        if $?.exitstatus.zero?
          log = Keylog.new(IO.binread(challenge.log_path))

          VimGolf.ui.info "\nHere are your keystrokes:"
          VimGolf.ui.print_log log

          # Handle incorrect solutions
          if !challenge.correct?()
            VimGolf.ui.error "\nUh oh, looks like your entry does not match the desired output."
            VimGolf.ui.error "Your score for this failed attempt was: #{log.score}"
            loop do
              VimGolf.ui.warn "[d] Show diff"
              VimGolf.ui.warn "[r] Retry the current challenge"
              VimGolf.ui.warn "[q] Quit vimgolf"

              case VimGolf.ui.ask_question "Choice> ",
                                  :type      => :warn,
                                  :choices   => [:diff, :retry, :quit]
              when :diff
                VimGolf.ui.warn "Showing vimdiff of your attempt (left) and correct output (right)"
                system(*GOLFSHOWDIFF.shellsplit + [challenge.work_path, challenge.output_path])
              when :retry
                VimGolf.ui.warn "Retrying current challenge..."
                raise RetryException
              when :quit
                raise Interrupt
              end
            end
          end

          # Handle correct solutions
          VimGolf.ui.info "\nSuccess! Your output matches. Your score: #{log.score}"

          loop do
            choices = []
            begin
              Config.load # raises error if user hasn't finished setup
              choices = [:w, :x]
              VimGolf.ui.warn "[w] Upload result and retry the challenge"
              VimGolf.ui.warn "[x] Upload result and quit"
            rescue
              choices = [:setup]
              VimGolf.ui.warn "[s] Set up vimgolf.com key to submit result"
            end if challenge.remote
            VimGolf.ui.warn "[r] Do not upload result and retry the challenge"
            VimGolf.ui.warn "[q] Do not upload result and quit"

            case VimGolf.ui.ask_question "Choice> ",
                                :type    => :warn,
                                :choices => choices + [:retry, :quit]
            when :w
              next unless upload?(challenge)
              raise RetryException
            when :x
              next unless upload?(challenge)
              raise Interrupt
            when :setup
              setup
              next # we can hopefully submit this time
            when :retry
              raise RetryException
            when :quit
              raise Interrupt
            end
          end

        else
          error = <<-MSG
          Uh oh, Vim did not exit properly.
          Please ensure you can execute 'Vim' from the commandline.
          If the problem persists, please report the error on github.com/igrigorik/vimgolf
          MSG

          VimGolf.ui.error error
        end

      rescue RetryException => e
        retry
      end

    rescue Interrupt
      VimGolf.ui.info "\nThanks for playing!"
    rescue RuntimeError, Exception => e
      VimGolf.ui.error "Uh oh, something went wrong! Error: #{e}"
      VimGolf.ui.error "If the error persists, please report it to github.com/igrigorik/vimgolf"
    end
upload?(challenge) click to toggle source
# File lib/vimgolf/cli.rb, line 227
def upload?(challenge)
  VimGolf.ui.warn "Uploading to VimGolf..."

  if challenge.upload == :ok
    VimGolf.ui.warn "Uploaded entry."
    VimGolf.ui.warn "View the leaderboard: #{GOLFHOST}/challenges/#{challenge.id}"
  else
    VimGolf.ui.error "Uh oh, upload failed. You're not cheating are you? :-)"
    nil
  end
end