# Giles Bowkett, Greg Brown, and several audience members from Giles' Ruby East presentation.
require 'tempfile'
class InteractiveEditor
  DEBIAN_SENSIBLE_EDITOR = "/usr/bin/sensible-editor"
  MACOSX_OPEN_CMD        = "open"
  XDG_OPEN               = "/usr/bin/xdg-open"

  def self.sensible_editor
    return ENV["VISUAL"] if ENV["VISUAL"]
    return ENV["EDITOR"] if ENV["EDITOR"]
    return MACOSX_OPEN_CMD if Platform::IMPL == :macosx
    if Platform::IMPL == :linux
      if File.executable?(XDG_OPEN)
        return XDG_OPEN
      end
      if File.executable?(DEBIAN_SENSIBLE_EDITOR)
        return DEBIAN_SENSIBLE_EDITOR
      end
    end
    raise "Could not determine what editor to use.  Please specify."
  end

  attr_accessor :editor
  def initialize(editor = :vim)
    @editor = editor.to_s
    if @editor == "mate"
      @editor = "mate -w"
    end
  end
  def edit_interactively
    unless @file
      @file = Tempfile.new(["irb_tempfile", ".rb"])
    end
    system("#{@editor} #{@file.path}")
    Object.class_eval(`cat #{@file.path}`)
    rescue Exception => error
      puts error
  end
end

module InteractiveEditing
  def edit_interactively(editor = InteractiveEditor.sensible_editor)
    unless IRB.conf[:interactive_editors] && IRB.conf[:interactive_editors][editor]
      IRB.conf[:interactive_editors] ||= {}
      IRB.conf[:interactive_editors][editor] = InteractiveEditor.new(editor)
    end
    IRB.conf[:interactive_editors][editor].edit_interactively
  end
  
  def handling_jruby_bug(&block)
    if RUBY_PLATFORM =~ /java/
      puts "JRuby IRB has a bug which prevents successful IRB vi/emacs editing."
      puts "The JRuby team is aware of this and working on it. But it might be unfixable."
      puts "(http://jira.codehaus.org/browse/JRUBY-2049)"
    else
      yield
    end
  end

  def vi
    handling_jruby_bug {edit_interactively(:vim)}
  end

  def mate
    edit_interactively(:mate)
  end

  # TODO: Hardcore Emacs users use emacsclient or gnuclient to open documents in
  # their existing sessions, rather than starting a brand new Emacs process.
  def emacs
    handling_jruby_bug {edit_interactively(:emacs)}
  end
end

# Since we only intend to use this from the IRB command line, I see no reason to
# extend the entire Object class with this module when we can just extend the
# IRB main object.
self.extend InteractiveEditing if Object.const_defined? :IRB
