lib/bio/shell/core.rb in bio-1.0.0 vs lib/bio/shell/core.rb in bio-1.1.0

- old
+ new

@@ -1,27 +1,27 @@ # # = bio/shell/core.rb - internal methods for the BioRuby shell # # Copyright:: Copyright (C) 2005, 2006 # Toshiaki Katayama <k@bioruby.org> -# License:: Ruby's +# License:: The Ruby License # -# $Id: core.rb,v 1.21 2006/02/27 09:09:57 k Exp $ +# $Id: core.rb,v 1.27 2007/06/28 11:21:40 k Exp $ # +module Bio::Shell::Core -module Bio::Shell::Ghost + SHELLDIR = "shell" + DATADIR = "data" + SESSION = File.join(SHELLDIR, "session") + PLUGIN = File.join(SHELLDIR, "plugin") + SCRIPT = File.join(SHELLDIR, "script.rb") + CONFIG = File.join(SESSION, "config") + OBJECT = File.join(SESSION, "object") + HISTORY = File.join(SESSION, "history") + BIOFLAT = File.join(DATADIR, "bioflat") - SAVEDIR = "session/" - CONFIG = "config" - OBJECT = "object" - HISTORY = "history" - SCRIPT = "script.rb" - PLUGIN = "plugin/" - DATADIR = "data/" - BIOFLAT = "bioflat/" - MARSHAL = [ Marshal::MAJOR_VERSION, Marshal::MINOR_VERSION ] MESSAGE = "...BioRuby in the shell..." ESC_SEQ = { @@ -34,191 +34,224 @@ :c => "\e[36m", :cyan => "\e[36m", :w => "\e[37m", :white => "\e[37m", :n => "\e[00m", :none => "\e[00m", :reset => "\e[00m", } - def history - SAVEDIR + HISTORY + def colors + ESC_SEQ end - def datadir - DATADIR + def shell_dir + File.join(@cache[:savedir], SHELLDIR) end - def esc_seq - ESC_SEQ + def data_dir + File.join(@cache[:savedir], DATADIR) end - ### save/restore the environment + def session_dir + File.join(@cache[:savedir], SESSION) + end - def setup - @config = {} - @cache = {} - check_version - check_marshal - load_config - load_plugin + def plugin_dir + File.join(@cache[:savedir], PLUGIN) end - + + def script_file + File.join(@cache[:savedir], SCRIPT) + end + + def script_dir + File.dirname(script_file) + end + + def config_file + File.join(@cache[:savedir], CONFIG) + end + + def object_file + File.join(@cache[:savedir], OBJECT) + end + + def history_file + File.join(@cache[:savedir], HISTORY) + end + + def bioflat_dir + File.join(@cache[:savedir], BIOFLAT) + end + + def ask_yes_or_no(message) + loop do + STDERR.print "#{message}" + answer = gets + if answer.nil? + # readline support might be broken + return false + elsif /^\s*[Nn]/.match(answer) + return false + elsif /^\s*[Yy]/.match(answer) + return true + else + # loop + end + end + end + +end + + +module Bio::Shell::Ghost + + include Bio::Shell::Core + # A hash to store persistent configurations attr_accessor :config # A hash to store temporal (per session) configurations attr_accessor :cache + ### save/restore the environment + + def configure(savedir) + @config = {} + @cache = { + :savedir => savedir, + :workdir => Dir.pwd, + } + create_save_dir + load_config + load_plugin + end + def load_session load_object - load_history - opening_splash + unless @cache[:mode] == :script + load_history + opening_splash + open_history + end end def save_session - closing_splash + unless @cache[:mode] == :script + closing_splash + end if create_save_dir_ask #save_history # changed to use our own... + close_history save_object save_config end + #STDERR.puts "Leaving directory '#{@cache[:workdir]}'" end - ### setup + ### directories - def check_version - if RUBY_VERSION < "1.8.2" - raise "BioRuby shell runs on Ruby version >= 1.8.2" - end - end - - def check_marshal - if @config[:marshal] and @config[:marshal] != MARSHAL - raise "Marshal version mismatch" - end - end - def create_save_dir - create_real_dir(SAVEDIR) - create_real_dir(DATADIR) - create_real_dir(PLUGIN) + create_real_dir(session_dir) + create_real_dir(plugin_dir) + create_real_dir(data_dir) end def create_save_dir_ask - if File.directory?(SAVEDIR) + if File.directory?(session_dir) @cache[:save] = true end - if @cache[:save].nil? - if ask_yes_or_no("Save session in '#{SAVEDIR}' directory? [y/n] ") - create_real_dir(SAVEDIR) - create_real_dir(DATADIR) - create_real_dir(PLUGIN) -# create_real_dir(BIOFLAT) + unless @cache[:save] + if ask_yes_or_no("Save session in '#{@cache[:workdir]}' directory? [y/n] ") + create_real_dir(session_dir) + create_real_dir(plugin_dir) + create_real_dir(data_dir) + create_real_dir(bioflat_dir) @cache[:save] = true else @cache[:save] = false end end return @cache[:save] end - def ask_yes_or_no(message) - loop do - print "#{message}" - answer = gets - if answer.nil? - # readline support might be broken - return false - elsif /^\s*[Nn]/.match(answer) - return false - elsif /^\s*[Yy]/.match(answer) - return true - else - # loop - end - end - end - def create_real_dir(dir) unless File.directory?(dir) begin - print "Creating directory (#{dir}) ... " - Dir.mkdir(dir) - puts "done" + STDERR.print "Creating directory (#{dir}) ... " + FileUtils.makedirs(dir) + STDERR.puts "done" rescue warn "Error: Failed to create directory (#{dir}) : #{$!}" end end end ### bioflat def create_flat_dir(dbname) - dir = BIOFLAT + dbname.to_s.strip - unless File.directory?(BIOFLAT) - Dir.mkdir(BIOFLAT) - end + dir = File.join(bioflat_dir, dbname.to_s.strip) unless File.directory?(dir) - Dir.mkdir(dir) + FileUtils.makedirs(dir) end return dir end def find_flat_dir(dbname) - dir = BIOFLAT + dbname.to_s.strip + dir = File.join(bioflat_dir, dbname.to_s.strip) if File.exists?(dir) return dir else return nil end end ### config def load_config - load_config_file(SAVEDIR + CONFIG) + load_config_file(config_file) end def load_config_file(file) if File.exists?(file) - print "Loading config (#{file}) ... " + STDERR.print "Loading config (#{file}) ... " if hash = YAML.load(File.read(file)) @config.update(hash) end - puts "done" + STDERR.puts "done" end end def save_config - save_config_file(SAVEDIR + CONFIG) + save_config_file(config_file) end def save_config_file(file) begin - print "Saving config (#{file}) ... " + STDERR.print "Saving config (#{file}) ... " File.open(file, "w") do |f| f.puts @config.to_yaml end - puts "done" + STDERR.puts "done" rescue warn "Error: Failed to save (#{file}) : #{$!}" end end def config_show @config.each do |k, v| - puts "#{k}\t= #{v.inspect}" + STDERR.puts "#{k}\t= #{v.inspect}" end end def config_echo - bind = IRB.conf[:MAIN_CONTEXT].workspace.binding + bind = Bio::Shell.cache[:binding] flag = ! @config[:echo] @config[:echo] = IRB.conf[:ECHO] = flag eval("conf.echo = #{flag}", bind) - puts "Echo #{flag ? 'on' : 'off'}" + STDERR.puts "Echo #{flag ? 'on' : 'off'}" end def config_color - bind = IRB.conf[:MAIN_CONTEXT].workspace.binding + bind = Bio::Shell.cache[:binding] flag = ! @config[:color] @config[:color] = flag if flag IRB.conf[:PROMPT_MODE] = :BIORUBY_COLOR eval("conf.prompt_mode = :BIORUBY_COLOR", bind) @@ -233,11 +266,11 @@ end def config_splash flag = ! @config[:splash] @config[:splash] = flag - puts "Splash #{flag ? 'on' : 'off'}" + STDERR.puts "Splash #{flag ? 'on' : 'off'}" opening_splash end def config_message(str = nil) str ||= MESSAGE @@ -246,119 +279,147 @@ end ### plugin def load_plugin - load_plugin_dir(PLUGIN) + load_plugin_dir(plugin_dir) end def load_plugin_dir(dir) if File.directory?(dir) Dir.glob("#{dir}/*.rb").sort.each do |file| - print "Loading plugin (#{file}) ... " + STDERR.print "Loading plugin (#{file}) ... " load file - puts "done" + STDERR.puts "done" end end end ### object + def check_marshal + if @config[:marshal] and @config[:marshal] != MARSHAL + raise "Marshal version mismatch" + end + end + def load_object - load_object_file(SAVEDIR + OBJECT) + begin + check_marshal + load_object_file(object_file) + rescue + warn "Error: Load aborted : #{$!}" + end end def load_object_file(file) if File.exists?(file) - print "Loading object (#{file}) ... " + STDERR.print "Loading object (#{file}) ... " begin - bind = IRB.conf[:MAIN_CONTEXT].workspace.binding + bind = Bio::Shell.cache[:binding] hash = Marshal.load(File.read(file)) hash.each do |k, v| begin Thread.current[:restore_value] = v eval("#{k} = Thread.current[:restore_value]", bind) rescue - puts "Warning: object '#{k}' couldn't be loaded : #{$!}" + STDERR.puts "Warning: object '#{k}' couldn't be loaded : #{$!}" end end rescue warn "Error: Failed to load (#{file}) : #{$!}" end - puts "done" + STDERR.puts "done" end end - + def save_object - save_object_file(SAVEDIR + OBJECT) + save_object_file(object_file) end def save_object_file(file) begin - print "Saving object (#{file}) ... " + STDERR.print "Saving object (#{file}) ... " + File.rename(file, "#{file}.old") if File.exist?(file) File.open(file, "w") do |f| - begin - bind = IRB.conf[:MAIN_CONTEXT].workspace.binding - list = eval("local_variables", bind) - list -= ["_"] - hash = {} - list.each do |elem| - value = eval(elem, bind) - if value - begin - Marshal.dump(value) - hash[elem] = value - rescue - # value could not be dumped. - end + bind = Bio::Shell.cache[:binding] + list = eval("local_variables", bind) + list -= ["_"] + hash = {} + list.each do |elem| + value = eval(elem, bind) + if value + begin + Marshal.dump(value) + hash[elem] = value + rescue + # value could not be dumped. end end - Marshal.dump(hash, f) - @config[:marshal] = MARSHAL - rescue - warn "Error: Failed to dump (#{file}) : #{$!}" end + Marshal.dump(hash, f) + @config[:marshal] = MARSHAL end - puts "done" + STDERR.puts "done" rescue + File.rename("#{file}.old", file) if File.exist?("#{file}.old") warn "Error: Failed to save (#{file}) : #{$!}" end end ### history + def open_history + @cache[:histfile] = File.open(history_file, "a") + @cache[:histfile].sync = true + end + + def store_history(line) + Bio::Shell.cache[:histfile].puts "# #{Time.now}" + Bio::Shell.cache[:histfile].puts line + end + + def close_history + if @cache[:histfile] + STDERR.print "Saving history (#{history_file}) ... " + @cache[:histfile].close + STDERR.puts "done" + end + end + def load_history if @cache[:readline] - load_history_file(SAVEDIR + HISTORY) + load_history_file(history_file) end end def load_history_file(file) if File.exists?(file) - print "Loading history (#{file}) ... " + STDERR.print "Loading history (#{file}) ... " File.open(file).each do |line| - #Readline::HISTORY.push line.chomp - date, hist = line.chomp.split("\t") - Readline::HISTORY.push hist if hist + unless line[/^# /] + Readline::HISTORY.push line.chomp + end end - puts "done" + STDERR.puts "done" end end + # not used (use open_history/close_history instead) def save_history if @cache[:readline] - save_history_file(SAVEDIR + HISTORY) + save_history_file(history_file) end end def save_history_file(file) begin - print "Saving history (#{file}) ... " + STDERR.print "Saving history (#{file}) ... " File.open(file, "w") do |f| f.puts Readline::HISTORY.to_a end - puts "done" + STDERR.puts "done" rescue warn "Error: Failed to save (#{file}) : #{$!}" end end @@ -384,48 +445,48 @@ end end end def script_begin - puts "-- 8< -- 8< -- 8< -- Script -- 8< -- 8< -- 8< --" + STDERR.puts "-- 8< -- 8< -- 8< -- Script -- 8< -- 8< -- 8< --" @script_begin = Readline::HISTORY.size end def script_end - puts "-- >8 -- >8 -- >8 -- Script -- >8 -- >8 -- >8 --" + STDERR.puts "-- >8 -- >8 -- >8 -- Script -- >8 -- >8 -- >8 --" @script_end = Readline::HISTORY.size - 2 end def save_script if @script_begin and @script_end and @script_begin <= @script_end - if File.exists?(SCRIPT) - message = "Overwrite script file (#{SCRIPT})? [y/n] " + if File.exists?(script_file) + message = "Overwrite script file (#{script_file})? [y/n] " else - message = "Save script file (#{SCRIPT})? [y/n] " + message = "Save script file (#{script_file})? [y/n] " end if ask_yes_or_no(message) - save_script_file(SCRIPT) + save_script_file(script_file) else - puts " ... save aborted." - end + STDERR.puts " ... save aborted." + end elsif @script_begin and @script_end and @script_begin - @script_end == 1 - puts " ... script aborted." + STDERR.puts " ... script aborted." else - puts "Error: Script range #{@script_begin}..#{@script_end} is invalid" + STDERR.puts "Error: Script range #{@script_begin}..#{@script_end} is invalid" end end def save_script_file(file) begin - print "Saving script (#{file}) ... " - File.open(file, "w") do |f| + STDERR.print "Saving script (#{file}) ... " + File.open(file, "w") do |f| f.puts "#!/usr/bin/env bioruby" f.puts f.puts Readline::HISTORY.to_a[@script_begin..@script_end] f.puts end - puts "done" + STDERR.puts "done" rescue @script_begin = nil warn "Error: Failed to save (#{file}) : #{$!}" end end @@ -437,12 +498,12 @@ @config[:message].to_s.split(//).join(" ") end def splash_message_color str = splash_message - ruby = ESC_SEQ[:ruby] - none = ESC_SEQ[:none] + ruby = colors[:ruby] + none = colors[:none] return str.sub(/R u b y/) { "#{ruby}R u b y#{none}" } end def splash_message_action(message = nil) s = message || splash_message @@ -462,11 +523,11 @@ end def splash_message_action_color(message = nil) s = message || splash_message l = s.length - c = ESC_SEQ + c = colors x = " " 0.step(l,2) do |i| l1 = l-i; l2 = l1/2; l4 = l2/2 STDERR.print "#{c[:n]}#{s[0,i]}#{x*l1}#{c[:y]}#{s[i,1]}\r" sleep(0.001) @@ -478,40 +539,40 @@ sleep(0.008) end end def opening_splash - puts + STDERR.puts if @config[:splash] if @config[:color] splash_message_action_color else splash_message_action end end if @config[:color] - print splash_message_color + STDERR.print splash_message_color else - print splash_message + STDERR.print splash_message end - puts - puts - print " Version : BioRuby #{Bio::BIORUBY_VERSION.join(".")}" - print " / Ruby #{RUBY_VERSION}" - puts - puts + STDERR.puts + STDERR.puts + STDERR.print " Version : BioRuby #{Bio::BIORUBY_VERSION.join(".")}" + STDERR.print " / Ruby #{RUBY_VERSION}" + STDERR.puts + STDERR.puts end def closing_splash - puts - puts + STDERR.puts + STDERR.puts if @config[:color] - print splash_message_color + STDERR.print splash_message_color else - print splash_message + STDERR.print splash_message end - puts - puts + STDERR.puts + STDERR.puts end end