class CodeRunner
	
	# In the next section are the implementations of all the standard Code Runner commands and some helper functions.
  
	def self.set_runner_defaults(copts = {})
	  	(DEFAULT_RUNNER_OPTIONS.keys - [:sys, :script_folder]).each do |var|
			DEFAULT_RUNNER_OPTIONS[var] =  copts[LONG_TO_SHORT[var]]
		end
		set_class_defaults(copts)
# 		ep DEFAULT_RUNNER_OPTIONS
	end
	
	def self.set_class_defaults(copts={})
		(CLASS_OPTIONS.keys - []).each do |var|
			CLASS_OPTIONS[var] =  copts[LONG_TO_SHORT[var]]
			set(var, CLASS_OPTIONS[var])
		end
	end
	
	# List the available modlets for the given code (copts[:C] or -C on the command line).
	
	def self.available_modlets(copts={})
		process_command_options(copts)
		puts "\nAvailable modlets for #{copts[:C]}:"
		entries = []
		begin
			entries += Dir.entries(SCRIPT_FOLDER + "/code_modules/#{copts[:C]}/my_modlets")
		rescue
		end
		begin
			entries += Dir.entries(SCRIPT_FOLDER + "/code_modules/#{copts[:C]}/default_modlets")
		rescue
		end
		entries.each do |modlet|
			puts "\t" + File.basename(modlet, '.rb') unless ['.', '..', '.svn', '.directory'].include? modlet or modlet=~ /defaults/
		end
	end
	
		# List the available defaults files for the given code (copts[:C] or -C on the command line).
	
	def self.available_defaults_files(copts={})
		process_command_options(copts)
		entries = []
		#begin
			##entries += Dir.entries(SCRIPT_FOLDER + "/code_modules/#{copts[:C]}/my_defaults_files")
			#entries += 
		#rescue
		#end
		#begin
		#run_class = setup_run_class(copts[:C], modlet: copts[:m])
		rc = run_class(copts)
		entries = [rc.rcp.user_defaults_location, rc.rcp.code_module_folder	+ "/defaults_files"].map{|folder|  Dir.entries(folder).grep(/_defaults\.rb$/) rescue []}.sum
			#entries += Dir.entries(SCRIPT_FOLDER + "/code_modules/#{copts[:C]}/defaults_files")
			#entries += Dir.entries(SCRIPT_FOLDER + "/code_modules/#{copts[:C]}/defaults_files")
		#rescue
		#end
		puts "\nAvailable defaults files for #{copts[:C]}:"
		entries.each do |defaults_file|
			#puts "\t" + File.basename(defaults_file, '.rb').sub(/_defaults/, '') unless ['.', '..', '.svn', '.directory'].include? defaults_file
			puts "\t" + File.basename(defaults_file, '.rb').sub(/_defaults/, '')
		end
	end
	
	# Cancel the job with the given id. The user is asked interactively for confirmation and whether they would like to delete the folder for that job as well.
	
	def self.cancel(id, copts={})
		runner = fetch_runner(copts)
		runner.cancel_job(id.to_i)
	end
		
	def self.continue_in_new_folder(folder, copts={})
		runner=fetch_runner(copts)
		options = {}
		if copts[:f] or copts[:j]
			options[:copy_ids] = runner.filtered_ids
		end

		runner.continue_in_new_folder(folder, options)
	end
	
	def self.delete(copts={})
		runner = fetch_runner(copts)
		runner.destroy
	end
	def self.differences_between(copts = {})
		runner = fetch_runner(copts)
		runs = runner.filtered_ids.map{|id| runner.run_list[id]}
		rcp_fetcher = (runs[0] || runner.run_class).rcp
		vars = rcp_fetcher.variables.dup + rcp_fetcher.run_info.dup
		vars.delete_if{|var| runs.map{|r| r.send(var)}.uniq.size == 1}
		vars.delete :id
		vars.delete :run_name
		vars.delete :output_file
		vars.delete :error_file
		vars.delete :executable
		vars.delete :comment
		vars.delete :naming_pars
		vars.delete :parameter_hash
		vars.unshift :id
		#vars.push 'File.basename(executable)'
		table = vars.map{|var| [var] + runs.map{|r| str = r.instance_eval(var.to_s).to_s; str.size>10?str[0..9]:str} }
		#vars[-1] = 'exec'
		col_widths = table.map{|row| row.map{|v| v.to_s.size}}.inject{|o,n| o.zip(n).map{|a| a.max}}		
		eputs
		table.each{|row| i=0; eputs row.map{|v| str = sprintf(" %#{col_widths[i]}s ", v.to_s); i+=1; str}.join('|'); eputs '-' * (col_widths.sum + col_widths.size*3 - 1) }
		#p table, col_widths
	end 
	
	def self.dumb_film(copts = {})
# 		process_copts(copts)
		#old_term = GraphKit::GNUPLOT_DEFAULT_TERM
		size = Terminal.terminal_size
		size[0] -= 2
		term = "dumb #{size.reverse.join(' ')}"
		string = "\n" * size[0]

		runner = fetch_runner(copts)
		string_to_eval = copts[:w]
		frame_array = copts[:F][:frame_array] || copts[:F][:fa]
		index_name = copts[:F][:index_name] || copts[:F][:in]
		#options = (options and options =~ /\S/) ? eval(options): {}
		puts string
		for index in frame_array[0]..frame_array[1]
			string.true_lines.times{print "\033[A"}
			kit = runner.graphkit_from_lists(copts[:G], copts[:g], index_name => index)
      kit.gp.term =  term
			kit.gnuplot(eval: string_to_eval)
			sleep(copts[:F][:fr] ? 1.0/copts[:F][:fr] :  0.1)
		end 
	end
# 	def self.executable_name # :nodoc:
# 		""
# 	end
# 	
# 	def self.rcp # :nodoc:
# 		@rcp ||= KitHash.new
# 	end
	def self.netcdf_plot(netcdf_file, vars, indices, copts={})
		process_command_options(copts)
		begin     
			require "numru/netcdf"
		rescue LoadError
				eputs "Error: No Ruby NetCDF library (was it installed correctly?): data analysis for netcdf files not possible."
				return
		end
		start_indices = indices.split(',').map{|idx|  idx = idx.split(':')[0] if idx =~ /:/ ; eval(idx) || 0}
		end_indices = indices.split(',').map{|idx| idx = idx.split(':')[1] if idx =~ /:/ ; eval(idx) || -1}
			
		ep 'start_indices', start_indices, 'end_indices', end_indices
		file = NumRu::NetCDF.open(netcdf_file)
		to_plot = vars.split(',').map do |var|
		  ep 'var', var
			[file.var(var).get('start'=> start_indices, 'end'=> end_indices).to_a.flatten]
		end
		ep 'to_plot', to_plot
		kit = GraphKit.quick_create(*to_plot)
		ep 'copts', copts
		kit.instance_eval(copts[:w]) if copts[:w]
		kit.gnuplot
		STDIN.gets
		kit.close
	end


	
	def self.print_queue_status(copts={})
		begin 
			eputs queue_status
		rescue => err
			eputs "General queue status doesn't work on this system; showing queue status for this folder"
# 			p err
			runner = fetch_runner(copts)
			eputs runner.queue_status
		end
	end
	
		
	
	
	
	def self.reference(class_or_method, copts={})
		code_folders = Dir.recursive_entries(SCRIPT_FOLDER + '/code_modules').grep(/\/ri$/).map{|fold| ['-d', fold]}.flatten
# 		ep code_folders
		
# 		require 'rdoc/ri/driver'
		
# "
# 		op = @ri_count ? [] : (@ri_count = true; ['--no-use-cache'])
# 		trap(1){puts 'No help available'}
# 		at_exit{raise ""}
# 		p op
		begin
			eputs "Looking up #{class_or_method}"
			RDoc::RI::Driver.run ['-d', SCRIPT_FOLDER + '/ri', class_or_method.to_s] + code_folders
		rescue => err
			eputs "Unknown class or method or no help available: #{err}"
		end
# 		trap(1){}
	end

	
	def self.directory(id, copts={})
		runner = fetch_runner(copts)
		puts runner.run_list[id.to_i].directory
	end
	def self.film(copts={})
		runner = fetch_runner(copts)
		copts[:F][:graphkit_modify] = copts[:w]
		runner.make_film_from_lists(copts[:G], copts[:g], copts[:F])
	end
	
	def self.generate_documentation(username = nil, copts = {})
		ep 'username', username||=ENV['USER']
		
		####### Here we use the command line documentation to generate a fake ruby file that rdoc will understand.
		File.open("class_methods_rdoc.rb", 'w') do |file|
			file.puts <<EOF
  class CodeRunner
	
	
#{COMMANDS_WITH_HELP.inject("") do |str, (long, short, nargs, comhelp, argnames, options)| 
	(puts "Please run this command in the coderunner trunk directory"; exit) unless Dir.pwd =~ /coderunner\/trunk$/
		str << <<EOF2
  # #{comhelp.gsub(/\n/, "\n  # ")}
  #
  # Possible options:
  #
#{options.inject("") do |str, opt|
		longop, shortop, req, ophelp = COMMAND_LINE_FLAGS_WITH_HELP.find{|arr| arr[1] == "-" + opt.to_s}
		str << "  # :#{opt} --- #{ophelp.gsub(/\n/, "\n  # ")}\n  #\n"
	end}
	
	def self.#{long}(#{(argnames+[""]).join(",")}command_options={}) 
	end
	
EOF2
	end
	}
  end
EOF
		end
# 		exit

		system "rm -rf doc/"
		system "rm -rf ri/"
		raise 'Please set RDOC_COMMAND' unless ENV['RDOC_COMMAND']
		system "#{ENV['RDOC_COMMAND']} --format=html -t 'CodeRunner Documentation' -m INDEX.rb  INDEX.rb code_runner_version.rb gnuplot.rb graphkit_gnuplot.rb graphkit.rb gsl_tools.rb  run_backwards_compatibility.rb feedback.rb run.rb fortran_namelist.rb graphs_and_films.rb  class_methods_rdoc.rb instance_methods.rb"
		system "#{ENV['RDOC_COMMAND']} -r --op ri INDEX.rb code_runner_version.rb gnuplot.rb graphkit_gnuplot.rb graphkit.rb gsl_tools.rb  run_backwards_compatibility.rb feedback.rb run.rb fortran_namelist.rb graphs_and_films.rb  class_methods_rdoc.rb instance_methods.rb"
		
		exit if username == ""
		
		string = "rsync -av --delete doc/  #{username},coderunner@web.sourceforge.net:htdocs/api_documentation/"

		puts string
		exec string
	
	end
  

	def self.generate_cubecalc(copts={})
		#return
		File.open('cubecalc.cc', 'w') do |file|
		file.puts <<EOF
#include <stdio.h>
#include <iostream>
#include <cstdlib>
#include <fstream>
#include <cstring>
#include <ctime>
using namespace std;

int main(int argc, char* argv[]){
	string line;
	cout << "Starting..." << endl;
	
	int calculate_sides = atoi(argv[1]); //Should the program calculate the area of the sides of the cube? 
	cout << calculate_sides << endl;
	
	char* input_file_name = argv[2]; //Get the input file name from the command line
	cout << input_file_name << endl;
	
	if (argc > 3){ //It has been told to sleep for a time
		bool cont = true;
		time_t start_t;
		time(&start_t);
		while (cont){
			time_t new_t;
			time(&new_t);
			cont = (new_t < (start_t + atoi(argv[3]) * 1.0));
		}
	}
	
	ifstream edges_file(input_file_name); //Read the edges from the input file
	float* edges = new float[3];
	int j = 0;
	while (edges_file >> edges[j++]){
		cout << edges[j-1] << endl;
	}
	
	
	FILE* output = fopen("results.txt", "w"); //Write the volume to the output file
	fprintf(output, "Volume was %f", edges[0] * edges[1] * edges[2]);
	fclose(output);
	
	if (calculate_sides == 1){ //If it has been told to calculate the sides
		cout << "calculating sides" << endl;
		FILE* sides = fopen("sides.txt", "w");
		for(int i=0; i<3; i++){
			cout << "Side " << i << ": " << edges[(i%3)] * edges[((i+1)%3)] << endl;
			fprintf(sides, "The area of side %d is %f\\n", i, edges[i%3] * edges[(i+1)%3]);
		}
		fclose(sides);
	}
}
	


EOF

		end
	end
	def self.launcher_directory
		ENV['HOME'] + "/.coderunner/to_launch/#{ENV['CODE_RUNNER_LAUNCHER']}"
	end
  def self.start_launcher(refresh, max_queue, copts={})
		#eputs "Starting launcher!"
		raise "Raise refresh is #{refresh}: it must be >= 0.1" if refresh.to_f < 0.1
		raise "Raise max_queue is #{max_queue}: it must be >= 5" if max_queue.to_i < 5
    #raise "Launcher already running" if %x[ps -e -o cmd].split("\n").grep(/coderunner\s+launch/).size > 0
    require 'thread'
    tl = launcher_directory #SCRIPT_FOLDER + '/to_launch'
		#exit unless Feedback.get_boolean( "Launch directory #{tl} already exists: it is suggested that you change the prefix by changing the environment variable CODE_RUNNER_LAUNCHER. Do you wish to continue (don't select yes unless you know what you are doing)?") if FileTest.exist? tl
		raise "Launch directory #{tl} already exists: it is suggested that you change the prefix by changing the environment variable CODE_RUNNER_LAUNCHER. Do you wish to continue (don't select yes unless you know what you are doing)?" if FileTest.exist? tl
#     FileUtils.rm_r tl if FileTest.exist? tl
    eputs "Starting launcher\n"
		at_exit{FileUtils.rm_r tl}
    FileUtils.makedirs tl
		Thread.new{loop{`cp #{tl}/queue_status.txt #{tl}/queue_status2.txt; ps > #{tl}/queue_status.txt`; sleep 1}}
		
    mutex = Mutex.new
    processes= []

		Thread.new do
			loop do
        Dir.entries(tl).each do |file|
          next unless file =~ (/(^.*)\.stop/)
					pid = $1
					mutex.synchronize{Process.kill(pid); processes.delete pid}
				end
				sleep refresh.to_i
			end
		end

    #Dir.chdir(tl) do
      ppid = $$
      loop do
				sleep refresh.to_i while processes.size >= max_queue.to_i
#         processes = []
        Dir.entries(tl).grep(/(^.*)\.start/).each do |file|
          file =~ (/(^.*)\.start/)
          id = $1
					command = ""
          command = File.read tl + '/' + file while command == ""
          pid = fork do
            processes.each do |wpid|
							# Make sure all previously submitted jobs have finished.
              sleep refresh.to_i while %x[ps -e -o pid,ppid].split("\n").grep(Regexp.new("^\\s*#{wpid}\\s+#{ppid}")).size > 0
            end              
						#p ["command", command]
            exec(command)
          end
					`cp #{tl}/queue_status.txt #{tl}/queue_status2.txt; ps > #{tl}/queue_status.txt`
          mutex.synchronize{processes.push pid}

          File.open(tl + '/' + id + '.pid', 'w'){|file| file.puts pid}
          FileUtils.rm(tl + '/' + file)
          
          Thread.new{Process.wait pid; mutex.synchronize{processes.delete pid}}
        end
#         processes.each{|pid| Process.wait pid}
        sleep refresh.to_i
      end
    #end
  end
      
	
	def self.code_runner_execute(ruby_fragment, copts={})
		#eval(ruby_fragment, GLOBAL_BINDING)
		eval(ruby_fragment)
	end
	def self.execute(ruby_fragment, copts={})
		eval(ruby_fragment, GLOBAL_BINDING)
		#eval(ruby_fragment)
	end
	def self.load_file(files, copts={})
		process_command_options(copts)
# 		begin
			files.split(/\s*,\s*/).each do |file|
# 				p file
 				raise ArgumentError.new("#{file} is not a file.") unless File.file? file
				load file
			end
# 		rescue
# 			eval(files)
# 		end
			
	end

	def self.parameter_scan(parameter_scan_array_file, copts={})
		parameter_scan_array = eval(File.read(parameter_scan_array_file))
# 	  	process_copts(copts)
		runner = fetch_runner(copts)
		skip = true unless copts[:k] == false
		folder = Dir.pwd
		Log.logf("self.parameter_scan")
# 		@@runners = {}
		@@mutex = Mutex.new
# 		@runner = new(folder, code: copts[:C], modlet: copts[:m], version: copts[:v], executable: copts[:X])
		@@psppipe = PPipe.new(parameter_scan_array.size + 2,  true, controller_refresh: 0.5, redirect: false)
		parameter_scan_array.each do |parameter_scan|
				@@psppipe.fork do
					runner.parameter_scan(parameter_scan, copts[:p][0], skip: skip, nprocs: copts[:n])
				end
		end
		@@psppipe.finish
		@@psppipe = nil
	end
	def self.plot_graph(copts = {})
# 		process_copts(copts)
		runner = fetch_runner(copts)
		string_to_eval = copts[:w]
		#options = (options and options =~ /\S/) ? eval(options): {}
		eputs 'Starting Graph'
		kit = runner.graphkit_from_lists(copts[:G], copts[:g])
		kit.gnuplot(eval: string_to_eval)
		gets
		kit.close
	end
	def self.readout(copts={})
# 		process_copts(copts)
		runner = fetch_runner(copts)
		puts runner.readout
	end
	def self.recheck(id, copts={})
# 		process_copts(copts)
		runner = fetch_runner(copts)
		runner.run_list[copts[:R]].recheck
		runner.respond_to_requests
	end
	def self.run_class(copts={})
		process_command_options(copts)
		copts[:no_update] = true
		unless copts[:C]
			if FileTest.exist? file=Dir.pwd + '/.code_runner_script_defaults.rb'
				copts[:C] = eval(File.read(file))[:code]
				copts[:m] = eval(File.read(file))[:modlet]
			elsif self.runner
				copts[:C] = self.runner.code
				copts[:m] = self.runner.modlet
			end
		end
		#ep ['code', 'modlet is', copts[:C], copts[:m]]
		            
		return setup_run_class(copts[:C], modlet: copts[:m])
	end
	def self.code_command(string, copts = {})
		run_class(copts).class_eval(string)
		                            
# 		 runner = fetch_runner(copts)
# 		 runner.run_class.class_eval(string)
	end
	def self.run_command(string, copts={})
# 	  	process_copts(copts)
		runner = fetch_runner(copts)
		
		eputs "Calling run_commmand..."
# 		puts "Warning: Use large cache is on (-U or -u) -- no results will be saved" if runner.use_large_cache
		ppipe = PPipe.new(runner.filtered_ids.size + 1, false) if copts[:M]
		no_save = (runner.class == RemoteCodeRunner or copts[:y] =~ /no-save/)
#		runner.generate_combined_ids
#		ep runner.filtered_ids
		runner.filtered_ids.each do |id|
			run = runner.combined_run_list[id]
			
			if no_save or run.is_component
				if copts[:M]
					fork{run.instance_eval(string)}
				else
					run.instance_eval(string)
				end
			else
				if copts[:M]
					pn = ppipe.fork do 
						Dir.chdir(run.directory) do
							run.instance_eval(string);
							run.save 
							run.write_results
						end
						ppipe.i_send(id, Marshal.dump(run), tp: 0)
					end
				else
					Dir.chdir(run.directory){run.instance_eval(string); run.save; run.write_results}
				end
				
			end
		end
		unless no_save
			(runner.filtered_ids.each{|id| runner.run_list[id] = Marshal.load(ppipe.w_recv(id).contents)};ppipe.finish) if copts[:M]
			runner.save_large_cache
		end
		
# 		Process.waitall
		runner.respond_to_requests
	end
	def self.runner_eval(string, copts = {})
# 		 process_copts(copts)
		 runner = fetch_runner(copts)
		 
		 return_val = runner.instance_eval(string)

		 if copts[:Z]
			 Kernel.puts(server_dump(return_val))
		 else
			 return return_val
		 end

	end
	def self.scan(scan_string, copts={})
# 	  	process_copts(copts)
		runner = fetch_runner(copts)
	  	runner.simple_scan(scan_string, nprocs: copts[:n], version: copts[:v], skip: copts[:k], parameters: copts[:p][0])
	end
	def self.submit(copts = {})
# 		process_copts(copts)
		runner = fetch_runner(copts)
# 		raise "something is already submitting" if FileTest.exist? "submitting" 
		runs = []
		raise "Parameters must be an array of inspected hashes" unless copts[:p].kind_of? Array
		Dir.chdir(copts[:Y]) do 

			copts[:p].push nil if copts[:p] == []
	# 				ep copts[:p]; exit
			copts[:p].each do |pars|
				run = runner.run_class.new(runner)
	# 			p pars
				run.update_submission_parameters(pars)
				runs.push run
			end
# 			exit
		end
		runner.submit(runs, nprocs: copts[:n], version: copts[:v], skip: copts[:k], job_chain: copts[:J], no_update_before_submit: copts[:no_update_before_submit])
		#puts "Got here"
		#exit(0)
	end
	def self.resubmit(copts = {})
# 		process_copts(copts)
		runner = fetch_runner(copts)
# 		raise "something is already submitting" if FileTest.exist? "submitting" 
		runs = []
		raise "Parameters must be an array of inspected hashes" unless copts[:p].kind_of? Array
		Dir.chdir(copts[:Y]) do 
			runs = runner.filtered_ids.map do |id|
				eputs id
				run = runner.run_list[id].dup
				if copts[:smart_resubmit_name]
					eputs "Smart name"
					run.set(:naming_pars,  [:resubmit_id])
					run.resubmit_id = run.id
				end
				run.update_submission_parameters(copts[:p][0], false)
				run.run_name = nil unless copts[:rerun]
				run
			end
		end
		#throw(:here)

		runner.submit(runs, nprocs: copts[:n], version: copts[:v], skip: copts[:k], job_chain: copts[:J], no_update_before_submit: copts[:no_update_before_submit], replace_existing: copts[:replace_existing], smart_resubmit_name: copts[:smart_resubmit_name], rerun: copts[:rerun])
	end

	# This method allows the straightforward submission of a single command using the batch queue on any system.
	def self.submit_command(jid, comm, copts={})
		process_command_options(copts)
		submitter = Object.new
		submitter.instance_variable_set(:@command, comm)
		submitter.instance_variable_set(:@jid, jid)
		submitter.instance_variable_set(:@nprocs, copts[:n])
		submitter.instance_variable_set(:@wall_mins, copts[:W])
		submitter.instance_variable_set(:@project, copts[:P])
		class << submitter
			include CodeRunner::SYSTEM_MODULE
			def executable_name
				'custom'
			end
			def job_identifier 
				@jid
			end
			def run_command
				@command
			end
		end
		submitter.execute
	end


	
	def self.readout(copts={})
		runner = fetch_runner(copts)
		runner.readout
	end
	def self.show_values_of(expression, copts={})
		runner = fetch_runner(copts)
		p runner.filtered_ids.map{|id| runner.run_list[id].instance_eval(expression)}.uniq.sort
	end
	def self.status_with_comments(copts={})
		copts[:with_comments] = true
		status(copts)
	end
	def self.status(copts={})
# 		process_copts(copts)
		runner = fetch_runner(copts)
		runner.print_out(0, with_comments: copts[:with_comments]) unless copts[:interactive_start] or copts[:Z] or copts[:no_print_out]
	end
	def self.status_loop(copts={})
# 		process_copts(copts)
		runner = fetch_runner(copts)
		runner.print_out(0, with_comments: copts[:with_comments]) unless copts[:interactive_start] or copts[:Z] or copts[:no_print_out]
		break_out = false
		loop do 
			old_trap = trap(2){eputs " Terminating loop, please wait..."; break_out = true}
			runner.use_large_cache = true
			runner.update(false)
			(trap(2, old_trap); break) if break_out
			runner.recheck_filtered_runs(false)
			runner.print_out(nil, with_comments: copts[:with_comments])
			trap(2, old_trap)
			break if break_out
			break if not runner.run_list.values.find do |r| 
				not [:Complete, :Failed].include? r.status
			end
			#ep "sleep"
		 	sleep 3
			#ep "end sleep"
		end
	end
	def self.write_graph(name, copts={})
# 		process_copts(copts)
		runner = fetch_runner(copts)
		eputs 'Starting Graph'
		kit = runner.graphkit_from_lists(copts[:G], copts[:g])
		#options = copts[:w]
		#options = (options and options =~ /\S/) ? eval(options): {}
		name = nil unless name =~ /\S/
		max = 0
		name.sub!(/^\~/, ENV['HOME']) if name
		if name and name =~ /%d\./	
			regex = Regexp.new(Regexp.escape(File.basename(name)).sub(/%d/, '(?<number>\d+)'))
			Dir.entries(File.dirname(name)).join("\n").scan(regex) do
				max = [max, $~[:number].to_i].max
			end
			name = name.sub(/%d/, (max + 1).to_s)
		end
		raise "kit doesn't have a file_name and no filename specified; can't write graph" unless name or (kit.file_name.class == String and kit.file_name =~ /\S/)
		Dir.chdir(COMMAND_FOLDER){kit.gnuplot_write((name or kit.file_name), {eval: copts[:w]})}
	end
	def self.read_default_command_options(copts)
		DEFAULT_COMMAND_OPTIONS.each do |key, value|
			copts[key] ||= value
		end
	end
	def self.process_command_options(copts)
		if copts[:true]
			copts[:true].to_s.split(//).each do |letter|
				copts[letter.to_sym] = true
			end
		end
		if copts[:false]
			copts[:false].to_s.split(//).each do |letter|
				copts[letter.to_sym] = false
			end
		end

		read_default_command_options(copts)
		copts.each do |key, value|
			copts[LONG_TO_SHORT[key]] = value if LONG_TO_SHORT[key]
		end

		
		if copts[:j] # j can be a number '65' or list of numbers '65,43,382' 
			copts[:f]= "#{eval("[#{copts[:j]}]").inspect}.include? id"
		end
		if copts[:X] and FileTest.exist? copts[:X]
			copts[:X] = File.expand_path(copts[:X])
		end
		if copts[:z]
			Log.log_file = Dir.pwd + '/.cr_logfile.txt'
			Log.clean_up
		else 
			Log.log_file = nil
		end
		copts[:F] = (copts[:F].class == Hash ? copts[:F] : (copts[:F].class == String and copts[:F] =~ /\A\{.*\}\Z/) ? eval(copts[:F]) : {})
		copts[:G]= [copts[:G]] if copts[:G].kind_of? String
		copts[:g]= [copts[:g]] if copts[:g].kind_of? String
# 		if copts[:p] and copts[:p].class == String # should be a hash or an inspected hash
# 			copts[:p] = eval(copts[:p])
# 		end
		copts[:p] = [copts[:p]].compact unless copts[:p].class == Array
		#for i in 0...copts[:p].size

		copts[:Y] ||= DEFAULT_COMMAND_OPTIONS[:Y] if DEFAULT_COMMAND_OPTIONS[:Y]
		if copts[:Y] and copts[:Y] =~ /:/ 
			set_class_defaults(copts)
			copts[:running_remotely] = true
		else
			copts[:Y] = copts[:Y].gsub(/~/, ENV['HOME']) if copts[:Y]
			Dir.chdir((copts[:Y] or Dir.pwd)) do
				set_runner_defaults(copts)
# 				ep DEFAULT_RUNNER_OPTIONS
			end
		end
# 		ep Log.log_file
		#copts[:code_copts].each{|k,v| CODE_OPTIONS[k] = v} if copts[:code_copts]
		copts.keys.map{|k| k.to_s}.grep(/_options$/).map{|k| k.to_sym}.each do |k|
	 		CODE_OPTIONS[k.to_s.sub('_options','').to_sym] = copts[k]
		end	
			
	end

	CODE_OPTIONS={}
	
	# Retrieve the runner with the folder (and possibly server) given in copts[:Y]. If no runner has been loaded for that folder, load one.
	
	def self.fetch_runner(copts={})
# 		ep copts
    # If copts(:Y) is an array of locations, return a merged runner of those locations
		if copts[:Y].kind_of? Array
			runners = copts[:Y].map do |location|
				new_copts = copts.dup.absorb(Y: location)
				fetch_runner(new_copts)
			end
			return Merged.new(*runners)
		end
		process_command_options(copts)
# 		ep copts
		@runners ||= {}
		runner = nil
		if copts[:Y] and copts[:Y] =~ /:/ 
			copts_r = copts.dup
			host, folder = copts[:Y].split(':')
			copts_r[:Y] = nil
			copts[:Y] = nil
			unless @runners[[host, folder]]
				copts[:cache] ||= :auto
				runner = @runners[[host, folder]] = RemoteCodeRunner.new(host, folder, copts)
				#(eputs 'Updating remote...'; runner.update) unless (copts[:g] and (copts[:g].kind_of? String or copts[:g].size > 0)) or copts[:no_update] or copts[:cache] 
			else 
				runner = @runners[[host, folder]]
			end
			runner.process_copts(copts)
		else
		  
			copts[:Y] ||= Dir.pwd
		  	Dir.chdir((copts[:Y] or Dir.pwd)) do
				unless @runners[copts[:Y]]
					runner = @runners[copts[:Y]] = CodeRunner.new(Dir.pwd, code: copts[:C], modlet: copts[:m], version: copts[:v], executable: copts[:X], defaults_file: copts[:D])
					runner.update unless copts[:no_update]
				else
					runner = @runners[copts[:Y]]
				end
 				#p 'reading defaults', runner.recalc_all, DEFAULT_RUNNER_OPTIONS
				runner.read_defaults
 				#p 'read defaults', runner.recalc_all
				
			end #Dir.chdir
		end
# 		ep copts
		return runner
# 		@r.read_defaults
	end
	def self.update_runners
		@runners ||= {}
		@runners.each{|runner| runner.update}
	end


   def self.runner
		@runners ||={}
		@runners.values[0]
	end

	
		def self.manual(copts={})
			help = <<EOF

			
-------------CodeRunner Manual---------------

  Written by Edmund Highcock (2009)

NAME

  coderunner


SYNOPSIS
	
  coderunner <command> [arguments] [options]


DESCRIPTION
	
  CodeRunner is a framework for the running and analysis of large simulations. It is a Ruby package and can be used to write Ruby scripts. However it also has a powerful command line interface. The aim is to be able to submit simulations, analyse data and plot graphs all using simple commands. This manual is a quick reference. For a more tutorial style introduction to CodeRunner go to      
       http://coderunner.sourceforge.net
       
  This help page documents the commandline interface. For API documentation see  
       http://coderunner.sourceforge.net/api_documentation

  As is standard, <> indicates a parameter to be supplied, and [] indicates an option, unless otherwise stated.
  
EXAMPLES

   $ coderunner sub -p '{height: 34.2, width: 221}' -n 24x4 -W 300
   
   $ coderunner can 34 -U
   
   $ coderunner plot -G 'height:width;{};depth==2.4 and status == :Completed;height'
   
   $ coderunner st -ul
   
   $ coderunner rc 'p status' -U

COMMANDS

   Either the long or the short form of the command may be used, except in interactive mode, where only short form can be used.

    Long(Short)  <Arguments>  (Meaningful Options)  
    ---------------------------------------------

#{(COMMANDS_WITH_HELP.sort_by{|arr| arr[0]}.map do |arr| 
	   sprintf(" %s %s(%s) \n\t%s", "#{arr[0]}(#{arr[1]})",    arr[4].map{|arg| "<#{arg}>"}.join(' ').sub(/(.)$/, '\1 '), arr[5].map{|op| op.to_s}.join(','), arr[3], )
    end).join("\n\n")}

OPTIONS

#{((COMMAND_LINE_FLAGS_WITH_HELP + LONG_COMMAND_LINE_OPTIONS).map do |arr|
   sprintf("%-15s %-2s\n\t%s", arr[0], arr[1], arr[3])
  end).join("\n\n")
		}

EOF
		 #help.gsub(/(.{63,73} |.{73})/){"#$1\n\t"}.paginate
		 help.paginate
		end



		

end