Skip to content

Instantly share code, notes, and snippets.

@amirrajan
Last active April 14, 2021 15:40
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save amirrajan/d105f9d41d418d84666c209544abba9a to your computer and use it in GitHub Desktop.
Save amirrajan/d105f9d41d418d84666c209544abba9a to your computer and use it in GitHub Desktop.
Interim Solution for Live Reload of RubyMotion Apps

Interim Solution for Live Reload of RubyMotion Apps

  1. Install rerun: gem install rerun.
  2. Add ./live_reload.rb with the following contents:
# gem install rerun
# gem install readline
# gem install open3
# gem install open3

require 'readline'
require 'pty'
require 'open3'
require 'find'
require 'FileUtils'

first_time = true
@rake_command = "rake"

Signal.trap('INT') do
  puts ''
  puts '============================'
  puts 'SIGINT has to be disable because sometimes repl/rerun sends it here. Yes I agree this is silly.'
  puts "run `kill -9 #{Process.pid}` or press enter to exit."
  puts '============================'
end

def delete_nosync_files
  Find.find('.')
      .find_all { |f| f =~ /dat/ && f =~ /nosync/ }
      .each do |f|
        begin
          FileUtils.rm(f)
        rescue
        end
      end
end

def validate_syntax! file
  results = `ruby -c repl.rb`
  if results =~ /Syntax OK/
    file = File.open(file, 'rb')
    contents = file.read
    file.close
    contents + "\n\n"
  else
    puts results
    nil
  end
end

Signal.trap('SIGUSR1') do
  if first_time
    first_time = false
  else
    if @repl
      monkey_file_contents = validate_syntax! 'monkey.rb'
      if monkey_file_contents
        if @previous_monkey_file_contents != monkey_file_contents
          @stdin.puts monkey_file_contents
          @previous_monkey_file_contents = monkey_file_contents
        end
      end

      repl_contents = validate_syntax! 'repl.rb'
      if repl_contents
        @stdin.puts repl_contents
      end
    else
      kill_repl_and_run_rake
    end
  end
end

def kill_repl_and_run_rake
  if `pgrep repl`.each_line.count == 0  && `pgrep \"#{@rake_command}\"`.each_line.count == 1
    puts "==========================================================================="
    puts "Currently deploying. Touch file after deployment completes to try again."
    puts "==========================================================================="
  else
    `pgrep repl`.each_line { |l| Process.kill('INT', l.to_i) }
    delete_nosync_files
    run_rake
  end
end

def run_rake
  PTY.spawn("#{@rake_command}") do |stdout, stdin, _|
    @stdin = stdin
    stdin.puts 'do_live_reload'
    Thread.new do
      loop do
        stdout.each { |line| print line }
        sleep 1
      end
    end
  end
end

PTY.spawn("rerun \"kill -30 #{Process.pid}\" --no-notify") do |stdout, _, _|
  Thread.new do
    loop do
      stdout.each { |line| print line if line !~ /Failed/ }
      sleep 1
    end
  end
end

run_rake

while expr = Readline.readline('', true)
  if expr == 'repl'
    if !@repl
      puts 'Repl mode enabled. The app will not be reloaded and repl.rb will be sent to RM instead.'
      @repl = true
    else
      @repl = false
      puts 'Repl mode disabled.'
      kill_repl_and_run_rake
    end
  elsif expr.start_with? 'rake'
    @rake_command = expr
    kill_repl_and_run_rake
  elsif expr == 'exit'
    exit(0)
  else
    @stdin.puts expr
  end
  sleep 0.2
end
  1. Run ruby live_reload.rb.

Everytime you save a file. live_reload.rb will execute rake. If you type repl into the terminal, "repl mode" will be enabled. In "repl mode" the app will stop rebuilding, and only the contents of repl.rb will be sent over. Typing repl again will disable "repl mode".

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment