lib/vimgolf/cli.rb in vimgolf-0.4.6 vs lib/vimgolf/cli.rb in vimgolf-0.4.7

- old
+ new

@@ -1,10 +1,9 @@ module VimGolf GOLFDEBUG = ENV['GOLFDEBUG'].to_sym rescue false GOLFHOST = ENV['GOLFHOST'] || "http://www.vimgolf.com" - GOLFDIFF = ENV['GOLFDIFF'] || 'diff' GOLFSHOWDIFF = ENV['GOLFSHOWDIFF'] || 'vim -d -n' GOLFVIM = ENV['GOLFVIM'] || 'vim' PROXY = ENV['http_proxy'] || '' class Error @@ -41,12 +40,17 @@ If you have the key, simply run the setup and paste in your key. DESC def setup - key = VimGolf.ui.ask "Please specify your VimGolf API key (register on vimgolf.com to get it):" + 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}) @@ -54,57 +58,86 @@ else VimGolf.ui.error "Invalid key, please double check your key on vimgolf.com" end end - desc "put [ID]", "launch Vim session" + desc "put CHALLENGE_ID", "launch vimgolf.com challenge" long_desc <<-DESC Launch a VimGolf session for the specified challenge ID. To find a currently active challenge ID, please visit vimgolf.com! DESC - def put(id = nil) + 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 + + desc "local INFILE OUTFILE", "launch local challenge" + long_desc <<-DESC + Launch a local VimGolf challenge. A temporary copy of INFILE is made; the original files will not be touched. + DESC + + 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 + + private + + def play(challenge) begin - VimGolf.ui.warn "Launching VimGolf session for challenge: #{id}" - # - n - no swap file, memory only editing - # - +0 - always start on line 0 - # - --noplugin - don't load any plugins, lets be fair! - # -i NONE - don't load .viminfo (for saved macros and the like) - # - u - load vimgolf .vimrc to level the playing field - vimcmd = "#{GOLFVIM} -Z -n --noplugin -i NONE +0 -u \"#{challenge.vimrc_path}\" -W \"#{challenge.log_path}\" \"#{challenge.work_path}\"" + 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 --nofork -i NONE +0 -u #{challenge.vimrc_path} -U NONE -W #{challenge.log_path} #{challenge.work_path}} debug(vimcmd) - system(vimcmd) + system(*vimcmd) # assembled as an array, bypasses the shell if $?.exitstatus.zero? - diff_files = "\"#{challenge.work_path}\" \"#{challenge.output_path}\"" - diff = `#{GOLFDIFF} #{diff_files}` log = Keylog.new(IO.read(challenge.log_path)) + VimGolf.ui.info "\nHere are your keystrokes:" + VimGolf.ui.print_log log + # Handle incorrect solutions - if diff.size > 0 + 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} #{diff_files}") + system(*GOLFSHOWDIFF.shellsplit + [challenge.work_path, challenge.output_path]) when :retry VimGolf.ui.warn "Retrying current challenge..." - challenge.start raise RetryException when :quit raise Interrupt end end @@ -112,36 +145,45 @@ # Handle correct solutions VimGolf.ui.info "\nSuccess! Your output matches. Your score: #{log.score}" loop do - VimGolf.ui.warn "[w] Upload result and retry the challenge" - VimGolf.ui.warn "[x] Upload result and quit" + 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 => [:w, :x, :retry, :quit] + :choices => choices + [:retry, :quit] when :w next unless upload?(challenge) - challenge.start raise RetryException when :x next unless upload?(challenge) raise Interrupt + when :setup + setup + next # we can hopefully submit this time when :retry - challenge.start raise RetryException when :quit raise Interrupt end end else error = <<-MSG - Uh oh, Vim did not exit properly. + 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 @@ -155,11 +197,9 @@ 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 - - private def upload?(challenge) VimGolf.ui.warn "Uploading to VimGolf..." if challenge.upload == :ok