+def arv_edit_save_tmp tmp
+ FileUtils::cp tmp.path, tmp.path + ".saved"
+ puts "Saved contents to " + tmp.path + ".saved"
+end
+
+def command_exists?(command)
+ ENV['PATH'].split(':').each {|folder| File.executable?(File.join(folder, command))}
+end
+
+def run_editor tmp_file, global_opts
+ need_edit = true
+ while need_edit
+ pid = Process::fork
+ if pid.nil?
+ editor = nil
+ [ENV["VISUAL"], ENV["EDITOR"], "nano", "vi"].each do |e|
+ editor ||= e if e and command_exists? e
+ end
+ if editor.nil?
+ puts "Could not find any editor to use, please set $VISUAL or $EDITOR to your desired editor."
+ exit 1
+ end
+ exec editor, tmp_file.path
+ else
+ Process.wait pid
+ end
+
+ if $?.exitstatus == 0
+ tmp_file.open
+ newcontent = tmp_file.read()
+
+ newobj = {}
+ begin
+ case global_opts[:format]
+ when 'json'
+ newobj = Oj.load(newcontent)
+ when 'yaml'
+ newobj = YAML.load(newcontent)
+ end
+ need_edit = false
+ rescue Exception => e
+ n = 1
+ newcontent.each_line do |line|
+ puts "#{n.to_s.rjust 4} #{line}"
+ n += 1
+ end
+ puts "Parse error! " + e.to_s
+ puts "\nTry again (y/n)? "
+ yn = "X"
+ while not ["y", "Y", "n", "N"].include?(yn)
+ yn = $stdin.read 1
+ end
+ if yn == 'n' or yn == 'N'
+ arv_edit_save_tmp tmp_file
+ abort
+ end
+ end
+ else
+ puts "Editor exited with status #{$?.exitstatus}"
+ exit $?.exitstatus
+ end
+ end
+
+ newobj
+end
+